From a96c146d30e5ae757fb4cf87cd95787ee152670e Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Mon, 23 Mar 2026 15:26:16 +0400 Subject: [PATCH 0001/1083] 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 0002/1083] 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 0003/1083] 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 0004/1083] 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 0005/1083] 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 0006/1083] 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 0007/1083] 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 747f588fa70e809aa17f3dbeb01a90df3f473f96 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 25 Mar 2026 15:27:36 +0100 Subject: [PATCH 0008/1083] Update UI of replies. --- .../components/TimelineItemEventRow.kt | 61 +++++++++++-------- .../matrix/ui/messages/reply/InReplyToView.kt | 13 ++-- .../textcomposer/ComposerModeView.kt | 9 ++- 3 files changed, 49 insertions(+), 34 deletions(-) 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..a814d8da42 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 @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.timeline.components import android.annotation.SuppressLint import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.draggable @@ -269,7 +270,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), @@ -742,11 +745,17 @@ private fun MessageEventBubbleContent( } else { inReplyToModifier.clickable(onClick = inReplyToClick) } - InReplyToView( - inReplyTo = inReplyTo, - hideImage = timelineProtectionState.hideMediaContent(inReplyTo.eventId()), - modifier = talkbackCompatModifier, - ) + Row( + talkbackCompatModifier + .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(6.dp)) + .background(ElementTheme.colors.bgCanvasDefault, RoundedCornerShape(6.dp)) + .padding(4.dp) + ) { + InReplyToView( + inReplyTo = inReplyTo, + hideImage = timelineProtectionState.hideMediaContent(inReplyTo.eventId()), + ) + } } if (inReplyToDetails != null) { // Use SubComposeLayout only if necessary as it can have consequences on the performance. @@ -833,25 +842,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/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt index dcf12f1953..0dc8aac09e 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt @@ -18,7 +18,6 @@ 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.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -82,19 +81,19 @@ private fun ReplyToReadyContent( modifier: Modifier = Modifier, ) { val paddings = if (metadata is InReplyToMetadata.Thumbnail) { - PaddingValues(start = 4.dp, end = 12.dp, top = 4.dp, bottom = 4.dp) + PaddingValues(end = 8.dp) } else { - PaddingValues(horizontal = 12.dp, vertical = 4.dp) + PaddingValues(start = 8.dp, end = 8.dp) } Row( modifier - .background(MaterialTheme.colorScheme.surface) + .background(ElementTheme.colors.bgCanvasDefault) .padding(paddings) ) { if (metadata is InReplyToMetadata.Thumbnail) { AttachmentThumbnail( info = metadata.attachmentThumbnailInfo, - backgroundColor = MaterialTheme.colorScheme.surfaceVariant, + backgroundColor = ElementTheme.colors.bgSubtlePrimary, modifier = Modifier .size(36.dp) .clip(RoundedCornerShape(4.dp)) @@ -128,7 +127,7 @@ private fun ReplyToLoadingContent( val paddings = PaddingValues(horizontal = 12.dp, vertical = 4.dp) Row( modifier - .background(MaterialTheme.colorScheme.surface) + .background(ElementTheme.colors.bgCanvasDefault) .padding(paddings) ) { Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { @@ -146,7 +145,7 @@ private fun ReplyToErrorContent( val paddings = PaddingValues(horizontal = 12.dp, vertical = 4.dp) Row( modifier - .background(MaterialTheme.colorScheme.surface) + .background(ElementTheme.colors.bgCanvasDefault) .padding(paddings) ) { Text( diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt index ac64245668..3d7c4f810c 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.textcomposer import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -120,6 +121,9 @@ private fun EditingModeView( } } +/** + * https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2019-6286 + */ @Composable private fun ReplyToModeView( replyToDetails: InReplyToDetails, @@ -129,8 +133,9 @@ private fun ReplyToModeView( ) { Row( modifier - .clip(RoundedCornerShape(13.dp)) - .background(MaterialTheme.colorScheme.surface) + .clip(RoundedCornerShape(6.dp)) + .background(ElementTheme.colors.bgCanvasDefault) + .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(6.dp)) .padding(4.dp) ) { InReplyToView( From 6c32b27cbd993fed4620ae25044a78916052ffd1 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 25 Mar 2026 14:43:07 +0000 Subject: [PATCH 0009/1083] Update screenshots --- ....components_TimelineItemEventRowDisambiguated_Day_0_en.png | 4 ++-- ...omponents_TimelineItemEventRowDisambiguated_Night_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_1_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_0_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_1_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_0_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_1_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_0_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_0_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_10_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_11_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_2_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_3_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_4_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_5_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_6_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_7_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_8_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_9_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_0_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_10_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_11_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_1_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_2_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_3_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_4_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_5_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_6_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_7_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_8_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_9_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_0_en.png | 4 ++-- ...aries.matrix.ui.messages.reply_InReplyToView_Day_10_en.png | 4 ++-- ...aries.matrix.ui.messages.reply_InReplyToView_Day_11_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_1_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_2_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_3_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_4_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_5_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_6_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_7_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_8_en.png | 4 ++-- ...raries.matrix.ui.messages.reply_InReplyToView_Day_9_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_0_en.png | 4 ++-- ...ies.matrix.ui.messages.reply_InReplyToView_Night_10_en.png | 4 ++-- ...ies.matrix.ui.messages.reply_InReplyToView_Night_11_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_1_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_2_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_3_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_4_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_5_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_6_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_7_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_8_en.png | 4 ++-- ...ries.matrix.ui.messages.reply_InReplyToView_Night_9_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Day_1_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Day_2_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Day_3_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Night_1_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Night_2_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Night_3_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png | 4 ++-- ...s.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png | 4 ++-- ...s.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png | 4 ++-- ...textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png | 4 ++-- ...textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_0_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_10_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_11_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_1_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_2_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_3_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_4_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_5_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_6_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_7_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_8_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_9_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_0_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_10_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_11_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_1_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_2_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_3_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_4_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_5_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_6_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_7_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_8_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_9_en.png | 4 ++-- 112 files changed, 224 insertions(+), 224 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png index 70cad36fb8..c70050658f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6ff9fab1ba47c6980973ab630452ba495c48c8a3a8a729165d8e4b349829610 -size 378850 +oid sha256:bd81cbc3db5d329fcc1f0d4866c220af7488bb68929d0e75b983a170d15a7ab7 +size 380173 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png index 63c81718ec..57e2226f1f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f89057d77318350e25c3f77f805d94b0565c6da49d75c5a4ea5f720bc940639 -size 377421 +oid sha256:3be2bb0c8e344780d59b67a4ba23e50890b24a8b8ad1c48673e34403ff8db496 +size 378130 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png index 3545243654..662ccbf182 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df9a19fd97818a42de31abad719e3970c6f43ff5a5c9da18178d56055a77bff4 -size 364535 +oid sha256:da65fa129fdfe903f3e466f4e1dc6c70a6930e0388a3f6d3fb116e5b91411cc3 +size 365497 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png index 60c7cb350d..11289371f2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1841032c1263db6fa60fb623f22dfe403ad0b84feaaa805f22ee4ab4c0a38003 -size 369676 +oid sha256:cd797555bb72d7bc1b874df24ca5793df5550b235fe9a28d20aaa04bf5f3d0fb +size 370592 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png index 6b0aacceea..64bcaa05f9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d1104ad18d9f1f3d1fdd8d06b1ad770e83683ffab1178cdfa39287ecc9cad2c -size 362744 +oid sha256:be969a809f346799887fe031e139dcc47db8bc851ca4ccfae8dad4ad9dc523f7 +size 363498 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png index 5632e96cc3..33ea565e67 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e338bf938a51a33a938bf56a7586f40027e6315a7274081d69ca1b7d90f4ac2 -size 367989 +oid sha256:48c0af64a6aab3a28ac0493bb86cb92424555d6793a0a5c6cd446c25a20ce915 +size 368757 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png index af596ec8bf..1a345fdd13 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc00bc0d3b8e39def6e436041ae33c7347590bd7db5593e971be1097fcea61d0 -size 352831 +oid sha256:9b4bef0095e989bd411426a2626155f1b75931f05c32d2632144f3c232f3aa93 +size 348379 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png index 0f49e8038e..7ef8d729ef 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7b737239c280a29096ed2e6baa119c0aa9ca43be19fc0dee4954421b1fd9676 -size 362812 +oid sha256:30db6503b7dde29553b5f806924565b1d60c13edeeaa982dd2ec7d2a5c8f1162 +size 364508 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png index 89e08bb36a..72f5c9a9e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25c2bd1012f42aca6e26e507227a5c2124d467e1f5a53f904771d3ee04ea135c -size 351416 +oid sha256:15ad31eb2b457790913442d3186fae215f77f345470748cd64a345849b9de9d0 +size 346837 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png index 29b0433aee..5a6ad7fc23 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a460c547938ad02671120449143521416d7aa749933b9de383426eb0739dfc3 -size 360735 +oid sha256:2e72a79c374fc23a1325e1bd294584b8b7f0b312c804b932144bc2e5d8911bd9 +size 361950 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png index 32287d297f..ca682211d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcc2ff819cc5ffc150733fb1d35d5c33980f3a02b64ba22ce1ff18937a6060ac -size 369227 +oid sha256:092a0d4c37d47c84c790a767b9acc77f38878876e609b986f80e5fb461e0a340 +size 370156 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png index 422d500669..51a93f68e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e0a453b674c183397bd7d73989c6076b117b77b76530ae950a880e1695b81a1 -size 354134 +oid sha256:097fe6208d9cadc707e6866c151a2ab843550a9fab4d2cf4908514ceafc4e396 +size 355327 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png index abae0a9fc1..e60716fb3b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:188123a9bb96d0ef73bb155dc3483bf9b62beff19c09476290c2e41deb037539 -size 367454 +oid sha256:f61a7a62c6fc96e23c8aaa793f5fff68e2197a067ad8f1614d1103e833b3230c +size 368585 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png index f6cbf9e1e0..73be879502 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a18bd271f6b62f41b4444db47ed670556aebc35ae04fab5d7469584a693b355b -size 344427 +oid sha256:091352ebd6bf2abfac5dfd99be5edc94159a5a45c1d3137c7271e0031116a254 +size 345649 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png index f85a41dda7..4ec235074c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec95fa651eb1c0d4177a39cdb2edfa341836ef7f950e00859330092bd3377ec8 -size 356956 +oid sha256:842632747c13219ee6c7a50d9003c9e07c622393ae4b066e86eacf04f807b181 +size 358344 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png index ec431d5dcc..bc6cb62827 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab3cd83565ad087a616318e19bf61543a6b147526f5cf954ccbe9a74697e7b0f -size 356246 +oid sha256:4f43d615fd1aec05ee483d3047e99c1ecc89a6e5a7e56e6cf7e1ea4c108be413 +size 357473 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png index 15dd124ae3..d39b6ec114 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba66f3cf4dd43a7142313ded0ba4250a161f0ee81b69e49479af6cc6386782af -size 363963 +oid sha256:898a1e8f0277d43a1127d99ec50687c24fe1154ceb290832a14fa5a43f12647a +size 365153 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png index 3299e1b955..0617c06d2f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba8724c2426d9cde19b8b447adae49fa84b15dda972f2ea5ee14ec8753c5fb70 -size 396669 +oid sha256:4cce6211c0a33407498145cb03a780d80553983146f487ba3e26f794ddf12369 +size 397594 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png index bb57c7a9a4..838c70dcdc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a98bbc32b55663fb92f37d8137ced36796f8be9e6597df307cc5e70dc3c77548 -size 355533 +oid sha256:f7e91b7aec4c43e2028a2e69a02f66e04f6a3188a42387013e3deb1faa7a108e +size 356627 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png index e0be9f97b2..44e5341280 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c43a1fc9e46f5aa0cb3c7b16138eab590f3851bc2931d49a07e1ddd298b835da -size 354924 +oid sha256:80c2e99ce6f851994da38077acc30ff386867f2093a8db4de3c1b82b0b6c1a8e +size 356307 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png index bf6cbaadcb..6a0ee13891 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d7b628cc474a421869207c8ffd86e46c193da3e1fe8ea115fb12574528da933 -size 364172 +oid sha256:b4fd5470ac81fbdaf471e297c0f5bd9c6b9945e006ab88079568848befe1049d +size 365366 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png index cf0a527c3d..cede2d333e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:531d5e33349addf7274516915d58c7b71ee6f02c7775dcfdbdd5aac22054ef1e -size 354717 +oid sha256:a75fb4510d405b29b120fa400d4f69a89965c11a2228b5cc2e772200a12227e1 +size 355912 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png index dfe3285500..ebe440bfdd 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3573fe8bc2e46dd8ec7a1802461e25fe81f4997028f22da10588f786523a8a0 -size 367332 +oid sha256:a3f7e96bbbb4b3661514713514d7f6cb27c6634ba2621c22c0dd4ff730e5e24a +size 368043 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png index 13940f7bbe..bd841f6f75 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab71afb3d5dc8091553a5691ad0ec6f29f054111f4f753a4b4e1ce69804a5295 -size 352399 +oid sha256:449cc2fa5ce39163a5d5eea3430c7dc457579d41b0213b8b46a61acaa76b3ccc +size 353304 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png index 0024d09ff8..2867c5dfd4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1dd9be6a617150efa3e26eed31adc31a91a9daf698ab1a1e720d98e946f00696 -size 365708 +oid sha256:4cb93499ea8f21d3fb79aa81b2746972f57a4732296bb421897e93a47ddf7d06 +size 366544 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png index 6e5f39b2aa..83d0f043e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:036665adb2b62bc19fac69180a6d9f3774831daa65993cadb49f9e0db67c50a8 -size 342324 +oid sha256:a6bb6a35c2e1d2090e6e6e5b3a1733d16fd433e63925082b2ea32293ecc639fd +size 343140 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png index 5c6c6874d5..e178f75d91 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0894fc410211b804f62d3cbaf717443b3f91661bb3adc0b317d94bdd020ea2ad -size 355530 +oid sha256:a1067826b5b1e3220eef3ee3b9a8c9f77bebb248ba2378cc2e7029b86c585c48 +size 356339 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png index 7cc5d83e7b..f43199a9d8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7311e62cbf34246e18a8cad6dd9b66f79d5a97bee7a209cf436f27df77c31c4 -size 354658 +oid sha256:437f71e1845447b8f09905b4d97dd46677d8d8db669a317f8cba9ada6f5f1aa8 +size 355551 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png index 50421fffa8..80db679074 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad2e5231f8aa2ece0bcdf7cf11d01fc02054591bceb954db5bde776982b3a993 -size 362278 +oid sha256:ffa5216fcff101f8ab1047ac9808f98749144e1b1197bc01905cd6ad251d31b7 +size 363081 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png index f19ffbc4f7..b7a7e2020b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2fc2bb23a0d904e8b8a60e3911c5f39c1623816ab0ffc5282f794ac84dad55dd -size 394921 +oid sha256:222460ba0557c96c2ad0e8aab675a254f515281d06bf4a7b642ea7ef79d5171d +size 395589 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png index 05df91e738..75bb1086fe 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15765ef6c94a2705d3c522d0bafc5494dcb182ec1fd096e4cfd2ead49f9e19ab -size 353748 +oid sha256:bb0a738e57b657bda2454526dcd78a37d38839183a5feae99bf7f107c12ccded +size 354661 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png index e6f7683c55..a93768052e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6f679df9cbe470096c5f939a1781973586fd9afb2d76b634c4ccc47180c7afb -size 353506 +oid sha256:7f98146a417290fcc741ef676fdb60f36822931358e943ad12faace7f96e995f +size 354422 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png index 38499a5838..c09d98903c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b9a9264b6637a35096b2f552a2dbe9f6fa6a078bb631c17bf1d207e10928f07 -size 362463 +oid sha256:54c9d1f121d83f1a161f6483a6b4bbefa220c235ae88097ed4d03baf10bbcf9c +size 363289 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png index b590ba1a5e..0e2c06b0f3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b144eda9c14fe696ad81309441181008eddeeec7c6b4aa4cc3b2b7c702ae6539 -size 353091 +oid sha256:932e5b29f2a64d70956470bee1be397775c6205f590081d3b90c98cf47845577 +size 353993 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en.png index fd8c973b2f..b2178a98a8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:831fd682ca73c8e76f63d6b504f1f48bb23a26f2c4b706764d9d10e3fd9408d7 -size 10345 +oid sha256:319efe6fe21e61125e9f935a13724ddab6ba6c8ae21c7d21bd70470c3a22989f +size 10275 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en.png index 57de8c7c5a..e19875f9b0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7a5321def638da7c0be09583cb2f1dfb426b72391101649499c50654b583ea7 -size 6047 +oid sha256:7732d4b601ddd133a4b3ae55cd89924a7b12fffaf2209039c92594176b6d4b7f +size 6094 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_11_en.png index fc75f53313..6e3ce81929 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96dd2df2b23af067aa88b042a8630ec90a3f97902a1633cb7549a602703129fe -size 9958 +oid sha256:f20f580ef41bc793db8de7d68dc32ca40a4a1208888211bd7985401aeb8eb887 +size 9933 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en.png index 86a1004473..c2427f09ce 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fdb88a54b6d4b4cd63f82c378a130f5db142826ccb8639e76f50e3b0c40b591 -size 19131 +oid sha256:21ed68f52eb3491a6ac8afa8ea30a1b30b85d2d8e31b55435d4b54c50ba7fa22 +size 19086 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en.png index c0a8409f4a..ce1aa75dbd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:910497ff71ac4339d7d74a5429adad2f433e3e013eba029bcdddf7a19d5dc7f7 -size 6995 +oid sha256:4c7b1a09703340606e5bbdd04b40639eb9a699eacfc13544c68cc023911b00ed +size 7036 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en.png index e674aec88f..b8be38269c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f63e794327c94cb5ac33a4c6aecfefecd33061d7dae11b0ec69f844d26760c5 -size 6751 +oid sha256:3f12bcd2d9f3f7886d18af3a2744d90ff404e31d76f5b639ceafa4a56def6b8a +size 6742 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en.png index fdf537d713..edb7b691b1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52dde3608560c4b9d72f77369bd118cc0afcdc975980e034717be191bd77ff87 -size 8879 +oid sha256:1bfa60a6f0c11fef5b2495d0c6eb7f8ee1307f1b0e26c5ca011ae42974f58a25 +size 8876 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en.png index 6efcfde23c..26feb79b74 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a31373ee4be724122839f9d9d7dbed0727a5f75a816f76edb962d107a281bc42 -size 17804 +oid sha256:3d2d4a34cc7b6dad27e647d8621611327ca44dac4e06a94275c8eb3e3255640c +size 17483 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en.png index b54cd19be0..cdfdcdef46 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d1ace89822dfcde7822bc2412787290d64094f6ee82afcd4247fa3bac36067e -size 6464 +oid sha256:916fa670e5d86b765b01a4304ea57871875170f9d98d148f3c0a2aa2c4c5d32c +size 6431 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en.png index 10e2663ec0..bb4ce4a2ba 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:817085c720aa5106231462bdab94c3a4bded7ea64285e42123c2972fb1492c5d -size 6416 +oid sha256:b4dd558d07a5c122615c6c733532d46db3989d4f1fa08a0df1dc78fd9079111d +size 6439 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en.png index 789e6ad754..7dada9cdd4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:936f352e9c70919e2f5d325dee2eb3048b625e77bbdc0ac1685d023c131a7cb2 -size 8977 +oid sha256:edfccd98d79cdd1f16c6d8068a54b752d29f52e7b5cead52addd24bff6be3e6d +size 8966 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en.png index 511ec6112b..6d0d14ef53 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd9e3f62c47e3cabeab49a3ffc6cc4ebde8c5baa03c5997dd9796a2eec3fd420 -size 6297 +oid sha256:6868dab8f078724ed45df7b8f391a205ea373bad58d80e33d8299e279e063a33 +size 6317 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en.png index 38469923aa..095a3410bf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b6bf627769f2bbaa1c76142e7f17f5c7d5b8c3e1029cad3d498085d0764cfe6 -size 10035 +oid sha256:72cb0735391078279290f06c187c910d0929f3de2736aab5426ca3265f2088d0 +size 10018 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en.png index 4de0e3dfbd..87fce6f844 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61171fff9c238017712540f8af20e75cbfb4a2a5e87419a43f3332bc38088f47 -size 6027 +oid sha256:93c0b838dcb60c3a5ccadfa4ef821a3478dfbc541edaae767f33ff25bb2841ca +size 6018 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_11_en.png index 5e3ac6761f..fbf2c4fed5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:672eb3e8dc52f074598d0425b039fb829649efc91c4eec741a836fd850c38b6f -size 9740 +oid sha256:7b38b70e42547fde8c3a291b82d15aeeed46061a6d35d7ba1bc84e02f1772aef +size 9708 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en.png index 80762319f3..5d4b40749a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:361324daf490ded4331db68f8891b4fd3b36e6aa26b1436df3024aaad7c2e5d1 -size 18454 +oid sha256:ecd7d668dc9fe5442cad662bef3f27d854c11f3f186d35da9c8f8f59e976e584 +size 18424 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en.png index 283f6b60a7..be2b979a76 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e4b543edb49c9d8cd38276ecc28d425a9baa50f2e87ca900586341d1275f52f -size 6943 +oid sha256:3323b411015fe4cab91a492c33db0ded076d69a8327a91af956472f529662130 +size 6932 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en.png index 43eed1e235..f96a9ea58c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c53797fb625f7aeca30c11204f29afa45f235f652a3af4d92efb9415e5578d1 -size 6692 +oid sha256:bf1ff1acd363de8d5055a10f389f4542798bfd8cd72502cc21caef193eff6671 +size 6672 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en.png index d72c6927a5..d52f37416a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8243879f43ea8e6709b93292582748448e6a4ed55bd2d6e71aecb0788a2c98f4 -size 8697 +oid sha256:e0094eb0a7870ef9f703c10b90c0d03a9ac9e86c0a70875dc025e63c89e9ecbb +size 8704 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en.png index 6f652cf7d1..26cbd5d0e9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd154b4458a13250e547b5d4d48cbc05901024abd1add7497087ccd6e1e2163e -size 17601 +oid sha256:ed3dcc9061307803439cebfb2903a1778435e01cf6f0e0f35df89f82a1e9160f +size 17325 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en.png index e6aa19ef86..a934693a97 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48ae21d563c8a8b0793fcee2ca31e10e1d5f27a337d86fa6cebf40a33fff335c -size 6370 +oid sha256:fa841c96088cb4dc2998254a75acb61399301b175f547e7ae69886709ae8b2f6 +size 6371 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en.png index 4434ead741..1eb7e6614d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c1afc8b6bfa23e9ed73413078bd487c5557bc8c26717cef6c940cc6f0edf113 -size 6385 +oid sha256:c6d6286677b18af00e1a9b1198f0ae9aed929be74bbc122d051d867a51f373a6 +size 6358 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en.png index 8220e6b24a..57ff1a49a7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8799ed0f6c481130b4f1e3b5ff2c47148e84d5d26aa94559643b82f6db5a3521 -size 8756 +oid sha256:d8c926148b9641484885d6ccabbb54966f5e67a2d9fca609005d8ed8ad7d15d3 +size 8747 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en.png index 4df564660f..b6e3e269a1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:faa63783632a02ad15b8685d7666f3cd690d7e4507cb68bc1c3e2c04dda37af1 -size 6232 +oid sha256:63edce0142c410df6cace76df14e545b0b9c93eaacdf6707b01c2b16bb78a168 +size 6244 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png index a5dfdf516a..a5db879ab2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e487991c578b7e3da4aa85c6b927716be10427c13db9ef65c2b784358f8f3eb4 -size 11276 +oid sha256:9775ee85b895e1eb6b58841a5232de980f44bf4a20c0f2e2bcab731f503fc762 +size 11000 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png index face9cac29..c186a409ad 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3434cec9678fed9ef856f82ba8c403ba4f910d2997d05b7c2ffa9c71e5e73d1 -size 18588 +oid sha256:d7ab6bf5d8255d61569c4400f5a911400f415a4e228de41e181ccb42e2742e47 +size 18637 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png index e10dd2f7f4..c229dd85d8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df36b9a00bc8cb59b12d679dfb6f64da43e77c7dd623fa60b6d4b29f7e00009b -size 7936 +oid sha256:8c54410a3733a3cecd1b161eb524e1809c270b8d2dd814c095eb73e013b486e0 +size 7840 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png index ef2f8bf31d..609162f4bc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0e7a2ab84947138437d1cd523a1a00778b362c9bb48679d6d15f1c8f1e10f9d -size 10841 +oid sha256:793eea182afcb72be59a090d3c3e622edcd6f9509271bef2e75a2f45f47a8fe4 +size 10567 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png index d103fa0c98..874da23636 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f53060ab0874d769da5864efdb8f4cae2635fcaaffe95444094351941c904f80 -size 17941 +oid sha256:5e1cd401ab146d2d15e94a591625ab40440e32030f4acfd4ed9bd18dce01a1f0 +size 17814 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png index 35d047c438..c4e3bc9a39 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:13ac54e860b1fdc289a90b89f78ad898a87c0bdf402d9055872e9974dda1c94d -size 7738 +oid sha256:0e47e98d0ace1eb50dfeb9935c27206abee28d42d0e092d410de4239dc6ac293 +size 7519 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png index 9a10ba343e..b51a04e421 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ebbb431d291ee5dd9cdb626e5a14c234fd3ae2d1b8d8b969f2081c6b27440d7 -size 72150 +oid sha256:2cf5e60d289daa62dff1c07469227acffd275a1e4a3534b60cbe37c89a2c4bb7 +size 72136 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png index 0808659fa8..217b3181b7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ac337c3f7c15411f092cbf0e2da541ce27f45d3e6a0f0eaa68d76382765030d -size 58752 +oid sha256:af4895f8222d984437a5d7427268d198345ad690161789d7bbb0340eeda916f7 +size 58660 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png index 7fabc79733..046d651b57 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:95f41eb15d088c3b0dfc88d4f45a3cd094e6b649254db96dc791b37c0bd56823 -size 71559 +oid sha256:6049adcc9de51802804d0224bd7d5a7ee8ae2a754411e4ca5685df8028d51480 +size 71727 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png index 250616700e..26ba390595 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bb5cfce24bb00859ba0108dc22a2af4855088611a28bff59d200059c966c7f6 -size 80168 +oid sha256:e339b203a782f7d73195b1cd6961c67dac8b313a6a965515e4bc2d2b83a2118d +size 80524 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png index ff20a49fb8..0a18ae1074 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ff3edf3e7a06d78070eb60ac005811ef7a36a7e588ad7054908add73600de05 -size 61262 +oid sha256:22cf555cb18cea56f2e6bd9f91dbf70353916f196ceba84b11ea017b9e95d794 +size 61511 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png index 5f5af0a341..063006fb88 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5eb7dc42fda918bdf0023209e1fcdedacd17e963d35d02130c909abed6582da6 -size 60178 +oid sha256:de1e98fb04a4188e2c6b795a3cf0b21129d0e99f8ea2748137e9f8122d413c6a +size 60353 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png index 813344a666..9bfef2c6a2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23cf73c95fec0934219c5c7921978189a5a12741a49255129774e3b0cde66a51 -size 67141 +oid sha256:1861fe30f2c653911cfe193d69c21affea73f458132d6a1b6381aa504d4cce74 +size 67327 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png index 454b45ec06..dcc6b6c915 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c836e3db5e6debbf5961cf56d00ca38ffe7105c150a65b23cffda79a893b2c2 -size 89141 +oid sha256:9b5f1d42f06c4c5949f1fb1d216c7af45c4606a782178c21b58d0a0e7504a333 +size 89006 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png index 4ea874b253..df1c374209 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:084829afc78b9072384d7c9d399e13a6246446705be78a07684c5c11497f5dd6 -size 59592 +oid sha256:f7074c637e0a3e9320f86a4f417931d59c2d5e199996e8e533f692a82ab0d8d2 +size 59581 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png index 35fc3774f7..442ea4ff99 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c8d2baecd4a076de262ce2bfc2f223c8e95adb33e1dd2e15c116674f8674735 -size 59533 +oid sha256:a0f084ce1bca37f796e7f50d78a4f03485b77fa742efd688d6b8accc2b41f5e9 +size 59734 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png index f7398ae396..4e4fd5476c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15256a6b4d1fe8e52080b9726cde401944cc6941f7527db1d18484c86ec88023 -size 66699 +oid sha256:20f92a0cbc8a60bb057b131e17300653ce21367627f611193b6b9ddeba5d4b37 +size 66908 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png index fe65732853..c5324db3d6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6712e76fb96f7830d48d4a1e276d42a20548a1bf425ce8049b55e413462741ed -size 59161 +oid sha256:3a0be3b08f1923c223eb433cda9d8c1bd86ba2dff1bce31e069b29953b13a084 +size 59085 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png index a839235a65..8fb1c22b45 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cbc055122bb58e8eb0b0972ca52e1cdb181ef3afd2357b80c2bc24e72dadc245 -size 69227 +oid sha256:17bc1cac4537bd0b9a2dcd91838ff7c20de7e6076dbb9b174ad801af76f234f8 +size 69080 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png index b15f640a90..c6b221f461 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b5c0b430384e644e82c84581d04a36483cf41dcf6dd625c0295ed95dfe3f034 -size 56269 +oid sha256:caceabb04420f3675940e3b95ec685cb2b02c69d87fd19843640a5e882dfa1ca +size 56124 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png index 37bd4f7226..b5e644918e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:902a758672768adc02266bf0227aaf692e8f1d1aba91ba96be985caccdfffd22 -size 68668 +oid sha256:d46716354df7925d15345b61d8e16d80c0b3552b687a896004f4174286ad18ef +size 68625 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png index ce2458cb2f..c2bbd56d35 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f777e7d5aca4d2c1a7d2ecc956bf1a354f330f24c5092559ba59f305473cb227 -size 77106 +oid sha256:6a0b4ad61421f6b142e51200fb40df935027962145fa09b9871a11cdfdea8c0f +size 77316 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png index 8fafafadf8..3bb5259f05 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37f5275fabb3ec2cfa3efd533b52dbe4366888886881ad3a659b00aec867660e -size 58728 +oid sha256:89b7d536f86c72378714e4fab14b24671a86726abdcd63a1e15abcefde6a6abb +size 58721 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png index 9e0f64a82f..4af97d2cc8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46ad6c535da1d483b62f8b573b329a55fb8b15e9319e3d112299d2ae7c507877 -size 57694 +oid sha256:d314aa8f8572a099c4aa0f96de8dfade75c57edee4732c3d1300e5356c0bed20 +size 57649 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png index 28d8e0a2e2..918c7fa1b5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf851692c986a98e8f7fe989bd691099a8e9cd75da3d7977e84cdc22bb8aff7e -size 64468 +oid sha256:cf3bc1027fdbbb194d1a0120123872f0ce75c41c43d5c73c72908ddbffaaebb1 +size 64314 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png index 9dff6bedcd..c5eb73aa1c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dad1c1d9ea123fb417553f399cbaa27525c0e4a20a214fb0f81144e5107aa90a -size 85479 +oid sha256:92273288bdfe895fe0664533f60e322893ece33d271259303e35d9358fbae5df +size 85238 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png index 8a42433377..4449d490db 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea6929e35c476530c462cd4d2ff77d294044e3a5fb2133fe77d91339093ef71f -size 57134 +oid sha256:d04a904fb5f98c075ed844668a06af29d03e7d1adf8bab7706d1cea39abcceb6 +size 57003 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png index 53d7cea25f..ff54d6d0c5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a72d17f9c9abd2aaf9a074eee0955bbb3a2ffeb132f680abbfae0dee5d281a50 -size 57200 +oid sha256:896b4497818ded4ce18ad6089fd436160f87189d79da1cb63ea652818de10041 +size 57009 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png index 9bfed4fc61..6d72c0f7cc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7c95c91b7c6b04f2851df6a64de1b10c7338a4d46921a90037fe50cd7d49262 -size 63957 +oid sha256:256349593b50a7e1f40db6c032aa39a640136934eadde8883936b0b1885f81b0 +size 63867 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png index a9c97db0ff..f05bee7bd5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:465cdce0b01b0044ab9b329629214171f39533f6219d0e7871176899c14df1c2 -size 56721 +oid sha256:25b5d39992361966545a3c04b3de7b20569a1e12800b3ecf38e090ceb2afa7c9 +size 56567 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png index c924d012b6..d9d7e2913e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5124db3fec69ba2ba44bd1ba2e3c7c7f861412637b62de2d4d741c7408ba111c -size 73253 +oid sha256:bfb2c4674cd8bd0bcd434a2790f3e121dbc6a6c39e41d0417c80cdfb44be91ae +size 73627 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png index 7e57b26400..7891573b3d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10874b3704e42faf8d77661a635551e4e685be1e17cfc7e963633cec8040c9dd -size 56785 +oid sha256:be931ad71b0562cd96456124c987ed79709f3ec7c55d736f4f71da1fdb036309 +size 56863 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png index 186f3dafc1..2e5b1dc647 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5f14eac2b49c3ba72ed9b9f6cab21c07a3c1b500e677c5353a5519ac9cb9077 -size 71491 +oid sha256:f3f24723f76f444a6503ee01399298ae4258a190cd6657dd1bf5308ea528d55f +size 72035 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png index 33c260415e..584285c1be 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d9ee6fa66bcd2b8f897d2f357c995f0f8d0d2fbc44ab0e8122e0cff17f7f86a -size 82796 +oid sha256:cfb33cec43d32917cb8f59e012244fa0c8824421cbedac516e002862f28f93db +size 83506 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png index c22d0bf38d..7414d959a4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d89ff053d51eb36a5045768ddb45763fbac67829ac256dd02661e8a8dec5c2ff -size 59808 +oid sha256:94d01e112a860c145c6c09d1d3a9bf948fe73e7b939d7f602704a3b4853de9f5 +size 60076 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png index 643aaaae5a..b6e7b4e2a5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb61501a314ece736f32ec8cc5269e315f2cf3a575e7b0fb3f604c5ec81bec34 -size 58928 +oid sha256:b064ba533e8bfa225f0548fc6e13d811a0ab0dddcd500cfbb72ed199a268c1b9 +size 59202 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png index 0bb7225a8b..c223cabf8f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf792e65d65749463ccc1b0a9ea41663b91d105fdeda1ad5498b4448b4b03e6c -size 66820 +oid sha256:8e0cdd88f5776e92aa0063c09f4c7c1c099d2b8cb0f4a13066925c1ca105b37a +size 66800 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png index 63b4246e64..042c2792ce 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dababe75d96905a844b9ef72d03ec378b70549005951a654b3d792ebd138d40e -size 101772 +oid sha256:fa0e313a3d429ddfba85b62f4d855489cb5cca62bc6693dcaa33f4d0ac622b85 +size 101888 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png index 32494f9b02..d1b0e795b5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b24c435152a26a2938a5774c91e819acdbd901c75b84997849f477ebb2ddc91 -size 58148 +oid sha256:3e3210208348505b93f4d673977f237bd7859b054699c1d66ece28591d20640b +size 58145 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png index 550543f30d..a014be7a5a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:add4c86c01e81b25f55aa6227533f6be9054f2cb4203cfd39ba6103494d3e640 -size 57748 +oid sha256:a0c9e887cd48c5aee046649a2ca5949abe763363659e29dd523869dc615e98f2 +size 58186 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png index 8e397b024e..4f07ac8b8f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27c823be03e6721a4034cdc4827a4d3dd34ac3e9d567651a8ce125cef435b57e -size 67151 +oid sha256:d5febf4de05a7794160b567dec3b00e818a6e3d4d7830d3dba97f72498aa5a3c +size 67172 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png index f99d139fc0..2d5e2c39da 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:882ca19a5e503c3c1143631760dcd061c4fecf313d55f363e3a4c7b9c693ba85 -size 57530 +oid sha256:f213b779238ac8536e4f0115d8de444a21c3b8ce31aac8aebd5415d8f80504a4 +size 57501 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png index ba74211c85..362033d451 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09d81b818719edccac051f7702d873a7e5464fe80244f8d6976648eecfd36b87 -size 70429 +oid sha256:27cc53e2336c9ccf90d97d2aed98f94f83315dcb9fe4bd489958b8df2366262c +size 70207 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png index fba3827ccd..aa712c48ec 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9027508487f18ad1c74a48563bd9997aeb49f500f4b5f272e095afe0d38b37a -size 53999 +oid sha256:bd6c1a82daedd923982d81956924eeaa37857d54dee55f31fda4520071b4f66b +size 53675 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png index c37fdc1ae2..804b238d8d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d25030399d0eb11d36f75338749689386e00a5100b0d4e9f05f61da5c16ce82 -size 68635 +oid sha256:ffce97ff7f1d6a2641d761aad6457883babe333075a454b5860d266719bdb3f9 +size 68525 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png index a83a48693d..ec221ef43a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44d6e39f26502a062f4d2bedbfde36e0010e2090c2a96438cca520a188b4e09d -size 79673 +oid sha256:58718344783197c680e18a7a3c97a3531293b6e2442ca5701d4605ecb567e70a +size 79724 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png index 31307b1de7..8369183006 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01358cf77f574e16c535b58428392a620b7a1b973f8135bcc7acc9cd12993686 -size 57325 +oid sha256:3d84207a6b1bf4815d2515974c721a0ba26fb406a31e96f3566b90e548c7bf49 +size 57077 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png index d3c00bfc0a..7cd4c1a580 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9209a8927ba2d25ce458f9acad040374d4818188959a654a52e62e81ba81da01 -size 56423 +oid sha256:2056d90bbf2676fae7d88b326c496aae95a1c31924c8b5d13ca363f486c72968 +size 56206 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png index c293a6ffdc..6b23cf2db8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60211550a5c617e356a775fbd3daffccc06c4d2992e30bc7c38baa7a18babf37 -size 64104 +oid sha256:5bca7347130b0b449ef2c917359753660446e4be7d2d4a13323489c63dbf28a4 +size 63589 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png index d12a76713d..f388e96dac 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d4e115598bd789d164ea1374cc761cf8391a7db658a29207e2f221dac678b62 -size 98295 +oid sha256:4fffdb6a8f159af3104d9f2e8edbc11395854f6ac6a558e303d20c79ea91857b +size 98128 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png index 16c70226c5..37890657c9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4c0053dcd73fadacfc2ad73c8e57a60e3c5f2186f1f83c083d08cf542e977c0 -size 55536 +oid sha256:534628991ee750aa4f4b4e3edda1ea26cf648eb74d06610d4207266b659d4421 +size 55083 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png index 3c9852479c..cb402d830b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38370c8eaa97e996514e9020f1d7dd6e8d1f87a66d99448f71dd531c0a158d5c -size 55352 +oid sha256:9de6ef77a1d574da317c3d1c3258f3068e79613387d0bc32e925f516338da9e9 +size 55092 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png index 0654617bd7..06a6ee8488 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:947ddd34efb97e8baad91a1c2865105190a7be599327a271db0466f4a86bf092 -size 64326 +oid sha256:350c89c3491e08a80f9910121140d56f2cf28fdc0b8f6ced380d1ec34b116c52 +size 63975 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png index 33d2768e08..e698f48771 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a4c884e8173cc9e031faff3da8c18c9411f5e39c9a56ad82941a36a4bb8381a -size 54795 +oid sha256:8659bbb89e5c26caea7f1d759e1c9bbd6ecedc525dcc2cb6b1cc844c835aeec1 +size 54455 From 7d28c522429caf488fcc17f5a0cf12fad01e88eb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 25 Mar 2026 16:51:41 +0100 Subject: [PATCH 0010/1083] Cleanup --- .../impl/timeline/components/TimelineItemEventRow.kt | 9 +++++---- .../android/libraries/textcomposer/ComposerModeView.kt | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) 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 a814d8da42..c9bc130905 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 @@ -745,8 +745,8 @@ private fun MessageEventBubbleContent( } else { inReplyToModifier.clickable(onClick = inReplyToClick) } - Row( - talkbackCompatModifier + Box( + modifier = talkbackCompatModifier .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(6.dp)) .background(ElementTheme.colors.bgCanvasDefault, RoundedCornerShape(6.dp)) .padding(4.dp) @@ -843,7 +843,7 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { threadInfo = TimelineItemThreadInfo.ThreadRoot( latestEventText = "This is the latest message in the thread", summary = ThreadSummary( - AsyncData.Success( + latestEvent = AsyncData.Success( EmbeddedEventInfo( eventOrTransactionId = EventOrTransactionId.Event(EventId("\$event-id")), content = MessageContent( @@ -861,7 +861,8 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { ), timestamp = 0L, ) - ), numberOfReplies = 20L + ), + numberOfReplies = 20L, ) ) ), diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt index 3d7c4f810c..15aabdcbb0 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.remember From a7e254cc8414c43920c178f9ee57d29b9ca71798 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 25 Mar 2026 19:57:34 +0100 Subject: [PATCH 0011/1083] 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 0012/1083] 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 ef041baeb4c22a2cc56f1911fcba82652f2ade05 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 27 Mar 2026 07:36:48 +0100 Subject: [PATCH 0013/1083] chore: update the build-rust-sdk script (#6476) --- tools/sdk/build-rust-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sdk/build-rust-sdk b/tools/sdk/build-rust-sdk index ea1b80c469..b3b57f7e98 100755 --- a/tools/sdk/build-rust-sdk +++ b/tools/sdk/build-rust-sdk @@ -228,7 +228,7 @@ cp \ if [ "${buildApp}" == "0" ]; then printf "\n## Building the application...\n\n" - ./gradlew assembleDebug + ./gradlew :app:assembleGplayDebug fi ## Clean remote checkout of SDK repo From bba2e6df3f6928b7c58f050617dfa2c642c2d4fa Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 27 Mar 2026 07:54:27 +0100 Subject: [PATCH 0014/1083] Fix `ForegroundServiceDidNotStartInTimeException` (#6470) * Start the `FetchPushForegroundService ` in foreground ASAP. This is a first step to mitigate `ForegroundServiceDidNotStartInTimeException` being thrown. * Don't stop the service immediately if it's running but not in foreground. Try waiting up to 5s for it to be in foreground. --- .../push/api/push/PushHandlingWakeLock.kt | 2 +- .../impl/push/DefaultPushHandlingWakeLock.kt | 2 +- .../impl/push/FetchPushForegroundService.kt | 57 ++++++++++++++++--- .../test/push/FakePushHandlingWakeLock.kt | 2 +- 4 files changed, 53 insertions(+), 10 deletions(-) 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 index 2b19ed9225..5c76eb1864 100644 --- 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 @@ -22,5 +22,5 @@ interface PushHandlingWakeLock { /** * Release the wakelock. If no wakelock is associated with the key, this method does nothing. */ - fun unlock() + suspend fun unlock() } 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 index 1388aac19b..9713110042 100644 --- 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 @@ -31,7 +31,7 @@ class DefaultPushHandlingWakeLock( count.incrementAndGet() } - override fun unlock() { + override suspend fun unlock() { Timber.d("Releasing wakelock used for push handling.") FetchPushForegroundService.stop(context) if (count.decrementAndGet() <= 0) { 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 f0f4ebb2de..d7cc950b99 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,6 +7,7 @@ package io.element.android.libraries.push.impl.push +import android.app.ActivityManager import android.app.Service import android.content.Context import android.content.Intent @@ -25,7 +26,12 @@ 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 @@ -51,11 +57,13 @@ class FetchPushForegroundService : Service() { } } - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + override fun onCreate() { + Timber.d("Creating FetchPushForegroundService") + bindings().inject(this) - wakelock.acquire(wakelockTimeout) - + Timber.d("Starting FetchPushForegroundService with wakelock timeout of $wakelockTimeout ms") + // Start the foreground service as soon as possible val notificationCompat = NotificationCompat.Builder(this, notificationChannels.getSilentChannelId()) .setSmallIcon(CommonDrawables.ic_notification) .setContentTitle(getString(CommonStrings.common_android_fetching_notifications_title)) @@ -65,6 +73,12 @@ class FetchPushForegroundService : Service() { .build() startForeground(NOTIFICATION_ID, notificationCompat) + super.onCreate() + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + wakelock.acquire(wakelockTimeout) + // The timeout is not automatic before Android 15, so we need to schedule it ourselves if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { coroutineScope.launch { @@ -86,10 +100,14 @@ class FetchPushForegroundService : Service() { override fun onTimeout(startId: Int) { super.onTimeout(startId) - pushHandlingWakeLock.unlock() + 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 @@ -107,9 +125,34 @@ class FetchPushForegroundService : Service() { } } - fun stop(context: Context) { - val intent = Intent(context, FetchPushForegroundService::class.java) - context.stopService(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 } } } } 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 index 925581db9b..077c8f661e 100644 --- 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 @@ -18,7 +18,7 @@ class FakePushHandlingWakeLock( lock.invoke(time) } - override fun unlock() { + override suspend fun unlock() { unlock.invoke() } } From 81cc055c91dec819740951c80f77995ffce8eb55 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 08:11:54 +0100 Subject: [PATCH 0015/1083] fix(deps): update dependency io.element.android:emojibase-bindings to v1.5.1 (#6474) 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 a8ca47e959..68d381df85 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -226,7 +226,7 @@ sentry = "io.sentry:sentry-android:8.36.0" matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" # Emojibase -matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.0" +matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.1" sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" # Di From 59754544248ad642837a41ea4964b4afa4bd882c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 08:13:05 +0100 Subject: [PATCH 0016/1083] fix(deps): update dependency com.google.firebase:firebase-bom to v34.11.0 (#6478) 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 68d381df85..f2f6d5afea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -80,7 +80,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:34.10.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.11.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } From 37da07a7208b9a9235638f27fc733fe5a2d15949 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Fri, 27 Mar 2026 21:18:55 +0100 Subject: [PATCH 0017/1083] 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 a2fe637978dc901fe525778b3fe556574c5a8dff Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 30 Mar 2026 12:26:16 +0300 Subject: [PATCH 0018/1083] Fix media cover placeholder floating (#6484) --- .../impl/local/audio/MediaAudioView.kt | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt index 01115b7c91..cb9d6ae9c8 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt @@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -51,6 +52,7 @@ import androidx.media3.common.Timeline import androidx.media3.exoplayer.ExoPlayer import androidx.media3.ui.AspectRatioFrameLayout import androidx.media3.ui.PlayerView +import com.bumble.appyx.core.node.LocalNodeTargetVisibility import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.audio.api.AudioFocus @@ -130,6 +132,8 @@ private fun ExoPlayerMediaAudioView( mutableStateOf(null) } + val isTargetVisible = LocalNodeTargetVisibility.current + val playableState: PlayableState.Playable by remember { derivedStateOf { PlayableState.Playable( @@ -196,13 +200,21 @@ private fun ExoPlayerMediaAudioView( exoPlayer.pause() } } + LaunchedEffect(isTargetVisible) { + if (!isTargetVisible) { + exoPlayer.pause() + } + } if (localMedia?.uri != null) { LaunchedEffect(localMedia.uri) { val mediaItem = MediaItem.fromUri(localMedia.uri) exoPlayer.setMediaItem(mediaItem) + exoPlayer.prepare() } } else { - exoPlayer.setMediaItems(emptyList()) + LaunchedEffect(Unit) { + exoPlayer.setMediaItems(emptyList()) + } } val context = LocalContext.current val waveform = info?.waveform @@ -247,7 +259,7 @@ private fun ExoPlayerMediaAudioView( } }, update = { playerView -> - playerView.isVisible = metadata.hasArtwork() + playerView.isVisible = metadata.hasArtwork() && isTargetVisible }, onRelease = { playerView -> playerView.player = null @@ -317,16 +329,19 @@ private fun ExoPlayerMediaAudioView( ) } - OnLifecycleEvent { _, event -> - when (event) { - Lifecycle.Event.ON_CREATE -> exoPlayer.addListener(playerListener) - Lifecycle.Event.ON_RESUME -> exoPlayer.prepare() - Lifecycle.Event.ON_PAUSE -> exoPlayer.pause() - Lifecycle.Event.ON_DESTROY -> { - exoPlayer.release() + DisposableEffect(exoPlayer) { + exoPlayer.addListener(playerListener) + onDispose { + if (!exoPlayer.isReleased) { exoPlayer.removeListener(playerListener) + exoPlayer.release() } - else -> Unit + } + } + + OnLifecycleEvent { _, event -> + if (event == Lifecycle.Event.ON_PAUSE) { + exoPlayer.pause() } } } From 4c31c9451e9a250115b8b69e31d3ceabcebb4ec0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:22:33 +0200 Subject: [PATCH 0019/1083] fix(deps): update dependency io.element.android:emojibase-bindings to v1.5.2 (#6487) 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 f2f6d5afea..86db5a9d73 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -226,7 +226,7 @@ sentry = "io.sentry:sentry-android:8.36.0" matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" # Emojibase -matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.1" +matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.2" sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" # Di From ad56b01e4a2e5a8c3cfe1aa97c5aa0864c395338 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 30 Mar 2026 18:44:08 +0200 Subject: [PATCH 0020/1083] Try handling `ForegroundServiceStartNotAllowedException` better (#6483) * Try handling `ForegroundServiceStartNotAllowedException` better The docs mention starting a foreground service when the app is on background is allowed when FCM receives a high priority notification, so we don't do it if the priority is not high. Also, we handle the case where starting the foreground service fails so it doesn't crash the app. --- .../impl/push/FetchPushForegroundService.kt | 38 ++++++++++++++++--- .../VectorFirebaseMessagingService.kt | 14 +++++-- .../VectorFirebaseMessagingServiceTest.kt | 29 ++++++++++++++ 3 files changed, 71 insertions(+), 10 deletions(-) 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 d7cc950b99..6dc6bdfa0e 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 @@ -17,6 +17,7 @@ import android.os.PowerManager import androidx.core.app.NotificationCompat 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 @@ -57,6 +58,8 @@ class FetchPushForegroundService : Service() { } } + private var isOnForeground = false + override fun onCreate() { Timber.d("Creating FetchPushForegroundService") @@ -71,12 +74,32 @@ class FetchPushForegroundService : Service() { .setVibrate(longArrayOf(0)) .setSound(null) .build() - startForeground(NOTIFICATION_ID, notificationCompat) + + // 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. + runCatchingExceptions { + startForeground(NOTIFICATION_ID, notificationCompat) + } + .onSuccess { + isOnForeground = true + Timber.d("FetchPushForegroundService started in foreground successfully") + } + .onFailure { + isOnForeground = false + Timber.e(it, "Failed to start FetchPushForegroundService in foreground") + } super.onCreate() } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (!isOnForeground) { + Timber.w("FetchPushForegroundService is not running in foreground, stopping it to avoid crash") + stopSelf() + return START_NOT_STICKY + } + wakelock.acquire(wakelockTimeout) // The timeout is not automatic before Android 15, so we need to schedule it ourselves @@ -91,18 +114,21 @@ class FetchPushForegroundService : Service() { } override fun stopService(intent: Intent?): Boolean { - wakelock.release() + if (isOnForeground) { + wakelock.release() + stopForeground(STOP_FOREGROUND_REMOVE) + } - stopForeground(STOP_FOREGROUND_REMOVE) return super.stopService(intent) } override fun onTimeout(startId: Int) { super.onTimeout(startId) - Timber.d("Wakelock timeout reached, stopping FetchPushForegroundService") - - coroutineScope.launch { pushHandlingWakeLock.unlock() } + if (isOnForeground) { + Timber.d("Wakelock timeout reached, stopping FetchPushForegroundService") + coroutineScope.launch { pushHandlingWakeLock.unlock() } + } } companion object { 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 67da09f1ab..3961f1f591 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 @@ -10,6 +10,7 @@ package io.element.android.libraries.pushproviders.firebase import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage +import com.google.firebase.messaging.RemoteMessage.PRIORITY_HIGH import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.log.logger.LoggerTag @@ -45,8 +46,11 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { override fun onMessageReceived(message: RemoteMessage) { Timber.tag(loggerTag.value).w("New Firebase message. Priority: ${message.priority}/${message.originalPriority}") - // Acquire wakelock to ensure the device stays awake while we handle the push and schedule and run the work - pushHandlingWakeLock.lock() + 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() + } coroutineScope.launch { val pushData = pushParser.parse(message.data) @@ -58,7 +62,9 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { "$it: ${message.data[it]}" }, ) - pushHandlingWakeLock.unlock() + if (isHighPriority) { + pushHandlingWakeLock.unlock() + } } else { val handled = pushHandler.handle( pushData = pushData, @@ -66,7 +72,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) { + if (!handled && isHighPriority) { pushHandlingWakeLock.unlock() } } 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 87ca74730c..798328e626 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 @@ -96,6 +96,7 @@ class VectorFirebaseMessagingServiceTest { putString("event_id", AN_EVENT_ID.value) putString("room_id", A_ROOM_ID.value) putString("cs", A_SECRET) + putString("google.priority", "high") }, ) ) @@ -127,6 +128,7 @@ class VectorFirebaseMessagingServiceTest { putString("event_id", AN_EVENT_ID.value) putString("room_id", A_ROOM_ID.value) putString("cs", A_SECRET) + putString("google.priority", "high") }, ) ) @@ -141,6 +143,33 @@ class VectorFirebaseMessagingServiceTest { unlockLambda.assertions().isCalledOnce() } + @Test + fun `test pushHandler with a remote message with normal priority won't lock the wakelock`() = runTest { + val lockLambda = lambdaRecorder { _ -> } + val unlockLambda = lambdaRecorder { } + val vectorFirebaseMessagingService = createVectorFirebaseMessagingService( + pushHandler = FakePushHandler(handleResult = { _, _ -> false }), + pushHandlingWakeLock = FakePushHandlingWakeLock( + lock = lockLambda, + unlock = unlockLambda + ) + ) + vectorFirebaseMessagingService.onMessageReceived( + message = RemoteMessage( + Bundle().apply { + putString("event_id", AN_EVENT_ID.value) + putString("room_id", A_ROOM_ID.value) + putString("cs", A_SECRET) + putString("google.priority", "normal") + }, + ) + ) + + // The wakelock should not be locked + lockLambda.assertions().isNeverCalled() + unlockLambda.assertions().isNeverCalled() + } + @Test fun `test new token is forwarded to the handler`() = runTest { val lambda = lambdaRecorder { } From add21b8dc88922c35ac10c63c17be2da61eabbef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:57:48 +0000 Subject: [PATCH 0021/1083] fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v26.03.31 --- 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 86db5a9d73..e0d4119abc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.03.24" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.03.31" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 182574015271846babd00ba93477037ceb636d11 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 31 Mar 2026 15:47:21 +0200 Subject: [PATCH 0022/1083] Fix permissions to publish GitHub pages. --- .github/workflows/generate_github_pages.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index e4fedf76ac..5006cc44b5 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -12,6 +12,8 @@ jobs: runs-on: ubuntu-latest # Skip in forks if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + permissions: + contents: write steps: - name: ⏬ Checkout with LFS uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 From 6ab47dae17af3e64c55385723b447b113f404481 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:48:37 +0200 Subject: [PATCH 0023/1083] Sync Strings from Localazy (#6486) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- .../src/main/res/values-da/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 6 +- .../src/main/res/values-da/translations.xml | 4 + .../src/main/res/values-da/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 25 +- .../src/main/res/values-da/translations.xml | 27 +- .../src/main/res/values-ru/translations.xml | 3 +- .../src/main/res/values-da/translations.xml | 10 +- .../src/main/res/values-da/translations.xml | 36 +- .../src/main/res/values-ru/translations.xml | 3 + .../src/main/res/values/localazy.xml | 1 + ...nfigureroom_ConfigureRoomViewDark_0_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_1_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_2_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_3_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_4_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_5_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_6_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_7_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_8_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_0_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_1_de.png | 2 +- ...figureroom_ConfigureRoomViewLight_2_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_3_de.png | 2 +- ...figureroom_ConfigureRoomViewLight_4_de.png | 2 +- ...figureroom_ConfigureRoomViewLight_5_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_6_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_7_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_8_de.png | 4 +- ...me.impl.spaces_HomeSpacesView_Day_0_de.png | 4 +- ...me.impl.spaces_HomeSpacesView_Day_1_de.png | 4 +- ...me.impl.spaces_HomeSpacesView_Day_2_de.png | 4 +- .../features.home.impl_HomeView_Day_4_de.png | 4 +- ...es.joinroom.impl_JoinRoomView_Day_9_de.png | 4 +- ...on.impl.send_SendLocationView_Day_0_de.png | 3 - ...on.impl.send_SendLocationView_Day_1_de.png | 3 - ...on.impl.send_SendLocationView_Day_2_de.png | 3 - ...on.impl.send_SendLocationView_Day_3_de.png | 3 - ...on.impl.send_SendLocationView_Day_4_de.png | 3 - ....impl.share_ShareLocationView_Day_0_de.png | 3 + ....impl.share_ShareLocationView_Day_1_de.png | 3 + ....impl.share_ShareLocationView_Day_2_de.png | 3 + ....impl.share_ShareLocationView_Day_3_de.png | 3 + ....impl.share_ShareLocationView_Day_4_de.png | 3 + ....impl.share_ShareLocationView_Day_5_de.png | 3 + ....impl.share_ShareLocationView_Day_6_de.png | 3 + ...on.impl.show_ShowLocationView_Day_0_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_1_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_2_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_3_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_4_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_5_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_6_de.png | 3 - ...on.impl.show_ShowLocationView_Day_7_de.png | 3 - ...essagesViewWithIdentityChange_Day_0_de.png | 4 +- ...essagesViewWithIdentityChange_Day_1_de.png | 4 +- ...ecomposer_MessageComposerView_Day_0_de.png | 4 +- ...d.list_PinnedMessagesListView_Day_3_de.png | 4 +- ...mEventRowWithReplyInformative_Day_0_de.png | 4 +- ...mEventRowWithReplyInformative_Day_1_de.png | 4 +- ...TimelineItemEventRowWithReply_Day_4_de.png | 4 +- ...TimelineItemEventRowWithReply_Day_8_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_10_de.png | 3 + ...s.impl.timeline_TimelineView_Day_11_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_12_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_13_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_14_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_15_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_16_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_17_de.png | 3 - ...es.impl.timeline_TimelineView_Day_4_de.png | 4 +- ...es.impl.timeline_TimelineView_Day_6_de.png | 4 +- ...s.messages.impl_MessagesView_Day_10_de.png | 4 +- ...itprofile_EditUserProfileView_Day_0_de.png | 4 +- ...itprofile_EditUserProfileView_Day_1_de.png | 4 +- ...itprofile_EditUserProfileView_Day_2_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_0_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_10_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_11_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_12_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_13_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_14_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_15_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_16_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_17_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_18_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_1_de.png | 2 +- ...roomdetails.impl_RoomDetailsDark_20_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_21_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_22_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_2_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_3_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_4_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_6_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_7_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_8_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_9_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_0_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_10_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_11_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_12_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_13_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_14_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_15_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_16_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_17_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_1_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_20_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_21_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_22_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_2_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_3_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_4_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_6_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_7_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_8_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_9_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_0_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_1_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_2_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_3_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_4_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_5_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_6_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_7_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_8_de.png | 4 +- ...edit.impl_RoomDetailsEditView_Day_9_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_14_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_0_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_1_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_2_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_3_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_4_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_5_de.png | 4 +- ...ared_UserProfileHeaderSection_Day_0_de.png | 4 +- ...rofile.shared_UserProfileView_Day_2_de.png | 4 +- ...mePickerHorizontal_DateTime_pickers_de.png | 4 +- ...PickerVerticalDark_DateTime_pickers_de.png | 4 +- ...ickerVerticalLight_DateTime_pickers_de.png | 4 +- ...components_OrganizationHeader_Day_0_de.png | 4 +- ...omponents_SpaceHeaderRootView_Day_0_de.png | 4 +- ...ix.ui.components_SpaceInfoRow_Day_0_de.png | 4 +- ....messages.reply_InReplyToView_Day_4_de.png | 4 +- ....messages.reply_InReplyToView_Day_8_de.png | 4 +- ...oser_MarkdownTextComposerEdit_Day_0_de.png | 4 +- ...mposer_TextComposerAddCaption_Day_0_de.png | 4 +- ...poser_TextComposerEditCaption_Day_0_de.png | 4 +- ..._TextComposerEditNotEncrypted_Day_0_de.png | 4 +- ...textcomposer_TextComposerEdit_Day_0_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_0_de.png | 4 +- ...extComposerReplyNotEncrypted_Day_10_de.png | 4 +- ...extComposerReplyNotEncrypted_Day_11_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_1_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_2_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_3_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_4_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_5_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_6_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_7_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_8_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_9_de.png | 4 +- ...extcomposer_TextComposerReply_Day_0_de.png | 4 +- ...xtcomposer_TextComposerReply_Day_10_de.png | 4 +- ...xtcomposer_TextComposerReply_Day_11_de.png | 4 +- ...extcomposer_TextComposerReply_Day_1_de.png | 4 +- ...extcomposer_TextComposerReply_Day_2_de.png | 4 +- ...extcomposer_TextComposerReply_Day_3_de.png | 4 +- ...extcomposer_TextComposerReply_Day_4_de.png | 4 +- ...extcomposer_TextComposerReply_Day_5_de.png | 4 +- ...extcomposer_TextComposerReply_Day_6_de.png | 4 +- ...extcomposer_TextComposerReply_Day_7_de.png | 4 +- ...extcomposer_TextComposerReply_Day_8_de.png | 4 +- ...extcomposer_TextComposerReply_Day_9_de.png | 4 +- ...extComposerSimpleNotEncrypted_Day_0_de.png | 4 +- ...xtcomposer_TextComposerSimple_Day_0_de.png | 4 +- screenshots/html/data.js | 2034 +++++++++-------- ...system.components_LocationPin_Day_0_en.png | 4 +- 182 files changed, 1418 insertions(+), 1395 deletions(-) create mode 100644 features/location/impl/src/main/res/values-da/translations.xml delete mode 100644 screenshots/de/features.location.impl.send_SendLocationView_Day_0_de.png delete mode 100644 screenshots/de/features.location.impl.send_SendLocationView_Day_1_de.png delete mode 100644 screenshots/de/features.location.impl.send_SendLocationView_Day_2_de.png delete mode 100644 screenshots/de/features.location.impl.send_SendLocationView_Day_3_de.png delete mode 100644 screenshots/de/features.location.impl.send_SendLocationView_Day_4_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_0_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_1_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_2_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_4_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png delete mode 100644 screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png delete mode 100644 screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png create mode 100644 screenshots/de/features.messages.impl.timeline_TimelineView_Day_10_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png diff --git a/features/ftue/impl/src/main/res/values-da/translations.xml b/features/ftue/impl/src/main/res/values-da/translations.xml index 9c3720ac00..473c8a9c73 100644 --- a/features/ftue/impl/src/main/res/values-da/translations.xml +++ b/features/ftue/impl/src/main/res/values-da/translations.xml @@ -2,8 +2,8 @@ "Kan ikke bekræfte?" "Opret en ny gendannelsesnøgle" - "Verificér denne enhed for at konfigurere sikre meddelelser." - "Bekræft din identitet" + "Vælg, hvordan du vil verificere dig for at konfigurere sikre beskeder." + "Bekræft din digitale identitet" "Brug en anden enhed" "Brug gendannelsesnøgle" "Nu kan du læse eller sende beskeder sikkert, og enhver du samtaler med kan også stole på denne enhed." diff --git a/features/home/impl/src/main/res/values-da/translations.xml b/features/home/impl/src/main/res/values-da/translations.xml index cd9ec06ada..fab528ce71 100644 --- a/features/home/impl/src/main/res/values-da/translations.xml +++ b/features/home/impl/src/main/res/values-da/translations.xml @@ -5,9 +5,9 @@ "Modtager du ikke notifikationer?" "Dit notifikationsping er blevet opdateret – tydeligere, hurtigere og mindre forstyrrende." "Vi har opdateret dine lyde" - "Gendan din kryptografiske identitet og meddelelseshistorik med en gendannelsesnøgle, hvis du har mistet alle dine eksisterende enheder." - "Opsæt gendannelse" - "Konfigurer gendannelse for at beskytte din konto" + "Dine chats sikkerhedskopieres automatisk med end-to-end-kryptering. For at kunne gendanne denne sikkerhedskopi og bevare din digitale identitet, hvis du mister adgang til alle dine enheder, får du brug for din gendannelsesnøgle." + "Hent gendannelsesnøgle" + "Sikkerhedskopier dine samtaler" "Bekræft din gendannelsesnøgle for at bevare adgangen til nøglelager og meddelelseshistorik." "Indtast din gendannelsesnøgle" "Har du glemt din gendannelsesnøgle?" diff --git a/features/location/impl/src/main/res/values-da/translations.xml b/features/location/impl/src/main/res/values-da/translations.xml new file mode 100644 index 0000000000..f15ab0fb2f --- /dev/null +++ b/features/location/impl/src/main/res/values-da/translations.xml @@ -0,0 +1,4 @@ + + + "Vælg, hvor længe du vil dele din aktuelle position." + diff --git a/features/lockscreen/impl/src/main/res/values-da/translations.xml b/features/lockscreen/impl/src/main/res/values-da/translations.xml index ffbd657970..76725ac637 100644 --- a/features/lockscreen/impl/src/main/res/values-da/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-da/translations.xml @@ -23,7 +23,7 @@ Vælg noget mindeværdigt. Hvis du glemmer denne pinkode, bliver du logget ud af "Indtast venligst den samme PIN-kode to gange" "PIN-koderne stemmer ikke overens" "Du vil være nødt til at logge ind igen og oprette en ny PIN-kode for at fortsætte." - "Du bliver logget ud" + "Denne enhed bliver fjernet" "Du har %1$d forsøg på at låse op" "Du har %1$d forsøg på at låse op" @@ -34,5 +34,5 @@ Vælg noget mindeværdigt. Hvis du glemmer denne pinkode, bliver du logget ud af "Brug biometri" "Brug PIN-kode" - "Logger ud…" + "Fjerner enhed…" diff --git a/features/logout/impl/src/main/res/values-da/translations.xml b/features/logout/impl/src/main/res/values-da/translations.xml index a828cd48b8..6bf98f8db5 100644 --- a/features/logout/impl/src/main/res/values-da/translations.xml +++ b/features/logout/impl/src/main/res/values-da/translations.xml @@ -1,17 +1,18 @@ - "Er du sikker på, at du vil logge ud?" - "Log ud" - "Log ud" - "Logger ud…" - "Du er ved at logge ud af din sidste session. Hvis du logger ud nu, mister du adgangen til dine krypterede meddelelser." - "Du har slået sikkerhedskopiering fra" - "Dine nøgler blev stadig sikkerhedskopieret, da du gik offline. Opret forbindelse igen, så dine nøgler kan sikkerhedskopieres, før du logger ud." + "Er du sikker på, at ønsker at fjerne denne enhed?" + "Fjern denne enhed" + "Fjern denne enhed" + "Fjerner enhed…" + "Dette er din eneste enhed. Hvis du fjerner den, skal du bruge en gendannelsesnøgle for at bekræfte din digitale identitet og gendanne dine krypterede chats, næste gang du logger ind." + "Du er ved at miste adgangen til dine krypterede chats" + "Dine nøgler blev stadig sikkerhedskopieret, da du gik offline. Opret forbindelse igen, så dine nøgler kan sikkerhedskopieres, før du fjerner denne enhed." "Dine nøgler bliver stadig sikkerhedskopieret" - "Vent på, at dette er fuldført, før du logger ud." + "Vent venligst, indtil dette er færdigt, før du fjerner denne enhed." "Dine nøgler bliver stadig sikkerhedskopieret" - "Log ud" - "Du er ved at logge ud af din sidste session. Hvis du logger af nu, mister du adgangen til dine krypterede meddelelser." - "Gendannelse er ikke konfigureret" - "Du er ved at logge ud af din sidste session. Hvis du logger af nu, kan du miste adgangen til dine krypterede meddelelser." + "Fjern denne enhed" + "Dette er din eneste enhed. Hvis du fjerner den, skal du bruge en gendannelsesnøgle for at bekræfte din digitale identitet og gendanne dine krypterede chats, næste gang du logger ind." + "Du er ved at miste adgangen til dine krypterede chats" + "Dette er din eneste enhed. Hvis du fjerner den, skal du bruge en gendannelsesnøgle for at bekræfte din digitale identitet og gendanne dine krypterede chats, næste gang du logger ind." + "Sørg for, at du har adgang til din gendannelsesnøgle, før du fjerner denne enhed." diff --git a/features/securebackup/impl/src/main/res/values-da/translations.xml b/features/securebackup/impl/src/main/res/values-da/translations.xml index 93b949bfb6..941b7fc480 100644 --- a/features/securebackup/impl/src/main/res/values-da/translations.xml +++ b/features/securebackup/impl/src/main/res/values-da/translations.xml @@ -2,16 +2,17 @@ "Slet nøglelager" "Aktivér sikkerhedskopiering" - "Gem din kryptografiske identitet og meddelelsesnøgler sikkert på serveren. Dette giver dig mulighed for at se din meddelelseshistorik på alle nye enheder. %1$s." + "Dette giver dig mulighed for at se din chathistorik på alle nye enheder og er påkrævet til sikkerhedskopiering af chats og digital identitet.%1$s ." "Nøgleopbevaring" - "Nøglelagring skal være slået til for at konfigurere gendannelse." + "Nøglelagring skal være slået til for at konfigurere gendannelse af dine samtaler." "Upload nøgler fra denne enhed" "Tillad lagring af nøgler" "Skift gendannelsesnøgle" - "Gendan din kryptografiske identitet og beskedhistorik med en gendannelsesnøgle, hvis du har mistet alle dine eksisterende enheder." + "Dine samtaler sikkerhedskopieres automatisk med end-to-end-kryptering. For at kunne gendanne denne sikkerhedskopi og bevare din digitale identitet, hvis du mister adgang til alle dine enheder, får du brug for din gendannelsesnøgle." "Indtast gendannelsesnøgle" "Din nøglelagring er i øjeblikket ikke synkroniseret." - "Opsæt gendannelse" + "Hent gendannelsesnøgle" + "Dine chats sikkerhedskopieres automatisk med end-to-end-kryptering. For at kunne gendanne denne sikkerhedskopi og bevare din digitale identitet, hvis du mister adgang til alle dine enheder, får du brug for din gendannelsesnøgle." "Åbn %1$s på en stationær enhed" "Log ind på din konto igen" "Når du bliver bedt om at verificere din enhed, skal du vælge %1$s" @@ -23,12 +24,12 @@ "Dine kontodetaljer, kontakter, personlige indstilliger og samtaler vil blive gemt" "Du mister al beskedhistorik, der kun er gemt på serveren." "Du bliver nødt til at verificere alle dine eksisterende enheder og kontakter påny" - "Nulstil kun din identitet, hvis du ikke har adgang til en anden enhed, der er logget ind, og du har mistet din gendannelsesnøgle." - "Kan du ikke bekræfte? Du skal nulstille din identitet." - "Slå fra" - "Du mister dine krypterede meddelelser, hvis du er logget ud af alle enheder." - "Er du sikker på, at du vil slå sikkerhedskopiering fra?" - "Hvis du sletter nøglelageret, fjernes din kryptografiske identitet og meddelelsesnøgler fra serveren og følgende sikkerhedsfunktioner deaktiveres:" + "Nulstil kun din digitale identitet, hvis du ikke har adgang til en anden enhed, der er logget ind, og du har mistet din gendannelsesnøgle." + "Kan du ikke bekræfte? Du er nødt til at nulstille din digitale identitet." + "Slet" + "Du mister din krypterede chathistorik og skal nulstille din digitale identitet, hvis du fjerner alle dine enheder." + "Er du sikker på, at du vil slette nøglelageret?" + "Hvis du sletter nøglelageret, fjernes din kryptografiske identitet og beskednøgler fra serveren og følgende sikkerhedsfunktioner deaktiveres:" "Du vil ikke kunne se historikken for krypterede beskeder på nye enheder" "Du mister adgangen til dine krypterede meddelelser, hvis du er logget ud %1$s overalt" "Er du sikker på, at du vil deaktivere nøglelagring og slette lageret?" @@ -58,12 +59,12 @@ "Generer din gendannelsesnøgle" "Del ikke dette med nogen!" "Opsætning af gendannelse lykkedes" - "Opsæt gendannelse" + "Hent gendannelsesnøgle" "Ja, nulstil nu" "Denne proces er irreversibel." - "Er du sikker på, at du ønsker at nulstille din identitet?" + "Er du sikker på, at du vil nulstille din digitale identitet?" "Der opstod en ukendt fejl. Kontroller, at adgangskoden til din konto er korrekt, og prøv igen." "Indtast…" - "Bekræft, at du ønsker at nulstille din identitet." + "Bekræft, at du ønsker at nulstille din digitale identitet." "Indtast adgangskoden til din konto for at fortsætte" 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 4ae9a2e423..35da59cdb9 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -12,6 +12,7 @@ "Введите ключ восстановления" "В настоящее время резервная копия ваших чатов не синхронизирована." "Получить ключ восстановления" + "Ваши чаты автоматически резервируются с использованием сквозного шифрования. Для восстановления этой резервной копии и сохранения вашей цифровой личности в случае потери доступа ко всем вашим устройствам вам потребуется ключ восстановления." "Откройте %1$s на компьютере" "Войдите в свой аккаунт еще раз" "Когда потребуется подтвердить устройство, выберите %1$s" @@ -25,7 +26,7 @@ "Вам нужно будет заново подтвердить все существующие устройства и контакты." "Сбрасывайте личность только в том случае, если у вас нет доступа к другим устройству, на которых выполнен вход, и вы потеряли ключ восстановления." "Не можете подтвердить? Вам потребуется сбросить личность вашей учетной записи." - "Выключить" + "Удалить" "Вы потеряете зашифрованные сообщения, если выйдете из всех устройств." "Вы действительно хотите отключить резервное копирование?" "Удаление хранилища ключей приведёт к удалению вашей криптографической личности и ключей сообщений с сервера, а также отключению следующих функций безопасности:" diff --git a/features/verifysession/impl/src/main/res/values-da/translations.xml b/features/verifysession/impl/src/main/res/values-da/translations.xml index 32cdf159d5..90e227eae6 100644 --- a/features/verifysession/impl/src/main/res/values-da/translations.xml +++ b/features/verifysession/impl/src/main/res/values-da/translations.xml @@ -2,8 +2,8 @@ "Kan ikke bekræfte?" "Opret en ny gendannelsesnøgle" - "Verificér denne enhed for at konfigurere sikre meddelelser." - "Bekræft din identitet" + "Vælg, hvordan du vil verificere dig for at konfigurere sikre beskeder." + "Bekræft din digitale identitet" "Brug en anden enhed" "Brug gendannelsesnøgle" "Nu kan du læse eller sende beskeder sikkert, og enhver du samtaler med kan også stole på denne enhed." @@ -17,7 +17,7 @@ "Bekræft, at numrene nedenfor stemmer overens med dem, der vises på din anden session." "Sammenlign tal" "Nu kan du læse eller sende beskeder sikkert med din anden enhed." - "Nu kan du stole på identiteten af denne bruger, når I sender og modtager beskeder fra hinanden." + "Nu kan du stole på denne brugers digitale identitet, når I sender eller modtager beskeder." "Enhed verificeret" "Indtast gendannelsesnøgle" "Enten udløb anmodningen, den blev afvist, eller der var en fejl i verifikationen." @@ -42,7 +42,7 @@ "Åbn appen på en anden bekræftet enhed" "For ekstra sikkerhed, verificér denne bruger ved at sammenligne et sæt emojier på jeres enheder. Gør dette ved at bruge en kommunikationsmetode i stoler på." "Verificér denne bruger?" - "For ekstra sikkerhed ønsker en anden bruger at bekræfte din identitet. Du får vist et sæt emojier til sammenligning." + "For ekstra sikkerhed ønsker en anden bruger at bekræfte din digitale identitet. I vil blive vist et sæt emojis, der skal sammenlignes." "Du burde se en popup på den anden enhed. Start verifikationen derfra nu." "Start verifikation på den anden enhed" "Start verifikation på den anden enhed" @@ -50,5 +50,5 @@ "Når du er blevet accepteret, kan du fortsætte med verifikationen." "Accepter anmodningen om at starte bekræftelsesprocessen i din anden session for at fortsætte." "Venter på at acceptere anmodningen" - "Logger ud…" + "Fjerner enhed…" 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 5d1a08a727..e12e049469 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -120,6 +120,7 @@ "Forlad klynge" "Indlæs mere" "Administrer konto" + "Administrer konto og enheder" "Administrer enheder" "Administrer rum" "Besked" @@ -162,14 +163,15 @@ "Del liveplacering" "Vis" "Log ind igen" - "Log ud" - "Log ud alligevel" + "Fjern denne enhed" + "Fjern denne enhed alligevel" "Spring over" "Start" "Start samtale" "Begynd forfra" "Begynd verifikation" "Tryk for at indlæse kort" + "Stop" "Tag billede" "Tryk for indstillinger" "Oversæt" @@ -190,6 +192,7 @@ "Avancerede indstillinger" "et billede" "Analyse-værktøj" + "Synkroniserer notifikationer…" "Du forlod rummet" "Du blev logget ud af sessionen" "Udseende" @@ -223,6 +226,7 @@ "Tom fil" "Kryptering" "Kryptering aktiveret" + "Slutter kl.%1$s" "Indtast din PIN-kode" "Fejl" "Der opstod en fejl, du modtager muligvis ikke meddelelser om nye meddelelser. Fejlfinding af meddelelser fra indstillingerne. @@ -249,6 +253,8 @@ "Linje kopieret til udklipsholder" "Linket er kopieret til udklipsholderen" "Forbind ny enhed" + "Aktuel position" + "Aktuel position afsluttet" "Indlæser…" "Indlæser flere…" @@ -344,9 +350,10 @@ "Indstillinger" "Del klynge" "Nye medlemmer ser historik" + "Deling af aktuel position" "Delt placering" "Delt klynge" - "Logger ud" + "Fjerner enhed" "Noget gik galt" "Vi stødte på et problem. Prøv venligst igen." "Klynge" @@ -366,12 +373,13 @@ "Tekst" "Tredjepartsmeddelelser" "Tråd" + "Tråde" "Emne" "Hvad handler det her rum om?" "Ude af stand til at dekryptere" "Sendt fra en usikker enhed" "Du har ikke adgang til denne meddelelse" - "Afsenderens verificerede identitet blev nulstillet" + "Afsenderens verificerede digitale identitet blev nulstillet" "Invitationer kunne ikke sendes til en eller flere brugere." "Kan ikke sende invitation(er)" "Lås op" @@ -396,16 +404,17 @@ "Talebesked" "Venter…" "Venter på denne besked" + "Venter på aktuel position…" "Alle kan se historikken" "Dig" "%1$s(%2$s ) har delt denne besked siden du ikke var i rummet da den blev sendt." "%1$s delte denne besked, siden du ikke var i rummet da den blev sendt." "Dette rum er konfigureret, så nye medlemmer kan læse historikken.%1$s" - "%1$ss identitet blev nulstillet. %2$s" - "%1$ss %2$s identitet blev nulstillet. %3$s" + "%1$ss digitale identitet blev nulstillet. %2$s" + "%1$ss %2$s digitale identitet blev nulstillet. %3$s" "(%1$s)" - "%1$ss identitet blev nulstillet." - "%1$ss %2$s identitet blev nulstillet. %3$s" + "%1$ss digitale identitet blev nulstillet." + "%1$ss %2$s digitale identitet blev nulstillet. %3$s" "Tilbagetræk verifikation" "Tillad adgang" "Linket %1$s fører dig til et andet websted %2$s @@ -437,6 +446,7 @@ Er du sikker på, at du vil fortsætte?" "%1$s kunne ikke få adgang til din placering. Prøv igen senere." "Kunne ikke uploade din talebesked." "Rummet findes ikke længere, eller invitationen er ikke længere gyldig." + "Aktiver venligst din GPS for at få adgang til lokationsbaserede funktioner." "Meddelelsen blev ikke fundet" "%1$s har ikke tilladelse til at få adgang til din placering. Du kan aktivere adgang i Indstillinger." "%1$s har ikke tilladelse til at se din placering. Aktivér adgang nedenfor." @@ -464,11 +474,11 @@ Er du sikker på, at du vil fortsætte?" "%1$d Fastgjorte beskeder" "Fastgjorte beskeder" - "Du er ved at gå til din %1$s konto for at nulstille din identitet. Derefter vil du blive ført tilbage til appen." - "Kan du ikke bekræfte? Gå til din konto for at nulstille din identitet." + "Du er ved at gå til din %1$s konto for at nulstille din digitale identitet. Derefter vil du blive ført tilbage til appen." + "Kan du ikke bekræfte? Gå til din konto for at nulstille din digitale identitet." "Træk verifikationen tilbage og send" "Du kan trække din verifikation tilbage og sende denne meddelelse alligevel, eller du kan annullere for nu og prøve igen senere efter at have gen-verificeret. %1$s" - "Din besked blev ikke sendt, fordi %1$s\'s verificerede identitet er blevet nulstillet" + "Din besked blev ikke sendt, fordi %1$s\'s verificerede digitale identitet er blevet nulstillet" "Send besked alligevel" "%1$s bruger en eller flere uverificerede enheder. Du kan sende beskeden alligevel, eller du kan annullere for nu og prøve igen senere, når %2$s har bekræftet alle deres enheder." "Din besked blev ikke sendt, fordi %1$s ikke har bekræftet alle enheder" @@ -500,7 +510,7 @@ Er du sikker på, at du vil fortsætte?" "Klynger" "Delt %1$s" "På kortet" - "Beskeden blev ikke sendt fordi %1$s s bekræftede identitet blev nulstillet." + "Beskeden blev ikke sendt fordi %1$s s bekræftede digitale identitet blev nulstillet." "Meddelelsen er ikke sendt, fordi %1$s ikke har bekræftet alle enheder." "Beskeden er ikke sendt, fordi du ikke har verificeret en eller flere af dine enheder." "Lokation" @@ -510,5 +520,5 @@ Er du sikker på, at du vil fortsætte?" "Du skal verificere denne enhed for at få adgang til historiske beskeder" "Du har ikke adgang til denne meddelelse" "Kan ikke dekryptere beskeden" - "Denne besked blev blokeret, enten fordi du ikke verificerede din enhed, eller fordi afsenderen skal have verificeret din identitet." + "Denne besked blev blokeret, enten fordi du ikke verificerede din enhed, eller fordi afsenderen endnu ikke har bekræftet din digitale identitet." 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 4ae92c03ea..e03a51eeb3 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -122,6 +122,7 @@ "Покинуть пространство" "Загрузить еще" "Настройки аккаунта" + "Управление учетной записью и устройствами" "Управление устройствами" "Управление комнатами" "Написать" @@ -172,6 +173,7 @@ "Начать заново" "Начать подтверждение" "Нажмите, чтобы загрузить карту" + "Остановить" "Сделать фото" "Нажмите для просмотра вариантов" "Перевести" @@ -226,6 +228,7 @@ "Пустой файл" "Шифрование" "Шифрование включено" + "Время завершения: %1$s" "Введите свой PIN-код" "Ошибка" "Произошла ошибка. Вы можете не получать уведомления о новых сообщениях. Устраните неполадки с уведомлениями в настройках. diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 98a8aa1862..457aec7d80 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -374,6 +374,7 @@ Reason: %1$s." "Text" "Third-party notices" "Thread" + "Threads" "Topic" "What is this room about?" "Unable to decrypt" diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png index 6c0d8d5eaa..f2b02ca79e 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c1196cd5631cae5cb944cd0cc6903c4758a8e331983b2bbd93500473733f004 -size 34294 +oid sha256:03d7fd58010b5eb1bdefef76648e08431728f51527815db9df58ee0010f871da +size 34304 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png index fc9aeb0fa7..cf7fd18f5d 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b724d4087e37920bcb0ecf7812248f1dc31294da738866fed3000c63a4ec329 -size 36263 +oid sha256:bce8b45b24c38b3a991dffd06d1b2f79da728820ab93f649138ae071883aff60 +size 36269 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png index 6722d77789..38a62af758 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c609a2f5a80242c1fa9fc20d6f6295a85a23e1795a2603c64bce035abc8da05 -size 45651 +oid sha256:241dd64dd76b17b3a024622963c809f8788e0c5ef5f841b9be500942e4618076 +size 45660 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png index c1910fa5ae..5b6e58f735 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:831db915b860b285a9548e6469faa4d33445d7f79b28f6b54029bfdf2d61b4c8 -size 46567 +oid sha256:24ce85ea23acfd4d062785c013f5b1faa96d6ab75c1bab242bf03b6e6e330b78 +size 46572 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png index 9a66f5b538..100e2139d3 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0c96581bc29034a47a345b5c5f215853ab5d5545b2d64124031fb930bbd9f64 -size 48063 +oid sha256:e36b034ca57ca657072a089fcb7f7cccd2a5ec9897f80077bba29f85f2dcc96c +size 48069 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png index 6722d77789..38a62af758 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c609a2f5a80242c1fa9fc20d6f6295a85a23e1795a2603c64bce035abc8da05 -size 45651 +oid sha256:241dd64dd76b17b3a024622963c809f8788e0c5ef5f841b9be500942e4618076 +size 45660 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png index 7dc00e9c6e..2e87baac06 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b79450f73b04b2cb5a6cb674f303bba6326303ecca06f6a065112bc3b3e01db -size 46700 +oid sha256:0b1b8c43a078f16dd5424960c63bc42524ce73d5198834b5291f9bd874ee7b0a +size 46711 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png index ce5528cf17..5f28babc08 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44fa3cfedf5f3b943fbc7ccb8a7e88163dd97d7a314f1a38e339658bfd84f741 -size 39853 +oid sha256:d25872cb05d6d9b0cca7c579f67e531a059251ed033b3fa10a8969d161c9b050 +size 39859 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png index 4a0d1f93b2..81083ef1a9 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f136a8ac494703edfe2f727e22befd07ffced587621ceb8b39136c3025fc4c -size 41511 +oid sha256:d2659371297c436c5aea18011221c081ec94299ba6a5643f5fda0214372b3096 +size 41515 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png index da5814af23..9ba16e11d1 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0c93f1419921ce124a015b3e6ca8dbed714f0e8eb7aa55d2e33e5fde2396ef7 -size 35296 +oid sha256:1845ce37a3c2cc763b745caeb6cfbc094b6bd65a3c8234dc8173a13c5377e038 +size 35299 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png index b3f0b141e5..7538d489f0 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:297914ef0da135e7294bb7bc476f581f2f28cb8cf4d8756b6d1379d1893b5c6c +oid sha256:abcd7267209f3ca0881cfbe3c9457f024d4368a1c8fc6bba8a00ab89e95ffac0 size 37563 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png index 8aa5a5b419..0608a5a46e 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e2bfad23495d22ef4ccc316efb4af24de9ee26731a39dc1cb665bfa7b1900de -size 47303 +oid sha256:099f4b603ee07216e66a75d5d08b8f17084648526ac14e4e611c7c090260b8fc +size 47304 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png index d1cc642217..62300fdbf1 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aec7bbe40f667e33c901290a357c0bdd35042b165e202f9f865d67587b38cde3 +oid sha256:dc0b352e7c81e7e6389985c4c29d1a7074bd733e56789f3f675bbecd6ff17be7 size 48289 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png index b261d63af0..fc8a1452d4 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68cf296625cf15e2fcef1a02fced8e68e3357af7211d66b7731ea198fa4c3440 +oid sha256:800381effd5dcdd3f41d28defd29cb21c99d254de86a91c1e7f60f476a4e393c size 49863 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png index 8aa5a5b419..0608a5a46e 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e2bfad23495d22ef4ccc316efb4af24de9ee26731a39dc1cb665bfa7b1900de -size 47303 +oid sha256:099f4b603ee07216e66a75d5d08b8f17084648526ac14e4e611c7c090260b8fc +size 47304 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png index 1e693e765d..b47aaf7358 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e41f2e18d265c3ba444041b286dca3e1973e861469d53f3f0933ccbfcdea5c5d -size 48394 +oid sha256:79db769c4c524aa2831ddf2e714102c0f1a5de1a7855025e67598c8f261e65da +size 48388 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png index 5f5d5a50f7..84c90cefef 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b3e812737af7688f1cc3ac6e251a0fc56b631754888760f960be8cf1174c24b -size 41186 +oid sha256:631556267b57adf739438e7a9c094c411273de3d74113216064268926499d292 +size 41188 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png index c5c4572551..13ddf126ee 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:454047441aedaf4eb85fd379acdbd0b9618ed348bc2ab876d92b963bc6ea34f0 -size 43106 +oid sha256:d8c0999d16e140465ab18fff34650ac850cf650316f52b4a3dd9145e6f928d04 +size 43107 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png index 57b0b95a3b..e7b089068f 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77959d24fd7c52c4d63090e51d189bd6c41c9c350c1a4c97a2260c05b226c119 -size 86868 +oid sha256:e46c26ec7af7c4d1c1bafc0fb8bda6ef4afe7dcc6ceb8a5a38f2872ccafbc6d0 +size 86687 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png index 5b2f0bbb1f..0d394678ce 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53a21b0c20ed1fb442fdb8d860805ee8f476cb2f527d571b07084751b58c762b -size 39239 +oid sha256:c50c374b59c957f4e007d9548c2e03ffb622fcba3de9bb0adb2e36336114263b +size 39053 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png index 5b2f0bbb1f..0d394678ce 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53a21b0c20ed1fb442fdb8d860805ee8f476cb2f527d571b07084751b58c762b -size 39239 +oid sha256:c50c374b59c957f4e007d9548c2e03ffb622fcba3de9bb0adb2e36336114263b +size 39053 diff --git a/screenshots/de/features.home.impl_HomeView_Day_4_de.png b/screenshots/de/features.home.impl_HomeView_Day_4_de.png index f200461dc7..40500e7b72 100644 --- a/screenshots/de/features.home.impl_HomeView_Day_4_de.png +++ b/screenshots/de/features.home.impl_HomeView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19266c73ca346e8a290c9eb4091cd5088b5569710a31d06353782be071c03fcb -size 58359 +oid sha256:55944dde4104ac2de65a11ab041d813416a21aae25e4cc21b9f624a2d33a80c0 +size 58447 diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png index 3730e14b8c..950394d6ef 100644 --- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png +++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f80183fc0e3b5b06b51bcf58f4547111d3df1f800aec777fbab41d9d7eb51a24 -size 42252 +oid sha256:b9b94629caba74d3fa8f9d939edc441b687c6496001b185c6b7dc4ba13a197d4 +size 41978 diff --git a/screenshots/de/features.location.impl.send_SendLocationView_Day_0_de.png b/screenshots/de/features.location.impl.send_SendLocationView_Day_0_de.png deleted file mode 100644 index 787f11c872..0000000000 --- a/screenshots/de/features.location.impl.send_SendLocationView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6be1e5c5f4abfdae4e8c8e059ab6bd23808d014c76a029762f3bc213935322aa -size 19235 diff --git a/screenshots/de/features.location.impl.send_SendLocationView_Day_1_de.png b/screenshots/de/features.location.impl.send_SendLocationView_Day_1_de.png deleted file mode 100644 index cf4202ecdb..0000000000 --- a/screenshots/de/features.location.impl.send_SendLocationView_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9666da59d98a5c1ea6c786d42d5f7ecdfacef41f795dd9481c8b207f00e5e92f -size 37893 diff --git a/screenshots/de/features.location.impl.send_SendLocationView_Day_2_de.png b/screenshots/de/features.location.impl.send_SendLocationView_Day_2_de.png deleted file mode 100644 index 43685df0a7..0000000000 --- a/screenshots/de/features.location.impl.send_SendLocationView_Day_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1db33582d79aee02c96c99e1c42149f91d5bc7a62d1b095428262b03619e1c4f -size 34219 diff --git a/screenshots/de/features.location.impl.send_SendLocationView_Day_3_de.png b/screenshots/de/features.location.impl.send_SendLocationView_Day_3_de.png deleted file mode 100644 index 787f11c872..0000000000 --- a/screenshots/de/features.location.impl.send_SendLocationView_Day_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6be1e5c5f4abfdae4e8c8e059ab6bd23808d014c76a029762f3bc213935322aa -size 19235 diff --git a/screenshots/de/features.location.impl.send_SendLocationView_Day_4_de.png b/screenshots/de/features.location.impl.send_SendLocationView_Day_4_de.png deleted file mode 100644 index eddcfdc5a4..0000000000 --- a/screenshots/de/features.location.impl.send_SendLocationView_Day_4_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bdbfd52bef468588d3655706a06c78d7c9fe6dab354a832b85236574d77af112 -size 19444 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_0_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_0_de.png new file mode 100644 index 0000000000..26a2d11771 --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e80b99b89c442b8126cf80c8497b524b03012075763dd34f646fa1f7850a5a25 +size 19956 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_1_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_1_de.png new file mode 100644 index 0000000000..e1f4b27424 --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94bc010e69f70262da8f693185bbb4e5ab65c1443ffb04409aad4b4ac6d6977d +size 38635 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_2_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_2_de.png new file mode 100644 index 0000000000..5b33246329 --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9fcdaa31d82e5e677b39ccea11767febe8d51789d410e0934b07ce27ab4033f +size 35151 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png new file mode 100644 index 0000000000..f4290dda6e --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2eb237f3bea51645310fe28e66a374ee7eea722d262261faf7a2d4ad7bfc9515 +size 30400 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_4_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_4_de.png new file mode 100644 index 0000000000..26a2d11771 --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e80b99b89c442b8126cf80c8497b524b03012075763dd34f646fa1f7850a5a25 +size 19956 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png new file mode 100644 index 0000000000..bdd4cde724 --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e17424dbbfb6a537bcd285ab3d4a4a8567a61cba89b17b7ac1caddbc26dfde6 +size 17320 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png new file mode 100644 index 0000000000..7967b79a1c --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f148e3b2e061cc9cc1e3a6568f4452175b51341a2c317aed2c52a355351cdff +size 42513 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png index 1e8329391e..d4d8b13367 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7023f8cfa5fcaf68d44790813287382df6b5f496e1c6bc3025f5e6f280b82f85 -size 11123 +oid sha256:c27b436e8284ef32e2d4fe1285587f1580b4139b6e098d9e37e976c98f595057 +size 19318 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png index 85da5bc99a..61d38bcadf 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4976c47e82967168892ef6a0125210b437aa5a2bd80f6100979a60ca365c259e -size 32420 +oid sha256:c0e8730caeac7c344ae3d7c605aa944a6b8d021b5f3b8cfd387cf9cc2814c6c9 +size 40339 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png index 53aa498533..f3502aceac 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1befcf4a87a8aa3c925e55d3ae8776627bad230cff5e09f6c8d33172749be313 -size 28793 +oid sha256:4b70b5cc45b554c282a435f59d5311483569ad6be9875f25a1b88e1c9119b264 +size 36812 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png index 1e8329391e..d1aa86b7c6 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7023f8cfa5fcaf68d44790813287382df6b5f496e1c6bc3025f5e6f280b82f85 -size 11123 +oid sha256:016809a14091abf8554648ea4cd45945541395772c540d8aa8b04a24c0190050 +size 32120 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png index 91776aecf1..d4d8b13367 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32b1ab1cc6703376e1649d5b4b0288b142d954d7cbe02fd966a523e2c7b01f43 -size 11254 +oid sha256:c27b436e8284ef32e2d4fe1285587f1580b4139b6e098d9e37e976c98f595057 +size 19318 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png index 5b2e833a43..a0d42acd55 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46d118957b387eff49efd968202186592087e32e01859b3c84f0f90b730e835a -size 14832 +oid sha256:10244806518a4f64985be17fa5814d1523ef8796398a02632d48bcdf2d9daf53 +size 19451 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png deleted file mode 100644 index 9942a70172..0000000000 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ef794ae82eaeda53e7300b4c935d9ce7f4487b204ee78020bd4f518f816f7880 -size 23288 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png deleted file mode 100644 index 02f54e7e52..0000000000 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d525359e7d0a5dc0dac54f05acf77dba55528bc3cfd614c047bccdd670267b67 -size 25989 diff --git a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_de.png b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_de.png index b46483bee6..80e1c0e9f0 100644 --- a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_de.png +++ b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0d3451e07ddc21d22d59ab932075b0b957f7a51903f373922193ade95afb43b -size 54648 +oid sha256:58932b4453c81582a8f3bd4e47a4dc37355bc65ce23413715d240212e44c5dbc +size 54567 diff --git a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png index fe5e6a62f3..aca8462ace 100644 --- a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png +++ b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ad8ffbf4727694e35b4104a0329443e4087ebfd780a15c0b2680d14fb50376d -size 65291 +oid sha256:b3da0fcc021270fe7cfde72e03f44f9c95428f18673aa86bbfb11a6acc0b344f +size 65207 diff --git a/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png index ae43fa0476..e7fbb21056 100644 --- a/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9eaef8876d48f81ff763ad24c6f4ae7aa2dd56e8968d75f2a1751c09805fd792 -size 18168 +oid sha256:ab856d0a2de029924cccaf9f2285f3178315d83fb12e02f7f71d9c69fdddc5d1 +size 17989 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png index 68dcee55c3..807e16c40a 100644 --- a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4b1981984e8edde71723dd40849471b514d101b3d545b0a6132bea1cda0358f -size 43592 +oid sha256:bbdd0d31786b29709c02e9f35191af1334b6f6a32cc0614a833f79d47551fc70 +size 42687 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png index bc903778fd..538acbb4fd 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:023e811a9fa6157440eb00ca584988273efc2f37ed3804208bf5aae8b9136673 -size 364436 +oid sha256:180a33d511c0bcea775972eb4c0f80856d40657d0683eaee67e3d9b58687ef3e +size 365444 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png index 628521bd47..7d0a21c3d6 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6257478d8e46e942ca037b1aa178477e188edb9777d67a3e7560929d6aba8880 -size 370034 +oid sha256:e2d3bbb762ad093c0e60d1bb1f838d078449a1f3d733771f35660c3bbe5b374b +size 370934 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png index 792aceaf60..de58d2b1bf 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc5e553875d40920c9a9066c25ba6094238a7894aeb26ab144ee4cd9083f1754 -size 363641 +oid sha256:29c9f1d6d7972e8fb27701407eeb6febae153e92e60ac21f60a5bcb01beeede8 +size 364778 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png index 0053487297..40d6fe691b 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1fb4257bed537387bda20ecb17ded43f4f9edfa1c3280b58fdd8a3dc9c91819 -size 365658 +oid sha256:1fb43a66477ee416f6e8bea4acdecea322fc9cac09c5cc4c8fe6644fdefe78df +size 366590 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_10_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_10_de.png new file mode 100644 index 0000000000..ff53dce724 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_10_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ebbbddf29df78c6a6b37f931052cac67ea7ae1c875e2d75fa6ae8aa1683971b +size 87348 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_11_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_11_de.png index ff53dce724..23715fd683 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_11_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ebbbddf29df78c6a6b37f931052cac67ea7ae1c875e2d75fa6ae8aa1683971b -size 87348 +oid sha256:0914e81c505541a4f000240469e746964c5f476a7884403616015fab62f23663 +size 51743 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_12_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_12_de.png index 23715fd683..44e66cdc1e 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_12_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0914e81c505541a4f000240469e746964c5f476a7884403616015fab62f23663 -size 51743 +oid sha256:fa15ce3aa51c83819e6fbdf235e6f732b0db187ea49344279b01614efd9ff6a3 +size 63456 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_13_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_13_de.png index 44e66cdc1e..04e605318e 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_13_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa15ce3aa51c83819e6fbdf235e6f732b0db187ea49344279b01614efd9ff6a3 -size 63456 +oid sha256:961a9289be61a16372087c645302e4043d71f73c4440e24473941a9a6aa41daa +size 48104 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_14_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_14_de.png index 04e605318e..e6bbd0bdff 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_14_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:961a9289be61a16372087c645302e4043d71f73c4440e24473941a9a6aa41daa -size 48104 +oid sha256:fb03835fff5c4d27009fd19af5494b71501445184f6cb984e39fa175e430fbbc +size 72082 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_15_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_15_de.png index e6bbd0bdff..7169b684d9 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_15_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb03835fff5c4d27009fd19af5494b71501445184f6cb984e39fa175e430fbbc -size 72082 +oid sha256:f9bb51eda6e69e8cd532a3adebbd33267580fdccc904c91e741cb2e8026f0b79 +size 57796 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_16_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_16_de.png index 7169b684d9..c3563a3472 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_16_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9bb51eda6e69e8cd532a3adebbd33267580fdccc904c91e741cb2e8026f0b79 -size 57796 +oid sha256:5b88d255f070df4fad03371c64ce31e080a35999352a6a87cc10f83d8d5da99c +size 64506 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png deleted file mode 100644 index c3563a3472..0000000000 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5b88d255f070df4fad03371c64ce31e080a35999352a6a87cc10f83d8d5da99c -size 64506 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png index f63e3636a0..ba7d60941b 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b28fefedd7a34cb758217de7b240b536abf6f485bd256fd718ebc181df45e15b -size 70537 +oid sha256:e916a49d3cd4d81d8ec5f3d66f0b930bfba6e9c20f1b9c5f7d4c0bfe51895036 +size 67398 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png index a624c779b4..0d70a656c2 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa1490b35cdd22c0b01db869e8bad73195481fa2a2e7e61eb289e3f51bfc6200 -size 73417 +oid sha256:86fa2e5742ba38c173add0921615a18c1271caa783fd1a505c80a06096a3c248 +size 71646 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png index b3df3736a3..6a6d9271cc 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddcd24501a9e91f4a42cbffd60693a93d2dd0c2bf28e469b1b4ea460e2630d17 -size 67293 +oid sha256:d5c26f5383e1d079f5fa8a62baff668032181568a52bbbbc90bc2ee5d70d78a7 +size 67208 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png index f085e23212..9fc37666a6 100644 --- a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c823b266179d70fc5b6b3a3b1e0654536d1971fbe615f9db99fc8203049bf5b -size 23526 +oid sha256:2fc98a42e6af1c52bcd185592680871187a5cc942de9eaac694c0209f50a0c64 +size 22678 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png index 52c0695203..2144c61e2d 100644 --- a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6c6e0585e05d474d7797176d1f8222654d1eea1522bf508b353bf6b5694eaed -size 65127 +oid sha256:6f493c136e7284783a35253f88a752ed973d628786e7c0db037a8c3a577ef8a3 +size 69694 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png index 293b43a7e4..0e09e3da59 100644 --- a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06b30b3ffe792671b4a68044fb8b4c0deb9f1a0c0e121f166e2e4c50430f6c98 -size 35065 +oid sha256:f1394337ff80f74e9f4b6c5c2c947db462677f2957e0b73d2e919aabb6d2fc99 +size 34412 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index c2ae0556f5..e38435bab5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ba073d0fe9e1119e008a086fda234bc3451df4685a4d4704cf8721244f92e10 -size 46184 +oid sha256:17ad93c86555868ac098ce3beadb8dbde57c89af9bc2caec61df1f3596325ae4 +size 46178 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 6d58ebeeb9..23fc5ecd1f 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:723d8bdb06037c0098aa35fa2a8300a9ecee7367b5ee608bef7216dac4f46d91 -size 44761 +oid sha256:d16ff2356729e9d5aea99f00b110efff09d6c0beaa33e100846f3c56cb0fb0a9 +size 44757 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index dc74aeddda..fa145bb3cd 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9864cca2481e1f2f02ee625fbd47f3a182fa997cc917bc842ed893c1d2eaa151 -size 43560 +oid sha256:e8c48700213f1ac24b20c08d8585bea693ae08cf4a3dc91e6ac6aa08c1a02cb4 +size 43518 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 2630d505bb..564d0ae6bc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aca90256973d9614b6dbbeb665b782ebf3c59922c3fd569552d58d8437f54d8 -size 45347 +oid sha256:6f97df43c4f6e479e7ccdaa94d0e817f2ab3f02cf21986df1af09805eed8bd59 +size 45340 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index dca83692da..90d69eb98c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb22c1fa6e30e4fa2f9500fd33f3aa44bab2c2a1eb1374b306a216a808c96192 -size 45260 +oid sha256:75b4afed84d26d914eb82cdef4d9b7757d7cb27b0ee938c2bcca48d10553ced9 +size 45253 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index ad0dceff1c..85c3b70cf2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d933933bb693c3e227a750d5db76afc227df9ee4932823c6aafe99ec98e6dc1 -size 45838 +oid sha256:b7d85799138c9367a1229f36d90481577f08e027c4e946789f48e098b3927a0e +size 45832 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 82316c99e6..133d94e153 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a6f8f86d9a770a893949c7bc1762e3e05c6940be58708f5ac7a1704ca84debf -size 46369 +oid sha256:3ffbe5ab44b8cd51b94d766ff8bf0cfe05b56152d94a75d2858aca6b25db0bb8 +size 46364 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index b70917c986..95a9128cc5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5978469c7701bfcdb1c4f5af0279ccd712c1c9a7ac17d26751659d0bd72fc7b -size 45626 +oid sha256:18f4ef21e7a652f29dc88206e514ad600c05cc9dd2a6a3532e4aa3e68894d7ba +size 45621 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index a6ac629dd2..eee91513e2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b81a4f9a425c64ff9d3bbe5f61fc9abf46d0c4d5f746aa8b35140dd7ad568a6 -size 44844 +oid sha256:d04a9c799ef61bf131131e527c8734dd8ca67880d92a9ad121b576bc11d4a992 +size 44835 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index 6d2de679d3..d99db83de0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8608f7c43d21b688f60f7416f144df912fb7f8852949cd9fdc6752b47f9f0338 -size 42918 +oid sha256:cd41d6b3943d4c5e74090acb90a712b930be74c49c6a39fbe2f3b60e90855fd0 +size 42886 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index b1448746d5..d02979f393 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a9bba827ce7181ac459aa41f933bcb1513a8adec101b89a7557b4759f1740fe -size 42871 +oid sha256:17e33f973d9e33f6e06e7b2b66d448d66183a353ed76c1d7712a13e2af9cbbc4 +size 42839 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index 956fc80005..e0520466b7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:941b9293c96017d16e5964bf13f5b6b7954af6588a8dce2a8f731bcc3efe0321 +oid sha256:ccc14ef7b66c52afcb6d806b4d8d170ffb83b7817a5ecfaffd706853bbc35cf3 size 41743 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index cdf129e144..d8814411f0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8dc02ed20454ffade7a393956c0dcbb6f15a7d7012c0322cc43291580ffdc99f -size 47790 +oid sha256:33521284c24815367a302bde9c49b2795ecb5d803ac322220f720c5269605ea8 +size 47818 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index 4392889de4..e89ffa97bd 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eca6cd07f5eab788aeb07a35fb23c8f4ffc316aa9dbd1b48efdf00d16e6b4093 -size 47567 +oid sha256:4f16ad28caae15b4bd13fa61dd5b95450a559b00dc005b157fecf44c9b7df625 +size 47553 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index 9f391af648..3ab82edebb 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:450d628e5540ec8234d6c3aa33cd657ff51a56b5518004eef628eab92328b616 -size 47221 +oid sha256:5c493224b3437d144e064f91a9dcc97779953cddd81aa5884631ca0046d72dad +size 47264 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index e53d7fab40..15c3785853 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6411a8af9386bfca9b171e16b60231bc51c0a7ed92ff462918a1342251ea65e0 -size 39459 +oid sha256:6ab93cdb57a580a52ed48dde779355440d6a67412f9699927a8d4214388fc4a0 +size 39451 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index cee674d4a0..ac8ea4aa9b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:731fc476ed64dcf665ccc999072be646b04b58d7e440ba96e38cddf6953f08a4 -size 45410 +oid sha256:2d1c6f0c3898e000774de48cd7590c44bc11c297163735f16cc2dccaaf23e538 +size 45428 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index 8cdd7726b9..85b757fb86 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53aea24a421f5c5bdb2b4b0cdaa3b73f45c2747abc2d547c52b35234bf1944ae -size 44602 +oid sha256:647eaeb0c9ddce71bf99e382fa45bfc560affe38e8581e12016a1e5a37e270ba +size 44587 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index f9a596640a..ddac91c4b5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fbb251010c11e7cf41cd9d772628eec858e2eb7eb102f0d07a177f25d7e0e42 -size 42559 +oid sha256:2b129c0c7e62d3874d1b7e466dbbca271873b20d3155981eafdbd9c33202eb04 +size 42527 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index 346aa30d3d..a4d831a49c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a898591cee5b687baf9ec6d1c4fa1c0de34b99e45ddc1541de15d468c1ea1b1 -size 45985 +oid sha256:35aab3535b161bb3b111a9a352f510b43a25f9c98a7e5648aa3a380cd8402063 +size 45969 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index 39f289f1e2..a85951f6d6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07d62137742d97ebd6f1ca605f8239808d063db2a5af5a217fafa9156a7d8906 -size 46085 +oid sha256:eb393ca334e520249176e392cbf9f495c8651904f2e03680bd740f4d9b1c1ade +size 46076 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index 064953e54c..d8ac60f111 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bbc17b6609505a390fe0baae91706366deeb8bbb41bfe8493e98e23a1753c28 -size 45479 +oid sha256:6d420ac1d49b4f2a47d00e6fc273e2f2768b14a05f0d10c8c655cb492abfe142 +size 45474 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index 77fe390317..3ec8b090c2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f9836b0fdd3bda742e2b4c7aa7f724f1d6dbefb748d4ed31ba6912ab6600f2b -size 44166 +oid sha256:8435264c98cefccc80e7a4bd32d903708e878f4c4ad2686aa35df8fdb9324882 +size 44159 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index 6fd394851a..8d470aa1eb 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f006c30451416d0a41c3d902f7c9dad8b4d404326e623534ac7a09fe5b2699f4 -size 47231 +oid sha256:c0cdc554f6e3ce1725e2459ca0c6133f7f14a15d730f190bbbb795eb11c0404e +size 47224 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index 3346f21554..dc8f2611d0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28e1fe354a3305ad933daa95a65611335357ceb6599484e85ee4d3ce2f019e79 -size 45747 +oid sha256:d408175ca51c0b36ec01cd950b079467e29bdfdec9b18a1b81f1480ffff51e6b +size 45740 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index 8028d785f4..5e1712b9a9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f7d823c76b57b8d37cd86bf6dde6e61092dadeb03f65e0fdb3d9d0e7b016513 -size 44564 +oid sha256:3bc00b126e3820666bad9a4904b3956ab391a6af0f74ce30794373af1c654ea8 +size 44592 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index eba1696597..6f725c591f 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15ec7bd1f0e7baa884e7e89aadc485a7ab02d80fdc2957c5ae10ad6369f3bbab -size 46376 +oid sha256:438edecdc96de067dfef71395ca0dbde45b5127f5a8d507dd4148f43da12f1c2 +size 46370 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index c9813ac9c7..db3edbd7ed 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1818053ea53eb07fb96a27350bb0e59c8b696dc0a34ae16f7b814743d377f06a -size 46272 +oid sha256:2272a4633116a8f58a24273fe348e4cf979eb31fa78a641ea6da28345e358846 +size 46265 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index aebb284744..8d78460895 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:966dd5700a19d89bb8192b153f381387e80094dab940fa876a4c4eafa73c23df -size 46776 +oid sha256:a45ea374ed7827a1aaddcb6b5d0eb344b4c0d79ae328099bdff79a8a3ef84b5d +size 46769 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index 74cd663399..f7d40446e8 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ba4a4082698d5aba2e36ed11e50df97b59c2d85e09b53b1e3d534e2dc97c34e -size 47377 +oid sha256:d4ba031a35b259142083b6fd508b7ab15cf169f7f5b1535bd81ef7e4fbdc0a6d +size 47370 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index 03fa90e4ca..fe75d48f6a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d258cc980ddde7603d07c1d0ede66eb05a61215e8a9f7591083f44e3fac48ce3 -size 46652 +oid sha256:7e87581df1ada41c9b7b85f576da8c32f856203a6c48e7f40128fbf30c7a33a0 +size 46646 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index 31d3ff96f5..56080a7551 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e1cd8ae0035eb0cda747eac54bd11e3d95b8f006e10c05752209b0aff5062e1 -size 46149 +oid sha256:d87b127824291e0343f53cf50a22f0e1e8b89e00be55ea5f625aac59f9109a4d +size 46142 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index f8dfb9f0c9..e9d5014602 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc96bea99a5bf31bb0f742383cba458f14baf150845a47e1d14681c806c2021c -size 43913 +oid sha256:827747ea2eae177d460d615b9da37db515f635ed433567945e1d88cb39337594 +size 43944 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 16ce3617ac..8bf44cdefc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b6d30a4661310b3de30ed34c55bbe37af245ccd0c363cf2b5fea7c66f058e4a -size 43792 +oid sha256:1765877cdc96b174cb7a2e087165c74d1ceca02137d0daa510ec247cc4f481b6 +size 43823 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 6de030abb8..52c52e8769 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5327a706c81ac518776c5ad183bf601c14c97ea7bebc9b7c52cd04a2919e40ed -size 42899 +oid sha256:6f3c5533e239f54302eb7867bda7571fd966b4c298be9ec48abad6a5025c22d7 +size 42890 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index bb4aea59b1..c510c5f777 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f989780ab77db2fe17b0e7c52f8d73ad9de1c336bb02b4dc29140a4cda55cd58 -size 48860 +oid sha256:abb0b25a08a6507a9b3c0f3ed79ca11b26dcc54a9350a0711f9385ccb0ffa29a +size 48855 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index 84672b20a9..aadf561762 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb5e80f50cfcf6e6eac762a3bde89bf474931ac8a10c951d480f354f6bf81875 -size 48581 +oid sha256:f615089fb33bf68a1f24bc1d7f78ba899ea80c5dd5e046b05df04055e7d15ed3 +size 48571 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index c8ed3fd3a9..2c22f9b92c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aadbf1e409f2837387ea390c82ec8bf16a979e995d01bc0250cdf9d4bc7c881f -size 48252 +oid sha256:c9f1b2f0372b538dfc219ac8ac699347a199f0df903813ad1a97b7e158f50f9f +size 48241 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index 83868afa29..22634ff9dc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ffc68081fe2c9c391f71635a160559d4827f5ce69589d799ed499612e77260f -size 40469 +oid sha256:ab5386c966f4b5981bee9d39cd6a315bdc86dd286ff2c5e08aca4c5bb3304b23 +size 40457 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index 7daf7e374e..95c8bffb80 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2fe91f0d2dc898b39893d1efb70a827197e59af026fe53badbd4b1dd9a7ad11 -size 46398 +oid sha256:39e4eab91f3d07daff1437991ec74005e7c79eed3f9b4ff71c154d68bbce3e71 +size 46400 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index 69515bc17a..7574b9b61d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3388b6b6f46a7c90f3c45568e22d7d795f91a8a5e3fc9fabe7acfdd99013f868 -size 45606 +oid sha256:49009a3a070a668b7487ce69b3bf1377ce113cf003e1571db3f90d8319ec084c +size 45597 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index de53328c9b..00e31d8cd9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8cec2bc057e632943ba3aa42fa427ad6f6e766682903d620067ab5c8437ef21 -size 43449 +oid sha256:9e268c85951e089414695eed071ec5c98a80030d130f92d8a934f815dcc75334 +size 43480 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 6620a09ccd..71787b6f1f 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a84cc9c31168887d8924044df0e558b4aeac360a52426027be5b5c1a020f116 -size 47082 +oid sha256:eb164e2c9796a1d12a0146b3fb67d29813be54d42b0628d17a323a525b866177 +size 47065 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index e1ed2068e2..ed016c1eea 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65b9e404e0cbc2315d595febce884f11034ef7119ca76ae9dccbab4d2248bc96 -size 47259 +oid sha256:5a0b75e17e467d1a8abcb59f0e490c57e1bc538f10a6900cbff2e2c14994f0f8 +size 47246 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index b0c9775ea3..d4eb3afff0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36cb6dee1515ad0239cd87969649d39ca53b528651565ce9f49461c6f7f12198 -size 46633 +oid sha256:cd5c0dbd3621d8936b4e7eaac29524fb837007daef330802d71a12c1978d973c +size 46623 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index 472623e81b..3466e4571a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6436222472999c9ce19fdab8e5ee9d10dbf846b2764a366826cb4150c0dd426 -size 45170 +oid sha256:706e54694211c141ad5cd505379f695504b2fa4b793a9aae5242d52f72b9aea8 +size 45157 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png index 547b9ac6d2..8c69f2926a 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c96373fa4553adb41fd650ddd7794addd57a2c007152bcd24a33a2677f692aa -size 29729 +oid sha256:efc41570c6e1c04f96a4226b629a55fbc979555cddc20e62659b57e9e9a516c6 +size 29702 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png index 830a59bc98..f3f3f717c5 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5acabb4f45503b9c685510dfae0ebffee07b6383d7471edc74a462bab952ed56 -size 24105 +oid sha256:420cffbe21d04b2e274cd5c6d24076f05a21081701a60925f7efe0aa64f82839 +size 24097 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png index d4f4218c6f..e963ada9fb 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1331106fd5cdb17e1a64517582e2017942bd30981e35c9104ed9691dad6f535 -size 30220 +oid sha256:2284ea6f41d947283f997d48c2532119c1562b606bdbf730bdba4755e67c28e8 +size 30135 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png index b9ce13764e..f1100ff0ed 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a0fae6a3d68c058cfe4cc4d0a7c395129262050f4c423dff5734318b6d5a5d9 -size 52439 +oid sha256:582e106bc388c89ad644b2899390e82e5740004061aec622b6b97aa1bac12f85 +size 49429 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png index 845659c354..0888d9e355 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fb81d71260f2ac8568d8505f4ebfec1ad97e8001a94db6815e9dde859a38e30 -size 48491 +oid sha256:cca14f96f4ba493ce291f9f982d47a84d6eea3090e774bc4f2b1df63472db696 +size 76461 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png index 43681f14c0..b54c41f267 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d3e9968441f6189ec0e234c34178f7802ea4da778000338da3506ee428182ef -size 29869 +oid sha256:45bd842b590d153fd7c727b08e34f69c73fba0f2c73530f7726efae1386b37c5 +size 29846 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png index a2a0734703..5e4641cef0 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1067316ebeedc49b187fec61da538e07431612d5b38efcf8f7360023d4c34c1 -size 27968 +oid sha256:4a1d1b889880d3e4065b7de036c7e6a26f6817dd6268df957d948ff06aaa8c7e +size 27881 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png index 698dc47f17..9f16c22be6 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f1cb7f8790e0bd8ca61e137494db81295d6bf3fd6eec0f04983178a17c2bbe6 -size 25608 +oid sha256:45c2edc8bc542bd02c26c696c339855f8176afa349f7097f35cd9b5d6a45ca43 +size 25889 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png index 528eed4126..440f2a693a 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91592dced46d59ecbd6edb157ddb5325fb6a8a495a9434c2d878763f317dd104 -size 30930 +oid sha256:2f74a6693ce54a06ddb795f4787252cc35ae457eeb71330e2c3522aad64c55ee +size 30928 diff --git a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png index 3f716d49eb..13f81454c3 100644 --- a/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png +++ b/screenshots/de/features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6d39446fb8d8889b01bb411d92022fcf80e04efa89fd9bee7c071de791f8213 -size 32436 +oid sha256:dc4d09a07b88320eaa41e006cd67c56a7e6d5459f15e0471b00b0cebf73f95c5 +size 32558 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png index 51dccd31d9..2e8f128b7c 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8944a90ad9e5cd283b9a46547ffed79b932fc0fba9caa51a5d2e91021d302bd -size 66333 +oid sha256:4ff016cdc3ea47662f224c49fd182cc16ca3bb1e09191ccaf2c418ab93a358a6 +size 74302 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png index 1b0d3b202d..9ac2444e4f 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae0a43f1e5cd9dac74a4bd9783d7dcec09acd8d972b5ab24f6f7b1afd55d0db1 -size 50203 +oid sha256:f8804204dff0d36762b0c02e9503f2e06b6be257b9e1c0c2af6df0c0fe2855b9 +size 50289 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png index 853875b8ee..36817c5f75 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59af40c662f9dce190b7dea5b7ec52e69c6d7cc20d70ee9ea605ed730923f216 -size 50362 +oid sha256:a69c330592d208be768c7f607bede843483a92140155c974ad4a84116ebd142d +size 50380 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png index e1425f18f5..40e51c9537 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e648d7ad31cd4369f8230685a9e4a87b87116a9187502d2c224412d722d8bc75 -size 52276 +oid sha256:428725b17dde8ae30898299043e2d5e03ce63f516c93e440e660823fabd43e4a +size 52036 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png index c46b7d0dc5..806bb43ddc 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7683c2be445f411fb2f5c408db5ffa6e40ff562c9cee757ce16b36e0643aed0 -size 61299 +oid sha256:ccd76b6702435a24f67ab28adc60b462acb2fb430daf87b6ddc53237940bb29a +size 61987 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png index a02909f45b..75087f2a67 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0cb890656c62a8c0b5004a905d6614e89d6c395632b168f49047443c4853e62 -size 61924 +oid sha256:524f0d29e59175ceb996b81b98625e168033077b12541f8747fa6c6082097cdd +size 62629 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png index 8e0058a639..8a71650321 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208b78836148e8403ecfbaca6b3f14bbcec1756cb13ea0fbc00cdbb6c970659b -size 57796 +oid sha256:e338d699f2cb5d4645742e9dff3dc7cd3dec20d2ad75821bd3fdb3fb8e917a96 +size 57250 diff --git a/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png b/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png index aba971c8a4..b7ab99464e 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileHeaderSection_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f20ceee8793c045bcad1c1f3ce30d6aa36ba5e688c8f8b14161849bc0bedff01 -size 15889 +oid sha256:4b8a6428ae3624826edb3917a78e641df0704e8c21519ac003ff27387d0e37cd +size 15902 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png index 2a37678990..e7254790cf 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aeea0d322e256f499ddda7dc6cd40c2163f75ac7b9755d75289dde47f28b7c3a -size 25016 +oid sha256:f7bf1f5e039bdff2ba1da2678d57637564288733b9958042b86867350277ca9f +size 25025 diff --git a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png index e8a6cb04c3..6463867d7d 100644 --- a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png +++ b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d45be0f3300cc450129a656e28dd131c66e84fa36bf692a69441867d42ad562 -size 34110 +oid sha256:f85a57b51f5ac9d7165be8d83c414b8a1fce87f2bbbf4a345f145f01ba80e3f2 +size 34420 diff --git a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_de.png b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_de.png index 18a8311f9c..bf3926ade2 100644 --- a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_de.png +++ b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f3d837f5d0d5899f0a20b71dd8f39c1bc304bbebfb1b34e48f7b2feab805133 -size 25895 +oid sha256:e050acd07312ef4e19b85323ec4c061f9320fde6291a2818e58771257caf777d +size 25803 diff --git a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_de.png b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_de.png index ca4eb19234..58f0d723a0 100644 --- a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_de.png +++ b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:070a29bc9f0e4a9148348eba4ed164be33f0a238b892caee66343ad43c16a6cb -size 25601 +oid sha256:cba578353fc5d7e9e9327b0ebc89b8aad9e3743014b3fffb93538bb89fb9026b +size 25479 diff --git a/screenshots/de/libraries.matrix.ui.components_OrganizationHeader_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_OrganizationHeader_Day_0_de.png index ac7f62e753..8c65dbd7b3 100644 --- a/screenshots/de/libraries.matrix.ui.components_OrganizationHeader_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_OrganizationHeader_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df1613037f5b06b6cf9886056977d2ca269bbb09729d9aecdba9915c77cbed78 -size 41954 +oid sha256:0a8a0630b584a45d35879c3d729921abe6d810245cbf19ed74fec7d24c702d40 +size 41390 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_de.png index a46fd0d98c..07b95441bd 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d26f94621d75228ea9bdee2abc8616b378a64cf8b63b7fb043f32fdef61082e3 -size 18046 +oid sha256:fcf290de055889a30b6859a0815655b07ee96e600e241ad18af768ba7d0691a2 +size 17777 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png index 90d4f208c7..47ae5e64e6 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1472df8a860358e2193de329ca363a85cede2c65dc51b7182545152f9caa036c -size 20165 +oid sha256:5f245cfa43b2310ab533005012debe347d196b4c177e696ff4399c8431397113 +size 18057 diff --git a/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_de.png b/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_de.png index 6a40ec4ecd..a0198d4d9e 100644 --- a/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_de.png +++ b/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d350923703149b79d86d1029b1f415eb0e90b69165956ae44a23acfba203aa0 -size 8839 +oid sha256:de86d0d2cfcb6c2fcdc1fa3ea89a31ccbdbeaad7068fb29992c2989e2f3cec20 +size 8789 diff --git a/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_de.png b/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_de.png index 97b55075c1..6e431b335b 100644 --- a/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_de.png +++ b/screenshots/de/libraries.matrix.ui.messages.reply_InReplyToView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83fe63b22d68a39a7d404ee2f6074c7adcab79f16e11655d08a37ac3065be59a -size 9327 +oid sha256:4d2cd5afa60a792cc025b6eb580556162b06f03e0bd15b1dad8fa5294ce49e17 +size 9315 diff --git a/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png b/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png index cc6bf7ea12..92f956925d 100644 --- a/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7515c7be72796a399518d0229c4c656e8bbaa759f5710782926b393e65a0dfec -size 52291 +oid sha256:40f902114622ce212797bd9c0a7cf8fa9d465cacf1f32af99422558b35907d02 +size 52217 diff --git a/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png index 5ffe8738ed..c36a2ce217 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17b1cc7c68f7f692d819b05cf2ed01454b2dfdf33d847dcabdfe3823aa2858d5 -size 58106 +oid sha256:e7326fadd145ca624810e858cc3413fb56a25f875854b7d2e75cd7e1d1b4134f +size 58018 diff --git a/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png index 15e163db41..f9cbe155c1 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4c0e08d0814afded19cccab71e3e25f93bafbb23e285a2d9885b55db95513b3 -size 56085 +oid sha256:dbb50973fb9da0bb43708e3e608de3a22a301a2dc0d8c699bd9e0f59d5b44f20 +size 55991 diff --git a/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png index 566e8a69fe..c6d05fe805 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a28623ac9a17d8d707a92b229e106836cbc04de108598f573e8ec8e89e3d997 -size 65096 +oid sha256:987e6f677fe5412dcd5c94a883bf5966b18d048b31f189614ae2763823e319e9 +size 65017 diff --git a/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png index cc6bf7ea12..92f956925d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7515c7be72796a399518d0229c4c656e8bbaa759f5710782926b393e65a0dfec -size 52291 +oid sha256:40f902114622ce212797bd9c0a7cf8fa9d465cacf1f32af99422558b35907d02 +size 52217 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png index d3d070cca3..9b074e7cae 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4dd776bc6cc47e98bb697fd45118580d809504af449e66f8e6233e239746635e -size 73608 +oid sha256:5aea70f07d78c618613628503eae01783fef2561e963e4249ab89813886ab8f4 +size 73530 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png index e0068535e0..c5b0d39e9d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b318e520274fa61235bb3078a8e43f50f00cb3e995691f7c250aafcff34adf6 -size 60221 +oid sha256:41a9554ef3d3c8a9cf0b2234335728528b212caf954086ac7f8767fe795ec0c0 +size 60076 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png index c78fd312b6..bcc10c35e7 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4265b64af0d85d26fee18c5840c78dc248dca6c0188f7d05599a17533bbf7c56 -size 73032 +oid sha256:4bf87c47d0cee012847b5f0a0264f6f4e4cb948f965ad28af58fa5dac6b7e3a6 +size 73133 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png index f3f25e7b89..7218918f91 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0046b0b393a115565f40ef8e3d56e44b2f0e60bac1c58f460c5b0ccc51c0758 -size 81592 +oid sha256:abd564eae0efae348f0cafbb5749879b29f2d2b0a82eb645cd0db4e75ada4ff3 +size 81908 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png index 92ee2953f2..e3d9c74293 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a67d6255f9b0f17dfc39655a9006d616e5a000edde5c43675f9c05edbd61eb8e -size 62741 +oid sha256:1aa1be60455968000254246a1b307c8336e2c8e36cee5122e159254adeacf78e +size 62919 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png index 3d9ecdc028..af6d69fde2 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9bafc0bc7aa73c3d984e01b4d94a1f2a50a2457add0b202b89bec0acd5f8a66f -size 61646 +oid sha256:1bb0d795e03931704043807bedc666f129ca23aa60b2690957588b15c2a6b5ff +size 61770 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png index 34d58521be..33ff1188ae 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1afc95b901ad97456215f1a2f8fde7fe35f5837032b906eea6053f14814d4218 -size 67238 +oid sha256:8a40c856d3959ea432fa4a5bc5624e10005d8f405c5b5c199acfa38c3107035c +size 67354 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png index 7696ab1dd2..b100db999d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:455dc658af36e11e5175585c6965731b4493428596fb5ef0b77b6b89abd007e4 -size 90662 +oid sha256:797c78b06b51daa6088b94f38e536d59b619340a270bf7a4f8cbbf08c6c44be8 +size 90472 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png index 409f5c23b0..2c0063362c 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4514e0bd54db4822486ed0d762768f186cfb24611fd6a8161567b17bd20462a -size 61057 +oid sha256:9c431aa38578a656d8f1bf8f58d2fe8534772ed127c2ce102b377052b007306e +size 60994 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png index c20f81e2a3..2141974bd3 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6408e9a851a3976291270c08a6cc3ec30a8b1148f2034b6fa7c5bc8a66111b40 -size 62277 +oid sha256:ecddf9e9d5c75c2675235b5399d899cb8ae24383d32ea1bdf1899cb95fb8be54 +size 61138 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png index a874dc1806..d0d960153f 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8911a8ec35fb8ff3ecb5fc3eec7503ed53d5643c19c2726044ae02569aa374fa -size 69866 +oid sha256:beb5791aeff09f5e757c8f560cc9b705c208eb886462a840bfcab7d78e622c15 +size 69793 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png index e2a8343fef..22917ebb0f 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fa428a419c4693a3bf3039aaaf81968ffbb1d330208170efd60f9e02768f20e -size 60619 +oid sha256:f3285a648f80647c159933a083458fefd4d7f59687b74baacfd4a8dc7296ff05 +size 60504 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png index ec8d9ddde3..632d13a773 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b18c02b0e05fe86aca68378a112e698958780e30891c5c0a3e7f316ffd00f657 -size 72919 +oid sha256:6f61101788599662175adfd0b8e3fffa7d0152db1019e8424b2a3011572d1a01 +size 73241 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png index 495d5b4fff..05dae33d65 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef6a20ea4f3d4b64b294566b242ea8f6021d1a7f54555d6cdbc90f3ed41bf6df -size 56467 +oid sha256:f7d5e0c9b9c13b2e3d1cdfb1cbd666ced079e0faf230febc2377b9e10fab58be +size 56519 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png index 45025e9fb0..2443e232c8 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eceb56163d5b3a4398fc7711b76b2b09cf98be3006c0f2469011b233cb2751a8 -size 71145 +oid sha256:81030d66c1ddbdf113dd49ea1a566cff5e6591d4733d27925673a99ad2f413f8 +size 71646 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png index 876f0759f5..5b4f8dddd2 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f88e186b6a2c7bb78a7d0a3244324fb873616f72ab77b7cbe71354671241025 -size 82466 +oid sha256:3c7ef69c814541c026cf01b4466cb10f8737db3f673e81dbb57d1e5e8902f972 +size 83116 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png index a95036ff4a..e6cd15541d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:669073bf986640f0602b24c8f203f6272eeb83d57c9fb6e88757364b0bdd55a6 -size 59507 +oid sha256:081a69d09ed70a4bbba08690df9dab86d4a10a980f1330b3b27943cb1c10dff5 +size 59746 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png index 592cf9b318..c8eec3eb85 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:586b85f5d172f37e9fc0f90317b31826844a6ee598cc1835df72d398e1c57caf -size 58625 +oid sha256:893e712436eafea1791ad4bde6ef16b6e8389ed6dfcf6f5cd206f4e5cb25b44a +size 58863 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png index 256f3f11be..23c18ff2f0 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f11d0c70af70619812455a42dcf01c9f891f727868c276975003aeb3bf8f97e -size 66007 +oid sha256:72906d598feb20fba5d764485aa54ec3b3eb49ba9574dea5f97fefe8a5519a45 +size 66137 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png index 0fb81544f4..29d057fff0 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:503b031ed7f21cb022b5e1d41ed83baa8998469e5140008f349bd755b2e76416 -size 101507 +oid sha256:fb9602983bbbf519d40a602fd7670585cf376aeb9a72a95e6da4077aae2d340b +size 101576 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png index 8193b57db1..ba9ec7f709 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26bc4f2e52ed22162d4c8a720f4d0b2793b3d97e45d3463616b3b21b0c4638af -size 57853 +oid sha256:b8e52bb1582b86c3ba756282de449d61c673d7750c35813a712061456f246e4a +size 57799 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png index 92082e6e30..6313c48a1e 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cca5604149f542ec66a1be21a9ee8220405c49e40e7f974d83d6c60d7133e4bb -size 59690 +oid sha256:9da73f77e0e7aa91c0620b6714dcf81234939f42773ef2afeb6bd920af6d3593 +size 57852 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png index 030c42869a..c115f5a9db 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fcd11760900caeb73940f5618b5c33b54827e9e4a25e2f95ebc1e0200b7cd49 -size 68033 +oid sha256:3ae4658c6ce320cf09ca92d8321736d5079e085d7d41791ff33a2811a48fe2da +size 68025 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png index 29186b70be..0b321d53de 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3be967e3c38366b75f13003171dce8d03886814d9b8663768d28876672f041e5 -size 57219 +oid sha256:0ae8ddc2b5c7794bebb89110d9538c86f9ad90e1edc6df837b1710f19bd13aed +size 57175 diff --git a/screenshots/de/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_de.png index 5b616e7a55..98ecbe8286 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6964f7b2f51a7d928d49038d1ed48b4576163c329564e4bd928c32cb9ed6648 -size 55506 +oid sha256:65a53d64c78f99ff6d36f8e6597ba7404a7e27581d823a5674d46459d15a97ca +size 55407 diff --git a/screenshots/de/libraries.textcomposer_TextComposerSimple_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerSimple_Day_0_de.png index 5fce0aa30e..fe5975ff4f 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerSimple_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerSimple_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7636fa5e1fb1ef1e5972f7c973ca0282c87e6624fb150abd7f9198083c39fc29 -size 43642 +oid sha256:ea1736c6617804eb12450189db18dec3d1959b2d426aeb298c6164609f23319c +size 43565 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 62bb50771b..1ecfab0491 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,87 +1,87 @@ // 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",20532,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20539,], ["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",20532,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20532,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20532,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20532,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20532,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20532,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20532,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20532,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20532,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20532,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20532,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20539,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20539,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20539,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20539,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20539,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20539,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20539,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20539,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20539,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20539,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20539,], ["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",20532,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20532,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20539,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20539,], ["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",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20532,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20539,], ["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",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20532,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20532,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20532,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20532,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20532,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20532,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20532,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20532,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20532,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20532,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20539,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20539,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20539,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20539,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20539,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20539,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20539,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20539,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20539,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20532,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20532,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20532,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20532,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20532,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20539,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20539,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20539,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20539,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20539,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20532,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20539,], ["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",20532,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20539,], ["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",20532,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20539,], ["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",20532,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20539,], ["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",20532,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20539,], ["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 +91,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","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20532,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20532,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20539,], ["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",20532,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20539,], ["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 +133,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",20532,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20539,], ["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",20532,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20532,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20532,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20532,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20532,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20532,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20532,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20539,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20532,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20532,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20532,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20532,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20532,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20539,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20539,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20539,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20539,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20539,], ["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 +159,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",20532,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20532,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20539,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20539,], ["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",20532,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20539,], ["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",20532,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20532,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20532,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20532,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20532,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20532,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20539,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20539,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20539,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20539,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20539,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20539,], ["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",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20532,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20532,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20532,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20539,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20539,], ["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",20532,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20532,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20532,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20532,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20532,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20539,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20539,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20539,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20539,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20539,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20532,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20539,], ["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",20532,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20532,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20532,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20532,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20532,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20532,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20532,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20532,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20539,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20539,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20539,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20539,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20539,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20539,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20539,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20539,], ["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",20532,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20532,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20532,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20532,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20532,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20532,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20532,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20539,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20539,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20539,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20539,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20539,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20539,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20539,], ["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","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20532,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20532,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20532,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20532,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20532,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20532,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20539,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20539,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20539,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20539,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20539,], ["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",20532,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20532,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20532,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20532,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20532,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20532,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20532,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20532,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20532,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20532,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20532,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20532,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20532,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20532,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20532,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20532,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20532,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20532,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20532,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20532,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20539,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20539,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20539,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20539,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20539,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20539,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20539,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20539,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20539,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20539,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20539,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20539,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20539,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20539,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20539,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20539,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20539,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20539,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20539,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20539,], ["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","",20532,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20532,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20532,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20532,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20532,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20532,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20532,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20539,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20539,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20539,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20539,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20539,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20539,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20539,], ["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",20532,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20532,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20532,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20539,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20539,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20539,], ["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",20532,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20539,], ["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",20532,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20532,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20532,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20532,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20532,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20532,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20532,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20532,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20532,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20532,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20539,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20539,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20539,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20539,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20539,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20539,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20539,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20539,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20539,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20539,], ["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 +308,19 @@ 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",20532,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20532,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20532,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20532,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20532,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20532,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20532,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20532,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20532,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20532,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20532,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20532,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20532,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20539,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20539,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20539,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20539,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20539,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20539,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20539,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20539,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20539,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20539,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20539,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20539,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20539,], ["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 +328,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",20532,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20532,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20539,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20539,], ["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",20532,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20532,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20532,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20532,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20532,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20532,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20532,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20532,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20532,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20532,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20539,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20539,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20539,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20539,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20539,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20539,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20539,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20539,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20539,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20539,], ["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,], @@ -368,48 +368,48 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating_Action_Buttons_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",20532,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20532,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20532,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20539,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20539,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20539,], ["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",20532,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20532,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20539,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20539,], ["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",20532,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20532,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20532,], -["features.home.impl.spaces_HomeSpacesView_Day_3_en","features.home.impl.spaces_HomeSpacesView_Night_3_en",20532,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20532,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20532,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20539,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20539,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20539,], +["features.home.impl.spaces_HomeSpacesView_Day_3_en","features.home.impl.spaces_HomeSpacesView_Night_3_en",20539,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20539,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20539,], ["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",20532,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20532,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20539,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20539,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20532,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20532,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20539,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20539,], ["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",20532,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20532,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20532,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20532,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20532,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20532,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20532,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20532,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20532,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20532,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20532,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20532,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20532,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20539,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20539,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20539,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20539,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20539,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20539,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20539,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20539,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20539,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20539,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20539,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20539,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20539,], ["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 +424,8 @@ export const screenshots = [ ["appicon.enterprise_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",20532,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20532,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20539,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20539,], ["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 +433,117 @@ 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",20532,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20539,], ["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",20532,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20539,], ["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",20532,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20532,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20539,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20539,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20532,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20532,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20539,], ["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",20532,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20532,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20532,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20539,], ["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",20532,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20532,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20532,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20532,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20539,], ["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",20532,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20532,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20532,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20532,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20532,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20532,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20532,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20532,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20539,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20539,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20539,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20539,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20539,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20539,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20539,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20539,], ["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",20532,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20532,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20532,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20532,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20532,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20539,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20539,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20539,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20532,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20532,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20539,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20539,], ["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",20532,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20532,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20532,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20532,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20532,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20532,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20532,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20532,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20539,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20539,], ["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",20532,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20532,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20532,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20532,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20532,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20532,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20539,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20539,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20539,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20539,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20539,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20539,], ["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",20532,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20539,], ["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,41 +598,43 @@ 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",20532,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20532,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20532,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20532,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20539,], +["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",20539,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20539,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20539,], ["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",20532,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20532,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20532,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20532,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20532,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20532,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20532,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20532,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20532,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20532,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20532,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20532,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20532,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20532,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20532,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20532,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20532,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20532,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20532,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20532,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20532,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20532,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20532,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20532,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20532,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20539,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20539,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20539,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20539,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20539,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20539,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20539,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20539,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20539,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20539,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20539,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20539,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20539,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20539,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20539,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20539,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20539,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20539,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20539,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20539,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20539,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20539,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20539,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20539,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20539,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20532,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20532,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20532,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20532,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20539,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20539,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20539,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20539,], ["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,], @@ -646,22 +648,22 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20532,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20532,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20539,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20539,], ["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",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20532,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20532,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20539,], ["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,], @@ -669,14 +671,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20532,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20532,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20539,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20539,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20532,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20539,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20532,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20539,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -690,7 +692,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",20532,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20539,], ["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,], @@ -699,7 +701,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",20532,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20539,], ["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,], @@ -708,23 +710,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20532,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20532,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20532,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20532,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20532,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20532,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20532,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20532,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20532,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20532,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20532,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20532,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20532,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20532,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20532,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20539,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20539,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20539,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20539,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20539,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20539,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20539,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20539,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20539,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20539,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20539,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20539,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20539,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20539,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20539,], ["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",20532,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20539,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -735,113 +737,112 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20532,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20532,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20532,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20539,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20539,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20539,], ["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",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20532,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20532,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20539,], ["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",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20532,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20539,], ["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",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20532,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20532,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20539,], ["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",20532,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20532,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20532,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20532,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20532,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20532,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20539,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20539,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20539,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20539,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20539,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20539,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], -["libraries.designsystem.components_PinIcon_Day_0_en","libraries.designsystem.components_PinIcon_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",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20532,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20532,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20539,], ["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",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20532,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20532,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20532,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20532,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20532,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20532,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20539,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20539,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20539,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20539,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20539,], ["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",20532,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20532,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20532,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20532,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20532,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20539,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20539,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20539,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20539,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20539,], ["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",20532,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20532,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20532,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20532,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20532,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20532,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20532,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20532,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20532,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20532,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20532,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20539,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20539,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20539,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20539,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20539,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20539,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20539,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20539,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20539,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20539,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20539,], ["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,], @@ -855,215 +856,215 @@ 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","",20532,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20532,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20532,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20532,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20539,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20539,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20539,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20539,], ["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","",20532,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20532,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20539,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20539,], ["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",20532,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20532,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20532,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20532,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20532,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20532,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20532,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20532,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20532,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20532,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20532,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20532,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20532,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20532,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20532,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20532,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20532,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20532,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20532,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20532,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20532,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20539,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20539,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20539,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20539,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20539,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20539,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20539,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20539,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20539,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20539,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20539,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20539,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20539,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20539,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20539,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20539,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20539,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20539,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20539,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20539,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20539,], ["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",20532,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20532,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20539,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20539,], ["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",20532,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20532,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20532,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20532,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20532,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20532,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20532,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20539,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20539,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20539,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20539,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20539,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20539,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20539,], ["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",20532,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20532,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20532,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20532,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20532,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20532,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20532,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20532,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20532,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20532,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20532,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20532,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20532,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20532,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20532,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20532,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20532,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20539,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20539,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20539,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20539,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20539,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20539,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20539,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20539,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20539,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20539,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20539,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20539,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20539,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20539,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20539,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20539,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20539,], ["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",20532,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20532,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20532,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20532,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20532,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20539,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20539,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20539,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20539,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20539,], ["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",20532,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20532,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20539,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20539,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20532,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20532,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20532,], -["features.roomdetails.impl_RoomDetails_0_en","",20532,], -["features.roomdetails.impl_RoomDetails_10_en","",20532,], -["features.roomdetails.impl_RoomDetails_11_en","",20532,], -["features.roomdetails.impl_RoomDetails_12_en","",20532,], -["features.roomdetails.impl_RoomDetails_13_en","",20532,], -["features.roomdetails.impl_RoomDetails_14_en","",20532,], -["features.roomdetails.impl_RoomDetails_15_en","",20532,], -["features.roomdetails.impl_RoomDetails_16_en","",20532,], -["features.roomdetails.impl_RoomDetails_17_en","",20532,], -["features.roomdetails.impl_RoomDetails_18_en","",20532,], -["features.roomdetails.impl_RoomDetails_19_en","",20532,], -["features.roomdetails.impl_RoomDetails_1_en","",20532,], -["features.roomdetails.impl_RoomDetails_20_en","",20532,], -["features.roomdetails.impl_RoomDetails_21_en","",20532,], -["features.roomdetails.impl_RoomDetails_22_en","",20532,], -["features.roomdetails.impl_RoomDetails_2_en","",20532,], -["features.roomdetails.impl_RoomDetails_3_en","",20532,], -["features.roomdetails.impl_RoomDetails_4_en","",20532,], -["features.roomdetails.impl_RoomDetails_5_en","",20532,], -["features.roomdetails.impl_RoomDetails_6_en","",20532,], -["features.roomdetails.impl_RoomDetails_7_en","",20532,], -["features.roomdetails.impl_RoomDetails_8_en","",20532,], -["features.roomdetails.impl_RoomDetails_9_en","",20532,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20532,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20532,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20532,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20532,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20532,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20532,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20532,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20532,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20532,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20539,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20539,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20539,], +["features.roomdetails.impl_RoomDetails_0_en","",20539,], +["features.roomdetails.impl_RoomDetails_10_en","",20539,], +["features.roomdetails.impl_RoomDetails_11_en","",20539,], +["features.roomdetails.impl_RoomDetails_12_en","",20539,], +["features.roomdetails.impl_RoomDetails_13_en","",20539,], +["features.roomdetails.impl_RoomDetails_14_en","",20539,], +["features.roomdetails.impl_RoomDetails_15_en","",20539,], +["features.roomdetails.impl_RoomDetails_16_en","",20539,], +["features.roomdetails.impl_RoomDetails_17_en","",20539,], +["features.roomdetails.impl_RoomDetails_18_en","",20539,], +["features.roomdetails.impl_RoomDetails_19_en","",20539,], +["features.roomdetails.impl_RoomDetails_1_en","",20539,], +["features.roomdetails.impl_RoomDetails_20_en","",20539,], +["features.roomdetails.impl_RoomDetails_21_en","",20539,], +["features.roomdetails.impl_RoomDetails_22_en","",20539,], +["features.roomdetails.impl_RoomDetails_2_en","",20539,], +["features.roomdetails.impl_RoomDetails_3_en","",20539,], +["features.roomdetails.impl_RoomDetails_4_en","",20539,], +["features.roomdetails.impl_RoomDetails_5_en","",20539,], +["features.roomdetails.impl_RoomDetails_6_en","",20539,], +["features.roomdetails.impl_RoomDetails_7_en","",20539,], +["features.roomdetails.impl_RoomDetails_8_en","",20539,], +["features.roomdetails.impl_RoomDetails_9_en","",20539,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20539,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20539,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20539,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20539,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20539,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20539,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20539,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20539,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20539,], ["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",20532,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20532,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20532,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20532,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20532,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20532,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20532,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20532,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20532,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20539,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20539,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20539,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20539,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20539,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20539,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20539,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20539,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20539,], ["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",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20532,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20532,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20532,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20539,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20539,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20539,], ["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",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20532,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20532,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20539,], ["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",20532,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20532,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20532,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20532,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20532,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20532,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20539,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20539,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20539,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20539,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20539,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20539,], ["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,], @@ -1086,16 +1087,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20532,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20532,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20539,], ["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",20532,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20539,], ["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,], @@ -1103,118 +1104,118 @@ 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",20532,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20532,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20532,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20539,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20539,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20539,], ["appicon.enterprise_RoundIcon_en","",0,], ["appicon.element_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",20532,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20532,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20532,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20532,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20532,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20532,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20532,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20532,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20539,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20539,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20539,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20539,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20539,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20539,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20539,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20539,], ["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","",20532,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20539,], ["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","",20532,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20532,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20532,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20532,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20532,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20532,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20532,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20532,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20532,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20532,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20532,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20532,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20532,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20532,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20532,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20539,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20539,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20539,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20539,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20539,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20539,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20539,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20539,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20539,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20539,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20539,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20539,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20539,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20539,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20539,], ["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,], @@ -1228,11 +1229,6 @@ export const screenshots = [ ["libraries.matrix.ui.components_SelectedUser_Day_1_en","libraries.matrix.ui.components_SelectedUser_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButtonIcon_Day_0_en","libraries.textcomposer.components_SendButtonIcon_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",20532,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",20532,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",20532,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",20532,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",20532,], ["libraries.matrix.ui.messages.sender_SenderName_Day_0_en","libraries.matrix.ui.messages.sender_SenderName_Night_0_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_1_en","libraries.matrix.ui.messages.sender_SenderName_Night_1_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_2_en","libraries.matrix.ui.messages.sender_SenderName_Night_2_en",0,], @@ -1242,28 +1238,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",20532,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20532,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20532,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20532,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20532,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20532,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20532,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20532,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20539,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20539,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20539,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20539,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20539,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20539,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20539,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20539,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20542,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20542,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20542,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20542,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20542,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20542,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20542,], ["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",20532,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20532,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20532,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20532,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20532,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20532,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20532,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20532,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20532,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20532,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20532,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20539,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20539,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20539,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20539,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20539,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20539,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20539,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20539,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20539,], ["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,], @@ -1273,107 +1274,107 @@ 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",20532,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20539,], ["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",20532,], +["features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en","features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en",20539,], ["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",20532,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20532,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20532,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20539,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20539,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20539,], ["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",20532,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20539,], ["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",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20532,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20532,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20532,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20532,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20532,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20532,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20532,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20532,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20532,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20532,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20532,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20532,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20532,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20532,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20532,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20539,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20539,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20539,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20539,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20539,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20539,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20539,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20539,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20539,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20539,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20539,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20539,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20539,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20539,], ["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",20532,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20532,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20532,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20532,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20532,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20532,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20532,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20539,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20539,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20539,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20539,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20539,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20539,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20539,], ["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",20532,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20539,], ["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",20532,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20539,], ["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",20532,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20532,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20532,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20532,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20532,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20532,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20532,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20532,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20532,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20532,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20532,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20532,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20532,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20532,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20532,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20539,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20539,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20539,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20539,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20539,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20539,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20539,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20539,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20539,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20539,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20539,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20539,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20539,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20539,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20539,], ["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",20532,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20532,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20539,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20539,], ["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,], @@ -1385,16 +1386,16 @@ 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",20532,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20532,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20532,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20532,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20532,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20539,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20539,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20539,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20539,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20539,], ["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",20532,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20532,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20539,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20539,], ["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,], @@ -1404,18 +1405,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",20532,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20539,], ["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",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20532,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20539,], ["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,], @@ -1423,18 +1424,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",20532,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20532,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20539,], ["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",20532,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20532,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20532,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20539,], ["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",20532,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20532,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20539,], ["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,], @@ -1443,41 +1444,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",20532,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20539,], ["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",20532,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20539,], ["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",20532,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20539,], ["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","",20532,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20539,], ["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",20532,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20532,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20539,], ["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",20532,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20539,], ["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_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20532,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20532,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20532,], +["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",20539,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20539,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20539,], ["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",20532,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20532,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20539,], ["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",20532,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20539,], ["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,], @@ -1486,8 +1488,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",20532,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20532,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20539,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20539,], ["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,], @@ -1502,8 +1504,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",20532,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20532,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20539,], ["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,], @@ -1526,85 +1528,85 @@ 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",20532,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",0,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20532,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20532,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20542,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20539,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20539,], +["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",20539,], ["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",20532,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20539,], ["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",20532,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20539,], ["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",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20532,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20532,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20539,], ["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",20532,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20532,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20532,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20532,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20532,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20532,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20539,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20539,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20539,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20539,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20539,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20539,], ["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","",20532,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20539,], ["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",20532,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20532,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20532,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20532,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20539,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20539,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20539,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20539,], ["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",20532,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20539,], ["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",20532,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20539,], ["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",20532,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20532,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20532,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20532,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20532,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20532,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20532,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20532,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20532,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20532,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20532,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20532,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20532,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20539,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20539,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20539,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20539,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20539,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20539,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20539,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20539,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20539,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20539,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20539,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20539,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20539,], ["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.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20532,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20532,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20539,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20539,], ["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",20532,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20539,], ["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/libraries.designsystem.components_LocationPin_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png index 8dda833412..fcc2640262 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f3df9c9de000b15692b982c7d69f85ce3d03cab468c342773c88eff3b4fca65 -size 9082 +oid sha256:4d8c17c2e421452f57e4679111569054e1ed1bacc952cc1df4c7efe1f67c47ef +size 13158 From be461516a74bcd53ffe25618b812485c78002dfc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:49:20 +0200 Subject: [PATCH 0024/1083] fix(deps): update dependency com.google.crypto.tink:tink-android to v1.21.0 (#6499) 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 86db5a9d73..3f16060207 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -84,7 +84,7 @@ google_firebase_bom = "com.google.firebase:firebase-bom:34.11.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } -google_tink = "com.google.crypto.tink:tink-android:1.20.0" +google_tink = "com.google.crypto.tink:tink-android:1.21.0" # AndroidX androidx_core = { module = "androidx.core:core", version.ref = "core" } From 579bc7db62f7baec38e0537db92c5c55ee011333 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 31 Mar 2026 16:57:37 +0200 Subject: [PATCH 0025/1083] Try fixing location pin previews (#6495) * Try fixing location pin previews * Update screenshots --------- Co-authored-by: ElementBot Co-authored-by: Benoit Marty --- .../designsystem/components/LocationPin.kt | 57 ++++++++++++------- ....impl.share_ShareLocationView_Day_5_en.png | 4 +- ...mpl.share_ShareLocationView_Night_5_en.png | 4 +- ...system.components_LocationPin_Day_0_en.png | 4 +- ...stem.components_LocationPin_Night_0_en.png | 4 +- 5 files changed, 46 insertions(+), 27 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt index af8e29d518..9e783d605c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt @@ -32,9 +32,13 @@ import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp +import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.createBitmap +import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.withSave import coil3.Image import coil3.ImageLoader @@ -50,6 +54,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData 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.utils.CommonDrawables private val PIN_WIDTH = 42.dp private val PIN_HEIGHT = PIN_WIDTH * 1.2f @@ -99,21 +104,33 @@ fun LocationPin( fun rememberLocationPinBitmap(variant: PinVariant): ImageBitmap? { val context = LocalContext.current val density = LocalDensity.current - val imageLoader = SingletonImageLoader.get(context) val colors = pinColors(variant) val cacheKey = rememberCacheKey(variant) - return produceState(initialValue = null, cacheKey) { - val memoryCacheKey = MemoryCache.Key(cacheKey) - val cached = imageLoader.memoryCache?.get(memoryCacheKey) - if (cached != null) { - value = cached.image.toBitmap().asImageBitmap() - } else { - val dimensions = PinDimensions(density) - val bitmap = LocationPinRenderer.renderPin(variant, colors, dimensions, context, imageLoader) - imageLoader.memoryCache?.set(memoryCacheKey, MemoryCache.Value(bitmap.asImage())) - value = bitmap.asImageBitmap() - } - }.value + val resources = LocalResources.current + + return if (LocalInspectionMode.current) { + // In preview mode, skip async loading and return a simple placeholder image instead to avoid using ImageLoader + val dimensions = PinDimensions(density) + val avatarImage = ResourcesCompat.getDrawable(resources, CommonDrawables.sample_avatar, context.theme)?.toBitmap()?.asImage() + LocationPinRenderer.renderPin(variant, colors, dimensions, avatarImage).asImageBitmap() + } else { + produceState(initialValue = null, cacheKey) { + val imageLoader = SingletonImageLoader.get(context) + val memoryCacheKey = MemoryCache.Key(cacheKey) + val cached = imageLoader.memoryCache?.get(memoryCacheKey) + if (cached != null) { + value = cached.image.toBitmap().asImageBitmap() + } else { + val dimensions = PinDimensions(density) + val bitmap = with(LocationPinRenderer) { + val avatarImage = loadAvatarImage(variant, context, imageLoader) + renderPin(variant, colors, dimensions, avatarImage) + } + imageLoader.memoryCache?.set(memoryCacheKey, MemoryCache.Value(bitmap.asImage())) + value = bitmap.asImageBitmap() + } + }.value + } } @Composable @@ -208,19 +225,17 @@ private object LocationPinRenderer { /** * Renders a pin variant to bitmap. Suspending for async avatar loading. */ - suspend fun renderPin( + fun renderPin( variant: PinVariant, colors: PinColors, dimensions: PinDimensions, - context: Context, - imageLoader: ImageLoader, + avatarImage: Image?, ): Bitmap { val bitmap = createBitmap(dimensions.pinWidth.toInt(), dimensions.pinHeight.toInt()) val canvas = Canvas(bitmap) canvas.drawPinShape(colors.fill, colors.stroke, dimensions) when (variant) { is PinVariant.UserLocation -> { - val avatarImage = loadAvatarImage(variant.avatarData, context, imageLoader) canvas.drawAvatar( avatarImage = avatarImage, avatarData = variant.avatarData, @@ -284,11 +299,15 @@ private object LocationPinRenderer { return path } - private suspend fun loadAvatarImage( - avatarData: AvatarData, + suspend fun loadAvatarImage( + variant: PinVariant, context: Context, imageLoader: ImageLoader, ): Image? { + val avatarData = when (variant) { + is PinVariant.UserLocation -> variant.avatarData + else -> return null + } val request = ImageRequest.Builder(context) .data(avatarData) // Disable hardware rendering for Canvas diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png index 69aea3df2a..74d6ac15ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ba1418b5d42a56db47e7cc574cedb886c75d9cf22828341bd954a4f1845670e -size 17925 +oid sha256:2621fef4175ad0f0982270284ffbbdb6b3b0534b09013c1cc378504a85d13068 +size 22385 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png index 060f25819e..d79bfca142 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d786937d790e13b53a5de8ae3321e5aa8744a979a3a99ecc36def6b7dbf6cf60 -size 17237 +oid sha256:69bcf19161f70c27256c1bf0e5b99c993c86dd3e77a42d0e87061730a5c0c752 +size 21649 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png index fcc2640262..c049cff102 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d8c17c2e421452f57e4679111569054e1ed1bacc952cc1df4c7efe1f67c47ef -size 13158 +oid sha256:ca6415ca7f858146a4c00e2fa1d9602fd9f3d42c0c8ba9830e121769af80676a +size 17255 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png index dac3588ed9..8074748111 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components_LocationPin_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9767298a096be7fc78210245e6b806a72a6c1ad16d7335e0f89728bbcf08ebd4 -size 15884 +oid sha256:d89b754907f98ef1df2cf227ec535cdad91dc15e90b4915039be39d8b2ae2ebd +size 16721 From 87184328eb922449f9a5c5ded7d7b1439201d7c9 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 31 Mar 2026 18:45:10 +0200 Subject: [PATCH 0026/1083] Fix crash when using `View.hideKeyboardAndAwaitAnimation` (#6502) * Fix crash when using `View.hideKeyboardAndAwaitAnimation` Remove the `View.OnApplyWindowInsetsListener` used in modern Android versions to detect if the insets changed after they do the first time: this is a single use operation and the listener will be called every time the insets change Also, replace `Mutex` with `CompletableDeferred` so it doesn't matter if it's called several times, we only care about the first one. * Don't try to hide the keyboard if it's already hidden. Also, add a 1s timeout in case everything goes wrong and we somehow never complete the future. --- .../android/libraries/androidutils/ui/View.kt | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt index ae724a7c44..5f19cba136 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt @@ -16,9 +16,11 @@ import android.view.ViewTreeObserver import android.view.WindowInsets import android.view.inputmethod.InputMethodManager import androidx.core.content.getSystemService +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.withTimeoutOrNull import kotlin.coroutines.resume +import kotlin.time.Duration.Companion.seconds fun View.hideKeyboard() { val imm = context?.getSystemService() @@ -26,29 +28,39 @@ fun View.hideKeyboard() { } suspend fun View.hideKeyboardAndAwaitAnimation() { - val imm = context?.getSystemService() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !rootWindowInsets.isVisible(WindowInsets.Type.ime())) { + // Keyboard is already hidden, no need to do anything + return + } - val mutex = Mutex() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val imm = context?.getSystemService() ?: return + val future = CompletableDeferred() + + val requested = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { setOnApplyWindowInsetsListener { view, insets -> if (!insets.isVisible(WindowInsets.Type.ime())) { - mutex.unlock() + future.complete(Unit) + // Remove the listener now, it's a single use operation + setOnApplyWindowInsetsListener(null) } insets } - imm?.hideSoftInputFromWindow(windowToken, 0) + imm.hideSoftInputFromWindow(windowToken, 0) } else { @Suppress("DEPRECATION") - imm?.hideSoftInputFromWindow(windowToken, 0, object : ResultReceiver(null) { + imm.hideSoftInputFromWindow(windowToken, 0, object : ResultReceiver(null) { override fun onReceiveResult(resultCode: Int, resultData: Bundle?) { - if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN || - resultCode == InputMethodManager.RESULT_HIDDEN) { - mutex.unlock() + if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN || resultCode == InputMethodManager.RESULT_HIDDEN) { + future.complete(Unit) } } }) } - mutex.lock() + + if (requested) { + // Await the future to ensure the keyboard hide animation has completed before proceeding + withTimeoutOrNull(1.seconds) { future.await() } + } } fun View.showKeyboard(andRequestFocus: Boolean = false) { From bd618ccba6e67ee085bbefdafb85a92218747129 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 1 Apr 2026 11:06:28 +0200 Subject: [PATCH 0027/1083] Fix content scrolling not working in the RTE (#6492) Implement a `customDetectVerticalDragGestures` that matches the original `detectVerticalDragGestures` expect we conditionally consume the initial DOWN event in compose to decide whether we need to drag the bottom sheet or scroll inside the Android `EditText` --- .../components/ExpandableBottomSheetLayout.kt | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt index 85307823f6..f70ed3b344 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ExpandableBottomSheetLayout.kt @@ -16,7 +16,10 @@ import android.widget.EditText import androidx.appcompat.app.ActionBar.LayoutParams import androidx.compose.animation.core.Animatable import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.detectVerticalDragGestures +import androidx.compose.foundation.gestures.awaitEachGesture +import androidx.compose.foundation.gestures.awaitFirstDown +import androidx.compose.foundation.gestures.awaitVerticalPointerSlopOrCancellation +import androidx.compose.foundation.gestures.verticalDrag import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column @@ -41,10 +44,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.input.pointer.PointerInputChange +import androidx.compose.ui.input.pointer.PointerInputScope import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.input.pointer.positionChange import androidx.compose.ui.layout.Layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview @@ -94,7 +101,7 @@ fun ExpandableBottomSheetLayout( .run { if (isSwipeGestureEnabled) { pointerInput(maxBottomSheetContentHeight) { - detectVerticalDragGestures( + customDetectVerticalDragGestures( onVerticalDrag = { _, dragAmount -> val calculatedHeight = max(minBottomContentHeightPx, currentBottomContentHeightPx - dragAmount.roundToInt()) val newHeight = min(calculatedMaxBottomContentHeightPx, calculatedHeight) @@ -120,7 +127,11 @@ fun ExpandableBottomSheetLayout( animatable.animateTo(destination) } - } + }, + canScroll = { + // We only consider we can scroll in the contents if the min size matches the max size so it's maximized + minBottomContentHeightPx == calculatedMaxBottomContentHeightPx + }, ) } } else { @@ -189,6 +200,45 @@ fun ExpandableBottomSheetLayout( ) } +// The original detectVerticalDragGestures doesn't allow us to conditionally consume the initial slop event that triggers the drag, +// which is necessary in our case to allow inner scrollables to work when the sheet is not fully expanded, so we need to re-implement it here +private suspend fun PointerInputScope.customDetectVerticalDragGestures( + onDragStart: (Offset) -> Unit = {}, + onDragEnd: () -> Unit = {}, + onDragCancel: () -> Unit = {}, + canScroll: () -> Boolean = { false }, + onVerticalDrag: (change: PointerInputChange, dragAmount: Float) -> Unit, +) { + awaitEachGesture { + val down = awaitFirstDown(requireUnconsumed = false) + var overSlop = 0f + val drag = + awaitVerticalPointerSlopOrCancellation(down.id, down.type) { change, over -> + // Consuming this event is what triggers the dragging instead of the inner content scrolling + // We should only consume it if we can't scroll in the inner content so we drag the bottom sheet instead, otherwise we let it pass through + // This is the only change compared to the original detectVerticalDragGestures implementation + if (!canScroll()) { + change.consume() + } + overSlop = over + } + if (drag != null) { + onDragStart.invoke(drag.position) + onVerticalDrag.invoke(drag, overSlop) + if ( + verticalDrag(drag.id) { + onVerticalDrag(it, it.positionChange().y) + it.consume() + } + ) { + onDragEnd() + } else { + onDragCancel() + } + } + } +} + @Preview(showBackground = true) @Composable @Suppress("UnusedPrivateMember") From 07d3152ca14e10d9742dddcbebfdfb4d23fd27d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 11:30:24 +0200 Subject: [PATCH 0028/1083] fix(deps): update dependency com.posthog:posthog-android to v3.39.0 (#6504) 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 3f16060207..3bc5cb31c3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -220,7 +220,7 @@ haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics -posthog = "com.posthog:posthog-android:3.37.0" +posthog = "com.posthog:posthog-android:3.39.0" sentry = "io.sentry:sentry-android:8.36.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 410a3d132be7fc294aa7a56097b8946d8acd2c88 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 1 Apr 2026 12:45:57 +0200 Subject: [PATCH 0029/1083] Add floating/sticky date badge in the timeline (#6496) * Add floating date indicator while scrolling the timeline (#6433) * Add `FeatureFlags.FloatingDateBadge`. This enables displaying the floating date badge in the timeline as you scroll. * Don't display the floating badge if the timeline isn't reversed. Otherwise, this will affect talkback users and break the existing navigation * Use `TimelineItem.formattedDate()` to get the date to display. Always try finding the closest one (usually it will be just the 1st one we try). * Align designs with iOS. Also fix shadows in fade animation by adding some paddings. * Update screenshots --------- Co-authored-by: Gianluca Iavicoli Co-authored-by: ElementBot --- .../features/messages/impl/MessagesView.kt | 6 + .../impl/timeline/TimelinePresenter.kt | 4 + .../messages/impl/timeline/TimelineState.kt | 1 + .../impl/timeline/TimelineStateProvider.kt | 2 + .../messages/impl/timeline/TimelineView.kt | 12 ++ .../timeline/components/FloatingDateBadge.kt | 144 ++++++++++++++++++ .../event/TimelineItemEventFactory.kt | 6 + .../impl/timeline/model/TimelineItem.kt | 8 + .../designsystem/theme/ColorAliases.kt | 3 + .../libraries/featureflag/api/FeatureFlags.kt | 9 +- ....components_FloatingDateBadge_Day_0_en.png | 3 + ...omponents_FloatingDateBadge_Night_0_en.png | 3 + 12 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/FloatingDateBadge.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en.png diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 0caebea8d5..8e81ee74a7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role @@ -464,6 +465,9 @@ private fun MessagesViewContent( val scrollBehavior = PinnedMessagesBannerViewDefaults.rememberScrollBehavior( pinnedMessagesCount = (state.pinnedMessagesBannerState as? PinnedMessagesBannerState.Visible)?.pinnedMessagesCount() ?: 0, ) + val density = LocalDensity.current + var pinnedBannerHeightDp by remember { mutableStateOf(0.dp) } + TimelineView( state = state.timelineState, timelineProtectionState = state.timelineProtectionState, @@ -479,11 +483,13 @@ private fun MessagesViewContent( forceJumpToBottomVisibility = forceJumpToBottomVisibility, onJoinCallClick = onJoinCallClick, nestedScrollConnection = scrollBehavior.nestedScrollConnection, + floatingDateTopOffset = pinnedBannerHeightDp, ) if (state.timelineState.timelineMode !is Timeline.Mode.Thread) { AnimatedVisibility( visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, + modifier = Modifier.onSizeChanged { pinnedBannerHeightDp = with(density) { it.height.toDp() } }, enter = expandVertically(), exit = shrinkVertically(), ) { 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..8a7011552e 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 @@ -149,6 +149,9 @@ class TimelinePresenter( val displayThreadSummaries by produceState(false) { value = featureFlagService.isFeatureEnabled(FeatureFlags.Threads) } + val displayFloatingDateBadge by produceState(false) { + value = featureFlagService.isFeatureEnabled(FeatureFlags.FloatingDateBadge) + } fun handleEvent(event: TimelineEvent) { when (event) { @@ -315,6 +318,7 @@ class TimelinePresenter( messageShieldDialogData = messageShieldDialogData.value, resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, + displayFloatingDateBadge = displayFloatingDateBadge, eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 03f0083856..1869ad6906 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -34,6 +34,7 @@ data class TimelineState( val messageShieldDialogData: MessageShieldData?, val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val displayThreadSummaries: Boolean, + val displayFloatingDateBadge: Boolean, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 184acf1386..9840ac5107 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -56,6 +56,7 @@ fun aTimelineState( messageShield: MessageShield? = null, resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), displayThreadSummaries: Boolean = false, + displayFloatingDateBadge: Boolean = false, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId @@ -75,6 +76,7 @@ fun aTimelineState( messageShieldDialogData = messageShield?.let { MessageShieldData(it) }, resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, + displayFloatingDateBadge = displayFloatingDateBadge, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 08a7191f3f..0137b1736d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -47,10 +47,12 @@ import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.Dp 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.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureView +import io.element.android.features.messages.impl.timeline.components.FloatingDateBadgeOverlay import io.element.android.features.messages.impl.timeline.components.TimelineItemRow import io.element.android.features.messages.impl.timeline.components.toText import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories @@ -105,6 +107,7 @@ fun TimelineView( lazyListState: LazyListState = rememberLazyListState(), forceJumpToBottomVisibility: Boolean = false, nestedScrollConnection: NestedScrollConnection = rememberNestedScrollInteropConnection(), + floatingDateTopOffset: Dp = 0.dp, ) { fun clearFocusRequestState() { state.eventSink(TimelineEvent.ClearFocusRequestState) @@ -210,6 +213,15 @@ fun TimelineView( onJumpToLive = ::onJumpToLive, onFocusEventRender = ::onFocusEventRender, ) + + if (state.displayFloatingDateBadge && useReverseLayout) { + FloatingDateBadgeOverlay( + lazyListState = lazyListState, + timelineItems = state.timelineItems, + isLive = state.isLive, + topOffset = floatingDateTopOffset, + ) + } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/FloatingDateBadge.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/FloatingDateBadge.kt new file mode 100644 index 0000000000..996bb07b81 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/FloatingDateBadge.kt @@ -0,0 +1,144 @@ +/* + * 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.features.messages.impl.timeline.components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Surface +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.floatingDateBadgeBackground +import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest +import kotlin.time.Duration.Companion.milliseconds + +@Composable +internal fun BoxScope.FloatingDateBadgeOverlay( + lazyListState: LazyListState, + timelineItems: ImmutableList, + isLive: Boolean, + topOffset: Dp = 0.dp, +) { + // This needs to be a state to trigger a `derivedState` recalculation + val updatedTimelineItems by rememberUpdatedState(timelineItems) + + // Look for the last visible item with a timestamp, starting from the last visible item and going backwards until we find one or reach the start of the list + val lastVisibleItemWithTimestamp by remember { + derivedStateOf { + var index = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf null + while (index >= 0) { + when (val item = updatedTimelineItems.getOrNull(index)) { + is TimelineItem.Event -> return@derivedStateOf item + is TimelineItem.Virtual -> if (item.model is TimelineItemDaySeparatorModel) return@derivedStateOf item + is TimelineItem.GroupedEvents -> return@derivedStateOf item.events.firstOrNull() + null -> Unit + } + index-- + } + null + } + } + + // Store the formatted date so we recompute it lazily and can keep it around even if we need to dispose the badge because the timeline items changed + var formattedDate: String? by remember { mutableStateOf(null) } + // Update the formatted date when we have a new non-null timestamp + LaunchedEffect(lastVisibleItemWithTimestamp) { + lastVisibleItemWithTimestamp?.formattedDate()?.let { formattedDate = it } + } + + val isAtBottom by remember { + derivedStateOf { + lazyListState.firstVisibleItemIndex < 3 && isLive + } + } + + var isBadgeVisible by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + snapshotFlow { lazyListState.isScrollInProgress } + .collectLatest { isScrolling -> + if (isScrolling) { + isBadgeVisible = true + } else { + delay(2000.milliseconds) + isBadgeVisible = false + } + } + } + + val showBadge = isBadgeVisible && !isAtBottom && formattedDate != null + + AnimatedVisibility( + visible = showBadge, + modifier = Modifier + .align(Alignment.TopCenter) + .padding(top = 8.dp + topOffset), + enter = fadeIn(animationSpec = tween(150)), + exit = fadeOut(animationSpec = tween(300)), + ) { + formattedDate?.let { dateText -> + FloatingDateBadge( + modifier = Modifier.padding(8.dp), + dateText = dateText, + ) + } + } +} + +@Composable +internal fun FloatingDateBadge( + dateText: String, + modifier: Modifier = Modifier, +) { + Surface( + modifier = modifier, + shape = RoundedCornerShape(16.dp), + color = ElementTheme.colors.floatingDateBadgeBackground, + shadowElevation = 4.dp, + ) { + Text( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), + text = dateText, + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } +} + +@PreviewsDayNight +@Composable +internal fun FloatingDateBadgePreview() = ElementPreview { + Box(modifier = Modifier.padding(16.dp)) { + FloatingDateBadge(dateText = "March 9, 2026") + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index 366c88157e..cf515a0b51 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -66,6 +66,11 @@ class TimelineItemEventFactory( timestamp = currentTimelineItem.event.timestamp, mode = DateFormatterMode.TimeOnly, ) + val sentDate = dateFormatter.format( + timestamp = currentTimelineItem.event.timestamp, + mode = DateFormatterMode.Day, + useRelative = true, + ) val senderAvatarData = AvatarData( id = currentSender.value, name = senderProfile.getDisambiguatedDisplayName(currentSender), @@ -108,6 +113,7 @@ class TimelineItemEventFactory( canBeRepliedTo = currentTimelineItem.event.canBeRepliedTo, sentTimeMillis = currentTimelineItem.event.timestamp, sentTime = sentTime, + sentDate = sentDate, groupPosition = groupPosition, reactionsState = currentTimelineItem.computeReactionsState(), readReceiptState = currentTimelineItem.computeReadReceiptState(roomMembers), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index e169b10403..c9adba21da 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -15,6 +15,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent +import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.api.core.EventId @@ -59,6 +60,12 @@ sealed interface TimelineItem { is GroupedEvents -> "groupedEvent" } + fun formattedDate(): String? = when (this) { + is Event -> sentDate.takeIf { it.isNotEmpty() } + is Virtual -> (model as? TimelineItemDaySeparatorModel)?.formattedDate?.takeIf { it.isNotEmpty() } + is GroupedEvents -> null + } + data class Virtual( val id: UniqueId, val model: TimelineItemVirtualModel @@ -75,6 +82,7 @@ sealed interface TimelineItem { val content: TimelineItemEventContent, val sentTimeMillis: Long = 0L, val sentTime: String = "", + val sentDate: String = "", val isMine: Boolean = false, val isEditable: Boolean, val canBeRepliedTo: Boolean, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt index 06827fb218..8973e312ce 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt @@ -75,6 +75,9 @@ val SemanticColors.pinnedMessageBannerIndicator val SemanticColors.pinnedMessageBannerBorder get() = if (isLight) LightColorTokens.colorAlphaGray400 else DarkColorTokens.colorAlphaGray400 +val SemanticColors.floatingDateBadgeBackground + get() = if (isLight) bgCanvasDefault else bgSubtlePrimary + @PreviewsDayNight @Composable internal fun ColorAliasesPreview() = ElementPreview { 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..9fe21a10c3 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 @@ -156,10 +156,17 @@ enum class FeatureFlags( ), ValidateNetworkWhenSchedulingNotificationFetching( key = "feature.validate_network_when_scheduling_notification_fetching", - title = "validate internet connectivity when scheduling notification fetching", + title = "Validate internet connectivity when scheduling notification fetching", description = "Only fetch events for push notifications when the device has internet connectivity. " + "Enabling this can be problematic in air-gapped environments.", defaultValue = { true }, isFinished = false, ), + FloatingDateBadge( + key = "feature.floating_date_badge", + title = "Display sticky date headers in the timeline", + description = "When scrolling, a sticky date badge will be displayed so you can easily know on which date the messages you're seeing were sent.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en.png new file mode 100644 index 0000000000..73693b6b51 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8109af7397a43f24a27b7c988f7b6bd23e555df038ff9a272068707796a60962 +size 8465 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en.png new file mode 100644 index 0000000000..042d482550 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25ba3336d226da0fb5956750b02f389c59b81c93e6150d8fb17d5195fd161204 +size 7705 From 556c793b8d5913396aa894068a14290642a637b7 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 1 Apr 2026 13:30:01 +0200 Subject: [PATCH 0030/1083] CI: yet another Maestro fix (#6505) * Fix the `assertSessionVerificationDisplayed.yaml` check * Previous 'Location' is now 'Share location' * We don't have a GPS location, so the text is 'Share selected location' * 'Create a new conversation' is now 'Create room' * Try adding a background logcat process * 'Sign out' is now 'Remove this device' * Adjust the logcat filtering so it silences everything that's not our app, otherwise the logs can get quite large --- .../scripts/maestro/maestro-local-with-screen-recording.sh | 3 +++ .maestro/tests/account/logout.yaml | 6 +++--- .../assertions/assertSessionVerificationDisplayed.yaml | 2 +- .maestro/tests/roomList/createAndDeleteDM.yaml | 2 +- .maestro/tests/roomList/createAndDeleteRoom.yaml | 2 +- .maestro/tests/roomList/timeline/messages/location.yaml | 4 ++-- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/scripts/maestro/maestro-local-with-screen-recording.sh b/.github/workflows/scripts/maestro/maestro-local-with-screen-recording.sh index 51a968fdec..4ee021c316 100755 --- a/.github/workflows/scripts/maestro/maestro-local-with-screen-recording.sh +++ b/.github/workflows/scripts/maestro/maestro-local-with-screen-recording.sh @@ -19,6 +19,9 @@ adb install -r $1 echo "Starting the screen recording..." adb push .github/workflows/scripts/maestro/local-recording.sh /data/local/tmp/ adb shell "chmod +x /data/local/tmp/local-recording.sh" +mkdir -p ~/.maestro/tests +# Start logcat in the background and save the output to a file, use `org.matrix.rust.sdk` tag since the SDK handles the logging +adb logcat 'org.matrix.rust.sdk:D *:S' > ~/.maestro/tests/logcat.txt & adb shell "/data/local/tmp/local-recording.sh & echo \$! > /data/local/tmp/screenrecord_pid.txt" & set +e ~/.maestro/bin/maestro test .maestro/allTests.yaml diff --git a/.maestro/tests/account/logout.yaml b/.maestro/tests/account/logout.yaml index f27f5dada3..a276182825 100644 --- a/.maestro/tests/account/logout.yaml +++ b/.maestro/tests/account/logout.yaml @@ -2,14 +2,14 @@ appId: ${MAESTRO_APP_ID} --- - tapOn: id: "home_screen-settings" -- tapOn: "Sign out" +- tapOn: "Remove this device" - takeScreenshot: build/maestro/900-SignOutScreen - back -- tapOn: "Sign out" +- tapOn: "Remove this device" # Ensure cancel cancels - tapOn: id: "dialog-negative" -- tapOn: "Sign out" +- tapOn: "Remove this device" - tapOn: id: "dialog-positive" - runFlow: ../assertions/assertInitDisplayed.yaml diff --git a/.maestro/tests/assertions/assertSessionVerificationDisplayed.yaml b/.maestro/tests/assertions/assertSessionVerificationDisplayed.yaml index fff0fe7b32..d2160e0934 100644 --- a/.maestro/tests/assertions/assertSessionVerificationDisplayed.yaml +++ b/.maestro/tests/assertions/assertSessionVerificationDisplayed.yaml @@ -1,5 +1,5 @@ appId: ${MAESTRO_APP_ID} --- - extendedWaitUntil: - visible: "Confirm your identity" + visible: "Confirm your digital identity" timeout: 60000 diff --git a/.maestro/tests/roomList/createAndDeleteDM.yaml b/.maestro/tests/roomList/createAndDeleteDM.yaml index e80dc377b5..a6279151ea 100644 --- a/.maestro/tests/roomList/createAndDeleteDM.yaml +++ b/.maestro/tests/roomList/createAndDeleteDM.yaml @@ -1,7 +1,7 @@ appId: ${MAESTRO_APP_ID} --- # Purpose: Test the creation and deletion of a DM room. -- tapOn: "Create a new conversation or room" +- tapOn: "Create room" - tapOn: "Search for someone" - inputText: ${MAESTRO_INVITEE1_MXID} - tapOn: diff --git a/.maestro/tests/roomList/createAndDeleteRoom.yaml b/.maestro/tests/roomList/createAndDeleteRoom.yaml index d0b17133d5..b53066ccd5 100644 --- a/.maestro/tests/roomList/createAndDeleteRoom.yaml +++ b/.maestro/tests/roomList/createAndDeleteRoom.yaml @@ -1,7 +1,7 @@ appId: ${MAESTRO_APP_ID} --- # Purpose: Test the creation and deletion of a room -- tapOn: "Create a new conversation or room" +- tapOn: "Create room" - tapOn: "New room" - tapOn: "Add name…" - inputText: "aRoomName" diff --git a/.maestro/tests/roomList/timeline/messages/location.yaml b/.maestro/tests/roomList/timeline/messages/location.yaml index c9382bd30c..863a699fd9 100644 --- a/.maestro/tests/roomList/timeline/messages/location.yaml +++ b/.maestro/tests/roomList/timeline/messages/location.yaml @@ -2,6 +2,6 @@ appId: ${MAESTRO_APP_ID} --- - takeScreenshot: build/maestro/520-Timeline - tapOn: "Add attachment" -- tapOn: "Location" -- tapOn: "Share my location" +- tapOn: "Share location" +- tapOn: "Share selected location" - takeScreenshot: build/maestro/521-Timeline From e2d418beb899cdf7cabf8359c722d5275d6a8bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 1 Apr 2026 13:37:57 +0200 Subject: [PATCH 0031/1083] Setting version for the release 26.04.0 --- plugins/src/main/kotlin/Versions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 618587d2bd..4fbc3fb20c 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -39,13 +39,13 @@ private const val versionYear = 26 * Month of the version on 2 digits. Value must be in [1,12]. * Do not update this value. it is updated by the release script. */ -private const val versionMonth = 3 +private const val versionMonth = 4 /** * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 4 +private const val versionReleaseNumber = 0 object Versions { /** From 6f59e91a92c492156e0671fd7b3b2941e71ef394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 1 Apr 2026 13:42:04 +0200 Subject: [PATCH 0032/1083] Adding fastlane file for version 26.04.0 --- fastlane/metadata/android/en-US/changelogs/202604000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202604000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202604000.txt b/fastlane/metadata/android/en-US/changelogs/202604000.txt new file mode 100644 index 0000000000..26b1479a0d --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202604000.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes for crashes from the SDK and notifications and UI improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases From df456cf9212181644a2ba47925ff7707dd4e3de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 1 Apr 2026 14:30:38 +0200 Subject: [PATCH 0033/1083] Changelog for version 26.04.0 --- CHANGES.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1b002992fb..37c4e23d0a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,49 @@ +Changes in Element X v26.04.0 +============================= + +## What's Changed +### ✨ Features +* Add floating/sticky date badge in the timeline by @kalix127 in https://github.com/element-hq/element-x-android/pull/6496 +### 🐛 Bugfixes +* Fix `ForegroundServiceDidNotStartInTimeException` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6470 +* Fix media cover placeholder floating by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6484 +* Try handling `ForegroundServiceStartNotAllowedException` better by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6483 +* Fix crash when using `View.hideKeyboardAndAwaitAnimation` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6502 +* Fix content scrolling not working in the RTE by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6492 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6486 +### 🧱 Build +* Add instructions for AI by @bmarty in https://github.com/element-hq/element-x-android/pull/6468 +* Fix permissions to publish GitHub pages. by @bmarty in https://github.com/element-hq/element-x-android/pull/6500 +* Try fixing location pin previews by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6495 +* CI: yet another Maestro fix by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6505 +### 📄 Documentation +* Add some instructions for features to the community PR notice message by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6465 +### 🚧 In development 🚧 +* Setup live location sharing feature by @ganfra in https://github.com/element-hq/element-x-android/pull/6342 +### Dependency upgrades +* Update dependency io.sentry:sentry-android to v8.36.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6461 +* Update metro to v0.11.4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6448 +* Sync compound tokens https://github.com/element-hq/compound-design-tokens/releases/tag/v8.0.0 by @bmarty in https://github.com/element-hq/element-x-android/pull/6459 +* Update sqldelight to v2.3.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6449 +* Update nschloe/action-cached-lfs-checkout action to v1.2.4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6442 +* Update kotlin to v2.3.20 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6437 +* Update dependency io.element.android:element-call-embedded to v0.18.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6358 +* fix(deps): update dependency io.element.android:emojibase-bindings to v1.5.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6474 +* fix(deps): update dependency com.google.firebase:firebase-bom to v34.11.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6478 +* fix(deps): update dependency io.element.android:emojibase-bindings to v1.5.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6487 +* fix(deps): update dependency com.google.crypto.tink:tink-android to v1.21.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6499 +* fix(deps): update dependency com.posthog:posthog-android to v3.39.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6504 +* fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v26.03.31 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6494 +### Others +* Iterate on space header by @bmarty in https://github.com/element-hq/element-x-android/pull/6456 +* Add margin after bullet points by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6446 +* chore: update the build-rust-sdk script by @bnjbvr in https://github.com/element-hq/element-x-android/pull/6476 +* Update replied message UI by @bmarty in https://github.com/element-hq/element-x-android/pull/6472 + + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.03.4...v26.04.0 + Changes in Element X v26.03.4 ============================= From a44cf4335b62f2579eec2f3de50bde8ee8a817f5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:13:07 +0200 Subject: [PATCH 0034/1083] chore(deps): update gradle/actions action to v6 (#6489) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/maestro-local.yml | 2 +- .github/workflows/nightlyReports.yml | 4 ++-- .github/workflows/quality.yml | 12 ++++++------ .github/workflows/recordScreenshots.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/sonar.yml | 2 +- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/tests.yml | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e33ba607e..7e5f16200a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,7 +56,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug APKs diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index b7912b2b72..71195ff163 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -61,7 +61,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug Gplay Enterprise APK diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 5006cc44b5..8780cd7c7b 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -23,7 +23,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index f320230584..c5587f40c1 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -50,7 +50,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug APK diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index ae5c72a3d9..10d41f5d1a 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -43,7 +43,7 @@ jobs: java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: false @@ -85,7 +85,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Dependency analysis diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 7845be8323..a1c7bd3c70 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -74,7 +74,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 @@ -113,7 +113,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Konsist tests @@ -154,7 +154,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run compose tests @@ -188,7 +188,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Build Gplay Debug @@ -233,7 +233,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Detekt @@ -274,7 +274,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Ktlint check diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 189ae26cf3..4bec9643c5 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -59,7 +59,7 @@ jobs: java-version: '21' # Add gradle cache, this should speed up the process - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Record screenshots diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f9df37160..b5514a72f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 - name: Create app bundle env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} @@ -87,7 +87,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 - name: Create Enterprise app bundle env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} @@ -131,7 +131,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 - name: Create APKs env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index d945b18f5c..347d99c0f7 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -50,7 +50,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Build debug code and test fixtures diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 914bf4b35c..e37076b9de 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -22,7 +22,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 602ad1e18e..f4205758c1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,7 +68,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} From 10d7ba900a8dfc3bfaa0a5299df3d545dd5162dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:34:03 +0200 Subject: [PATCH 0035/1083] fix(deps): update dependency androidx.work:work-runtime-ktx to v2.11.2 (#6479) 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 3ab675a239..fecf589792 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ lifecycle = "2.10.0" activity = "1.13.0" media3 = "1.9.3" camera = "1.5.3" -work = "2.11.1" +work = "2.11.2" # Compose compose_bom = "2026.03.00" From 0f5283520fd588aec9bea9813824c54f266bae13 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:35:01 +0200 Subject: [PATCH 0036/1083] Update dependency net.zetetic:sqlcipher-android to v4.14.0 (#6460) 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 fecf589792..19e21b96bf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -200,7 +200,7 @@ matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } -sqlcipher = "net.zetetic:sqlcipher-android:4.13.0" +sqlcipher = "net.zetetic:sqlcipher-android:4.14.0" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" unifiedpush = "org.unifiedpush.android:connector:3.3.2" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" From 212e7390e1d303acce1e9cc80ea0113e616307c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:44:32 +0200 Subject: [PATCH 0037/1083] fix(deps): update metro to v0.12.0 (#6503) 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 19e21b96bf..9f8878440b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.6.1" # DI -metro = "0.11.4" +metro = "0.12.0" # Auto service autoservice = "1.1.1" From fe05c272327575e615c333b30ede4fc1724a85ca Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 1 Apr 2026 18:08:32 +0200 Subject: [PATCH 0038/1083] Import token v10.0.0./tools/compound/import_tokens.sh -b v10.0.0 --- libraries/compound/src/main/assets/theme.iife.js | 2 +- .../android/compound/tokens/generated/CompoundIcons.kt | 5 ----- .../android/compound/tokens/generated/SemanticColors.kt | 4 ++++ .../android/compound/tokens/generated/SemanticColorsDark.kt | 2 ++ .../compound/tokens/generated/SemanticColorsDarkHc.kt | 2 ++ .../android/compound/tokens/generated/SemanticColorsLight.kt | 2 ++ .../compound/tokens/generated/SemanticColorsLightHc.kt | 2 ++ 7 files changed, 13 insertions(+), 6 deletions(-) diff --git a/libraries/compound/src/main/assets/theme.iife.js b/libraries/compound/src/main/assets/theme.iife.js index 1dd693cbd4..e7205e4f81 100644 --- a/libraries/compound/src/main/assets/theme.iife.js +++ b/libraries/compound/src/main/assets/theme.iife.js @@ -1 +1 @@ -var CompoundTheme=(function($t){"use strict";const{min:oi,max:si}=Math,qt=(e,t=0,r=1)=>oi(si(t,e),r),xe=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=qt(e[t],0,255)):t===3&&(e[t]=qt(e[t],0,1));return e},fn={};for(let e of["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"])fn[`[object ${e}]`]=e.toLowerCase();function N(e){return fn[Object.prototype.toString.call(e)]||"object"}const E=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):N(e[0])=="object"&&t?t.split("").filter(r=>e[0][r]!==void 0).map(r=>e[0][r]):e[0].slice(0),Et=e=>{if(e.length<2)return null;const t=e.length-1;return N(e[t])=="string"?e[t].toLowerCase():null},{PI:Wt,min:hn,max:dn}=Math,et=e=>Math.round(e*100)/100,Ce=e=>Math.round(e*100)/100,ft=Wt*2,ke=Wt/3,ii=Wt/180,ai=180/Wt;function bn(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}const $={format:{},autodetect:[]};let _=class{constructor(...t){const r=this;if(N(t[0])==="object"&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];let n=Et(t),o=!1;if(!n){o=!0,$.sorted||($.autodetect=$.autodetect.sort((i,s)=>s.p-i.p),$.sorted=!0);for(let i of $.autodetect)if(n=i.test(...t),n)break}if($.format[n]){const i=$.format[n].apply(null,o?t:t.slice(0,-1));r._rgb=xe(i)}else throw new Error("unknown format: "+t);r._rgb.length===3&&r._rgb.push(1)}toString(){return N(this.hex)=="function"?this.hex():`[${this._rgb.join(",")}]`}};const ci="3.2.0",k=(...e)=>new _(...e);k.version=ci;const Lt={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},ui=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,li=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,pn=e=>{if(e.match(ui)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const t=parseInt(e,16),r=t>>16,n=t>>8&255,o=t&255;return[r,n,o,1]}if(e.match(li)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(""),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);const t=parseInt(e,16),r=t>>24&255,n=t>>16&255,o=t>>8&255,i=Math.round((t&255)/255*100)/100;return[r,n,o,i]}throw new Error(`unknown hex color: ${e}`)},{round:Ut}=Math,mn=(...e)=>{let[t,r,n,o]=E(e,"rgba"),i=Et(e)||"auto";o===void 0&&(o=1),i==="auto"&&(i=o<1?"rgba":"rgb"),t=Ut(t),r=Ut(r),n=Ut(n);let a="000000"+(t<<16|r<<8|n).toString(16);a=a.substr(a.length-6);let c="0"+Ut(o*255).toString(16);switch(c=c.substr(c.length-2),i.toLowerCase()){case"rgba":return`#${a}${c}`;case"argb":return`#${c}${a}`;default:return`#${a}`}};_.prototype.name=function(){const e=mn(this._rgb,"rgb");for(let t of Object.keys(Lt))if(Lt[t]===e)return t.toLowerCase();return e},$.format.named=e=>{if(e=e.toLowerCase(),Lt[e])return pn(Lt[e]);throw new Error("unknown color name: "+e)},$.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&N(e)==="string"&&Lt[e.toLowerCase()])return"named"}}),_.prototype.alpha=function(e,t=!1){return e!==void 0&&N(e)==="number"?t?(this._rgb[3]=e,this):new _([this._rgb[0],this._rgb[1],this._rgb[2],e],"rgb"):this._rgb[3]},_.prototype.clipped=function(){return this._rgb._clipped||!1};const ct={Kn:18,labWhitePoint:"d65",Xn:.95047,Yn:1,Zn:1.08883,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},fi=new Map([["a",[1.0985,.35585]],["b",[1.0985,.35585]],["c",[.98074,1.18232]],["d50",[.96422,.82521]],["d55",[.95682,.92149]],["d65",[.95047,1.08883]],["e",[1,1,1]],["f2",[.99186,.67393]],["f7",[.95041,1.08747]],["f11",[1.00962,.6435]],["icc",[.96422,.82521]]]);function ht(e){const t=fi.get(String(e).toLowerCase());if(!t)throw new Error("unknown Lab illuminant "+e);ct.labWhitePoint=e,ct.Xn=t[0],ct.Zn=t[1]}function Kt(){return ct.labWhitePoint}const Re=(...e)=>{e=E(e,"lab");const[t,r,n]=e,[o,i,s]=hi(t,r,n),[a,c,u]=gn(o,i,s);return[a,c,u,e.length>3?e[3]:1]},hi=(e,t,r)=>{const{kE:n,kK:o,kKE:i,Xn:s,Yn:a,Zn:c}=ct,u=(e+16)/116,f=.002*t+u,l=u-.005*r,h=f*f*f,d=l*l*l,b=h>n?h:(116*f-16)/o,g=e>i?Math.pow((e+16)/116,3):e/o,m=d>n?d:(116*l-16)/o,y=b*s,L=g*a,w=m*c;return[y,L,w]},qe=e=>{const t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*Math.pow(e,1/2.4)-.055)*t},gn=(e,t,r)=>{const{MtxAdaptMa:n,MtxAdaptMaI:o,MtxXYZ2RGB:i,RefWhiteRGB:s,Xn:a,Yn:c,Zn:u}=ct,f=a*n.m00+c*n.m10+u*n.m20,l=a*n.m01+c*n.m11+u*n.m21,h=a*n.m02+c*n.m12+u*n.m22,d=s.X*n.m00+s.Y*n.m10+s.Z*n.m20,b=s.X*n.m01+s.Y*n.m11+s.Z*n.m21,g=s.X*n.m02+s.Y*n.m12+s.Z*n.m22,m=(e*n.m00+t*n.m10+r*n.m20)*(d/f),y=(e*n.m01+t*n.m11+r*n.m21)*(b/l),L=(e*n.m02+t*n.m12+r*n.m22)*(g/h),w=m*o.m00+y*o.m10+L*o.m20,x=m*o.m01+y*o.m11+L*o.m21,S=m*o.m02+y*o.m12+L*o.m22,R=qe(w*i.m00+x*i.m10+S*i.m20),M=qe(w*i.m01+x*i.m11+S*i.m21),p=qe(w*i.m02+x*i.m12+S*i.m22);return[R*255,M*255,p*255]},Me=(...e)=>{const[t,r,n,...o]=E(e,"rgb"),[i,s,a]=_n(t,r,n),[c,u,f]=di(i,s,a);return[c,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]};function di(e,t,r){const{Xn:n,Yn:o,Zn:i,kE:s,kK:a}=ct,c=e/n,u=t/o,f=r/i,l=c>s?Math.pow(c,1/3):(a*c+16)/116,h=u>s?Math.pow(u,1/3):(a*u+16)/116,d=f>s?Math.pow(f,1/3):(a*f+16)/116;return[116*h-16,500*(l-h),200*(h-d)]}function Oe(e){const t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4))*t}const _n=(e,t,r)=>{e=Oe(e/255),t=Oe(t/255),r=Oe(r/255);const{MtxRGB2XYZ:n,MtxAdaptMa:o,MtxAdaptMaI:i,Xn:s,Yn:a,Zn:c,As:u,Bs:f,Cs:l}=ct;let h=e*n.m00+t*n.m10+r*n.m20,d=e*n.m01+t*n.m11+r*n.m21,b=e*n.m02+t*n.m12+r*n.m22;const g=s*o.m00+a*o.m10+c*o.m20,m=s*o.m01+a*o.m11+c*o.m21,y=s*o.m02+a*o.m12+c*o.m22;let L=h*o.m00+d*o.m10+b*o.m20,w=h*o.m01+d*o.m11+b*o.m21,x=h*o.m02+d*o.m12+b*o.m22;return L*=g/u,w*=m/f,x*=y/l,h=L*i.m00+w*i.m10+x*i.m20,d=L*i.m01+w*i.m11+x*i.m21,b=L*i.m02+w*i.m12+x*i.m22,[h,d,b]};_.prototype.lab=function(){return Me(this._rgb)},Object.assign(k,{lab:(...e)=>new _(...e,"lab"),getLabWhitePoint:Kt,setLabWhitePoint:ht}),$.format.lab=Re,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"lab"),N(e)==="array"&&e.length===3)return"lab"}}),_.prototype.darken=function(e=1){const t=this,r=t.lab();return r[0]-=ct.Kn*e,new _(r,"lab").alpha(t.alpha(),!0)},_.prototype.brighten=function(e=1){return this.darken(-e)},_.prototype.darker=_.prototype.darken,_.prototype.brighter=_.prototype.brighten,_.prototype.get=function(e){const[t,r]=e.split("."),n=this[t]();if(r){const o=t.indexOf(r)-(t.substr(0,2)==="ok"?2:0);if(o>-1)return n[o];throw new Error(`unknown channel ${r} in mode ${t}`)}else return n};const{pow:bi}=Math,pi=1e-7,mi=20;_.prototype.luminance=function(e,t="rgb"){if(e!==void 0&&N(e)==="number"){if(e===0)return new _([0,0,0,this._rgb[3]],"rgb");if(e===1)return new _([255,255,255,this._rgb[3]],"rgb");let r=this.luminance(),n=mi;const o=(s,a)=>{const c=s.interpolate(a,.5,t),u=c.luminance();return Math.abs(e-u)e?o(s,c):o(c,a)},i=(r>e?o(new _([0,0,0]),this):o(this,new _([255,255,255]))).rgb();return new _([...i,this._rgb[3]])}return gi(...this._rgb.slice(0,3))};const gi=(e,t,r)=>(e=Ae(e),t=Ae(t),r=Ae(r),.2126*e+.7152*t+.0722*r),Ae=e=>(e/=255,e<=.03928?e/12.92:bi((e+.055)/1.055,2.4)),H={},Nt=(e,t,r=.5,...n)=>{let o=n[0]||"lrgb";if(!H[o]&&!n.length&&(o=Object.keys(H)[0]),!H[o])throw new Error(`interpolation mode ${o} is not defined`);return N(e)!=="object"&&(e=new _(e)),N(t)!=="object"&&(t=new _(t)),H[o](e,t,r).alpha(e.alpha()+r*(t.alpha()-e.alpha()))};_.prototype.mix=_.prototype.interpolate=function(e,t=.5,...r){return Nt(this,e,t,...r)},_.prototype.premultiply=function(e=!1){const t=this._rgb,r=t[3];return e?(this._rgb=[t[0]*r,t[1]*r,t[2]*r,r],this):new _([t[0]*r,t[1]*r,t[2]*r,r],"rgb")};const{sin:_i,cos:vi}=Math,vn=(...e)=>{let[t,r,n]=E(e,"lch");return isNaN(n)&&(n=0),n=n*ii,[t,vi(n)*r,_i(n)*r]},Se=(...e)=>{e=E(e,"lch");const[t,r,n]=e,[o,i,s]=vn(t,r,n),[a,c,u]=Re(o,i,s);return[a,c,u,e.length>3?e[3]:1]},yi=(...e)=>{const t=bn(E(e,"hcl"));return Se(...t)},{sqrt:wi,atan2:xi,round:Ci}=Math,yn=(...e)=>{const[t,r,n]=E(e,"lab"),o=wi(r*r+n*n);let i=(xi(n,r)*ai+360)%360;return Ci(o*1e4)===0&&(i=Number.NaN),[t,o,i]},$e=(...e)=>{const[t,r,n,...o]=E(e,"rgb"),[i,s,a]=Me(t,r,n),[c,u,f]=yn(i,s,a);return[c,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]};_.prototype.lch=function(){return $e(this._rgb)},_.prototype.hcl=function(){return bn($e(this._rgb))},Object.assign(k,{lch:(...e)=>new _(...e,"lch"),hcl:(...e)=>new _(...e,"hcl")}),$.format.lch=Se,$.format.hcl=yi,["lch","hcl"].forEach(e=>$.autodetect.push({p:2,test:(...t)=>{if(t=E(t,e),N(t)==="array"&&t.length===3)return e}})),_.prototype.saturate=function(e=1){const t=this,r=t.lch();return r[1]+=ct.Kn*e,r[1]<0&&(r[1]=0),new _(r,"lch").alpha(t.alpha(),!0)},_.prototype.desaturate=function(e=1){return this.saturate(-e)},_.prototype.set=function(e,t,r=!1){const[n,o]=e.split("."),i=this[n]();if(o){const s=n.indexOf(o)-(n.substr(0,2)==="ok"?2:0);if(s>-1){if(N(t)=="string")switch(t.charAt(0)){case"+":i[s]+=+t;break;case"-":i[s]+=+t;break;case"*":i[s]*=+t.substr(1);break;case"/":i[s]/=+t.substr(1);break;default:i[s]=+t}else if(N(t)==="number")i[s]=t;else throw new Error("unsupported value for Color.set");const a=new _(i,n);return r?(this._rgb=a._rgb,this):a}throw new Error(`unknown channel ${o} in mode ${n}`)}else return i},_.prototype.tint=function(e=.5,...t){return Nt(this,"white",e,...t)},_.prototype.shade=function(e=.5,...t){return Nt(this,"black",e,...t)};const ki=(e,t,r)=>{const n=e._rgb,o=t._rgb;return new _(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"rgb")};H.rgb=ki;const{sqrt:Ee,pow:Tt}=Math,Ri=(e,t,r)=>{const[n,o,i]=e._rgb,[s,a,c]=t._rgb;return new _(Ee(Tt(n,2)*(1-r)+Tt(s,2)*r),Ee(Tt(o,2)*(1-r)+Tt(a,2)*r),Ee(Tt(i,2)*(1-r)+Tt(c,2)*r),"rgb")};H.lrgb=Ri;const qi=(e,t,r)=>{const n=e.lab(),o=t.lab();return new _(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"lab")};H.lab=qi;const jt=(e,t,r,n)=>{let o,i;n==="hsl"?(o=e.hsl(),i=t.hsl()):n==="hsv"?(o=e.hsv(),i=t.hsv()):n==="hcg"?(o=e.hcg(),i=t.hcg()):n==="hsi"?(o=e.hsi(),i=t.hsi()):n==="lch"||n==="hcl"?(n="hcl",o=e.hcl(),i=t.hcl()):n==="oklch"&&(o=e.oklch().reverse(),i=t.oklch().reverse());let s,a,c,u,f,l;(n.substr(0,1)==="h"||n==="oklch")&&([s,c,f]=o,[a,u,l]=i);let h,d,b,g;return!isNaN(s)&&!isNaN(a)?(a>s&&a-s>180?g=a-(s+360):a180?g=a+360-s:g=a-s,d=s+r*g):isNaN(s)?isNaN(a)?d=Number.NaN:(d=a,(f==1||f==0)&&n!="hsv"&&(h=u)):(d=s,(l==1||l==0)&&n!="hsv"&&(h=c)),h===void 0&&(h=c+r*(u-c)),b=f+r*(l-f),n==="oklch"?new _([b,h,d],n):new _([d,h,b],n)},wn=(e,t,r)=>jt(e,t,r,"lch");H.lch=wn,H.hcl=wn;const Mi=e=>{if(N(e)=="number"&&e>=0&&e<=16777215){const t=e>>16,r=e>>8&255,n=e&255;return[t,r,n,1]}throw new Error("unknown num color: "+e)},Oi=(...e)=>{const[t,r,n]=E(e,"rgb");return(t<<16)+(r<<8)+n};_.prototype.num=function(){return Oi(this._rgb)},Object.assign(k,{num:(...e)=>new _(...e,"num")}),$.format.num=Mi,$.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&N(e[0])==="number"&&e[0]>=0&&e[0]<=16777215)return"num"}});const Ai=(e,t,r)=>{const n=e.num(),o=t.num();return new _(n+r*(o-n),"num")};H.num=Ai;const{floor:Si}=Math,$i=(...e)=>{e=E(e,"hcg");let[t,r,n]=e,o,i,s;n=n*255;const a=r*255;if(r===0)o=i=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const c=Si(t),u=t-c,f=n*(1-r),l=f+a*(1-u),h=f+a*u,d=f+a;switch(c){case 0:[o,i,s]=[d,h,f];break;case 1:[o,i,s]=[l,d,f];break;case 2:[o,i,s]=[f,d,h];break;case 3:[o,i,s]=[f,l,d];break;case 4:[o,i,s]=[h,f,d];break;case 5:[o,i,s]=[d,f,l];break}}return[o,i,s,e.length>3?e[3]:1]},Ei=(...e)=>{const[t,r,n]=E(e,"rgb"),o=hn(t,r,n),i=dn(t,r,n),s=i-o,a=s*100/255,c=o/(255-s)*100;let u;return s===0?u=Number.NaN:(t===i&&(u=(r-n)/s),r===i&&(u=2+(n-t)/s),n===i&&(u=4+(t-r)/s),u*=60,u<0&&(u+=360)),[u,a,c]};_.prototype.hcg=function(){return Ei(this._rgb)};const Li=(...e)=>new _(...e,"hcg");k.hcg=Li,$.format.hcg=$i,$.autodetect.push({p:1,test:(...e)=>{if(e=E(e,"hcg"),N(e)==="array"&&e.length===3)return"hcg"}});const Ni=(e,t,r)=>jt(e,t,r,"hcg");H.hcg=Ni;const{cos:Pt}=Math,Ti=(...e)=>{e=E(e,"hsi");let[t,r,n]=e,o,i,s;return isNaN(t)&&(t=0),isNaN(r)&&(r=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(s=(1-r)/3,o=(1+r*Pt(ft*t)/Pt(ke-ft*t))/3,i=1-(s+o)):t<2/3?(t-=1/3,o=(1-r)/3,i=(1+r*Pt(ft*t)/Pt(ke-ft*t))/3,s=1-(o+i)):(t-=2/3,i=(1-r)/3,s=(1+r*Pt(ft*t)/Pt(ke-ft*t))/3,o=1-(i+s)),o=qt(n*o*3),i=qt(n*i*3),s=qt(n*s*3),[o*255,i*255,s*255,e.length>3?e[3]:1]},{min:ji,sqrt:Pi,acos:zi}=Math,Bi=(...e)=>{let[t,r,n]=E(e,"rgb");t/=255,r/=255,n/=255;let o;const i=ji(t,r,n),s=(t+r+n)/3,a=s>0?1-i/s:0;return a===0?o=NaN:(o=(t-r+(t-n))/2,o/=Pi((t-r)*(t-r)+(t-n)*(r-n)),o=zi(o),n>r&&(o=ft-o),o/=ft),[o*360,a,s]};_.prototype.hsi=function(){return Bi(this._rgb)};const Ii=(...e)=>new _(...e,"hsi");k.hsi=Ii,$.format.hsi=Ti,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"hsi"),N(e)==="array"&&e.length===3)return"hsi"}});const Gi=(e,t,r)=>jt(e,t,r,"hsi");H.hsi=Gi;const Le=(...e)=>{e=E(e,"hsl");const[t,r,n]=e;let o,i,s;if(r===0)o=i=s=n*255;else{const a=[0,0,0],c=[0,0,0],u=n<.5?n*(1+r):n+r-n*r,f=2*n-u,l=t/360;a[0]=l+1/3,a[1]=l,a[2]=l-1/3;for(let h=0;h<3;h++)a[h]<0&&(a[h]+=1),a[h]>1&&(a[h]-=1),6*a[h]<1?c[h]=f+(u-f)*6*a[h]:2*a[h]<1?c[h]=u:3*a[h]<2?c[h]=f+(u-f)*(2/3-a[h])*6:c[h]=f;[o,i,s]=[c[0]*255,c[1]*255,c[2]*255]}return e.length>3?[o,i,s,e[3]]:[o,i,s,1]},xn=(...e)=>{e=E(e,"rgba");let[t,r,n]=e;t/=255,r/=255,n/=255;const o=hn(t,r,n),i=dn(t,r,n),s=(i+o)/2;let a,c;return i===o?(a=0,c=Number.NaN):a=s<.5?(i-o)/(i+o):(i-o)/(2-i-o),t==i?c=(r-n)/(i-o):r==i?c=2+(n-t)/(i-o):n==i&&(c=4+(t-r)/(i-o)),c*=60,c<0&&(c+=360),e.length>3&&e[3]!==void 0?[c,a,s,e[3]]:[c,a,s]};_.prototype.hsl=function(){return xn(this._rgb)};const Fi=(...e)=>new _(...e,"hsl");k.hsl=Fi,$.format.hsl=Le,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"hsl"),N(e)==="array"&&e.length===3)return"hsl"}});const Ki=(e,t,r)=>jt(e,t,r,"hsl");H.hsl=Ki;const{floor:Xi}=Math,Di=(...e)=>{e=E(e,"hsv");let[t,r,n]=e,o,i,s;if(n*=255,r===0)o=i=s=n;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;const a=Xi(t),c=t-a,u=n*(1-r),f=n*(1-r*c),l=n*(1-r*(1-c));switch(a){case 0:[o,i,s]=[n,l,u];break;case 1:[o,i,s]=[f,n,u];break;case 2:[o,i,s]=[u,n,l];break;case 3:[o,i,s]=[u,f,n];break;case 4:[o,i,s]=[l,u,n];break;case 5:[o,i,s]=[n,u,f];break}}return[o,i,s,e.length>3?e[3]:1]},{min:Vi,max:Yi}=Math,Zi=(...e)=>{e=E(e,"rgb");let[t,r,n]=e;const o=Vi(t,r,n),i=Yi(t,r,n),s=i-o;let a,c,u;return u=i/255,i===0?(a=Number.NaN,c=0):(c=s/i,t===i&&(a=(r-n)/s),r===i&&(a=2+(n-t)/s),n===i&&(a=4+(t-r)/s),a*=60,a<0&&(a+=360)),[a,c,u]};_.prototype.hsv=function(){return Zi(this._rgb)};const Ji=(...e)=>new _(...e,"hsv");k.hsv=Ji,$.format.hsv=Di,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"hsv"),N(e)==="array"&&e.length===3)return"hsv"}});const Hi=(e,t,r)=>jt(e,t,r,"hsv");H.hsv=Hi;function Qt(e,t){let r=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(s=>[s]));let n=t[0].length,o=t[0].map((s,a)=>t.map(c=>c[a])),i=e.map(s=>o.map(a=>Array.isArray(s)?s.reduce((c,u,f)=>c+u*(a[f]||0),0):a.reduce((c,u)=>c+u*s,0)));return r===1&&(i=i[0]),n===1?i.map(s=>s[0]):i}const Ne=(...e)=>{e=E(e,"lab");const[t,r,n,...o]=e,[i,s,a]=Wi([t,r,n]),[c,u,f]=gn(i,s,a);return[c,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]};function Wi(e){var t=[[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],r=[[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],n=Qt(r,e);return Qt(t,n.map(o=>o**3))}const Te=(...e)=>{const[t,r,n,...o]=E(e,"rgb"),i=_n(t,r,n);return[...Ui(i),...o.length>0&&o[0]<1?[o[0]]:[]]};function Ui(e){const t=[[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],r=[[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],n=Qt(t,e);return Qt(r,n.map(o=>Math.cbrt(o)))}_.prototype.oklab=function(){return Te(this._rgb)},Object.assign(k,{oklab:(...e)=>new _(...e,"oklab")}),$.format.oklab=Ne,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"oklab"),N(e)==="array"&&e.length===3)return"oklab"}});const Qi=(e,t,r)=>{const n=e.oklab(),o=t.oklab();return new _(n[0]+r*(o[0]-n[0]),n[1]+r*(o[1]-n[1]),n[2]+r*(o[2]-n[2]),"oklab")};H.oklab=Qi;const ta=(e,t,r)=>jt(e,t,r,"oklch");H.oklch=ta;const{pow:je,sqrt:Pe,PI:ze,cos:Cn,sin:kn,atan2:ea}=Math,ra=(e,t="lrgb",r=null)=>{const n=e.length;r||(r=Array.from(new Array(n)).map(()=>1));const o=n/r.reduce(function(l,h){return l+h});if(r.forEach((l,h)=>{r[h]*=o}),e=e.map(l=>new _(l)),t==="lrgb")return na(e,r);const i=e.shift(),s=i.get(t),a=[];let c=0,u=0;for(let l=0;l{const d=l.get(t);f+=l.alpha()*r[h+1];for(let b=0;b=360;)h-=360;s[l]=h}else s[l]=s[l]/a[l];return f/=n,new _(s,t).alpha(f>.99999?1:f,!0)},na=(e,t)=>{const r=e.length,n=[0,0,0,0];for(let o=0;o.9999999&&(n[3]=1),new _(xe(n))},{pow:oa}=Math;function te(e){let t="rgb",r=k("#ccc"),n=0,o=[0,1],i=[0,1],s=[],a=[0,0],c=!1,u=[],f=!1,l=0,h=1,d=!1,b={},g=!0,m=1;const y=function(p){if(p=p||["#fff","#000"],p&&N(p)==="string"&&k.brewer&&k.brewer[p.toLowerCase()]&&(p=k.brewer[p.toLowerCase()]),N(p)==="array"){p.length===1&&(p=[p[0],p[0]]),p=p.slice(0);for(let C=0;C=c[O];)O++;return O-1}return 0};let w=p=>p,x=p=>p;const S=function(p,C){let O,q;if(C==null&&(C=!1),isNaN(p)||p===null)return r;C?q=p:c&&c.length>2?q=L(p)/(c.length-2):h!==l?q=(p-l)/(h-l):q=1,q=x(q),C||(q=w(q)),m!==1&&(q=oa(q,m)),q=a[0]+q*(1-a[0]-a[1]),q=qt(q,0,1);const T=Math.floor(q*1e4);if(g&&b[T])O=b[T];else{if(N(u)==="array")for(let A=0;A=P&&A===s.length-1){O=u[A];break}if(q>P&&qb={};y(e);const M=function(p){const C=k(S(p));return f&&C[f]?C[f]():C};return M.classes=function(p){if(p!=null){if(N(p)==="array")c=p,o=[p[0],p[p.length-1]];else{const C=k.analyze(o);p===0?c=[C.min,C.max]:c=k.limits(C,"e",p)}return M}return c},M.domain=function(p){if(!arguments.length)return i;i=p.slice(0),l=p[0],h=p[p.length-1],s=[];const C=u.length;if(p.length===C&&l!==h)for(let O of Array.from(p))s.push((O-l)/(h-l));else{for(let O=0;O2){const O=p.map((T,A)=>A/(p.length-1)),q=p.map(T=>(T-l)/(h-l));q.every((T,A)=>O[A]===T)||(x=T=>{if(T<=0||T>=1)return T;let A=0;for(;T>=q[A+1];)A++;const P=(T-q[A])/(q[A+1]-q[A]);return O[A]+P*(O[A+1]-O[A])})}}return o=[l,h],M},M.mode=function(p){return arguments.length?(t=p,R(),M):t},M.range=function(p,C){return y(p),M},M.out=function(p){return f=p,M},M.spread=function(p){return arguments.length?(n=p,M):n},M.correctLightness=function(p){return p==null&&(p=!0),d=p,R(),d?w=function(C){const O=S(0,!0).lab()[0],q=S(1,!0).lab()[0],T=O>q;let A=S(C,!0).lab()[0];const P=O+(q-O)*C;let G=A-P,Y=0,U=1,ut=20;for(;Math.abs(G)>.01&&ut-- >0;)(function(){return T&&(G*=-1),G<0?(Y=C,C+=(U-C)*.5):(U=C,C+=(Y-C)*.5),A=S(C,!0).lab()[0],G=A-P})();return C}:w=C=>C,M},M.padding=function(p){return p!=null?(N(p)==="number"&&(p=[p,p]),a=p,M):a},M.colors=function(p,C){arguments.length<2&&(C="hex");let O=[];if(arguments.length===0)O=u.slice(0);else if(p===1)O=[M(.5)];else if(p>1){const q=o[0],T=o[1]-q;O=sa(0,p).map(A=>M(q+A/(p-1)*T))}else{e=[];let q=[];if(c&&c.length>2)for(let T=1,A=c.length,P=1<=A;P?TA;P?T++:T--)q.push((c[T-1]+c[T])*.5);else q=o;O=q.map(T=>M(T))}return k[C]&&(O=O.map(q=>q[C]())),O},M.cache=function(p){return p!=null?(g=p,M):g},M.gamma=function(p){return p!=null?(m=p,M):m},M.nodata=function(p){return p!=null?(r=k(p),M):r},M}function sa(e,t,r){let n=[],o=ei;o?s++:s--)n.push(s);return n}const ia=function(e){let t=[1,1];for(let r=1;rnew _(i)),e.length===2)[r,n]=e.map(i=>i.lab()),t=function(i){const s=[0,1,2].map(a=>r[a]+i*(n[a]-r[a]));return new _(s,"lab")};else if(e.length===3)[r,n,o]=e.map(i=>i.lab()),t=function(i){const s=[0,1,2].map(a=>(1-i)*(1-i)*r[a]+2*(1-i)*i*n[a]+i*i*o[a]);return new _(s,"lab")};else if(e.length===4){let i;[r,n,o,i]=e.map(s=>s.lab()),t=function(s){const a=[0,1,2].map(c=>(1-s)*(1-s)*(1-s)*r[c]+3*(1-s)*(1-s)*s*n[c]+3*(1-s)*s*s*o[c]+s*s*s*i[c]);return new _(a,"lab")}}else if(e.length>=5){let i,s,a;i=e.map(c=>c.lab()),a=e.length-1,s=ia(a),t=function(c){const u=1-c,f=[0,1,2].map(l=>i.reduce((h,d,b)=>h+s[b]*u**(a-b)*c**b*d[l],0));return new _(f,"lab")}}else throw new RangeError("No point in running bezier with only one color.");return t},ca=e=>{const t=aa(e);return t.scale=()=>te(t),t},{round:Rn}=Math;_.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Rn)},_.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,r)=>r<3?e===!1?t:Rn(t):t)},Object.assign(k,{rgb:(...e)=>new _(...e,"rgb")}),$.format.rgb=(...e)=>{const t=E(e,"rgba");return t[3]===void 0&&(t[3]=1),t},$.autodetect.push({p:3,test:(...e)=>{if(e=E(e,"rgba"),N(e)==="array"&&(e.length===3||e.length===4&&N(e[3])=="number"&&e[3]>=0&&e[3]<=1))return"rgb"}});const nt=(e,t,r)=>{if(!nt[r])throw new Error("unknown blend mode "+r);return nt[r](e,t)},_t=e=>(t,r)=>{const n=k(r).rgb(),o=k(t).rgb();return k.rgb(e(n,o))},vt=e=>(t,r)=>{const n=[];return n[0]=e(t[0],r[0]),n[1]=e(t[1],r[1]),n[2]=e(t[2],r[2]),n},ua=e=>e,la=(e,t)=>e*t/255,fa=(e,t)=>e>t?t:e,ha=(e,t)=>e>t?e:t,da=(e,t)=>255*(1-(1-e/255)*(1-t/255)),ba=(e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)),pa=(e,t)=>255*(1-(1-t/255)/(e/255)),ma=(e,t)=>e===255?255:(e=255*(t/255)/(1-e/255),e>255?255:e);nt.normal=_t(vt(ua)),nt.multiply=_t(vt(la)),nt.screen=_t(vt(da)),nt.overlay=_t(vt(ba)),nt.darken=_t(vt(fa)),nt.lighten=_t(vt(ha)),nt.dodge=_t(vt(ma)),nt.burn=_t(vt(pa));const{pow:ga,sin:_a,cos:va}=Math;function ya(e=300,t=-1.5,r=1,n=1,o=[0,1]){let i=0,s;N(o)==="array"?s=o[1]-o[0]:(s=0,o=[o,o]);const a=function(c){const u=ft*((e+120)/360+t*c),f=ga(o[0]+s*c,n),h=(i!==0?r[0]+c*i:r)*f*(1-f)/2,d=va(u),b=_a(u),g=f+h*(-.14861*d+1.78277*b),m=f+h*(-.29227*d-.90649*b),y=f+h*(1.97294*d);return k(xe([g*255,m*255,y*255,1]))};return a.start=function(c){return c==null?e:(e=c,a)},a.rotations=function(c){return c==null?t:(t=c,a)},a.gamma=function(c){return c==null?n:(n=c,a)},a.hue=function(c){return c==null?r:(r=c,N(r)==="array"?(i=r[1]-r[0],i===0&&(r=r[1])):i=0,a)},a.lightness=function(c){return c==null?o:(N(c)==="array"?(o=c,s=c[1]-c[0]):(o=[c,c],s=0),a)},a.scale=()=>k.scale(a),a.hue(r),a}const wa="0123456789abcdef",{floor:xa,random:Ca}=Math,ka=(e=Ca)=>{let t="#";for(let r=0;r<6;r++)t+=wa.charAt(xa(e()*16));return new _(t,"hex")},{log:qn,pow:Ra,floor:qa,abs:Ma}=Math;function Mn(e,t=null){const r={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return N(e)==="object"&&(e=Object.values(e)),e.forEach(n=>{t&&N(n)==="object"&&(n=n[t]),n!=null&&!isNaN(n)&&(r.values.push(n),r.sum+=n,nr.max&&(r.max=n),r.count+=1)}),r.domain=[r.min,r.max],r.limits=(n,o)=>On(r,n,o),r}function On(e,t="equal",r=7){N(e)=="array"&&(e=Mn(e));const{min:n,max:o}=e,i=e.values.sort((a,c)=>a-c);if(r===1)return[n,o];const s=[];if(t.substr(0,1)==="c"&&(s.push(n),s.push(o)),t.substr(0,1)==="e"){s.push(n);for(let a=1;a 0");const a=Math.LOG10E*qn(n),c=Math.LOG10E*qn(o);s.push(n);for(let u=1;u200&&(l=!1)}const b={};for(let m=0;mm-y),s.push(g[0]);for(let m=1;m{e=new _(e),t=new _(t);const r=e.luminance(),n=t.luminance();return r>n?(r+.05)/(n+.05):(n+.05)/(r+.05)};const An=.027,Aa=5e-4,Sa=.1,Sn=1.14,ee=.022,$n=1.414,$a=(e,t)=>{e=new _(e),t=new _(t),e.alpha()<1&&(e=Nt(t,e,e.alpha(),"rgb"));const r=En(...e.rgb()),n=En(...t.rgb()),o=r>=ee?r:r+Math.pow(ee-r,$n),i=n>=ee?n:n+Math.pow(ee-n,$n),s=Math.pow(i,.56)-Math.pow(o,.57),a=Math.pow(i,.65)-Math.pow(o,.62),c=Math.abs(i-o)0?c-An:c+An)*100};function En(e,t,r){return .2126729*Math.pow(e/255,2.4)+.7151522*Math.pow(t/255,2.4)+.072175*Math.pow(r/255,2.4)}const{sqrt:dt,pow:F,min:Ea,max:La,atan2:Ln,abs:Nn,cos:re,sin:Tn,exp:Na,PI:jn}=Math;function Ta(e,t,r=1,n=1,o=1){var i=function(Ct){return 360*Ct/(2*jn)},s=function(Ct){return 2*jn*Ct/360};e=new _(e),t=new _(t);const[a,c,u]=Array.from(e.lab()),[f,l,h]=Array.from(t.lab()),d=(a+f)/2,b=dt(F(c,2)+F(u,2)),g=dt(F(l,2)+F(h,2)),m=(b+g)/2,y=.5*(1-dt(F(m,7)/(F(m,7)+F(25,7)))),L=c*(1+y),w=l*(1+y),x=dt(F(L,2)+F(u,2)),S=dt(F(w,2)+F(h,2)),R=(x+S)/2,M=i(Ln(u,L)),p=i(Ln(h,w)),C=M>=0?M:M+360,O=p>=0?p:p+360,q=Nn(C-O)>180?(C+O+360)/2:(C+O)/2,T=1-.17*re(s(q-30))+.24*re(s(2*q))+.32*re(s(3*q+6))-.2*re(s(4*q-63));let A=O-C;A=Nn(A)<=180?A:O<=C?A+360:A-360,A=2*dt(x*S)*Tn(s(A)/2);const P=f-a,G=S-x,Y=1+.015*F(d-50,2)/dt(20+F(d-50,2)),U=1+.045*R,ut=1+.015*R*T,xt=30*Na(-F((q-275)/25,2)),lt=-(2*dt(F(R,7)/(F(R,7)+F(25,7))))*Tn(2*s(xt)),Mt=dt(F(P/(r*Y),2)+F(G/(n*U),2)+F(A/(o*ut),2)+lt*(G/(n*U))*(A/(o*ut)));return La(0,Ea(100,Mt))}function ja(e,t,r="lab"){e=new _(e),t=new _(t);const n=e.get(r),o=t.get(r);let i=0;for(let s in n){const a=(n[s]||0)-(o[s]||0);i+=a*a}return Math.sqrt(i)}const Pa=(...e)=>{try{return new _(...e),!0}catch{return!1}},za={cool(){return te([k.hsl(180,1,.9),k.hsl(250,.7,.4)])},hot(){return te(["#000","#f00","#ff0","#fff"]).mode("rgb")}},Be={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]},Pn=Object.keys(Be),zn=new Map(Pn.map(e=>[e.toLowerCase(),e])),Ba=typeof Proxy=="function"?new Proxy(Be,{get(e,t){const r=t.toLowerCase();if(zn.has(r))return e[zn.get(r)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(Pn)}}):Be,Ia=(...e)=>{e=E(e,"cmyk");const[t,r,n,o]=e,i=e.length>4?e[4]:1;return o===1?[0,0,0,i]:[t>=1?0:255*(1-t)*(1-o),r>=1?0:255*(1-r)*(1-o),n>=1?0:255*(1-n)*(1-o),i]},{max:Bn}=Math,Ga=(...e)=>{let[t,r,n]=E(e,"rgb");t=t/255,r=r/255,n=n/255;const o=1-Bn(t,Bn(r,n)),i=o<1?1/(1-o):0,s=(1-t-o)*i,a=(1-r-o)*i,c=(1-n-o)*i;return[s,a,c,o]};_.prototype.cmyk=function(){return Ga(this._rgb)},Object.assign(k,{cmyk:(...e)=>new _(...e,"cmyk")}),$.format.cmyk=Ia,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"cmyk"),N(e)==="array"&&e.length===4)return"cmyk"}});const Fa=(...e)=>{const t=E(e,"hsla");let r=Et(e)||"lsa";return t[0]=et(t[0]||0)+"deg",t[1]=et(t[1]*100)+"%",t[2]=et(t[2]*100)+"%",r==="hsla"||t.length>3&&t[3]<1?(t[3]="/ "+(t.length>3?t[3]:1),r="hsla"):t.length=3,`${r.substr(0,3)}(${t.join(" ")})`},Ka=(...e)=>{const t=E(e,"lab");let r=Et(e)||"lab";return t[0]=et(t[0])+"%",t[1]=et(t[1]),t[2]=et(t[2]),r==="laba"||t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(" ")})`},Xa=(...e)=>{const t=E(e,"lch");let r=Et(e)||"lab";return t[0]=et(t[0])+"%",t[1]=et(t[1]),t[2]=isNaN(t[2])?"none":et(t[2])+"deg",r==="lcha"||t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(" ")})`},Da=(...e)=>{const t=E(e,"lab");return t[0]=et(t[0]*100)+"%",t[1]=Ce(t[1]),t[2]=Ce(t[2]),t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(" ")})`},In=(...e)=>{const[t,r,n,...o]=E(e,"rgb"),[i,s,a]=Te(t,r,n),[c,u,f]=yn(i,s,a);return[c,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]},Va=(...e)=>{const t=E(e,"lch");return t[0]=et(t[0]*100)+"%",t[1]=Ce(t[1]),t[2]=isNaN(t[2])?"none":et(t[2])+"deg",t.length>3&&t[3]<1?t[3]="/ "+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(" ")})`},{round:Ie}=Math,Ya=(...e)=>{const t=E(e,"rgba");let r=Et(e)||"rgb";if(r.substr(0,3)==="hsl")return Fa(xn(t),r);if(r.substr(0,3)==="lab"){const n=Kt();ht("d50");const o=Ka(Me(t),r);return ht(n),o}if(r.substr(0,3)==="lch"){const n=Kt();ht("d50");const o=Xa($e(t),r);return ht(n),o}return r.substr(0,5)==="oklab"?Da(Te(t)):r.substr(0,5)==="oklch"?Va(In(t)):(t[0]=Ie(t[0]),t[1]=Ie(t[1]),t[2]=Ie(t[2]),(r==="rgba"||t.length>3&&t[3]<1)&&(t[3]="/ "+(t.length>3?t[3]:1),r="rgba"),`${r.substr(0,3)}(${t.slice(0,r==="rgb"?3:4).join(" ")})`)},Gn=(...e)=>{e=E(e,"lch");const[t,r,n,...o]=e,[i,s,a]=vn(t,r,n),[c,u,f]=Ne(i,s,a);return[c,u,f,...o.length>0&&o[0]<1?[o[0]]:[]]},bt=/((?:-?\d+)|(?:-?\d+(?:\.\d+)?)%|none)/.source,ot=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%?)|none)/.source,ne=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%)|none)/.source,rt=/\s*/.source,zt=/\s+/.source,Ge=/\s*,\s*/.source,oe=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?)|none)/.source,Bt=/\s*(?:\/\s*((?:[01]|[01]?\.\d+)|\d+(?:\.\d+)?%))?/.source,Fn=new RegExp("^rgba?\\("+rt+[bt,bt,bt].join(zt)+Bt+"\\)$"),Kn=new RegExp("^rgb\\("+rt+[bt,bt,bt].join(Ge)+rt+"\\)$"),Xn=new RegExp("^rgba\\("+rt+[bt,bt,bt,ot].join(Ge)+rt+"\\)$"),Dn=new RegExp("^hsla?\\("+rt+[oe,ne,ne].join(zt)+Bt+"\\)$"),Vn=new RegExp("^hsl?\\("+rt+[oe,ne,ne].join(Ge)+rt+"\\)$"),Yn=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,Zn=new RegExp("^lab\\("+rt+[ot,ot,ot].join(zt)+Bt+"\\)$"),Jn=new RegExp("^lch\\("+rt+[ot,ot,oe].join(zt)+Bt+"\\)$"),Hn=new RegExp("^oklab\\("+rt+[ot,ot,ot].join(zt)+Bt+"\\)$"),Wn=new RegExp("^oklch\\("+rt+[ot,ot,oe].join(zt)+Bt+"\\)$"),{round:Un}=Math,It=e=>e.map((t,r)=>r<=2?qt(Un(t),0,255):t),K=(e,t=0,r=100,n=!1)=>(typeof e=="string"&&e.endsWith("%")&&(e=parseFloat(e.substring(0,e.length-1))/100,n?e=t+(e+1)*.5*(r-t):e=t+e*(r-t)),+e),W=(e,t)=>e==="none"?t:e,Fe=e=>{if(e=e.toLowerCase().trim(),e==="transparent")return[0,0,0,0];let t;if($.format.named)try{return $.format.named(e)}catch{}if((t=e.match(Fn))||(t=e.match(Kn))){let r=t.slice(1,4);for(let o=0;o<3;o++)r[o]=+K(W(r[o],0),0,255);r=It(r);const n=t[4]!==void 0?+K(t[4],0,1):1;return r[3]=n,r}if(t=e.match(Xn)){const r=t.slice(1,5);for(let n=0;n<4;n++)r[n]=+K(r[n],0,255);return r}if((t=e.match(Dn))||(t=e.match(Vn))){const r=t.slice(1,4);r[0]=+W(r[0].replace("deg",""),0),r[1]=+K(W(r[1],0),0,100)*.01,r[2]=+K(W(r[2],0),0,100)*.01;const n=It(Le(r)),o=t[4]!==void 0?+K(t[4],0,1):1;return n[3]=o,n}if(t=e.match(Yn)){const r=t.slice(1,4);r[1]*=.01,r[2]*=.01;const n=Le(r);for(let o=0;o<3;o++)n[o]=Un(n[o]);return n[3]=+t[4],n}if(t=e.match(Zn)){const r=t.slice(1,4);r[0]=K(W(r[0],0),0,100),r[1]=K(W(r[1],0),-125,125,!0),r[2]=K(W(r[2],0),-125,125,!0);const n=Kt();ht("d50");const o=It(Re(r));ht(n);const i=t[4]!==void 0?+K(t[4],0,1):1;return o[3]=i,o}if(t=e.match(Jn)){const r=t.slice(1,4);r[0]=K(r[0],0,100),r[1]=K(W(r[1],0),0,150,!1),r[2]=+W(r[2].replace("deg",""),0);const n=Kt();ht("d50");const o=It(Se(r));ht(n);const i=t[4]!==void 0?+K(t[4],0,1):1;return o[3]=i,o}if(t=e.match(Hn)){const r=t.slice(1,4);r[0]=K(W(r[0],0),0,1),r[1]=K(W(r[1],0),-.4,.4,!0),r[2]=K(W(r[2],0),-.4,.4,!0);const n=It(Ne(r)),o=t[4]!==void 0?+K(t[4],0,1):1;return n[3]=o,n}if(t=e.match(Wn)){const r=t.slice(1,4);r[0]=K(W(r[0],0),0,1),r[1]=K(W(r[1],0),0,.4,!1),r[2]=+W(r[2].replace("deg",""),0);const n=It(Gn(r)),o=t[4]!==void 0?+K(t[4],0,1):1;return n[3]=o,n}};Fe.test=e=>Fn.test(e)||Dn.test(e)||Zn.test(e)||Jn.test(e)||Hn.test(e)||Wn.test(e)||Kn.test(e)||Xn.test(e)||Vn.test(e)||Yn.test(e)||e==="transparent",_.prototype.css=function(e){return Ya(this._rgb,e)};const Za=(...e)=>new _(...e,"css");k.css=Za,$.format.css=Fe,$.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&N(e)==="string"&&Fe.test(e))return"css"}}),$.format.gl=(...e)=>{const t=E(e,"rgba");return t[0]*=255,t[1]*=255,t[2]*=255,t};const Ja=(...e)=>new _(...e,"gl");k.gl=Ja,_.prototype.gl=function(){const e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},_.prototype.hex=function(e){return mn(this._rgb,e)};const Ha=(...e)=>new _(...e,"hex");k.hex=Ha,$.format.hex=pn,$.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&N(e)==="string"&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return"hex"}});const{log:se}=Math,Qn=e=>{const t=e/100;let r,n,o;return t<66?(r=255,n=t<6?0:-155.25485562709179-.44596950469579133*(n=t-2)+104.49216199393888*se(n),o=t<20?0:-254.76935184120902+.8274096064007395*(o=t-10)+115.67994401066147*se(o)):(r=351.97690566805693+.114206453784165*(r=t-55)-40.25366309332127*se(r),n=325.4494125711974+.07943456536662342*(n=t-50)-28.0852963507957*se(n),o=255),[r,n,o,1]},{round:Wa}=Math,Ua=(...e)=>{const t=E(e,"rgb"),r=t[0],n=t[2];let o=1e3,i=4e4;const s=.4;let a;for(;i-o>s;){a=(i+o)*.5;const c=Qn(a);c[2]/c[0]>=n/r?i=a:o=a}return Wa(a)};_.prototype.temp=_.prototype.kelvin=_.prototype.temperature=function(){return Ua(this._rgb)};const Ke=(...e)=>new _(...e,"temp");Object.assign(k,{temp:Ke,kelvin:Ke,temperature:Ke}),$.format.temp=$.format.kelvin=$.format.temperature=Qn,_.prototype.oklch=function(){return In(this._rgb)},Object.assign(k,{oklch:(...e)=>new _(...e,"oklch")}),$.format.oklch=Gn,$.autodetect.push({p:2,test:(...e)=>{if(e=E(e,"oklch"),N(e)==="array"&&e.length===3)return"oklch"}}),Object.assign(k,{analyze:Mn,average:ra,bezier:ca,blend:nt,brewer:Ba,Color:_,colors:Lt,contrast:Oa,contrastAPCA:$a,cubehelix:ya,deltaE:Ta,distance:ja,input:$,interpolate:Nt,limits:On,mix:Nt,random:ka,scale:te,scales:za,valid:Pa});class v{constructor(){this.hex="#000000",this.rgb_r=0,this.rgb_g=0,this.rgb_b=0,this.xyz_x=0,this.xyz_y=0,this.xyz_z=0,this.luv_l=0,this.luv_u=0,this.luv_v=0,this.lch_l=0,this.lch_c=0,this.lch_h=0,this.hsluv_h=0,this.hsluv_s=0,this.hsluv_l=0,this.hpluv_h=0,this.hpluv_p=0,this.hpluv_l=0,this.r0s=0,this.r0i=0,this.r1s=0,this.r1i=0,this.g0s=0,this.g0i=0,this.g1s=0,this.g1i=0,this.b0s=0,this.b0i=0,this.b1s=0,this.b1i=0}static fromLinear(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,.4166666666666667)-.055}static toLinear(t){return t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92}static yToL(t){return t<=v.epsilon?t/v.refY*v.kappa:116*Math.pow(t/v.refY,.3333333333333333)-16}static lToY(t){return t<=8?v.refY*t/v.kappa:v.refY*Math.pow((t+16)/116,3)}static rgbChannelToHex(t){const r=Math.round(t*255),n=r%16,o=(r-n)/16|0;return v.hexChars.charAt(o)+v.hexChars.charAt(n)}static hexToRgbChannel(t,r){const n=v.hexChars.indexOf(t.charAt(r)),o=v.hexChars.indexOf(t.charAt(r+1));return(n*16+o)/255}static distanceFromOriginAngle(t,r,n){const o=r/(Math.sin(n)-t*Math.cos(n));return o<0?1/0:o}static distanceFromOrigin(t,r){return Math.abs(r)/Math.sqrt(Math.pow(t,2)+1)}static min6(t,r,n,o,i,s){return Math.min(t,Math.min(r,Math.min(n,Math.min(o,Math.min(i,s)))))}rgbToHex(){this.hex="#",this.hex+=v.rgbChannelToHex(this.rgb_r),this.hex+=v.rgbChannelToHex(this.rgb_g),this.hex+=v.rgbChannelToHex(this.rgb_b)}hexToRgb(){this.hex=this.hex.toLowerCase(),this.rgb_r=v.hexToRgbChannel(this.hex,1),this.rgb_g=v.hexToRgbChannel(this.hex,3),this.rgb_b=v.hexToRgbChannel(this.hex,5)}xyzToRgb(){this.rgb_r=v.fromLinear(v.m_r0*this.xyz_x+v.m_r1*this.xyz_y+v.m_r2*this.xyz_z),this.rgb_g=v.fromLinear(v.m_g0*this.xyz_x+v.m_g1*this.xyz_y+v.m_g2*this.xyz_z),this.rgb_b=v.fromLinear(v.m_b0*this.xyz_x+v.m_b1*this.xyz_y+v.m_b2*this.xyz_z)}rgbToXyz(){const t=v.toLinear(this.rgb_r),r=v.toLinear(this.rgb_g),n=v.toLinear(this.rgb_b);this.xyz_x=.41239079926595*t+.35758433938387*r+.18048078840183*n,this.xyz_y=.21263900587151*t+.71516867876775*r+.072192315360733*n,this.xyz_z=.019330818715591*t+.11919477979462*r+.95053215224966*n}xyzToLuv(){const t=this.xyz_x+15*this.xyz_y+3*this.xyz_z;let r=4*this.xyz_x,n=9*this.xyz_y;t!==0?(r/=t,n/=t):(r=NaN,n=NaN),this.luv_l=v.yToL(this.xyz_y),this.luv_l===0?(this.luv_u=0,this.luv_v=0):(this.luv_u=13*this.luv_l*(r-v.refU),this.luv_v=13*this.luv_l*(n-v.refV))}luvToXyz(){if(this.luv_l===0){this.xyz_x=0,this.xyz_y=0,this.xyz_z=0;return}const t=this.luv_u/(13*this.luv_l)+v.refU,r=this.luv_v/(13*this.luv_l)+v.refV;this.xyz_y=v.lToY(this.luv_l),this.xyz_x=0-9*this.xyz_y*t/((t-4)*r-t*r),this.xyz_z=(9*this.xyz_y-15*r*this.xyz_y-r*this.xyz_x)/(3*r)}luvToLch(){if(this.lch_l=this.luv_l,this.lch_c=Math.sqrt(this.luv_u*this.luv_u+this.luv_v*this.luv_v),this.lch_c<1e-8)this.lch_h=0;else{const t=Math.atan2(this.luv_v,this.luv_u);this.lch_h=t*180/Math.PI,this.lch_h<0&&(this.lch_h=360+this.lch_h)}}lchToLuv(){const t=this.lch_h/180*Math.PI;this.luv_l=this.lch_l,this.luv_u=Math.cos(t)*this.lch_c,this.luv_v=Math.sin(t)*this.lch_c}calculateBoundingLines(t){const r=Math.pow(t+16,3)/1560896,n=r>v.epsilon?r:t/v.kappa,o=n*(284517*v.m_r0-94839*v.m_r2),i=n*(838422*v.m_r2+769860*v.m_r1+731718*v.m_r0),s=n*(632260*v.m_r2-126452*v.m_r1),a=n*(284517*v.m_g0-94839*v.m_g2),c=n*(838422*v.m_g2+769860*v.m_g1+731718*v.m_g0),u=n*(632260*v.m_g2-126452*v.m_g1),f=n*(284517*v.m_b0-94839*v.m_b2),l=n*(838422*v.m_b2+769860*v.m_b1+731718*v.m_b0),h=n*(632260*v.m_b2-126452*v.m_b1);this.r0s=o/s,this.r0i=i*t/s,this.r1s=o/(s+126452),this.r1i=(i-769860)*t/(s+126452),this.g0s=a/u,this.g0i=c*t/u,this.g1s=a/(u+126452),this.g1i=(c-769860)*t/(u+126452),this.b0s=f/h,this.b0i=l*t/h,this.b1s=f/(h+126452),this.b1i=(l-769860)*t/(h+126452)}calcMaxChromaHpluv(){const t=v.distanceFromOrigin(this.r0s,this.r0i),r=v.distanceFromOrigin(this.r1s,this.r1i),n=v.distanceFromOrigin(this.g0s,this.g0i),o=v.distanceFromOrigin(this.g1s,this.g1i),i=v.distanceFromOrigin(this.b0s,this.b0i),s=v.distanceFromOrigin(this.b1s,this.b1i);return v.min6(t,r,n,o,i,s)}calcMaxChromaHsluv(t){const r=t/360*Math.PI*2,n=v.distanceFromOriginAngle(this.r0s,this.r0i,r),o=v.distanceFromOriginAngle(this.r1s,this.r1i,r),i=v.distanceFromOriginAngle(this.g0s,this.g0i,r),s=v.distanceFromOriginAngle(this.g1s,this.g1i,r),a=v.distanceFromOriginAngle(this.b0s,this.b0i,r),c=v.distanceFromOriginAngle(this.b1s,this.b1i,r);return v.min6(n,o,i,s,a,c)}hsluvToLch(){if(this.hsluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hsluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hsluv_l,this.calculateBoundingLines(this.hsluv_l);const t=this.calcMaxChromaHsluv(this.hsluv_h);this.lch_c=t/100*this.hsluv_s}this.lch_h=this.hsluv_h}lchToHsluv(){if(this.lch_l>99.9999999)this.hsluv_s=0,this.hsluv_l=100;else if(this.lch_l<1e-8)this.hsluv_s=0,this.hsluv_l=0;else{this.calculateBoundingLines(this.lch_l);const t=this.calcMaxChromaHsluv(this.lch_h);this.hsluv_s=this.lch_c/t*100,this.hsluv_l=this.lch_l}this.hsluv_h=this.lch_h}hpluvToLch(){if(this.hpluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hpluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hpluv_l,this.calculateBoundingLines(this.hpluv_l);const t=this.calcMaxChromaHpluv();this.lch_c=t/100*this.hpluv_p}this.lch_h=this.hpluv_h}lchToHpluv(){if(this.lch_l>99.9999999)this.hpluv_p=0,this.hpluv_l=100;else if(this.lch_l<1e-8)this.hpluv_p=0,this.hpluv_l=0;else{this.calculateBoundingLines(this.lch_l);const t=this.calcMaxChromaHpluv();this.hpluv_p=this.lch_c/t*100,this.hpluv_l=this.lch_l}this.hpluv_h=this.lch_h}hsluvToRgb(){this.hsluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hpluvToRgb(){this.hpluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hsluvToHex(){this.hsluvToRgb(),this.rgbToHex()}hpluvToHex(){this.hpluvToRgb(),this.rgbToHex()}rgbToHsluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHsluv()}rgbToHpluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHpluv()}hexToHsluv(){this.hexToRgb(),this.rgbToHsluv()}hexToHpluv(){this.hexToRgb(),this.rgbToHpluv()}}v.hexChars="0123456789abcdef",v.refY=1,v.refU=.19783000664283,v.refV=.46831999493879,v.kappa=903.2962962,v.epsilon=.0088564516,v.m_r0=3.240969941904521,v.m_r1=-1.537383177570093,v.m_r2=-.498610760293,v.m_g0=-.96924363628087,v.m_g1=1.87596750150772,v.m_g2=.041555057407175,v.m_b0=.055630079696993,v.m_b1=-.20397695888897,v.m_b2=1.056971514242878;function to(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ie={exports:{}},Xe,eo;function Xt(){if(eo)return Xe;eo=1;function e(t,r){return Object.prototype.hasOwnProperty.call(t,r)}return Xe=e,Xe}var De,ro;function Ve(){if(ro)return De;ro=1;var e=Xt(),t,r;function n(){r=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],t=!0;for(var s in{toString:null})t=!1}function o(s,a,c){var u,f=0;t==null&&n();for(u in s)if(i(a,s,u,c)===!1)break;if(t)for(var l=s.constructor,h=!!l&&s===l.prototype;(u=r[f++])&&!((u!=="constructor"||!h&&e(s,u))&&s[u]!==Object.prototype[u]&&i(a,s,u,c)===!1););}function i(s,a,c,u){return s.call(u,a[c],c,a)}return De=o,De}var Ye,no;function oo(){if(no)return Ye;no=1;var e=Ve();function t(r){var n=[];return e(r,function(o,i){typeof o=="function"&&n.push(i)}),n.sort()}return Ye=t,Ye}var Ze,so;function Dt(){if(so)return Ze;so=1;function e(t,r,n){var o=t.length;r==null?r=0:r<0?r=Math.max(o+r,0):r=Math.min(r,o),n==null?n=o:n<0?n=Math.max(o+n,0):n=Math.min(n,o);for(var i=[];r1?n(arguments,1):e(i);r(a,function(c){i[c]=t(i[c],i)})}return Ue=o,Ue}var Qe,uo;function V(){if(uo)return Qe;uo=1;var e=Xt(),t=Ve();function r(n,o,i){t(n,function(s,a){if(e(n,a))return o.call(i,n[a],a,n)})}return Qe=r,Qe}var tr,lo;function ec(){if(lo)return tr;lo=1;function e(t){return t}return tr=e,tr}var er,fo;function ho(){if(fo)return er;fo=1;function e(t){return function(r){return r[t]}}return er=e,er}var rr,bo;function nr(){if(bo)return rr;bo=1;var e=/^\[object (.*)\]$/,t=Object.prototype.toString,r;function n(o){return o===null?"Null":o===r?"Undefined":e.exec(t.call(o))[1]}return rr=n,rr}var or,po;function sr(){if(po)return or;po=1;var e=nr();function t(r,n){return e(r)===n}return or=t,or}var ir,mo;function rc(){if(mo)return ir;mo=1;var e=sr(),t=Array.isArray||function(r){return e(r,"Array")};return ir=t,ir}var ar,go;function _o(){if(go)return ar;go=1;var e=V(),t=rc();function r(s,a){for(var c=-1,u=s.length;++cs&&(s=c,i=a);return i}return Or=t,Or}var Ar,Do;function Sr(){if(Do)return Ar;Do=1;var e=V();function t(r){var n=[];return e(r,function(o,i){n.push(o)}),n}return Ar=t,Ar}var $r,Vo;function bc(){if(Vo)return $r;Vo=1;var e=dc(),t=Sr();function r(n,o){return e(t(n),o)}return $r=r,$r}var Er,Yo;function Zo(){if(Yo)return Er;Yo=1;var e=V();function t(n,o){for(var i=0,s=arguments.length,a;++i2;if(!t(n)&&!a)throw new Error("reduce of empty object with no initial value");return e(n,function(c,u,f){a?i=o.call(s,i,c,u,f):(i=c,a=!0)}),i}return Dr=r,Dr}var Vr,ls;function qc(){if(ls)return Vr;ls=1;var e=Lo(),t=yt();function r(n,o,i){return o=t(o,i),e(n,function(s,a,c){return!o(s,a,c)},i)}return Vr=r,Vr}var Yr,fs;function Mc(){if(fs)return Yr;fs=1;var e=sr();function t(r){return e(r,"Function")}return Yr=t,Yr}var Zr,hs;function Oc(){if(hs)return Zr;hs=1;var e=Mc();function t(r,n){var o=r[n];if(o!==void 0)return e(o)?o.call(r):o}return Zr=t,Zr}var Jr,ds;function Ac(){if(ds)return Jr;ds=1;var e=es();function t(r,n,o){var i=/^(.+)\.(.+)$/.exec(n);i?e(r,i[1])[i[2]]=o:r[n]=o}return Jr=t,Jr}var Hr,bs;function Sc(){if(bs)return Hr;bs=1;var e=Bo();function t(r,n){if(e(r,n)){for(var o=n.split("."),i=o.pop();n=o.shift();)r=r[n];return delete r[i]}else return!0}return Hr=t,Hr}var Wr,ps;function Ur(){return ps||(ps=1,Wr={bindAll:tc(),contains:nc(),deepFillIn:oc(),deepMatches:_o(),deepMixIn:sc(),equals:ac(),every:qo(),fillIn:cc(),filter:Lo(),find:uc(),flatten:lc(),forIn:Ve(),forOwn:V(),functions:oo(),get:Po(),has:Bo(),hasOwn:Xt(),keys:fc(),map:Fo(),matches:hc(),max:bc(),merge:gc(),min:vc(),mixIn:Zo(),namespace:es(),omit:xc(),pick:Cc(),pluck:kc(),reduce:Rc(),reject:qc(),result:Oc(),set:Ac(),size:cs(),some:lr(),unset:Sc(),values:Sr()}),Wr}var ms;function gs(){return ms||(ms=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Ur(),n={A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},o=(0,r.map)(n,function(i){var s=100*(i.x/i.y),a=100,c=100*(1-i.x-i.y)/i.y;return[s,a,c]});t.default=o,e.exports=t.default})(ie,ie.exports)),ie.exports}var ae={exports:{}},_s;function vs(){return _s||(_s=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=Math,n=r.pow,o=r.sign,i=r.abs,s={decode:function(l){return l<=.04045?l/12.92:n((l+.055)/1.055,2.4)},encode:function(l){return l<=.0031308?12.92*l:1.055*n(l,1/2.4)-.055}},a={encode:function(l){return l<.001953125?16*l:n(l,1/1.8)},decode:function(l){return l<16*.001953125?l/16:n(l,1.8)}};function c(f){return{decode:function(h){return o(h)*n(i(h),f)},encode:function(h){return o(h)*n(i(h),1/f)}}}var u={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:s},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:c(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:c(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:a}};t.default=u,e.exports=t.default})(ae,ae.exports)),ae.exports}var pt={},ys;function ws(){if(ys)return pt;ys=1,Object.defineProperty(pt,"__esModule",{value:!0});function e(s){return[[s[0][0],s[1][0],s[2][0]],[s[0][1],s[1][1],s[2][1]],[s[0][2],s[1][2],s[2][2]]]}function t(s){return s[0][0]*(s[2][2]*s[1][1]-s[2][1]*s[1][2])+s[1][0]*(s[2][1]*s[0][2]-s[2][2]*s[0][1])+s[2][0]*(s[1][2]*s[0][1]-s[1][1]*s[0][2])}function r(s){var a=1/t(s);return[[(s[2][2]*s[1][1]-s[2][1]*s[1][2])*a,(s[2][1]*s[0][2]-s[2][2]*s[0][1])*a,(s[1][2]*s[0][1]-s[1][1]*s[0][2])*a],[(s[2][0]*s[1][2]-s[2][2]*s[1][0])*a,(s[2][2]*s[0][0]-s[2][0]*s[0][2])*a,(s[1][0]*s[0][2]-s[1][2]*s[0][0])*a],[(s[2][1]*s[1][0]-s[2][0]*s[1][1])*a,(s[2][0]*s[0][1]-s[2][1]*s[0][0])*a,(s[1][1]*s[0][0]-s[1][0]*s[0][1])*a]]}function n(s,a){return[s[0][0]*a[0]+s[0][1]*a[1]+s[0][2]*a[2],s[1][0]*a[0]+s[1][1]*a[1]+s[1][2]*a[2],s[2][0]*a[0]+s[2][1]*a[1]+s[2][2]*a[2]]}function o(s,a){return[[s[0][0]*a[0],s[0][1]*a[1],s[0][2]*a[2]],[s[1][0]*a[0],s[1][1]*a[1],s[1][2]*a[2]],[s[2][0]*a[0],s[2][1]*a[1],s[2][2]*a[2]]]}function i(s,a){return[[s[0][0]*a[0][0]+s[0][1]*a[1][0]+s[0][2]*a[2][0],s[0][0]*a[0][1]+s[0][1]*a[1][1]+s[0][2]*a[2][1],s[0][0]*a[0][2]+s[0][1]*a[1][2]+s[0][2]*a[2][2]],[s[1][0]*a[0][0]+s[1][1]*a[1][0]+s[1][2]*a[2][0],s[1][0]*a[0][1]+s[1][1]*a[1][1]+s[1][2]*a[2][1],s[1][0]*a[0][2]+s[1][1]*a[1][2]+s[1][2]*a[2][2]],[s[2][0]*a[0][0]+s[2][1]*a[1][0]+s[2][2]*a[2][0],s[2][0]*a[0][1]+s[2][1]*a[1][1]+s[2][2]*a[2][1],s[2][0]*a[0][2]+s[2][1]*a[1][2]+s[2][2]*a[2][2]]]}return pt.transpose=e,pt.determinant=t,pt.inverse=r,pt.multiply=n,pt.scalar=o,pt.product=i,pt}var Yt={},xs;function $c(){if(xs)return Yt;xs=1,Object.defineProperty(Yt,"__esModule",{value:!0});var e=Math,t=e.PI;function r(o){for(var i=o*180/t;i<0;)i+=360;for(;i>360;)i-=360;return i}function n(o){for(var i=t*o/180;i<0;)i+=2*t;for(;i>2*t;)i-=2*t;return i}return Yt.fromRadian=r,Yt.toRadian=n,Yt}var Zt={},Cs;function Ec(){if(Cs)return Zt;Cs=1,Object.defineProperty(Zt,"__esModule",{value:!0});var e=Math,t=e.round;function r(o){return o[0]=="#"&&(o=o.slice(1)),o.length<6&&(o=o.split("").map(function(i){return i+i}).join("")),o.match(/../g).map(function(i){return parseInt(i,16)/255})}function n(o){var i=o.map(function(s){return s=t(255*s).toString(16),s.length<2&&(s="0"+s),s}).join("");return"#"+i}return Zt.fromHex=r,Zt.toHex=n,Zt}var ce={exports:{}},ks;function Lc(){return ks||(ks=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=ws(),n=u(r),o=gs(),i=c(o),s=vs(),a=c(s);function c(l){return l&&l.__esModule?l:{default:l}}function u(l){if(l&&l.__esModule)return l;var h={};if(l!=null)for(var d in l)Object.prototype.hasOwnProperty.call(l,d)&&(h[d]=l[d]);return h.default=l,h}function f(){var l=arguments.length<=0||arguments[0]===void 0?a.default.sRGB:arguments[0],h=arguments.length<=1||arguments[1]===void 0?i.default.D65:arguments[1],d=[l.r,l.g,l.b],b=n.transpose(d.map(function(w){var x=w.x/w.y,S=1,R=(1-w.x-w.y)/w.y;return[x,S,R]})),g=l.gamma,m=n.multiply(n.inverse(b),h),y=n.scalar(b,m),L=n.inverse(y);return{fromRgb:function(x){return n.multiply(y,x.map(g.decode))},toRgb:function(x){return n.multiply(L,x).map(g.encode)}}}t.default=f,e.exports=t.default})(ce,ce.exports)),ce.exports}var Qr,Rs;function ue(){if(Rs)return Qr;Rs=1;var e=gs(),t=vs(),r=ws(),n=$c(),o=Ec(),i=Lc();return Qr={illuminant:e,workspace:t,matrix:r,degree:n,rgb:o,xyz:i},Qr}var Nc=ue();const le=to(Nc);var st={},qs;function fe(){if(qs)return st;qs=1,Object.defineProperty(st,"__esModule",{value:!0}),st.cfs=st.distance=st.lerp=st.corLerp=void 0;var e=Ur();function t(h,d,b){return d in h?Object.defineProperty(h,d,{value:b,enumerable:!0,configurable:!0,writable:!0}):h[d]=b,h}function r(h){if(Array.isArray(h)){for(var d=0,b=Array(h.length);dm/2&&(h>d?d+=m:h+=m)}return((1-b)*h+b*d)%(m||1/0)}function u(h,d,b){var g={};for(var m in h)g[m]=c(h[m],d[m],b,m);return g}function f(h,d){var b=0;for(var g in h)b+=i(h[g]-d[g],2);return s(b)}function l(h){return e.merge.apply(void 0,r(h.split("").map(function(d){return t({},d,!0)})))}return st.corLerp=c,st.lerp=u,st.distance=f,st.cfs=l,st}var he={exports:{}},Ms;function Tc(){return Ms||(Ms=1,(function(e,t){var r=(function(){function s(a,c){var u=[],f=!0,l=!1,h=void 0;try{for(var d=a[Symbol.iterator](),b;!(f=(b=d.next()).done)&&(u.push(b.value),!(c&&u.length===c));f=!0);}catch(g){l=!0,h=g}finally{try{!f&&d.return&&d.return()}finally{if(l)throw h}}return u}return function(a,c){if(Array.isArray(a))return a;if(Symbol.iterator in Object(a))return s(a,c);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(t,"__esModule",{value:!0});var n=ue(),o=fe();function i(s,a){var c=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],u=-c,f=1+c,l=Math,h=l.min,d=l.max,b=["000","fff"].map(function(R){return a.fromXyz(s.fromRgb(n.rgb.fromHex(R)))}),g=r(b,2),m=g[0],y=g[1];function L(R){var M=s.toRgb(a.toXyz(R)),p=M.map(function(C){return C>=u&&C<=f}).reduce(function(C,O){return C&&O},!0);return[p,M]}function w(R,M){for(var p=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,o.distance)(R,M)>p;){var C=(0,o.lerp)(R,M,.5),O=L(C),q=r(O,1),T=q[0];T?R=C:M=C}return R}function x(R){return(0,o.lerp)(m,y,R)}function S(R){return R.map(function(M){return d(u,h(f,M))})}return{contains:L,limit:w,spine:x,crop:S}}t.default=i,e.exports=t.default})(he,he.exports)),he.exports}var de={exports:{}},it={},Os;function As(){if(Os)return it;Os=1;var e=(function(){function l(h,d){var b=[],g=!0,m=!1,y=void 0;try{for(var L=h[Symbol.iterator](),w;!(g=(w=L.next()).done)&&(b.push(w.value),!(d&&b.length===d));g=!0);}catch(x){m=!0,y=x}finally{try{!g&&L.return&&L.return()}finally{if(m)throw y}}return b}return function(h,d){if(Array.isArray(h))return h;if(Symbol.iterator in Object(h))return l(h,d);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(it,"__esModule",{value:!0}),it.toNotation=it.fromNotation=it.toHue=it.fromHue=void 0;var t=fe(),r=Math,n=r.floor,o=[{s:"R",h:20.14,e:.8,H:0},{s:"Y",h:90,e:.7,H:100},{s:"G",h:164.25,e:1,H:200},{s:"B",h:237.53,e:1.2,H:300},{s:"R",h:380.14,e:.8,H:400}],i=o.map(function(l){return l.s}).slice(0,-1).join("");function s(l){l50){var g=[d,h];h=g[0],d=g[1],b=100-b}return b<1?i[h]:i[h]+b.toFixed()+i[d]}return it.fromHue=s,it.toHue=a,it.fromNotation=u,it.toNotation=f,it}var Ss;function jc(){return Ss||(Ss=1,(function(e,t){var r=(function(){function P(G,Y){var U=[],ut=!0,xt=!1,Jt=void 0;try{for(var lt=G[Symbol.iterator](),Mt;!(ut=(Mt=lt.next()).done)&&(U.push(Mt.value),!(Y&&U.length===Y));ut=!0);}catch(Ct){xt=!0,Jt=Ct}finally{try{!ut&<.return&<.return()}finally{if(xt)throw Jt}}return U}return function(G,Y){if(Array.isArray(G))return G;if(Symbol.iterator in Object(G))return P(G,Y);throw new TypeError("Invalid attempt to destructure non-iterable instance")}})();Object.defineProperty(t,"__esModule",{value:!0});var n=ue(),o=As(),i=c(o),s=fe(),a=Ur();function c(P){if(P&&P.__esModule)return P;var G={};if(P!=null)for(var Y in P)Object.prototype.hasOwnProperty.call(P,Y)&&(G[Y]=P[Y]);return G.default=P,G}var u=Math,f=u.pow,l=u.sqrt,h=u.exp,d=u.abs,b=u.sign,g=Math,m=g.sin,y=g.cos,L=g.atan2,w={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},x=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],S=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],R=x,M=n.matrix.inverse(x),p=n.matrix.product(S,n.matrix.inverse(x)),C=n.matrix.product(x,n.matrix.inverse(S)),O={whitePoint:n.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:"average",discounting:!1},q=(0,s.cfs)("QJMCshH"),T=(0,s.cfs)("JCh");function A(){var P=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],G=arguments.length<=1||arguments[1]===void 0?q:arguments[1];P=(0,a.merge)(O,P);var Y=P.whitePoint,U=P.adaptingLuminance,ut=P.backgroundLuminance,xt=w[P.surroundType],Jt=xt.F,lt=xt.c,Mt=xt.N_c,Ct=Y[1],Ys=1/(5*U+1),Ot=.2*f(Ys,4)*5*U+.1*f(1-f(Ys,4),2)*f(5*U,1/3),_e=ut/Ct,an=.725*f(1/_e,.2),Zs=an,Js=1.48+l(_e),Hs=P.discounting?1:Jt*(1-1/3.6*h(-(U+42)/92)),d0=n.matrix.multiply(x,Y),b0=d0.map(function(j){return Hs*Ct/j+1-Hs}),cn=r(b0,3),Ws=cn[0],Us=cn[1],Qs=cn[2],p0=ti(Y),m0=ei(p0),ve=ri(m0);function ti(j){var z=n.matrix.multiply(R,j),B=r(z,3),Z=B[0],D=B[1],tt=B[2];return[Ws*Z,Us*D,Qs*tt]}function g0(j){var z=r(j,3),B=z[0],Z=z[1],D=z[2];return n.matrix.multiply(M,[B/Ws,Z/Us,D/Qs])}function ei(j){return n.matrix.multiply(p,j).map(function(z){var B=f(Ot*d(z)/100,.42);return b(z)*400*B/(27.13+B)+.1})}function _0(j){return n.matrix.multiply(C,j.map(function(z){var B=z-.1;return b(B)*100/Ot*f(27.13*d(B)/(400-d(B)),2.380952380952381)}))}function ri(j){var z=r(j,3),B=z[0],Z=z[1],D=z[2];return(B*2+Z+D/20-.305)*an}function un(j){return 4/lt*l(j/100)*(ve+4)*f(Ot,.25)}function v0(j){return 6.25*f(lt*j/((ve+4)*f(Ot,.25)),2)}function ni(j){return j*f(Ot,.25)}function y0(j,z){return f(j/100,2)*z/f(Ot,.25)}function w0(j){return j/f(Ot,.25)}function x0(j,z){return 100*l(j/z)}function ln(j,z){var B=z.Q,Z=z.J,D=z.M,tt=z.C,at=z.s,mt=z.h,gt=z.H,J={};return j.J&&(J.J=isNaN(Z)?v0(B):Z),j.C&&(isNaN(tt)?isNaN(D)?(B=isNaN(B)?un(Z):B,J.C=y0(at,B)):J.C=w0(D):J.C=z.C),j.h&&(J.h=isNaN(mt)?i.toHue(gt):mt),j.Q&&(J.Q=isNaN(B)?un(Z):B),j.M&&(J.M=isNaN(D)?ni(tt):D),j.s&&(isNaN(at)?(B=isNaN(B)?un(Z):B,D=isNaN(D)?ni(tt):D,J.s=x0(D,B)):J.s=at),j.H&&(J.H=isNaN(gt)?i.fromHue(mt):gt),J}function C0(j){var z=ti(j),B=ei(z),Z=r(B,3),D=Z[0],tt=Z[1],at=Z[2],mt=D-tt*12/11+at/11,gt=(D+tt-2*at)/9,J=L(gt,mt),Ft=n.degree.fromRadian(J),ye=1/4*(y(J+2)+3.8),we=ri(B),Ht=100*f(we/ve,lt*Js),kt=5e4/13*Mt*Zs*ye*l(mt*mt+gt*gt)/(D+tt+21/20*at),Rt=f(kt,.9)*l(Ht/100)*f(1.64-f(.29,_e),.73);return ln(G,{J:Ht,C:Rt,h:Ft})}function k0(j){var z=ln(T,j),B=z.J,Z=z.C,D=z.h,tt=n.degree.toRadian(D),at=f(Z/(l(B/100)*f(1.64-f(.29,_e),.73)),10/9),mt=1/4*(y(tt+2)+3.8),gt=ve*f(B/100,1/lt/Js),J=5e4/13*Mt*Zs*mt/at,Ft=gt/an+.305,ye=Ft*61/20*460/1403,we=61/20*220/1403,Ht=21/20*6300/1403-27/1403,kt=m(tt),Rt=y(tt),At,St;at===0||isNaN(at)?At=St=0:d(kt)>=d(Rt)?(St=ye/(J/kt+we*Rt/kt+Ht),At=St*Rt/kt):(At=ye/(J/Rt+we+Ht*kt/Rt),St=At*kt/Rt);var R0=[20/61*Ft+451/1403*At+288/1403*St,20/61*Ft-891/1403*At-261/1403*St,20/61*Ft-220/1403*At-6300/1403*St],q0=_0(R0),M0=g0(q0);return M0}return{fromXyz:C0,toXyz:k0,fillOut:ln}}t.default=A,e.exports=t.default})(de,de.exports)),de.exports}var be={exports:{}},$s;function Pc(){return $s||($s=1,(function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=ue(),n=Math,o=n.sqrt,i=n.pow,s=n.exp,a=n.log,c=n.cos,u=n.sin,f=n.atan2,l={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function h(){var d=arguments.length<=0||arguments[0]===void 0?"UCS":arguments[0],b=l[d],g=b.K_L,m=b.c_1,y=b.c_2;function L(S){var R=S.J,M=S.M,p=S.h,C=r.degree.toRadian(p),O=(1+100*m)*R/(1+m*R),q=1/y*a(1+y*M),T=q*c(C),A=q*u(C);return{J_p:O,a_p:T,b_p:A}}function w(S){var R=S.J_p,M=S.a_p,p=S.b_p,C=-R/(m*R-100*m-1),O=o(i(M,2)+i(p,2)),q=(s(y*O)-1)/y,T=f(p,M),A=r.degree.fromRadian(T);return{J:C,M:q,h:A}}function x(S,R){return o(i((S.J_p-R.J_p)/g,2)+i(S.a_p-R.a_p,2)+i(S.b_p-R.b_p,2))}return{fromCam:L,toCam:w,distance:x}}t.default=h,e.exports=t.default})(be,be.exports)),be.exports}var tn,Es;function zc(){if(Es)return tn;Es=1;var e=fe(),t=Tc(),r=jc(),n=Pc(),o=As();return tn={gamut:t,cfs:e.cfs,lerp:e.lerp,cam:r,ucs:n,hq:o},tn}var Bc=zc();const Ls=to(Bc);function Ns(e){const t=new v;return t.rgb_r=e[0],t.rgb_g=e[1],t.rgb_b=e[2],t.rgbToHsluv(),[t.hsluv_h,t.hsluv_s,t.hsluv_l]}function Ic(e){const t=new v;return t.hsluv_h=e[0],t.hsluv_s=e[1],t.hsluv_l=e[2],t.hsluvToRgb(),[t.rgb_r,t.rgb_g,t.rgb_b]}const Ts=Ls.cam({whitePoint:le.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:"average",discounting:!1},Ls.cfs("JCh")),js=le.xyz(le.workspace.sRGB,le.illuminant.D65),Ps=e=>js.toRgb(Ts.toXyz({J:e[0],C:e[1],h:e[2]})),en=e=>{const t=Ts.fromXyz(js.fromRgb(e));return[t.J,t.C,t.h]},[Gc,Fc]=(()=>{const e={k_l:1,c1:.007,c2:.0228},t=Math.PI,r=64/t/5,n=1/(5*r+1),o=.2*n**4*(5*r)+.1*(1-n**4)**2*(5*r)**(1/3);return[i=>{const[s,a,c]=i,u=a*o**.25;let f=(1+100*e.c1)*s/(1+e.c1*s);f/=e.k_l;const l=1/e.c2*Math.log(1+e.c2*u),h=l*Math.cos(c*(t/180)),d=l*Math.sin(c*(t/180));return[f,h,d]},i=>{const[s,a,c]=i,u=Math.sqrt(a*a+c*c),f=(Math.exp(u*e.c2)-1)/e.c2,l=(180/t*Math.atan2(c,a)+360)%360,h=f/o**.25;return[s/(1+e.c1*(100-s)),h,l]}]})(),Kc=e=>Ps(Fc(e)),zs=e=>Gc(en(e)),pe=console;pe.color=(e,t="")=>{const n=k(e).luminance();pe.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?"#000":"#fff"}`)},pe.ramp=(e,t=1)=>{pe.log("%c ",`font-size: 1px;line-height: 16px;background: ${k.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};const Bs=(e,t,r,n,o,i,s=.1)=>{if(e===r||t===n)return!0;const a=(n-t)/(r-e),c=(i+o/a-t+a*e)/(a+1/a),u=i+o/a-c/a;return(o-c)**2+(i-u)**2{const o=(t[0]+r[0])/2,i=e(o);return Bs(...t,...r,o,i,n)?null:[o,i]},rn=(e,t,r,n=.1)=>{const o=(r-t)/10,i=[];for(let s=t;sMath.round(e*10**t)/10**t,Dc=(e,t=1,r=90,n=.005)=>{const o=rn(c=>e(c).gl()[0],0,t,n),i=rn(c=>e(c).gl()[1],0,t,n),s=rn(c=>e(c).gl()[2],0,t,n),a=Array.from(new Set([...o.map(c=>me(c[0])),...i.map(c=>me(c[0])),...s.map(c=>me(c[0]))].sort((c,u)=>c-u)));return`linear-gradient(${r}deg, ${a.map(c=>`${e(c).hex()} ${me(c*100)}%`).join()});`},Vc=e=>{e.Color.prototype.jch=function(){return en(this._rgb.slice(0,3).map(o=>o/255))},e.jch=(...o)=>new e.Color(...Ps(o).map(i=>Math.floor(i*255)),"rgb"),e.Color.prototype.jab=function(){return zs(this._rgb.slice(0,3).map(o=>o/255))},e.jab=(...o)=>new e.Color(...Kc(o).map(i=>Math.floor(i*255)),"rgb"),e.Color.prototype.hsluv=function(){return Ns(this._rgb.slice(0,3).map(o=>o/255))},e.hsluv=(...o)=>new e.Color(...Ic(o).map(i=>Math.floor(i*255)),"rgb");const t=e.interpolate,r={jch:en,jab:zs,hsluv:Ns},n=(o,i,s)=>(Math.abs(o-i)>360/2&&(o>i?i+=360:o+=360),((1-s)*o+s*i)%360);e.interpolate=(o,i,s=.5,a="lrgb")=>{if(r[a]){typeof o!="object"&&(o=new e.Color(o)),typeof i!="object"&&(i=new e.Color(i));const c=r[a](o.gl()),u=r[a](i.gl()),f=Number.isNaN(o.hsl()[0]),l=Number.isNaN(i.hsl()[0]);let h,d,b;switch(a){case"hsluv":c[1]<1e-10&&(c[0]=u[0]),c[1]===0&&(c[1]=u[1]),u[1]<1e-10&&(u[0]=c[0]),u[1]===0&&(u[1]=c[1]),h=n(c[0],u[0],s),d=c[1]+(u[1]-c[1])*s,b=c[2]+(u[2]-c[2])*s;break;case"jch":f&&(c[2]=u[2]),l&&(u[2]=c[2]),h=c[0]+(u[0]-c[0])*s,d=c[1]+(u[1]-c[1])*s,b=n(c[2],u[2],s);break;default:h=c[0]+(u[0]-c[0])*s,d=c[1]+(u[1]-c[1])*s,b=c[2]+(u[2]-c[2])*s}return e[a](h,d,b).alpha(o.alpha()+s*(i.alpha()-o.alpha()))}return t(o,i,s,a)},e.getCSSGradient=Dc};const X={mainTRC:2.4,sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1};function Is(e,t,r=-1){const n=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)n[1])return 0;let o=0,i=0,s="BoW";return e=e>X.blkThrs?e:e+Math.pow(X.blkThrs-e,X.blkClmp),t=t>X.blkThrs?t:t+Math.pow(X.blkThrs-t,X.blkClmp),Math.abs(t-e)e?(o=(Math.pow(t,X.normBG)-Math.pow(e,X.normTXT))*X.scaleBoW,i=o-.1?0:o+X.loWoBoffset),r<0?i*100:r==0?Math.round(Math.abs(i)*100)+""+s+"":Number.isInteger(r)?(i*100).toFixed(r):0)}function ge(e=[0,0,0]){function t(r){return Math.pow(r/255,X.mainTRC)}return X.sRco*t(e[0])+X.sGco*t(e[1])+X.sBco*t(e[2])}const Gs=(e,t,r,n,o,i,s,a,c)=>{const u=1-c,f=u*u,l=f*u,d=c*c*c,b=l*e+f*3*c*r+u*3*c*c*o+d*s,g=l*t+f*3*c*n+u*3*c*c*i+d*a;return{x:b,y:g}},Yc=(e,t)=>{const r=[];let n={x:+e[0],y:+e[1]};for(let o=0,i=e.length;i-2*!0>o;o+=2){const s=[{x:+e[o-2],y:+e[o-1]},{x:+e[o],y:+e[o+1]},{x:+e[o+2],y:+e[o+3]},{x:+e[o+4],y:+e[o+5]}];i-4===o?s[3]=s[2]:o||(s[0]={x:+e[o],y:+e[o+1]}),r.push([n.x,n.y,(-s[0].x+6*s[1].x+s[2].x)/6,(-s[0].y+6*s[1].y+s[2].y)/6,(s[1].x+6*s[2].x-s[3].x)/6,(s[1].y+6*s[2].y-s[3].y)/6,s[2].x,s[2].y]),n=s[2]}return r},Zc=(e,t,r,n,o,i,s,a)=>{let u=e,f=t,l=0;for(let h=1;h<5;h++){const{x:d,y:b}=Gs(e,t,r,n,o,i,s,a,h/5);l+=Math.hypot(d-u,b-f),u=d,f=b}return l+=Math.hypot(s-u,a-f),l},Jc=(e,t,r,n,o,i,s,a)=>{const c=Math.floor(Zc(e,t,r,n,o,i,s,a)*.75),u=[];let f=0;for(let l=0;l<=c;l++){const h=l/c,d=Gs(e,t,r,n,o,i,s,a,h),b=Math.round(d.x);if(u[b]=d.y,b-f>1){const g=u[f],m=u[b];for(let y=f+1;yu[Math.round(l)]||null},Gt={CAM02:"jab",CAM02p:"jch",HEX:"hex",HSL:"hsl",HSLuv:"hsluv",HSV:"hsv",LAB:"lab",LCH:"lch",RGB:"rgb",OKLAB:"oklab",OKLCH:"oklch"};function wt(e,t=0){const r=10**t;return Math.round(e*r)/r}function Hc(e,t){let r;return e>1?r=(e-1)*t+1:e<-1?r=(e+1)*t-1:r=1,wt(r,2)}function Wc(e){return k(String(e)).jch()}function Uc(e){return k(String(e)).hsluv()}function Qc(e,t,r){const n=[[],[],[]];if(e.forEach((i,s)=>n.forEach((a,c)=>a.push(t[s],i[c]))),r==="hcl"){const i=n[1];for(let s=1;s{const s=[];for(let a=1;a{i[c]=i[a]}),s.length=0;break}if(s.length){const a=k("#ccc").jch()[2];s.forEach(c=>{i[c]=a})}s.length=0;for(let a=i.length-1;a>0;a-=2)if(Number.isNaN(i[a]))s.push(a);else{s.forEach(c=>{i[c]=i[a]});break}for(let a=1;aYc(i).map(s=>Jc(...s)));return i=>{const s=o.map(a=>{for(let c=0;cn*i**e+o}function nn({swatches:e,colorKeys:t,colorspace:r,colorSpace:n=r??"LAB",shift:o=1,fullScale:i=!0,smooth:s=!1,distributeLightness:a="linear",sortColor:c=!0,asFun:u=!1}={}){r!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead.");const f=Gt[n];if(!f)throw new Error(`Colorspace “${n}” not supported`);if(!t)throw new Error(`Colorkeys missing: returned “${t}”`);let l;if(i)l=t.map(w=>e-e*(k(w).jch()[0]/100)).sort((w,x)=>w-x).concat(e),l.unshift(0);else{let w=t.map(R=>k(R).jch()[0]/100),x=Math.min(...w),S=Math.max(...w);l=w.map(R=>R===0||isNaN((R-x)/(S-x))?0:e-(R-x)/(S-x)*e).sort((R,M)=>R-M)}let h=t0(o,[1,e],[1,e]);if(h=l.map(w=>Math.max(0,h(w))),l=h,a==="polynomial"){const w=R=>Math.sqrt(Math.sqrt((Math.pow(R,2.25)+Math.pow(R,4))/2));l=h.map(R=>R/e).map(R=>w(R)*e)}const d=t.map((w,x)=>({colorKeys:Wc(w),index:x})).sort((w,x)=>x.colorKeys[0]-w.colorKeys[0]).map(w=>t[w.index]);let b=[],g;if(i){const w=f==="lch"?k.lch(...k("#fff").lch()):"#ffffff",x=f==="lch"?k.lch(...k("#000").lch()):"#000000";b=[w,...d,x]}else c?b=d:b=t;let m;if(s){const w=b;if(b=b.map(x=>k(String(x))[f]()),f==="hcl"&&b.forEach(x=>{x[1]=Number.isNaN(x[1])?0:x[1]}),f==="jch")for(let x=0;xg(S))}else g=k.scale(b.map(w=>typeof w=="object"&&w.constructor===k.Color?w:String(w))).domain(l).mode(f);return u?g:(!s||s===!1?g.colors(e):m).filter(w=>w!=null)}function e0(e,t){const r=[],n={};return Object.keys(e).forEach(s=>{n[e[s][t]]=e[s]}),Object.keys(n).forEach(s=>r.push(n[s])),r}function r0(e){return Number.isNaN(e)?0:e}function on(e,t,r=!1){if(!e)throw new Error(`Cannot convert color value of “${e}”`);if(!Gt[t])throw new Error(`Cannot convert to colorspace “${t}”`);const n=Gt[t],o=k(String(e))[n]();if(t==="HSL"&&o.pop(),t==="HEX"){if(r){const u=k(String(e)).rgb();return{r:u[0],g:u[1],b:u[2]}}return o}const i={};let s=o.map(r0);s=s.map((u,f)=>{let l=wt(u),h=f;n==="hsluv"&&(h+=2);let d=n.charAt(h);return n==="jch"&&d==="c"&&(d="C"),i[d==="j"?"J":d]=l,n in{lab:1,lch:1,jab:1,jch:1}?r||(d==="l"||d==="j")&&(l+="%"):n!=="hsluv"&&(d==="s"||d==="l"||d==="v")&&(i[d]=wt(u,2),r||(l=wt(u*100),l+="%")),l});const c=`${n}(${s.join(", ")})`;return r?i:c}function Fs(e,t,r){const n=[e,t,r].map(o=>(o/=255,o<=.03928?o/12.92:((o+.055)/1.055)**2.4));return n[0]*.2126+n[1]*.7152+n[2]*.0722}function n0(e,t,r,n="wcag2"){if(r===void 0){const o=k.rgb(...t).hsluv()[2];r=wt(o/100,2)}if(n==="wcag2"){const o=Fs(e[0],e[1],e[2]),i=Fs(t[0],t[1],t[2]),s=(o+.05)/(i+.05),a=(i+.05)/(o+.05);return r<.5?s>=1?s:-a:s<1?a:s===1?s:-s}else{if(n==="wcag3")return r<.5?Is(ge(e),ge(t))*-1:Is(ge(e),ge(t));throw new Error(`Contrast calculation method ${n} unsupported; use 'wcag2' or 'wcag3'`)}}function o0(e,t){if(!e)throw new Error("Array undefined");if(!Array.isArray(e))throw new Error("Passed object is not an array");const r=t==="wcag2"?0:1;return Math.min(...e.filter(n=>n>=r))}function s0(e,t){if(!e)throw new Error("Ratios undefined");e=e.sort((a,c)=>a-c);const r=o0(e,t),n=e.indexOf(r),o=[],i=e.slice(0,n),s=e.slice(n,e.length);for(let a=0;aa-c),o}const i0=(e,t,r,n,o)=>{const s=nn({swatches:3e3,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),a={},c=l=>{if(a[l])return a[l];const h=k(s(l)).rgb(),d=n0(h,t,r,o);return a[l]=d,d},u=l=>{const h=c(0),d=c(3e3),b=hg&&w;)w--,m/=2,Lf.push(s(u(+l)))),f};class Q{constructor({name:t,colorKeys:r,colorspace:n,colorSpace:o=n??"RGB",ratios:i,smooth:s=!1,output:a="HEX",saturation:c=100}){if(n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),this._name=t,this._colorKeys=r,this._modifiedKeys=r,this._colorspace=o,this._ratios=i,this._smooth=s,this._output=a,this._saturation=c,!this._name)throw new Error("Color missing name");if(!this._colorKeys)throw new Error("Color Keys are undefined");if(!Gt[this._colorspace])throw new Error(`Colorspace “${o}” not supported`);if(!Gt[this._output])throw new Error(`Output “${this._output}” not supported`);for(let u=0;u{let n=k(`${r}`).oklch(),i=n[1]*(this._saturation/100),s=k.oklch(n[0],i,n[2]),a=k.rgb(s).hex();t.push(a)}),this._modifiedKeys=t,this._generateColorScale()}_generateColorScale(){this._colorScale=nn({swatches:3e3,colorKeys:this._modifiedKeys,colorSpace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}}class Ks extends Q{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){Q.prototype._generateColorScale.call(this);const t=nn({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});t.push(...this.colorKeys);const r=t.map((i,s)=>({value:Math.round(Uc(i)[2]),index:s})),o=e0(r,"value").map(i=>t[i.index]);return o.length>=101&&(o.length=100,o.push("#ffffff")),this._backgroundColorScale=o.map(i=>on(i,this._output)),this._backgroundColorScale}}class a0{constructor({colors:t,backgroundColor:r,lightness:n,contrast:o=1,saturation:i=100,output:s="HEX",formula:a="wcag2"}){if(this._output=s,this._colors=t,this._lightness=n,this._saturation=i,this._formula=a,this._setBackgroundColor(r),this._setBackgroundColorValue(),this._contrast=o,!this._colors)throw new Error("No colors are defined");if(!this._backgroundColor)throw new Error("Background color is undefined");if(t.forEach(c=>{if(!c.ratios)throw new Error(`Color ${c.name}'s ratios are undefined`)}),!Gt[this._output])throw new Error(`Output “${s}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(t){this._formula=t,this._findContrastColors()}get formula(){return this._formula}set contrast(t){this._contrast=t,this._findContrastColors()}get contrast(){return this._contrast}set lightness(t){this._lightness=t,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(t){this._saturation=t,this._updateColorSaturation(t),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(t){this._setBackgroundColor(t),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(t){this._colors=t,this._findContrastColors()}get colors(){return this._colors}set addColor(t){this._colors.push(t),this._findContrastColors()}set removeColor(t){const r=this._colors.filter(n=>n.name!==t.name);this._colors=r,this._findContrastColors()}set updateColor(t){if(Array.isArray(t))for(let r=0;rs.name===t[r].color);n=n[0];let o=this._colors.indexOf(n);const i=this._colors.filter(s=>s.name!==t[r].color);t[r].name&&(n.name=t[r].name),t[r].colorKeys&&(n.colorKeys=t[r].colorKeys),t[r].ratios&&(n.ratios=t[r].ratios),(t[r].colorSpace!==void 0||t[r].colorspace!==void 0)&&(t[r].colorspace!==void 0&&t[r].colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),n.colorSpace=t[r].colorSpace??t[r].colorspace),t[r].smooth&&(n.smooth=t[r].smooth),n._generateColorScale(),i.splice(o,0,n),this._colors=i}else{let r=this._colors.filter(i=>i.name===t.color);r=r[0];let n=this._colors.indexOf(r);const o=this._colors.filter(i=>i.name!==t.color);t.name&&(r.name=t.name),t.colorKeys&&(r.colorKeys=t.colorKeys),t.ratios&&(r.ratios=t.ratios),(t.colorSpace!==void 0||t.colorspace!==void 0)&&(t.colorspace!==void 0&&t.colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),r.colorSpace=t.colorSpace??t.colorspace),t.smooth&&(r.smooth=t.smooth),r._generateColorScale(),o.splice(n,0,r),this._colors=o}this._findContrastColors()}set output(t){this._output=t,this._colors.forEach(r=>{r.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(t){if(typeof t=="string"){const r=new Ks({name:"background",colorKeys:[t],output:"RGB"}),n=wt(k(String(t)).hsluv()[2]);this._backgroundColor=r,this._lightness=n,this._backgroundColorValue=r[this._lightness]}else{t.output="RGB";const r=t.backgroundColorScale[this._lightness];this._backgroundColor=t,this._backgroundColorValue=r}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(t){this._colors.map(r=>{r.saturation=t})}_findContrastColors(){const t=k(String(this._backgroundColorValue)).rgb(),r=this._lightness/100,o={background:on(this._backgroundColorValue,this._output)},i=[],s=[],a={...o};return i.push(o),this._colors.map(c=>{if(c.ratios!==void 0){let u;const f=[],l={name:c.name,values:f};let h;Array.isArray(c.ratios)?h=c.ratios:Array.isArray(c.ratios)||(u=Object.keys(c.ratios),h=Object.values(c.ratios)),h=h.map(b=>Hc(+b,this._contrast));const d=i0(c,t,r,h,this._formula).map(b=>on(b,this._output));for(let b=0;b{const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},Ds=(e,t,r)=>{const n=e/255,o=t/255,i=r/255,s=Math.min(n,o,i),a=Math.max(n,o,i),c=a-s;let u=0,f=0,l=0;return c===0?u=0:a===n?u=(o-i)/c%6:a===o?u=(i-n)/c+2:u=(n-o)/c+4,u=Math.round(u*60),u<0&&(u+=360),l=(a+s)/2,f=c===0?0:c/(1-Math.abs(2*l-1)),f=+(f*100).toFixed(1),l=+(l*100).toFixed(1),[u,f,Math.round(l)]},u0=(e,t,r,n)=>{const o=r/100,i=t*Math.min(o,1-o)/100,s=d=>{const b=(d+e/30)%12,g=o-i*Math.max(Math.min(b-3,9-b,1),-1);return Math.round(255*g).toString(16).padStart(2,"0").toUpperCase()},a=s(0),c=s(8),u=s(4),l=((d,b,g)=>Math.min(Math.max(d,b),g))(n,0,1),h=Math.round(l*255).toString(16).padStart(2,"0").toUpperCase();return`#${a}${c}${u}${h}`},l0=(e,t,r=1)=>{const n=Xs(e),o=Xs(t==="white"?"#FFFFFF":t==="black"?"#000000":t),i=n.map((u,f)=>[(u-o[f])/(255-o[f]),(u-o[f])/(0-o[f])]),s=c0(Math.max(...i.flat().filter(u=>/^-?\d+\.?\d*$/.test(u)))),a=n.map((u,f)=>Math.round((u-o[f]+o[f]*s)/s));if(a.includes(Number.NaN)){const u=Ds(n[0],n[1],n[2]);return{h:u[0],s:Math.round(u[1]*r),l:u[2],a:1}}const c=Ds(a[0],a[1],a[2]);return{h:c[0],s:Math.round(c[1]*r),l:c[2],a:s}},sn={backgroundColor:"gray",colorSpace:"OKLCH",colorSmoothing:!1,formula:"wcag2",output:"HEX",colors:{gray:[I(215,20,90),I(215,8,50),I(215,6,25)],red:[I(358,100,58),I(350,100,30)],orange:[I(32,100,48),I(12,100,30)],yellow:[I(50,100,50),I(25,100,20)],lime:[I(100,68,50),I(115,86,25)],green:[I(163,87,42),I(168,100,25)],cyan:[I(185,80,45),I(200,98,35)],blue:[I(212,98,46),I(222,95,25)],purple:[I(258,94,64),I(265,100,35)],fuchsia:[I(295,56,50),I(285,80,25)],pink:[I(334,90,50),I(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function I(e,t,r){return k.hsl(e,t/100,r/100).hex()}function f0(e,t){const r=e.colorSpace,n=e.colorSmoothing,o=e.themes[t].ratios,i=new Ks({name:"gray",colorKeys:e.colors.gray,colorspace:r,ratios:o,smooth:n}),s=new Q({name:"blue",colorKeys:e.colors.blue,colorspace:r,ratios:o,smooth:n}),a=new Q({name:"cyan",colorKeys:e.colors.cyan,colorspace:r,ratios:o,smooth:n}),c=new Q({name:"fuchsia",colorKeys:e.colors.fuchsia,colorspace:r,ratios:o,smooth:n}),u=new Q({name:"green",colorKeys:e.colors.green,colorspace:r,ratios:o,smooth:n}),f=new Q({name:"lime",colorKeys:e.colors.lime,colorspace:r,ratios:o,smooth:n}),l=new Q({name:"orange",colorKeys:e.colors.orange,colorspace:r,ratios:o,smooth:n}),h=new Q({name:"pink",colorKeys:e.colors.pink,colorspace:r,ratios:o,smooth:n}),d=new Q({name:"purple",colorKeys:e.colors.purple,colorspace:r,ratios:o,smooth:n}),b=new Q({name:"red",colorKeys:e.colors.red,colorspace:r,ratios:o,smooth:n}),g=new Q({name:"yellow",colorKeys:e.colors.yellow,colorspace:r,ratios:o,smooth:n}),m={gray:i,red:b,orange:l,yellow:g,lime:f,green:u,cyan:a,blue:s,purple:d,fuchsia:c,pink:h};return e.colors.custom&&(m.custom=new Q({name:"custom",colorKeys:e.colors.custom,colorspace:r,ratios:o,smooth:n})),new a0({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function Vs(e){const t={};for(const r of Object.keys(e.themes))t[r]=f0(e,r);return t}function h0(e){sn.colors.custom=[e];const t=Vs(sn);return Object.fromEntries(Object.entries(t).map(([r,n])=>{const o=n.find(s=>s&&s.name==="custom"),i=Object.fromEntries(o.values.map(({name:s,value:a})=>[s,a]));for(const[s,a]of Object.entries(i)){const c=l0(a,n[0].background);i[`alpha${s.charAt(0).toUpperCase()+s.slice(1)}`]=u0(c.h,c.s,c.l,c.a)}return[r,i]}))}return $t.generateCustomColors=h0,$t.generateThemesJson=Vs,$t.hslToHex=I,$t.leonardoConfig=sn,Object.defineProperty($t,Symbol.toStringTag,{value:"Module"}),$t})({}); +var CompoundTheme=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),c=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},l=(e,r,i)=>(i=e==null?{}:t(a(e)),c(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),{min:u,max:d}=Math,f=(e,t=0,n=1)=>u(d(t,e),n),p=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=f(e[t],0,255)):t===3&&(e[t]=f(e[t],0,1));return e},m={};for(let e of[`Boolean`,`Number`,`String`,`Function`,`Array`,`Date`,`RegExp`,`Undefined`,`Null`])m[`[object ${e}]`]=e.toLowerCase();function h(e){return m[Object.prototype.toString.call(e)]||`object`}var g=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):h(e[0])==`object`&&t?t.split(``).filter(t=>e[0][t]!==void 0).map(t=>e[0][t]):e[0].slice(0),_=e=>{if(e.length<2)return null;let t=e.length-1;return h(e[t])==`string`?e[t].toLowerCase():null},{PI:v,min:y,max:b}=Math,x=e=>Math.round(e*100)/100,S=e=>Math.round(e*100)/100,C=v*2,w=v/3,T=v/180,ee=180/v;function E(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}var D={format:{},autodetect:[]},O=class{constructor(...e){let t=this;if(h(e[0])===`object`&&e[0].constructor&&e[0].constructor===this.constructor)return e[0];let n=_(e),r=!1;if(!n){r=!0,D.sorted||=(D.autodetect=D.autodetect.sort((e,t)=>t.p-e.p),!0);for(let t of D.autodetect)if(n=t.test(...e),n)break}if(D.format[n])t._rgb=p(D.format[n].apply(null,r?e:e.slice(0,-1)));else throw Error(`unknown format: `+e);t._rgb.length===3&&t._rgb.push(1)}toString(){return h(this.hex)==`function`?this.hex():`[${this._rgb.join(`,`)}]`}},te=`3.2.0`,k=(...e)=>new O(...e);k.version=te;var A={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,laserlemon:`#ffff54`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrod:`#fafad2`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,maroon2:`#7f0000`,maroon3:`#b03060`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,purple2:`#7f007f`,purple3:`#a020f0`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`},ne=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,re=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,ie=e=>{if(e.match(ne)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);let t=parseInt(e,16);return[t>>16,t>>8&255,t&255,1]}if(e.match(re)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);let t=parseInt(e,16);return[t>>24&255,t>>16&255,t>>8&255,Math.round((t&255)/255*100)/100]}throw Error(`unknown hex color: ${e}`)},{round:ae}=Math,oe=(...e)=>{let[t,n,r,i]=g(e,`rgba`),a=_(e)||`auto`;i===void 0&&(i=1),a===`auto`&&(a=i<1?`rgba`:`rgb`),t=ae(t),n=ae(n),r=ae(r);let o=`000000`+(t<<16|n<<8|r).toString(16);o=o.substr(o.length-6);let s=`0`+ae(i*255).toString(16);switch(s=s.substr(s.length-2),a.toLowerCase()){case`rgba`:return`#${o}${s}`;case`argb`:return`#${s}${o}`;default:return`#${o}`}};O.prototype.name=function(){let e=oe(this._rgb,`rgb`);for(let t of Object.keys(A))if(A[t]===e)return t.toLowerCase();return e},D.format.named=e=>{if(e=e.toLowerCase(),A[e])return ie(A[e]);throw Error(`unknown color name: `+e)},D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&A[e.toLowerCase()])return`named`}}),O.prototype.alpha=function(e,t=!1){return e!==void 0&&h(e)===`number`?t?(this._rgb[3]=e,this):new O([this._rgb[0],this._rgb[1],this._rgb[2],e],`rgb`):this._rgb[3]},O.prototype.clipped=function(){return this._rgb._clipped||!1};var j={Kn:18,labWhitePoint:`d65`,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},se=new Map([[`a`,[1.0985,.35585]],[`b`,[1.0985,.35585]],[`c`,[.98074,1.18232]],[`d50`,[.96422,.82521]],[`d55`,[.95682,.92149]],[`d65`,[.95047,1.08883]],[`e`,[1,1,1]],[`f2`,[.99186,.67393]],[`f7`,[.95041,1.08747]],[`f11`,[1.00962,.6435]],[`icc`,[.96422,.82521]]]);function M(e){let t=se.get(String(e).toLowerCase());if(!t)throw Error(`unknown Lab illuminant `+e);j.labWhitePoint=e,j.Xn=t[0],j.Zn=t[1]}function ce(){return j.labWhitePoint}var N=(...e)=>{e=g(e,`lab`);let[t,n,r]=e,[i,a,o]=le(t,n,r),[s,c,l]=de(i,a,o);return[s,c,l,e.length>3?e[3]:1]},le=(e,t,n)=>{let{kE:r,kK:i,kKE:a,Xn:o,Yn:s,Zn:c}=j,l=(e+16)/116,u=.002*t+l,d=l-.005*n,f=u*u*u,p=d*d*d,m=f>r?f:(116*u-16)/i,h=e>a?((e+16)/116)**3:e/i,g=p>r?p:(116*d-16)/i;return[m*o,h*s,g*c]},ue=e=>{let t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*e**(1/2.4)-.055)*t},de=(e,t,n)=>{let{MtxAdaptMa:r,MtxAdaptMaI:i,MtxXYZ2RGB:a,RefWhiteRGB:o,Xn:s,Yn:c,Zn:l}=j,u=s*r.m00+c*r.m10+l*r.m20,d=s*r.m01+c*r.m11+l*r.m21,f=s*r.m02+c*r.m12+l*r.m22,p=o.X*r.m00+o.Y*r.m10+o.Z*r.m20,m=o.X*r.m01+o.Y*r.m11+o.Z*r.m21,h=o.X*r.m02+o.Y*r.m12+o.Z*r.m22,g=(e*r.m00+t*r.m10+n*r.m20)*(p/u),_=(e*r.m01+t*r.m11+n*r.m21)*(m/d),v=(e*r.m02+t*r.m12+n*r.m22)*(h/f),y=g*i.m00+_*i.m10+v*i.m20,b=g*i.m01+_*i.m11+v*i.m21,x=g*i.m02+_*i.m12+v*i.m22,S=ue(y*a.m00+b*a.m10+x*a.m20),C=ue(y*a.m01+b*a.m11+x*a.m21),w=ue(y*a.m02+b*a.m12+x*a.m22);return[S*255,C*255,w*255]},fe=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=he(t,n,r),[c,l,u]=pe(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function pe(e,t,n){let{Xn:r,Yn:i,Zn:a,kE:o,kK:s}=j,c=e/r,l=t/i,u=n/a,d=c>o?c**(1/3):(s*c+16)/116,f=l>o?l**(1/3):(s*l+16)/116,p=u>o?u**(1/3):(s*u+16)/116;return[116*f-16,500*(d-f),200*(f-p)]}function me(e){let t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:((e+.055)/1.055)**2.4)*t}var he=(e,t,n)=>{e=me(e/255),t=me(t/255),n=me(n/255);let{MtxRGB2XYZ:r,MtxAdaptMa:i,MtxAdaptMaI:a,Xn:o,Yn:s,Zn:c,As:l,Bs:u,Cs:d}=j,f=e*r.m00+t*r.m10+n*r.m20,p=e*r.m01+t*r.m11+n*r.m21,m=e*r.m02+t*r.m12+n*r.m22,h=o*i.m00+s*i.m10+c*i.m20,g=o*i.m01+s*i.m11+c*i.m21,_=o*i.m02+s*i.m12+c*i.m22,v=f*i.m00+p*i.m10+m*i.m20,y=f*i.m01+p*i.m11+m*i.m21,b=f*i.m02+p*i.m12+m*i.m22;return v*=h/l,y*=g/u,b*=_/d,f=v*a.m00+y*a.m10+b*a.m20,p=v*a.m01+y*a.m11+b*a.m21,m=v*a.m02+y*a.m12+b*a.m22,[f,p,m]};O.prototype.lab=function(){return fe(this._rgb)},Object.assign(k,{lab:(...e)=>new O(...e,`lab`),getLabWhitePoint:ce,setLabWhitePoint:M}),D.format.lab=N,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`lab`),h(e)===`array`&&e.length===3)return`lab`}}),O.prototype.darken=function(e=1){let t=this,n=t.lab();return n[0]-=j.Kn*e,new O(n,`lab`).alpha(t.alpha(),!0)},O.prototype.brighten=function(e=1){return this.darken(-e)},O.prototype.darker=O.prototype.darken,O.prototype.brighter=O.prototype.brighten,O.prototype.get=function(e){let[t,n]=e.split(`.`),r=this[t]();if(n){let e=t.indexOf(n)-(t.substr(0,2)===`ok`?2:0);if(e>-1)return r[e];throw Error(`unknown channel ${n} in mode ${t}`)}else return r};var{pow:ge}=Math,_e=1e-7,ve=20;O.prototype.luminance=function(e,t=`rgb`){if(e!==void 0&&h(e)===`number`){if(e===0)return new O([0,0,0,this._rgb[3]],`rgb`);if(e===1)return new O([255,255,255,this._rgb[3]],`rgb`);let n=this.luminance(),r=ve,i=(n,a)=>{let o=n.interpolate(a,.5,t),s=o.luminance();return Math.abs(e-s)<_e||!r--?o:s>e?i(n,o):i(o,a)};return new O([...(n>e?i(new O([0,0,0]),this):i(this,new O([255,255,255]))).rgb(),this._rgb[3]])}return ye(...this._rgb.slice(0,3))};var ye=(e,t,n)=>(e=be(e),t=be(t),n=be(n),.2126*e+.7152*t+.0722*n),be=e=>(e/=255,e<=.03928?e/12.92:ge((e+.055)/1.055,2.4)),P={},F=(e,t,n=.5,...r)=>{let i=r[0]||`lrgb`;if(!P[i]&&!r.length&&(i=Object.keys(P)[0]),!P[i])throw Error(`interpolation mode ${i} is not defined`);return h(e)!==`object`&&(e=new O(e)),h(t)!==`object`&&(t=new O(t)),P[i](e,t,n).alpha(e.alpha()+n*(t.alpha()-e.alpha()))};O.prototype.mix=O.prototype.interpolate=function(e,t=.5,...n){return F(this,e,t,...n)},O.prototype.premultiply=function(e=!1){let t=this._rgb,n=t[3];return e?(this._rgb=[t[0]*n,t[1]*n,t[2]*n,n],this):new O([t[0]*n,t[1]*n,t[2]*n,n],`rgb`)};var{sin:xe,cos:Se}=Math,Ce=(...e)=>{let[t,n,r]=g(e,`lch`);return isNaN(r)&&(r=0),r*=T,[t,Se(r)*n,xe(r)*n]},we=(...e)=>{e=g(e,`lch`);let[t,n,r]=e,[i,a,o]=Ce(t,n,r),[s,c,l]=N(i,a,o);return[s,c,l,e.length>3?e[3]:1]},Te=(...e)=>we(...E(g(e,`hcl`))),{sqrt:Ee,atan2:De,round:Oe}=Math,ke=(...e)=>{let[t,n,r]=g(e,`lab`),i=Ee(n*n+r*r),a=(De(r,n)*ee+360)%360;return Oe(i*1e4)===0&&(a=NaN),[t,i,a]},Ae=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=fe(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};O.prototype.lch=function(){return Ae(this._rgb)},O.prototype.hcl=function(){return E(Ae(this._rgb))},Object.assign(k,{lch:(...e)=>new O(...e,`lch`),hcl:(...e)=>new O(...e,`hcl`)}),D.format.lch=we,D.format.hcl=Te,[`lch`,`hcl`].forEach(e=>D.autodetect.push({p:2,test:(...t)=>{if(t=g(t,e),h(t)===`array`&&t.length===3)return e}})),O.prototype.saturate=function(e=1){let t=this,n=t.lch();return n[1]+=j.Kn*e,n[1]<0&&(n[1]=0),new O(n,`lch`).alpha(t.alpha(),!0)},O.prototype.desaturate=function(e=1){return this.saturate(-e)},O.prototype.set=function(e,t,n=!1){let[r,i]=e.split(`.`),a=this[r]();if(i){let e=r.indexOf(i)-(r.substr(0,2)===`ok`?2:0);if(e>-1){if(h(t)==`string`)switch(t.charAt(0)){case`+`:a[e]+=+t;break;case`-`:a[e]+=+t;break;case`*`:a[e]*=+t.substr(1);break;case`/`:a[e]/=+t.substr(1);break;default:a[e]=+t}else if(h(t)===`number`)a[e]=t;else throw Error(`unsupported value for Color.set`);let i=new O(a,r);return n?(this._rgb=i._rgb,this):i}throw Error(`unknown channel ${i} in mode ${r}`)}else return a},O.prototype.tint=function(e=.5,...t){return F(this,`white`,e,...t)},O.prototype.shade=function(e=.5,...t){return F(this,`black`,e,...t)},P.rgb=(e,t,n)=>{let r=e._rgb,i=t._rgb;return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`rgb`)};var{sqrt:je,pow:Me}=Math;P.lrgb=(e,t,n)=>{let[r,i,a]=e._rgb,[o,s,c]=t._rgb;return new O(je(Me(r,2)*(1-n)+Me(o,2)*n),je(Me(i,2)*(1-n)+Me(s,2)*n),je(Me(a,2)*(1-n)+Me(c,2)*n),`rgb`)},P.lab=(e,t,n)=>{let r=e.lab(),i=t.lab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`lab`)};var Ne=(e,t,n,r)=>{let i,a;r===`hsl`?(i=e.hsl(),a=t.hsl()):r===`hsv`?(i=e.hsv(),a=t.hsv()):r===`hcg`?(i=e.hcg(),a=t.hcg()):r===`hsi`?(i=e.hsi(),a=t.hsi()):r===`lch`||r===`hcl`?(r=`hcl`,i=e.hcl(),a=t.hcl()):r===`oklch`&&(i=e.oklch().reverse(),a=t.oklch().reverse());let o,s,c,l,u,d;(r.substr(0,1)===`h`||r===`oklch`)&&([o,c,u]=i,[s,l,d]=a);let f,p,m,h;return!isNaN(o)&&!isNaN(s)?(h=s>o&&s-o>180?s-(o+360):s180?s+360-o:s-o,p=o+n*h):isNaN(o)?isNaN(s)?p=NaN:(p=s,(u==1||u==0)&&r!=`hsv`&&(f=l)):(p=o,(d==1||d==0)&&r!=`hsv`&&(f=c)),f===void 0&&(f=c+n*(l-c)),m=u+n*(d-u),r===`oklch`?new O([m,f,p],r):new O([p,f,m],r)},Pe=(e,t,n)=>Ne(e,t,n,`lch`);P.lch=Pe,P.hcl=Pe;var Fe=e=>{if(h(e)==`number`&&e>=0&&e<=16777215)return[e>>16,e>>8&255,e&255,1];throw Error(`unknown num color: `+e)},Ie=(...e)=>{let[t,n,r]=g(e,`rgb`);return(t<<16)+(n<<8)+r};O.prototype.num=function(){return Ie(this._rgb)},Object.assign(k,{num:(...e)=>new O(...e,`num`)}),D.format.num=Fe,D.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&h(e[0])===`number`&&e[0]>=0&&e[0]<=16777215)return`num`}}),P.num=(e,t,n)=>{let r=e.num();return new O(r+n*(t.num()-r),`num`)};var{floor:Le}=Math,Re=(...e)=>{e=g(e,`hcg`);let[t,n,r]=e,i,a,o;r*=255;let s=n*255;if(n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Le(t),c=t-e,l=r*(1-n),u=l+s*(1-c),d=l+s*c,f=l+s;switch(e){case 0:[i,a,o]=[f,d,l];break;case 1:[i,a,o]=[u,f,l];break;case 2:[i,a,o]=[l,f,d];break;case 3:[i,a,o]=[l,u,f];break;case 4:[i,a,o]=[d,l,f];break;case 5:[i,a,o]=[f,l,u];break}}return[i,a,o,e.length>3?e[3]:1]},ze=(...e)=>{let[t,n,r]=g(e,`rgb`),i=y(t,n,r),a=b(t,n,r),o=a-i,s=o*100/255,c=i/(255-o)*100,l;return o===0?l=NaN:(t===a&&(l=(n-r)/o),n===a&&(l=2+(r-t)/o),r===a&&(l=4+(t-n)/o),l*=60,l<0&&(l+=360)),[l,s,c]};O.prototype.hcg=function(){return ze(this._rgb)},k.hcg=(...e)=>new O(...e,`hcg`),D.format.hcg=Re,D.autodetect.push({p:1,test:(...e)=>{if(e=g(e,`hcg`),h(e)===`array`&&e.length===3)return`hcg`}}),P.hcg=(e,t,n)=>Ne(e,t,n,`hcg`);var{cos:Be}=Math,Ve=(...e)=>{e=g(e,`hsi`);let[t,n,r]=e,i,a,o;return isNaN(t)&&(t=0),isNaN(n)&&(n=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(o=(1-n)/3,i=(1+n*Be(C*t)/Be(w-C*t))/3,a=1-(o+i)):t<2/3?(t-=1/3,i=(1-n)/3,a=(1+n*Be(C*t)/Be(w-C*t))/3,o=1-(i+a)):(t-=2/3,a=(1-n)/3,o=(1+n*Be(C*t)/Be(w-C*t))/3,i=1-(a+o)),i=f(r*i*3),a=f(r*a*3),o=f(r*o*3),[i*255,a*255,o*255,e.length>3?e[3]:1]},{min:He,sqrt:Ue,acos:We}=Math,Ge=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i,a=He(t,n,r),o=(t+n+r)/3,s=o>0?1-a/o:0;return s===0?i=NaN:(i=(t-n+(t-r))/2,i/=Ue((t-n)*(t-n)+(t-r)*(n-r)),i=We(i),r>n&&(i=C-i),i/=C),[i*360,s,o]};O.prototype.hsi=function(){return Ge(this._rgb)},k.hsi=(...e)=>new O(...e,`hsi`),D.format.hsi=Ve,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsi`),h(e)===`array`&&e.length===3)return`hsi`}}),P.hsi=(e,t,n)=>Ne(e,t,n,`hsi`);var Ke=(...e)=>{e=g(e,`hsl`);let[t,n,r]=e,i,a,o;if(n===0)i=a=o=r*255;else{let e=[0,0,0],s=[0,0,0],c=r<.5?r*(1+n):r+n-r*n,l=2*r-c,u=t/360;e[0]=u+1/3,e[1]=u,e[2]=u-1/3;for(let t=0;t<3;t++)e[t]<0&&(e[t]+=1),e[t]>1&&--e[t],6*e[t]<1?s[t]=l+(c-l)*6*e[t]:2*e[t]<1?s[t]=c:3*e[t]<2?s[t]=l+(c-l)*(2/3-e[t])*6:s[t]=l;[i,a,o]=[s[0]*255,s[1]*255,s[2]*255]}return e.length>3?[i,a,o,e[3]]:[i,a,o,1]},qe=(...e)=>{e=g(e,`rgba`);let[t,n,r]=e;t/=255,n/=255,r/=255;let i=y(t,n,r),a=b(t,n,r),o=(a+i)/2,s,c;return a===i?(s=0,c=NaN):s=o<.5?(a-i)/(a+i):(a-i)/(2-a-i),t==a?c=(n-r)/(a-i):n==a?c=2+(r-t)/(a-i):r==a&&(c=4+(t-n)/(a-i)),c*=60,c<0&&(c+=360),e.length>3&&e[3]!==void 0?[c,s,o,e[3]]:[c,s,o]};O.prototype.hsl=function(){return qe(this._rgb)},k.hsl=(...e)=>new O(...e,`hsl`),D.format.hsl=Ke,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsl`),h(e)===`array`&&e.length===3)return`hsl`}}),P.hsl=(e,t,n)=>Ne(e,t,n,`hsl`);var{floor:Je}=Math,Ye=(...e)=>{e=g(e,`hsv`);let[t,n,r]=e,i,a,o;if(r*=255,n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Je(t),s=t-e,c=r*(1-n),l=r*(1-n*s),u=r*(1-n*(1-s));switch(e){case 0:[i,a,o]=[r,u,c];break;case 1:[i,a,o]=[l,r,c];break;case 2:[i,a,o]=[c,r,u];break;case 3:[i,a,o]=[c,l,r];break;case 4:[i,a,o]=[u,c,r];break;case 5:[i,a,o]=[r,c,l];break}}return[i,a,o,e.length>3?e[3]:1]},{min:Xe,max:Ze}=Math,Qe=(...e)=>{e=g(e,`rgb`);let[t,n,r]=e,i=Xe(t,n,r),a=Ze(t,n,r),o=a-i,s,c,l;return l=a/255,a===0?(s=NaN,c=0):(c=o/a,t===a&&(s=(n-r)/o),n===a&&(s=2+(r-t)/o),r===a&&(s=4+(t-n)/o),s*=60,s<0&&(s+=360)),[s,c,l]};O.prototype.hsv=function(){return Qe(this._rgb)},k.hsv=(...e)=>new O(...e,`hsv`),D.format.hsv=Ye,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsv`),h(e)===`array`&&e.length===3)return`hsv`}}),P.hsv=(e,t,n)=>Ne(e,t,n,`hsv`);function $e(e,t){let n=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(e=>[e]));let r=t[0].length,i=t[0].map((e,n)=>t.map(e=>e[n])),a=e.map(e=>i.map(t=>Array.isArray(e)?e.reduce((e,n,r)=>e+n*(t[r]||0),0):t.reduce((t,n)=>t+n*e,0)));return n===1&&(a=a[0]),r===1?a.map(e=>e[0]):a}var et=(...e)=>{e=g(e,`lab`);let[t,n,r,...i]=e,[a,o,s]=tt([t,n,r]),[c,l,u]=de(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function tt(e){return $e([[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],$e([[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],e).map(e=>e**3))}var nt=(...e)=>{let[t,n,r,...i]=g(e,`rgb`);return[...rt(he(t,n,r)),...i.length>0&&i[0]<1?[i[0]]:[]]};function rt(e){return $e([[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],$e([[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],e).map(e=>Math.cbrt(e)))}O.prototype.oklab=function(){return nt(this._rgb)},Object.assign(k,{oklab:(...e)=>new O(...e,`oklab`)}),D.format.oklab=et,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklab`),h(e)===`array`&&e.length===3)return`oklab`}}),P.oklab=(e,t,n)=>{let r=e.oklab(),i=t.oklab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`oklab`)},P.oklch=(e,t,n)=>Ne(e,t,n,`oklch`);var{pow:it,sqrt:at,PI:ot,cos:st,sin:ct,atan2:lt}=Math,ut=(e,t=`lrgb`,n=null)=>{let r=e.length;n||=Array.from(Array(r)).map(()=>1);let i=r/n.reduce(function(e,t){return e+t});if(n.forEach((e,t)=>{n[t]*=i}),e=e.map(e=>new O(e)),t===`lrgb`)return dt(e,n);let a=e.shift(),o=a.get(t),s=[],c=0,l=0;for(let e=0;e{let i=e.get(t);u+=e.alpha()*n[r+1];for(let e=0;e=360;)t-=360;o[e]=t}else o[e]=o[e]/s[e];return u/=r,new O(o,t).alpha(u>.99999?1:u,!0)},dt=(e,t)=>{let n=e.length,r=[0,0,0,0];for(let i=0;i.9999999&&(r[3]=1),new O(p(r))},{pow:ft}=Math;function pt(e){let t=`rgb`,n=k(`#ccc`),r=0,i=[0,1],a=[0,1],o=[],s=[0,0],c=!1,l=[],u=!1,d=0,p=1,m=!1,g={},_=!0,v=1,y=function(e){if(e||=[`#fff`,`#000`],e&&h(e)===`string`&&k.brewer&&k.brewer[e.toLowerCase()]&&(e=k.brewer[e.toLowerCase()]),h(e)===`array`){e.length===1&&(e=[e[0],e[0]]),e=e.slice(0);for(let t=0;t=c[n];)n++;return n-1}return 0},x=e=>e,S=e=>e,C=function(e,r){let i,a;if(r??=!1,isNaN(e)||e===null)return n;a=r?e:c&&c.length>2?b(e)/(c.length-2):p===d?1:(e-d)/(p-d),a=S(a),r||(a=x(a)),v!==1&&(a=ft(a,v)),a=s[0]+a*(1-s[0]-s[1]),a=f(a,0,1);let u=Math.floor(a*1e4);if(_&&g[u])i=g[u];else{if(h(l)===`array`)for(let e=0;e=n&&e===o.length-1){i=l[e];break}if(a>n&&ag={};y(e);let T=function(e){let t=k(C(e));return u&&t[u]?t[u]():t};return T.classes=function(e){if(e!=null){if(h(e)===`array`)c=e,i=[e[0],e[e.length-1]];else{let t=k.analyze(i);c=e===0?[t.min,t.max]:k.limits(t,`e`,e)}return T}return c},T.domain=function(e){if(!arguments.length)return a;a=e.slice(0),d=e[0],p=e[e.length-1],o=[];let t=l.length;if(e.length===t&&d!==p)for(let t of Array.from(e))o.push((t-d)/(p-d));else{for(let e=0;e2){let t=e.map((t,n)=>n/(e.length-1)),n=e.map(e=>(e-d)/(p-d));n.every((e,n)=>t[n]===e)||(S=e=>{if(e<=0||e>=1)return e;let r=0;for(;e>=n[r+1];)r++;let i=(e-n[r])/(n[r+1]-n[r]);return t[r]+i*(t[r+1]-t[r])})}}return i=[d,p],T},T.mode=function(e){return arguments.length?(t=e,w(),T):t},T.range=function(e,t){return y(e,t),T},T.out=function(e){return u=e,T},T.spread=function(e){return arguments.length?(r=e,T):r},T.correctLightness=function(e){return e??=!0,m=e,w(),x=m?function(e){let t=C(0,!0).lab()[0],n=C(1,!0).lab()[0],r=t>n,i=C(e,!0).lab()[0],a=t+(n-t)*e,o=i-a,s=0,c=1,l=20;for(;Math.abs(o)>.01&&l-- >0;)(function(){return r&&(o*=-1),o<0?(s=e,e+=(c-e)*.5):(c=e,e+=(s-e)*.5),i=C(e,!0).lab()[0],o=i-a})();return e}:e=>e,T},T.padding=function(e){return e==null?s:(h(e)===`number`&&(e=[e,e]),s=e,T)},T.colors=function(t,n){arguments.length<2&&(n=`hex`);let r=[];if(arguments.length===0)r=l.slice(0);else if(t===1)r=[T(.5)];else if(t>1){let e=i[0],n=i[1]-e;r=mt(0,t,!1).map(r=>T(e+r/(t-1)*n))}else{e=[];let t=[];if(c&&c.length>2)for(let e=1,n=c.length,r=1<=n;r?en;r?e++:e--)t.push((c[e-1]+c[e])*.5);else t=i;r=t.map(e=>T(e))}return k[n]&&(r=r.map(e=>e[n]())),r},T.cache=function(e){return e==null?_:(_=e,T)},T.gamma=function(e){return e==null?v:(v=e,T)},T.nodata=function(e){return e==null?n:(n=k(e),T)},T}function mt(e,t,n){let r=[],i=ea;i?t++:t--)r.push(t);return r}var ht=function(e){let t=[1,1];for(let n=1;nnew O(e)),e.length===2)[n,r]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>n[t]+e*(r[t]-n[t])),`lab`)};else if(e.length===3)[n,r,i]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*n[t]+2*(1-e)*e*r[t]+e*e*i[t]),`lab`)};else if(e.length===4){let a;[n,r,i,a]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*(1-e)*n[t]+3*(1-e)*(1-e)*e*r[t]+3*(1-e)*e*e*i[t]+e*e*e*a[t]),`lab`)}}else if(e.length>=5){let n,r,i;n=e.map(e=>e.lab()),i=e.length-1,r=ht(i),t=function(e){let t=1-e;return new O([0,1,2].map(a=>n.reduce((n,o,s)=>n+r[s]*t**(i-s)*e**s*o[a],0)),`lab`)}}else throw RangeError(`No point in running bezier with only one color.`);return t},_t=e=>{let t=gt(e);return t.scale=()=>pt(t),t},{round:vt}=Math;O.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(vt)},O.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,n)=>n<3?e===!1?t:vt(t):t)},Object.assign(k,{rgb:(...e)=>new O(...e,`rgb`)}),D.format.rgb=(...e)=>{let t=g(e,`rgba`);return t[3]===void 0&&(t[3]=1),t},D.autodetect.push({p:3,test:(...e)=>{if(e=g(e,`rgba`),h(e)===`array`&&(e.length===3||e.length===4&&h(e[3])==`number`&&e[3]>=0&&e[3]<=1))return`rgb`}});var I=(e,t,n)=>{if(!I[n])throw Error(`unknown blend mode `+n);return I[n](e,t)},L=e=>(t,n)=>{let r=k(n).rgb(),i=k(t).rgb();return k.rgb(e(r,i))},R=e=>(t,n)=>{let r=[];return r[0]=e(t[0],n[0]),r[1]=e(t[1],n[1]),r[2]=e(t[2],n[2]),r};I.normal=L(R(e=>e)),I.multiply=L(R((e,t)=>e*t/255)),I.screen=L(R((e,t)=>255*(1-(1-e/255)*(1-t/255)))),I.overlay=L(R((e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)))),I.darken=L(R((e,t)=>e>t?t:e)),I.lighten=L(R((e,t)=>e>t?e:t)),I.dodge=L(R((e,t)=>e===255?255:(e=t/255*255/(1-e/255),e>255?255:e))),I.burn=L(R((e,t)=>255*(1-(1-t/255)/(e/255))));var{pow:yt,sin:bt,cos:xt}=Math;function St(e=300,t=-1.5,n=1,r=1,i=[0,1]){let a=0,o;h(i)===`array`?o=i[1]-i[0]:(o=0,i=[i,i]);let s=function(s){let c=C*((e+120)/360+t*s),l=yt(i[0]+o*s,r),u=(a===0?n:n[0]+s*a)*l*(1-l)/2,d=xt(c),f=bt(c),m=l+u*(-.14861*d+1.78277*f),h=l+u*(-.29227*d-.90649*f),g=l+1.97294*d*u;return k(p([m*255,h*255,g*255,1]))};return s.start=function(t){return t==null?e:(e=t,s)},s.rotations=function(e){return e==null?t:(t=e,s)},s.gamma=function(e){return e==null?r:(r=e,s)},s.hue=function(e){return e==null?n:(n=e,h(n)===`array`?(a=n[1]-n[0],a===0&&(n=n[1])):a=0,s)},s.lightness=function(e){return e==null?i:(h(e)===`array`?(i=e,o=e[1]-e[0]):(i=[e,e],o=0),s)},s.scale=()=>k.scale(s),s.hue(n),s}var Ct=`0123456789abcdef`,{floor:wt,random:Tt}=Math,Et=(e=Tt)=>{let t=`#`;for(let n=0;n<6;n++)t+=Ct.charAt(wt(e()*16));return new O(t,`hex`)},{log:Dt,pow:Ot,floor:kt,abs:At}=Math;function jt(e,t=null){let n={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return h(e)===`object`&&(e=Object.values(e)),e.forEach(e=>{t&&h(e)===`object`&&(e=e[t]),e!=null&&!isNaN(e)&&(n.values.push(e),n.sum+=e,en.max&&(n.max=e),n.count+=1)}),n.domain=[n.min,n.max],n.limits=(e,t)=>Mt(n,e,t),n}function Mt(e,t=`equal`,n=7){h(e)==`array`&&(e=jt(e));let{min:r,max:i}=e,a=e.values.sort((e,t)=>e-t);if(n===1)return[r,i];let o=[];if(t.substr(0,1)===`c`&&(o.push(r),o.push(i)),t.substr(0,1)===`e`){o.push(r);for(let e=1;e 0`);let e=Math.LOG10E*Dt(r),t=Math.LOG10E*Dt(i);o.push(r);for(let r=1;r200&&(l=!1)}let f={};for(let e=0;ee-t),o.push(p[0]);for(let e=1;e{e=new O(e),t=new O(t);let n=e.luminance(),r=t.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)},Pt=.027,Ft=5e-4,It=.1,Lt=1.14,Rt=.022,zt=1.414,Bt=(e,t)=>{e=new O(e),t=new O(t),e.alpha()<1&&(e=F(t,e,e.alpha(),`rgb`));let n=Vt(...e.rgb()),r=Vt(...t.rgb()),i=n>=Rt?n:n+(Rt-n)**+zt,a=r>=Rt?r:r+(Rt-r)**+zt,o=a**.56-i**.57,s=a**.65-i**.62,c=Math.abs(a-i)0?c-Pt:c+Pt)*100};function Vt(e,t,n){return .2126729*(e/255)**2.4+.7151522*(t/255)**2.4+.072175*(n/255)**2.4}var{sqrt:z,pow:B,min:Ht,max:Ut,atan2:Wt,abs:Gt,cos:Kt,sin:qt,exp:Jt,PI:Yt}=Math;function Xt(e,t,n=1,r=1,i=1){var a=function(e){return 360*e/(2*Yt)},o=function(e){return 2*Yt*e/360};e=new O(e),t=new O(t);let[s,c,l]=Array.from(e.lab()),[u,d,f]=Array.from(t.lab()),p=(s+u)/2,m=(z(B(c,2)+B(l,2))+z(B(d,2)+B(f,2)))/2,h=.5*(1-z(B(m,7)/(B(m,7)+B(25,7)))),g=c*(1+h),_=d*(1+h),v=z(B(g,2)+B(l,2)),y=z(B(_,2)+B(f,2)),b=(v+y)/2,x=a(Wt(l,g)),S=a(Wt(f,_)),C=x>=0?x:x+360,w=S>=0?S:S+360,T=Gt(C-w)>180?(C+w+360)/2:(C+w)/2,ee=1-.17*Kt(o(T-30))+.24*Kt(o(2*T))+.32*Kt(o(3*T+6))-.2*Kt(o(4*T-63)),E=w-C;E=Gt(E)<=180?E:w<=C?E+360:E-360,E=2*z(v*y)*qt(o(E)/2);let D=u-s,te=y-v,k=1+.015*B(p-50,2)/z(20+B(p-50,2)),A=1+.045*b,ne=1+.015*b*ee,re=30*Jt(-B((T-275)/25,2)),ie=-(2*z(B(b,7)/(B(b,7)+B(25,7))))*qt(2*o(re));return Ut(0,Ht(100,z(B(D/(n*k),2)+B(te/(r*A),2)+B(E/(i*ne),2)+ie*(te/(r*A))*(E/(i*ne)))))}function Zt(e,t,n=`lab`){e=new O(e),t=new O(t);let r=e.get(n),i=t.get(n),a=0;for(let e in r){let t=(r[e]||0)-(i[e]||0);a+=t*t}return Math.sqrt(a)}var Qt=(...e)=>{try{return new O(...e),!0}catch{return!1}},$t={cool(){return pt([k.hsl(180,1,.9),k.hsl(250,.7,.4)])},hot(){return pt([`#000`,`#f00`,`#ff0`,`#fff`],[0,.25,.75,1]).mode(`rgb`)}},en={OrRd:[`#fff7ec`,`#fee8c8`,`#fdd49e`,`#fdbb84`,`#fc8d59`,`#ef6548`,`#d7301f`,`#b30000`,`#7f0000`],PuBu:[`#fff7fb`,`#ece7f2`,`#d0d1e6`,`#a6bddb`,`#74a9cf`,`#3690c0`,`#0570b0`,`#045a8d`,`#023858`],BuPu:[`#f7fcfd`,`#e0ecf4`,`#bfd3e6`,`#9ebcda`,`#8c96c6`,`#8c6bb1`,`#88419d`,`#810f7c`,`#4d004b`],Oranges:[`#fff5eb`,`#fee6ce`,`#fdd0a2`,`#fdae6b`,`#fd8d3c`,`#f16913`,`#d94801`,`#a63603`,`#7f2704`],BuGn:[`#f7fcfd`,`#e5f5f9`,`#ccece6`,`#99d8c9`,`#66c2a4`,`#41ae76`,`#238b45`,`#006d2c`,`#00441b`],YlOrBr:[`#ffffe5`,`#fff7bc`,`#fee391`,`#fec44f`,`#fe9929`,`#ec7014`,`#cc4c02`,`#993404`,`#662506`],YlGn:[`#ffffe5`,`#f7fcb9`,`#d9f0a3`,`#addd8e`,`#78c679`,`#41ab5d`,`#238443`,`#006837`,`#004529`],Reds:[`#fff5f0`,`#fee0d2`,`#fcbba1`,`#fc9272`,`#fb6a4a`,`#ef3b2c`,`#cb181d`,`#a50f15`,`#67000d`],RdPu:[`#fff7f3`,`#fde0dd`,`#fcc5c0`,`#fa9fb5`,`#f768a1`,`#dd3497`,`#ae017e`,`#7a0177`,`#49006a`],Greens:[`#f7fcf5`,`#e5f5e0`,`#c7e9c0`,`#a1d99b`,`#74c476`,`#41ab5d`,`#238b45`,`#006d2c`,`#00441b`],YlGnBu:[`#ffffd9`,`#edf8b1`,`#c7e9b4`,`#7fcdbb`,`#41b6c4`,`#1d91c0`,`#225ea8`,`#253494`,`#081d58`],Purples:[`#fcfbfd`,`#efedf5`,`#dadaeb`,`#bcbddc`,`#9e9ac8`,`#807dba`,`#6a51a3`,`#54278f`,`#3f007d`],GnBu:[`#f7fcf0`,`#e0f3db`,`#ccebc5`,`#a8ddb5`,`#7bccc4`,`#4eb3d3`,`#2b8cbe`,`#0868ac`,`#084081`],Greys:[`#ffffff`,`#f0f0f0`,`#d9d9d9`,`#bdbdbd`,`#969696`,`#737373`,`#525252`,`#252525`,`#000000`],YlOrRd:[`#ffffcc`,`#ffeda0`,`#fed976`,`#feb24c`,`#fd8d3c`,`#fc4e2a`,`#e31a1c`,`#bd0026`,`#800026`],PuRd:[`#f7f4f9`,`#e7e1ef`,`#d4b9da`,`#c994c7`,`#df65b0`,`#e7298a`,`#ce1256`,`#980043`,`#67001f`],Blues:[`#f7fbff`,`#deebf7`,`#c6dbef`,`#9ecae1`,`#6baed6`,`#4292c6`,`#2171b5`,`#08519c`,`#08306b`],PuBuGn:[`#fff7fb`,`#ece2f0`,`#d0d1e6`,`#a6bddb`,`#67a9cf`,`#3690c0`,`#02818a`,`#016c59`,`#014636`],Viridis:[`#440154`,`#482777`,`#3f4a8a`,`#31678e`,`#26838f`,`#1f9d8a`,`#6cce5a`,`#b6de2b`,`#fee825`],Spectral:[`#9e0142`,`#d53e4f`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#e6f598`,`#abdda4`,`#66c2a5`,`#3288bd`,`#5e4fa2`],RdYlGn:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#d9ef8b`,`#a6d96a`,`#66bd63`,`#1a9850`,`#006837`],RdBu:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#f7f7f7`,`#d1e5f0`,`#92c5de`,`#4393c3`,`#2166ac`,`#053061`],PiYG:[`#8e0152`,`#c51b7d`,`#de77ae`,`#f1b6da`,`#fde0ef`,`#f7f7f7`,`#e6f5d0`,`#b8e186`,`#7fbc41`,`#4d9221`,`#276419`],PRGn:[`#40004b`,`#762a83`,`#9970ab`,`#c2a5cf`,`#e7d4e8`,`#f7f7f7`,`#d9f0d3`,`#a6dba0`,`#5aae61`,`#1b7837`,`#00441b`],RdYlBu:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee090`,`#ffffbf`,`#e0f3f8`,`#abd9e9`,`#74add1`,`#4575b4`,`#313695`],BrBG:[`#543005`,`#8c510a`,`#bf812d`,`#dfc27d`,`#f6e8c3`,`#f5f5f5`,`#c7eae5`,`#80cdc1`,`#35978f`,`#01665e`,`#003c30`],RdGy:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#ffffff`,`#e0e0e0`,`#bababa`,`#878787`,`#4d4d4d`,`#1a1a1a`],PuOr:[`#7f3b08`,`#b35806`,`#e08214`,`#fdb863`,`#fee0b6`,`#f7f7f7`,`#d8daeb`,`#b2abd2`,`#8073ac`,`#542788`,`#2d004b`],Set2:[`#66c2a5`,`#fc8d62`,`#8da0cb`,`#e78ac3`,`#a6d854`,`#ffd92f`,`#e5c494`,`#b3b3b3`],Accent:[`#7fc97f`,`#beaed4`,`#fdc086`,`#ffff99`,`#386cb0`,`#f0027f`,`#bf5b17`,`#666666`],Set1:[`#e41a1c`,`#377eb8`,`#4daf4a`,`#984ea3`,`#ff7f00`,`#ffff33`,`#a65628`,`#f781bf`,`#999999`],Set3:[`#8dd3c7`,`#ffffb3`,`#bebada`,`#fb8072`,`#80b1d3`,`#fdb462`,`#b3de69`,`#fccde5`,`#d9d9d9`,`#bc80bd`,`#ccebc5`,`#ffed6f`],Dark2:[`#1b9e77`,`#d95f02`,`#7570b3`,`#e7298a`,`#66a61e`,`#e6ab02`,`#a6761d`,`#666666`],Paired:[`#a6cee3`,`#1f78b4`,`#b2df8a`,`#33a02c`,`#fb9a99`,`#e31a1c`,`#fdbf6f`,`#ff7f00`,`#cab2d6`,`#6a3d9a`,`#ffff99`,`#b15928`],Pastel2:[`#b3e2cd`,`#fdcdac`,`#cbd5e8`,`#f4cae4`,`#e6f5c9`,`#fff2ae`,`#f1e2cc`,`#cccccc`],Pastel1:[`#fbb4ae`,`#b3cde3`,`#ccebc5`,`#decbe4`,`#fed9a6`,`#ffffcc`,`#e5d8bd`,`#fddaec`,`#f2f2f2`]},tn=Object.keys(en),nn=new Map(tn.map(e=>[e.toLowerCase(),e])),rn=typeof Proxy==`function`?new Proxy(en,{get(e,t){let n=t.toLowerCase();if(nn.has(n))return e[nn.get(n)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tn)}}):en,an=(...e)=>{e=g(e,`cmyk`);let[t,n,r,i]=e,a=e.length>4?e[4]:1;return i===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-i),n>=1?0:255*(1-n)*(1-i),r>=1?0:255*(1-r)*(1-i),a]},{max:on}=Math,sn=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i=1-on(t,on(n,r)),a=i<1?1/(1-i):0;return[(1-t-i)*a,(1-n-i)*a,(1-r-i)*a,i]};O.prototype.cmyk=function(){return sn(this._rgb)},Object.assign(k,{cmyk:(...e)=>new O(...e,`cmyk`)}),D.format.cmyk=an,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`cmyk`),h(e)===`array`&&e.length===4)return`cmyk`}});var cn=(...e)=>{let t=g(e,`hsla`),n=_(e)||`lsa`;return t[0]=x(t[0]||0)+`deg`,t[1]=x(t[1]*100)+`%`,t[2]=x(t[2]*100)+`%`,n===`hsla`||t.length>3&&t[3]<1?(t[3]=`/ `+(t.length>3?t[3]:1),n=`hsla`):t.length=3,`${n.substr(0,3)}(${t.join(` `)})`},ln=(...e)=>{let t=g(e,`lab`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=x(t[2]),n===`laba`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(` `)})`},un=(...e)=>{let t=g(e,`lch`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,n===`lcha`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(` `)})`},dn=(...e)=>{let t=g(e,`lab`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=S(t[2]),t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(` `)})`},fn=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=nt(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},pn=(...e)=>{let t=g(e,`lch`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(` `)})`},{round:mn}=Math,hn=(...e)=>{let t=g(e,`rgba`),n=_(e)||`rgb`;if(n.substr(0,3)===`hsl`)return cn(qe(t),n);if(n.substr(0,3)===`lab`){let e=ce();M(`d50`);let r=ln(fe(t),n);return M(e),r}if(n.substr(0,3)===`lch`){let e=ce();M(`d50`);let r=un(Ae(t),n);return M(e),r}return n.substr(0,5)===`oklab`?dn(nt(t)):n.substr(0,5)===`oklch`?pn(fn(t)):(t[0]=mn(t[0]),t[1]=mn(t[1]),t[2]=mn(t[2]),(n===`rgba`||t.length>3&&t[3]<1)&&(t[3]=`/ `+(t.length>3?t[3]:1),n=`rgba`),`${n.substr(0,3)}(${t.slice(0,n===`rgb`?3:4).join(` `)})`)},gn=(...e)=>{e=g(e,`lch`);let[t,n,r,...i]=e,[a,o,s]=Ce(t,n,r),[c,l,u]=et(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},V=`((?:-?\\d+)|(?:-?\\d+(?:\\.\\d+)?)%|none)`,H=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%?)|none)`,_n=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%)|none)`,U=`\\s*`,vn=`\\s+`,yn=`\\s*,\\s*`,bn=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:deg)?)|none)`,xn=`\\s*(?:\\/\\s*((?:[01]|[01]?\\.\\d+)|\\d+(?:\\.\\d+)?%))?`,Sn=RegExp(`^rgba?\\(`+U+[V,V,V].join(vn)+xn+`\\)$`),Cn=RegExp(`^rgb\\(`+U+[V,V,V].join(yn)+U+`\\)$`),wn=RegExp(`^rgba\\(`+U+[V,V,V,H].join(yn)+U+`\\)$`),Tn=RegExp(`^hsla?\\(`+U+[bn,_n,_n].join(vn)+xn+`\\)$`),En=RegExp(`^hsl?\\(`+U+[bn,_n,_n].join(yn)+U+`\\)$`),Dn=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,On=RegExp(`^lab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),kn=RegExp(`^lch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),An=RegExp(`^oklab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),jn=RegExp(`^oklch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),{round:Mn}=Math,Nn=e=>e.map((e,t)=>t<=2?f(Mn(e),0,255):e),W=(e,t=0,n=100,r=!1)=>(typeof e==`string`&&e.endsWith(`%`)&&(e=parseFloat(e.substring(0,e.length-1))/100,e=r?t+(e+1)*.5*(n-t):t+e*(n-t)),+e),G=(e,t)=>e===`none`?t:e,Pn=e=>{if(e=e.toLowerCase().trim(),e===`transparent`)return[0,0,0,0];let t;if(D.format.named)try{return D.format.named(e)}catch{}if((t=e.match(Sn))||(t=e.match(Cn))){let e=t.slice(1,4);for(let t=0;t<3;t++)e[t]=+W(G(e[t],0),0,255);e=Nn(e);let n=t[4]===void 0?1:+W(t[4],0,1);return e[3]=n,e}if(t=e.match(wn)){let e=t.slice(1,5);for(let t=0;t<4;t++)e[t]=+W(e[t],0,255);return e}if((t=e.match(Tn))||(t=e.match(En))){let e=t.slice(1,4);e[0]=+G(e[0].replace(`deg`,``),0),e[1]=W(G(e[1],0),0,100)*.01,e[2]=W(G(e[2],0),0,100)*.01;let n=Nn(Ke(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(Dn)){let e=t.slice(1,4);e[1]*=.01,e[2]*=.01;let n=Ke(e);for(let e=0;e<3;e++)n[e]=Mn(n[e]);return n[3]=+t[4],n}if(t=e.match(On)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,100),e[1]=W(G(e[1],0),-125,125,!0),e[2]=W(G(e[2],0),-125,125,!0);let n=ce();M(`d50`);let r=Nn(N(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(kn)){let e=t.slice(1,4);e[0]=W(e[0],0,100),e[1]=W(G(e[1],0),0,150,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=ce();M(`d50`);let r=Nn(we(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(An)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),-.4,.4,!0),e[2]=W(G(e[2],0),-.4,.4,!0);let n=Nn(et(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(jn)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),0,.4,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=Nn(gn(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}};Pn.test=e=>Sn.test(e)||Tn.test(e)||On.test(e)||kn.test(e)||An.test(e)||jn.test(e)||Cn.test(e)||wn.test(e)||En.test(e)||Dn.test(e)||e===`transparent`,O.prototype.css=function(e){return hn(this._rgb,e)},k.css=(...e)=>new O(...e,`css`),D.format.css=Pn,D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&Pn.test(e))return`css`}}),D.format.gl=(...e)=>{let t=g(e,`rgba`);return t[0]*=255,t[1]*=255,t[2]*=255,t},k.gl=(...e)=>new O(...e,`gl`),O.prototype.gl=function(){let e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},O.prototype.hex=function(e){return oe(this._rgb,e)},k.hex=(...e)=>new O(...e,`hex`),D.format.hex=ie,D.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return`hex`}});var{log:Fn}=Math,In=e=>{let t=e/100,n,r,i;return t<66?(n=255,r=t<6?0:-155.25485562709179-.44596950469579133*(r=t-2)+104.49216199393888*Fn(r),i=t<20?0:-254.76935184120902+.8274096064007395*(i=t-10)+115.67994401066147*Fn(i)):(n=351.97690566805693+.114206453784165*(n=t-55)-40.25366309332127*Fn(n),r=325.4494125711974+.07943456536662342*(r=t-50)-28.0852963507957*Fn(r),i=255),[n,r,i,1]},{round:Ln}=Math,Rn=(...e)=>{let t=g(e,`rgb`),n=t[0],r=t[2],i=1e3,a=4e4,o;for(;a-i>.4;){o=(a+i)*.5;let e=In(o);e[2]/e[0]>=r/n?a=o:i=o}return Ln(o)};O.prototype.temp=O.prototype.kelvin=O.prototype.temperature=function(){return Rn(this._rgb)};var zn=(...e)=>new O(...e,`temp`);Object.assign(k,{temp:zn,kelvin:zn,temperature:zn}),D.format.temp=D.format.kelvin=D.format.temperature=In,O.prototype.oklch=function(){return fn(this._rgb)},Object.assign(k,{oklch:(...e)=>new O(...e,`oklch`)}),D.format.oklch=gn,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklch`),h(e)===`array`&&e.length===3)return`oklch`}}),Object.assign(k,{analyze:jt,average:ut,bezier:_t,blend:I,brewer:rn,Color:O,colors:A,contrast:Nt,contrastAPCA:Bt,cubehelix:St,deltaE:Xt,distance:Zt,input:D,interpolate:F,limits:Mt,mix:F,random:Et,scale:pt,scales:$t,valid:Qt});var K=k,q=class e{constructor(){this.hex=`#000000`,this.rgb_r=0,this.rgb_g=0,this.rgb_b=0,this.xyz_x=0,this.xyz_y=0,this.xyz_z=0,this.luv_l=0,this.luv_u=0,this.luv_v=0,this.lch_l=0,this.lch_c=0,this.lch_h=0,this.hsluv_h=0,this.hsluv_s=0,this.hsluv_l=0,this.hpluv_h=0,this.hpluv_p=0,this.hpluv_l=0,this.r0s=0,this.r0i=0,this.r1s=0,this.r1i=0,this.g0s=0,this.g0i=0,this.g1s=0,this.g1i=0,this.b0s=0,this.b0i=0,this.b1s=0,this.b1i=0}static fromLinear(e){return e<=.0031308?12.92*e:1.055*e**(1/2.4)-.055}static toLinear(e){return e>.04045?((e+.055)/1.055)**2.4:e/12.92}static yToL(t){return t<=e.epsilon?t/e.refY*e.kappa:116*(t/e.refY)**(1/3)-16}static lToY(t){return t<=8?e.refY*t/e.kappa:e.refY*((t+16)/116)**3}static rgbChannelToHex(t){let n=Math.round(t*255),r=n%16,i=(n-r)/16|0;return e.hexChars.charAt(i)+e.hexChars.charAt(r)}static hexToRgbChannel(t,n){let r=e.hexChars.indexOf(t.charAt(n)),i=e.hexChars.indexOf(t.charAt(n+1));return(r*16+i)/255}static distanceFromOriginAngle(e,t,n){let r=t/(Math.sin(n)-e*Math.cos(n));return r<0?1/0:r}static distanceFromOrigin(e,t){return Math.abs(t)/Math.sqrt(e**2+1)}static min6(e,t,n,r,i,a){return Math.min(e,Math.min(t,Math.min(n,Math.min(r,Math.min(i,a)))))}rgbToHex(){this.hex=`#`,this.hex+=e.rgbChannelToHex(this.rgb_r),this.hex+=e.rgbChannelToHex(this.rgb_g),this.hex+=e.rgbChannelToHex(this.rgb_b)}hexToRgb(){this.hex=this.hex.toLowerCase(),this.rgb_r=e.hexToRgbChannel(this.hex,1),this.rgb_g=e.hexToRgbChannel(this.hex,3),this.rgb_b=e.hexToRgbChannel(this.hex,5)}xyzToRgb(){this.rgb_r=e.fromLinear(e.m_r0*this.xyz_x+e.m_r1*this.xyz_y+e.m_r2*this.xyz_z),this.rgb_g=e.fromLinear(e.m_g0*this.xyz_x+e.m_g1*this.xyz_y+e.m_g2*this.xyz_z),this.rgb_b=e.fromLinear(e.m_b0*this.xyz_x+e.m_b1*this.xyz_y+e.m_b2*this.xyz_z)}rgbToXyz(){let t=e.toLinear(this.rgb_r),n=e.toLinear(this.rgb_g),r=e.toLinear(this.rgb_b);this.xyz_x=.41239079926595*t+.35758433938387*n+.18048078840183*r,this.xyz_y=.21263900587151*t+.71516867876775*n+.072192315360733*r,this.xyz_z=.019330818715591*t+.11919477979462*n+.95053215224966*r}xyzToLuv(){let t=this.xyz_x+15*this.xyz_y+3*this.xyz_z,n=4*this.xyz_x,r=9*this.xyz_y;t===0?(n=NaN,r=NaN):(n/=t,r/=t),this.luv_l=e.yToL(this.xyz_y),this.luv_l===0?(this.luv_u=0,this.luv_v=0):(this.luv_u=13*this.luv_l*(n-e.refU),this.luv_v=13*this.luv_l*(r-e.refV))}luvToXyz(){if(this.luv_l===0){this.xyz_x=0,this.xyz_y=0,this.xyz_z=0;return}let t=this.luv_u/(13*this.luv_l)+e.refU,n=this.luv_v/(13*this.luv_l)+e.refV;this.xyz_y=e.lToY(this.luv_l),this.xyz_x=0-9*this.xyz_y*t/((t-4)*n-t*n),this.xyz_z=(9*this.xyz_y-15*n*this.xyz_y-n*this.xyz_x)/(3*n)}luvToLch(){this.lch_l=this.luv_l,this.lch_c=Math.sqrt(this.luv_u*this.luv_u+this.luv_v*this.luv_v),this.lch_c<1e-8?this.lch_h=0:(this.lch_h=Math.atan2(this.luv_v,this.luv_u)*180/Math.PI,this.lch_h<0&&(this.lch_h=360+this.lch_h))}lchToLuv(){let e=this.lch_h/180*Math.PI;this.luv_l=this.lch_l,this.luv_u=Math.cos(e)*this.lch_c,this.luv_v=Math.sin(e)*this.lch_c}calculateBoundingLines(t){let n=(t+16)**3/1560896,r=n>e.epsilon?n:t/e.kappa,i=r*(284517*e.m_r0-94839*e.m_r2),a=r*(838422*e.m_r2+769860*e.m_r1+731718*e.m_r0),o=r*(632260*e.m_r2-126452*e.m_r1),s=r*(284517*e.m_g0-94839*e.m_g2),c=r*(838422*e.m_g2+769860*e.m_g1+731718*e.m_g0),l=r*(632260*e.m_g2-126452*e.m_g1),u=r*(284517*e.m_b0-94839*e.m_b2),d=r*(838422*e.m_b2+769860*e.m_b1+731718*e.m_b0),f=r*(632260*e.m_b2-126452*e.m_b1);this.r0s=i/o,this.r0i=a*t/o,this.r1s=i/(o+126452),this.r1i=(a-769860)*t/(o+126452),this.g0s=s/l,this.g0i=c*t/l,this.g1s=s/(l+126452),this.g1i=(c-769860)*t/(l+126452),this.b0s=u/f,this.b0i=d*t/f,this.b1s=u/(f+126452),this.b1i=(d-769860)*t/(f+126452)}calcMaxChromaHpluv(){let t=e.distanceFromOrigin(this.r0s,this.r0i),n=e.distanceFromOrigin(this.r1s,this.r1i),r=e.distanceFromOrigin(this.g0s,this.g0i),i=e.distanceFromOrigin(this.g1s,this.g1i),a=e.distanceFromOrigin(this.b0s,this.b0i),o=e.distanceFromOrigin(this.b1s,this.b1i);return e.min6(t,n,r,i,a,o)}calcMaxChromaHsluv(t){let n=t/360*Math.PI*2,r=e.distanceFromOriginAngle(this.r0s,this.r0i,n),i=e.distanceFromOriginAngle(this.r1s,this.r1i,n),a=e.distanceFromOriginAngle(this.g0s,this.g0i,n),o=e.distanceFromOriginAngle(this.g1s,this.g1i,n),s=e.distanceFromOriginAngle(this.b0s,this.b0i,n),c=e.distanceFromOriginAngle(this.b1s,this.b1i,n);return e.min6(r,i,a,o,s,c)}hsluvToLch(){this.hsluv_l>99.9999999?(this.lch_l=100,this.lch_c=0):this.hsluv_l<1e-8?(this.lch_l=0,this.lch_c=0):(this.lch_l=this.hsluv_l,this.calculateBoundingLines(this.hsluv_l),this.lch_c=this.calcMaxChromaHsluv(this.hsluv_h)/100*this.hsluv_s),this.lch_h=this.hsluv_h}lchToHsluv(){if(this.lch_l>99.9999999)this.hsluv_s=0,this.hsluv_l=100;else if(this.lch_l<1e-8)this.hsluv_s=0,this.hsluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHsluv(this.lch_h);this.hsluv_s=this.lch_c/e*100,this.hsluv_l=this.lch_l}this.hsluv_h=this.lch_h}hpluvToLch(){this.hpluv_l>99.9999999?(this.lch_l=100,this.lch_c=0):this.hpluv_l<1e-8?(this.lch_l=0,this.lch_c=0):(this.lch_l=this.hpluv_l,this.calculateBoundingLines(this.hpluv_l),this.lch_c=this.calcMaxChromaHpluv()/100*this.hpluv_p),this.lch_h=this.hpluv_h}lchToHpluv(){if(this.lch_l>99.9999999)this.hpluv_p=0,this.hpluv_l=100;else if(this.lch_l<1e-8)this.hpluv_p=0,this.hpluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHpluv();this.hpluv_p=this.lch_c/e*100,this.hpluv_l=this.lch_l}this.hpluv_h=this.lch_h}hsluvToRgb(){this.hsluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hpluvToRgb(){this.hpluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hsluvToHex(){this.hsluvToRgb(),this.rgbToHex()}hpluvToHex(){this.hpluvToRgb(),this.rgbToHex()}rgbToHsluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHsluv()}rgbToHpluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHpluv()}hexToHsluv(){this.hexToRgb(),this.rgbToHsluv()}hexToHpluv(){this.hexToRgb(),this.rgbToHpluv()}};q.hexChars=`0123456789abcdef`,q.refY=1,q.refU=.19783000664283,q.refV=.46831999493879,q.kappa=903.2962962,q.epsilon=.0088564516,q.m_r0=3.240969941904521,q.m_r1=-1.537383177570093,q.m_r2=-.498610760293,q.m_g0=-.96924363628087,q.m_g1=1.87596750150772,q.m_g2=.041555057407175,q.m_b0=.055630079696993,q.m_b1=-.20397695888897,q.m_b2=1.056971514242878;var Bn=s(((e,t)=>{function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=n})),Vn=s(((e,t)=>{var n=Bn(),r,i;function a(){for(var e in i=[`toString`,`toLocaleString`,`valueOf`,`hasOwnProperty`,`isPrototypeOf`,`propertyIsEnumerable`,`constructor`],r=!0,{toString:null})r=!1}function o(e,t,o){var c,l=0;for(c in r??a(),e)if(s(t,e,c,o)===!1)break;if(r)for(var u=e.constructor,d=!!u&&e===u.prototype;(c=i[l++])&&!((c!==`constructor`||!d&&n(e,c))&&e[c]!==Object.prototype[c]&&s(t,e,c,o)===!1););}function s(e,t,n,r){return e.call(r,t[n],n,t)}t.exports=o})),Hn=s(((e,t)=>{var n=Vn();function r(e){var t=[];return n(e,function(e,n){typeof e==`function`&&t.push(n)}),t.sort()}t.exports=r})),Un=s(((e,t)=>{function n(e,t,n){var r=e.length;t=t==null?0:t<0?Math.max(r+t,0):Math.min(t,r),n=n==null?r:n<0?Math.max(r+n,0):Math.min(n,r);for(var i=[];t{var n=Un();function r(e,t,r){var i=n(arguments,2);return function(){return e.apply(t,i.concat(n(arguments)))}}t.exports=r})),Gn=s(((e,t)=>{function n(e,t,n){if(e!=null)for(var r=-1,i=e.length;++r{var n=Hn(),r=Wn(),i=Gn(),a=Un();function o(e,t){i(arguments.length>1?a(arguments,1):n(e),function(t){e[t]=r(e[t],e)})}t.exports=o})),J=s(((e,t)=>{var n=Bn(),r=Vn();function i(e,t,i){r(e,function(r,a){if(n(e,a))return t.call(i,e[a],a,e)})}t.exports=i})),qn=s(((e,t)=>{function n(e){return e}t.exports=n})),Jn=s(((e,t)=>{function n(e){return function(t){return t[e]}}t.exports=n})),Yn=s(((e,t)=>{var n=/^\[object (.*)\]$/,r=Object.prototype.toString,i;function a(e){return e===null?`Null`:e===i?`Undefined`:n.exec(r.call(e))[1]}t.exports=a})),Xn=s(((e,t)=>{var n=Yn();function r(e,t){return n(e)===t}t.exports=r})),Zn=s(((e,t)=>{var n=Xn();t.exports=Array.isArray||function(e){return n(e,`Array`)}})),Qn=s(((e,t)=>{var n=J(),r=Zn();function i(e,t){for(var n=-1,r=e.length;++n{var n=qn(),r=Jn(),i=Qn();function a(e,t){if(e==null)return n;switch(typeof e){case`function`:return t===void 0?e:function(n,r,i){return e.call(t,n,r,i)};case`object`:return function(t){return i(t,e)};case`string`:case`number`:return r(e)}}t.exports=a})),$n=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!1;return n(e,function(n,r){if(t(n,r,e))return a=!0,!1}),a}t.exports=i})),er=s(((e,t)=>{var n=$n();function r(e,t){return n(e,function(e){return e===t})}t.exports=r})),tr=s(((e,t)=>{function n(e){return!!e&&typeof e==`object`&&e.constructor===Object}t.exports=n})),nr=s(((e,t)=>{var n=J(),r=tr();function i(e,t){for(var a=0,o=arguments.length,s;++a{var n=J(),r=tr();function i(e,t){for(var r=0,i=arguments.length,o;++r{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!0;return n(e,function(n,r){if(!t(n,r,e))return a=!1,!1}),a}t.exports=i})),ar=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Object`)}t.exports=r})),or=s(((e,t)=>{function n(e,t){return e===t?e!==0||1/e==1/t:e!==e&&t!==t}t.exports=n})),sr=s(((e,t)=>{var n=Bn(),r=ir(),i=ar(),a=or();function o(e){return function(t,r){return n(this,r)&&e(t,this[r])}}function s(e,t){return n(this,t)}function c(e,t,n){return n||=a,!i(e)||!i(t)?n(e,t):r(e,o(n),t)&&r(t,s,e)}t.exports=c})),cr=s(((e,t)=>{var n=Gn(),r=Un(),i=J();function a(e,t){return n(r(arguments,1),function(t){i(t,function(t,n){e[n]??(e[n]=t)})}),e}t.exports=a})),lr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){t(e,n,r)&&(a[n]=e)}),a}t.exports=i})),ur=s(((e,t)=>{var n=$n(),r=Y();function i(e,t,i){t=r(t,i);var a;return n(e,function(e,n,r){if(t(e,n,r))return a=e,!0}),a}t.exports=i})),dr=s(((e,t)=>{var n=J(),r=tr();function i(e,t,a,o){return n(e,function(e,n){var s=a?a+`.`+n:n;o!==0&&r(e)?i(e,t,s,o-1):t[s]=e}),t}function a(e,t){return e==null?{}:(t??=-1,i(e,{},``,t))}t.exports=a})),fr=s(((e,t)=>{function n(e){switch(typeof e){case`string`:case`number`:case`boolean`:return!0}return e==null}t.exports=n})),pr=s(((e,t)=>{fr();function n(e,t){for(var n=t.split(`.`),r=n.pop();t=n.shift();)if(e=e[t],e==null)return;return e[r]}t.exports=n})),mr=s(((e,t)=>{var n=pr(),r;function i(e,t){return n(e,t)!==r}t.exports=i})),hr=s(((e,t)=>{var n=J();t.exports=Object.keys||function(e){var t=[];return n(e,function(e,n){t.push(n)}),t}})),gr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){a[n]=t(e,n,r)}),a}t.exports=i})),_r=s(((e,t)=>{var n=J();function r(e,t){var r=!0;return n(t,function(t,n){if(e[n]!==t)return r=!1}),r}t.exports=r})),vr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return 1/0;if(e.length&&!t)return Math.max.apply(Math,e);t=n(t,r);for(var i,a=-1/0,o,s,c=-1,l=e.length;++ca&&(a=s,i=o);return i}t.exports=r})),yr=s(((e,t)=>{var n=J();function r(e){var t=[];return n(e,function(e,n){t.push(e)}),t}t.exports=r})),br=s(((e,t)=>{var n=vr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),xr=s(((e,t)=>{var n=J();function r(e,t){for(var r=0,a=arguments.length,o;++r{var n=Yn(),r=tr(),i=xr();function a(e){switch(n(e)){case`Object`:return o(e);case`Array`:return l(e);case`RegExp`:return s(e);case`Date`:return c(e);default:return e}}function o(e){return r(e)?i({},e):e}function s(e){var t=``;return t+=e.multiline?`m`:``,t+=e.global?`g`:``,t+=e.ignoreCase?`i`:``,new RegExp(e.source,t)}function c(e){return new Date(+e)}function l(e){return e.slice()}t.exports=a})),Cr=s(((e,t)=>{var n=Sr(),r=J(),i=Yn(),a=tr();function o(e,t){switch(i(e)){case`Object`:return s(e,t);case`Array`:return c(e,t);default:return n(e)}}function s(e,t){if(a(e)){var n={};return r(e,function(e,n){this[n]=o(e,t)},n),n}else if(t)return t(e);else return e}function c(e,t){for(var n=[],r=-1,i=e.length;++r{var n=Bn(),r=Cr(),i=ar();function a(){for(var e=1,t,o,s,c=r(arguments[0]);s=arguments[e++];)for(t in s)n(s,t)&&(o=s[t],i(o)&&i(c[t])?c[t]=a(c[t],o):c[t]=r(o));return c}t.exports=a})),Tr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return-1/0;if(e.length&&!t)return Math.min.apply(Math,e);t=n(t,r);for(var i,a=1/0,o,s,c=-1,l=e.length;++c{var n=Tr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),Dr=s(((e,t)=>{var n=Gn();function r(e,t){return t&&n(t.split(`.`),function(t){e[t]||(e[t]={}),e=e[t]}),e}t.exports=r})),Or=s(((e,t)=>{function n(e,t,n){if(n||=0,e==null)return-1;for(var r=e.length,i=n<0?r+n:n;i{var n=Or();function r(e,t){return n(e,t)!==-1}t.exports=r})),Ar=s(((e,t)=>{var n=Un(),r=kr();function i(e,t){var i=typeof arguments[1]==`string`?n(arguments,1):arguments[1],a={};for(var o in e)e.hasOwnProperty(o)&&!r(i,o)&&(a[o]=e[o]);return a}t.exports=i})),jr=s(((e,t)=>{var n=Un();function r(e,t){for(var r=typeof arguments[1]==`string`?n(arguments,1):arguments[1],i={},a=0,o;o=r[a++];)i[o]=e[o];return i}t.exports=r})),Mr=s(((e,t)=>{var n=gr(),r=Jn();function i(e,t){return n(e,r(t))}t.exports=i})),Nr=s(((e,t)=>{var n=J();function r(e){var t=0;return n(e,function(){t++}),t}t.exports=r})),Pr=s(((e,t)=>{var n=J(),r=Nr();function i(e,t,i,a){var o=arguments.length>2;if(!r(e)&&!o)throw Error(`reduce of empty object with no initial value`);return n(e,function(e,n,r){o?i=t.call(a,i,e,n,r):(i=e,o=!0)}),i}t.exports=i})),Fr=s(((e,t)=>{var n=lr(),r=Y();function i(e,t,i){return t=r(t,i),n(e,function(e,n,r){return!t(e,n,r)},i)}t.exports=i})),Ir=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Function`)}t.exports=r})),Lr=s(((e,t)=>{var n=Ir();function r(e,t){var r=e[t];if(r!==void 0)return n(r)?r.call(e):r}t.exports=r})),Rr=s(((e,t)=>{var n=Dr();function r(e,t,r){var i=/^(.+)\.(.+)$/.exec(t);i?n(e,i[1])[i[2]]=r:e[t]=r}t.exports=r})),zr=s(((e,t)=>{var n=mr();function r(e,t){if(n(e,t)){for(var r=t.split(`.`),i=r.pop();t=r.shift();)e=e[t];return delete e[i]}else return!0}t.exports=r})),Br=s(((e,t)=>{t.exports={bindAll:Kn(),contains:er(),deepFillIn:nr(),deepMatches:Qn(),deepMixIn:rr(),equals:sr(),every:ir(),fillIn:cr(),filter:lr(),find:ur(),flatten:dr(),forIn:Vn(),forOwn:J(),functions:Hn(),get:pr(),has:mr(),hasOwn:Bn(),keys:hr(),map:gr(),matches:_r(),max:br(),merge:wr(),min:Er(),mixIn:xr(),namespace:Dr(),omit:Ar(),pick:jr(),pluck:Mr(),reduce:Pr(),reject:Fr(),result:Lr(),set:Rr(),size:Nr(),some:$n(),unset:zr(),values:yr()}})),Vr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.default=(0,Br().map)({A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},function(e){return[100*(e.x/e.y),100,100*(1-e.x-e.y)/e.y]}),t.exports=e.default})),Hr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=Math,r=n.pow,i=n.sign,a=n.abs,o={decode:function(e){return e<=.04045?e/12.92:r((e+.055)/1.055,2.4)},encode:function(e){return e<=.0031308?12.92*e:1.055*r(e,1/2.4)-.055}},s={encode:function(e){return e<.001953125?16*e:r(e,1/1.8)},decode:function(e){return e<16*.001953125?e/16:r(e,1.8)}};function c(e){return{decode:function(t){return i(t)*r(a(t),e)},encode:function(t){return i(t)*r(a(t),1/e)}}}e.default={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:o},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:c(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:c(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:s}},t.exports=e.default})),Ur=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});function t(e){return[[e[0][0],e[1][0],e[2][0]],[e[0][1],e[1][1],e[2][1]],[e[0][2],e[1][2],e[2][2]]]}function n(e){return e[0][0]*(e[2][2]*e[1][1]-e[2][1]*e[1][2])+e[1][0]*(e[2][1]*e[0][2]-e[2][2]*e[0][1])+e[2][0]*(e[1][2]*e[0][1]-e[1][1]*e[0][2])}function r(e){var t=1/n(e);return[[(e[2][2]*e[1][1]-e[2][1]*e[1][2])*t,(e[2][1]*e[0][2]-e[2][2]*e[0][1])*t,(e[1][2]*e[0][1]-e[1][1]*e[0][2])*t],[(e[2][0]*e[1][2]-e[2][2]*e[1][0])*t,(e[2][2]*e[0][0]-e[2][0]*e[0][2])*t,(e[1][0]*e[0][2]-e[1][2]*e[0][0])*t],[(e[2][1]*e[1][0]-e[2][0]*e[1][1])*t,(e[2][0]*e[0][1]-e[2][1]*e[0][0])*t,(e[1][1]*e[0][0]-e[1][0]*e[0][1])*t]]}function i(e,t){return[e[0][0]*t[0]+e[0][1]*t[1]+e[0][2]*t[2],e[1][0]*t[0]+e[1][1]*t[1]+e[1][2]*t[2],e[2][0]*t[0]+e[2][1]*t[1]+e[2][2]*t[2]]}function a(e,t){return[[e[0][0]*t[0],e[0][1]*t[1],e[0][2]*t[2]],[e[1][0]*t[0],e[1][1]*t[1],e[1][2]*t[2]],[e[2][0]*t[0],e[2][1]*t[1],e[2][2]*t[2]]]}function o(e,t){return[[e[0][0]*t[0][0]+e[0][1]*t[1][0]+e[0][2]*t[2][0],e[0][0]*t[0][1]+e[0][1]*t[1][1]+e[0][2]*t[2][1],e[0][0]*t[0][2]+e[0][1]*t[1][2]+e[0][2]*t[2][2]],[e[1][0]*t[0][0]+e[1][1]*t[1][0]+e[1][2]*t[2][0],e[1][0]*t[0][1]+e[1][1]*t[1][1]+e[1][2]*t[2][1],e[1][0]*t[0][2]+e[1][1]*t[1][2]+e[1][2]*t[2][2]],[e[2][0]*t[0][0]+e[2][1]*t[1][0]+e[2][2]*t[2][0],e[2][0]*t[0][1]+e[2][1]*t[1][1]+e[2][2]*t[2][1],e[2][0]*t[0][2]+e[2][1]*t[1][2]+e[2][2]*t[2][2]]]}e.transpose=t,e.determinant=n,e.inverse=r,e.multiply=i,e.scalar=a,e.product=o})),Wr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.PI;function n(e){for(var n=e*180/t;n<0;)n+=360;for(;n>360;)n-=360;return n}function r(e){for(var n=t*e/180;n<0;)n+=2*t;for(;n>2*t;)n-=2*t;return n}e.fromRadian=n,e.toRadian=r})),Gr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.round;function n(e){return e[0]==`#`&&(e=e.slice(1)),e.length<6&&(e=e.split(``).map(function(e){return e+e}).join(``)),e.match(/../g).map(function(e){return parseInt(e,16)/255})}function r(e){return`#`+e.map(function(e){return e=t(255*e).toString(16),e.length<2&&(e=`0`+e),e}).join(``)}e.fromHex=n,e.toHex=r})),Kr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=o(Ur()),r=a(Vr()),i=a(Hr());function a(e){return e&&e.__esModule?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function s(){var e=arguments.length<=0||arguments[0]===void 0?i.default.sRGB:arguments[0],t=arguments.length<=1||arguments[1]===void 0?r.default.D65:arguments[1],a=[e.r,e.g,e.b],o=n.transpose(a.map(function(e){return[e.x/e.y,1,(1-e.x-e.y)/e.y]})),s=e.gamma,c=n.multiply(n.inverse(o),t),l=n.scalar(o,c),u=n.inverse(l);return{fromRgb:function(e){return n.multiply(l,e.map(s.decode))},toRgb:function(e){return n.multiply(u,e).map(s.encode)}}}e.default=s,t.exports=e.default})),qr=s(((e,t)=>{t.exports={illuminant:Vr(),workspace:Hr(),matrix:Ur(),degree:Wr(),rgb:Gr(),xyz:Kr()}})),Jr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.cfs=e.distance=e.lerp=e.corLerp=void 0;var t=Br();function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ti/2&&(e>t?t+=i:e+=i),((1-n)*e+n*t)%(i||1/0)}function u(e,t,n){var r={};for(var i in e)r[i]=l(e[i],t[i],n,i);return r}function d(e,t){var n=0;for(var r in e)n+=o(e[r]-t[r],2);return s(n)}function f(e){return t.merge.apply(void 0,r(e.split(``).map(function(e){return n({},e,!0)})))}e.corLerp=l,e.lerp=u,e.distance=d,e.cfs=f})),Yr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=Jr();function a(e,t){var a=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],o=-a,s=1+a,c=Math,l=c.min,u=c.max,d=n([`000`,`fff`].map(function(n){return t.fromXyz(e.fromRgb(r.rgb.fromHex(n)))}),2),f=d[0],p=d[1];function m(n){var r=e.toRgb(t.toXyz(n));return[r.map(function(e){return e>=o&&e<=s}).reduce(function(e,t){return e&&t},!0),r]}function h(e,t){for(var r=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,i.distance)(e,t)>r;){var a=(0,i.lerp)(e,t,.5);n(m(a),1)[0]?e=a:t=a}return e}function g(e){return(0,i.lerp)(f,p,e)}function _(e){return e.map(function(e){return u(o,l(s,e))})}return{contains:m,limit:h,spine:g,crop:_}}e.default=a,t.exports=e.default})),Xr=s((e=>{var t=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0}),e.toNotation=e.fromNotation=e.toHue=e.fromHue=void 0;var n=Jr(),r=Math.floor,i=[{s:`R`,h:20.14,e:.8,H:0},{s:`Y`,h:90,e:.7,H:100},{s:`G`,h:164.25,e:1,H:200},{s:`B`,h:237.53,e:1.2,H:300},{s:`R`,h:380.14,e:.8,H:400}],a=i.map(function(e){return e.s}).slice(0,-1).join(``);function o(e){e50){var o=[n,t];t=o[0],n=o[1],i=100-i}return i<1?a[t]:a[t]+i.toFixed()+a[n]}e.fromHue=o,e.toHue=s,e.fromNotation=l,e.toNotation=u})),Zr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=s(Xr()),a=Jr(),o=Br();function s(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var c=Math,l=c.pow,u=c.sqrt,d=c.exp,f=c.abs,p=c.sign,m=Math,h=m.sin,g=m.cos,_=m.atan2,v={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},y=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],b=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],x=y,S=r.matrix.inverse(y),C=r.matrix.product(b,r.matrix.inverse(y)),w=r.matrix.product(y,r.matrix.inverse(b)),T={whitePoint:r.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ee=(0,a.cfs)(`QJMCshH`),E=(0,a.cfs)(`JCh`);function D(){var e=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],t=arguments.length<=1||arguments[1]===void 0?ee:arguments[1];e=(0,o.merge)(T,e);var a=e.whitePoint,s=e.adaptingLuminance,c=e.backgroundLuminance,m=v[e.surroundType],b=m.F,D=m.c,O=m.N_c,te=a[1],k=1/(5*s+1),A=.2*l(k,4)*5*s+.1*l(1-l(k,4),2)*l(5*s,1/3),ne=c/te,re=.725*l(1/ne,.2),ie=re,ae=1.48+u(ne),oe=e.discounting?1:b*(1-1/3.6*d(-(s+42)/92)),j=n(r.matrix.multiply(y,a).map(function(e){return oe*te/e+1-oe}),3),se=j[0],M=j[1],ce=j[2],N=pe(de(le(a)));function le(e){var t=n(r.matrix.multiply(x,e),3),i=t[0],a=t[1],o=t[2];return[se*i,M*a,ce*o]}function ue(e){var t=n(e,3),i=t[0],a=t[1],o=t[2];return r.matrix.multiply(S,[i/se,a/M,o/ce])}function de(e){return r.matrix.multiply(C,e).map(function(e){var t=l(A*f(e)/100,.42);return p(e)*400*t/(27.13+t)+.1})}function fe(e){return r.matrix.multiply(w,e.map(function(e){var t=e-.1;return p(t)*100/A*l(27.13*f(t)/(400-f(t)),1/.42)}))}function pe(e){var t=n(e,3),r=t[0],i=t[1],a=t[2];return(r*2+i+a/20-.305)*re}function me(e){return 4/D*u(e/100)*(N+4)*l(A,.25)}function he(e){return 6.25*l(D*e/((N+4)*l(A,.25)),2)}function ge(e){return e*l(A,.25)}function _e(e,t){return l(e/100,2)*t/l(A,.25)}function ve(e){return e/l(A,.25)}function ye(e,t){return 100*u(e/t)}function be(e,t){var n=t.Q,r=t.J,a=t.M,o=t.C,s=t.s,c=t.h,l=t.H,u={};return e.J&&(u.J=isNaN(r)?he(n):r),e.C&&(isNaN(o)?isNaN(a)?(n=isNaN(n)?me(r):n,u.C=_e(s,n)):u.C=ve(a):u.C=t.C),e.h&&(u.h=isNaN(c)?i.toHue(l):c),e.Q&&(u.Q=isNaN(n)?me(r):n),e.M&&(u.M=isNaN(a)?ge(o):a),e.s&&(isNaN(s)?(n=isNaN(n)?me(r):n,a=isNaN(a)?ge(o):a,u.s=ye(a,n)):u.s=s),e.H&&(u.H=isNaN(l)?i.fromHue(c):l),u}function P(e){var i=de(le(e)),a=n(i,3),o=a[0],s=a[1],c=a[2],d=o-s*12/11+c/11,f=(o+s-2*c)/9,p=_(f,d),m=r.degree.fromRadian(p),h=1/4*(g(p+2)+3.8),v=100*l(pe(i)/N,D*ae);return be(t,{J:v,C:l(5e4/13*O*ie*h*u(d*d+f*f)/(o+s+21/20*c),.9)*u(v/100)*l(1.64-l(.29,ne),.73),h:m})}function F(e){var t=be(E,e),n=t.J,i=t.C,a=t.h,o=r.degree.toRadian(a),s=l(i/(u(n/100)*l(1.64-l(.29,ne),.73)),10/9),c=1/4*(g(o+2)+3.8),d=N*l(n/100,1/D/ae),p=5e4/13*O*ie*c/s,m=d/re+.305,_=m*61/20*460/1403,v=61/20*220/1403,y=21/20*6300/1403-27/1403,b=h(o),x=g(o),S,C;return s===0||isNaN(s)?S=C=0:f(b)>=f(x)?(C=_/(p/b+v*x/b+y),S=C*x/b):(S=_/(p/x+v+y*b/x),C=S*b/x),ue(fe([20/61*m+451/1403*S+288/1403*C,20/61*m-891/1403*S-261/1403*C,20/61*m-220/1403*S-6300/1403*C]))}return{fromXyz:P,toXyz:F,fillOut:be}}e.default=D,t.exports=e.default})),Qr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=qr(),r=Math,i=r.sqrt,a=r.pow,o=r.exp,s=r.log,c=r.cos,l=r.sin,u=r.atan2,d={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function f(){var e=d[arguments.length<=0||arguments[0]===void 0?`UCS`:arguments[0]],t=e.K_L,r=e.c_1,f=e.c_2;function p(e){var t=e.J,i=e.M,a=e.h,o=n.degree.toRadian(a),u=(1+100*r)*t/(1+r*t),d=1/f*s(1+f*i);return{J_p:u,a_p:d*c(o),b_p:d*l(o)}}function m(e){var t=e.J_p,s=e.a_p,c=e.b_p,l=-t/(r*t-100*r-1),d=(o(f*i(a(s,2)+a(c,2)))-1)/f,p=u(c,s);return{J:l,M:d,h:n.degree.fromRadian(p)}}function h(e,n){return i(a((e.J_p-n.J_p)/t,2)+a(e.a_p-n.a_p,2)+a(e.b_p-n.b_p,2))}return{fromCam:p,toCam:m,distance:h}}e.default=f,t.exports=e.default})),$r=s(((e,t)=>{var n=Jr(),r=Yr(),i=Zr(),a=Qr(),o=Xr();t.exports={gamut:r,cfs:n.cfs,lerp:n.lerp,cam:i,ucs:a,hq:o}})),ei=l(qr(),1),ti=l($r(),1);function ni(e){let t=new q;return t.rgb_r=e[0],t.rgb_g=e[1],t.rgb_b=e[2],t.rgbToHsluv(),[t.hsluv_h,t.hsluv_s,t.hsluv_l]}function ri(e){let t=new q;return t.hsluv_h=e[0],t.hsluv_s=e[1],t.hsluv_l=e[2],t.hsluvToRgb(),[t.rgb_r,t.rgb_g,t.rgb_b]}var ii=ti.default.cam({whitePoint:ei.default.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ti.default.cfs(`JCh`)),ai=ei.default.xyz(ei.default.workspace.sRGB,ei.default.illuminant.D65),oi=e=>ai.toRgb(ii.toXyz({J:e[0],C:e[1],h:e[2]})),si=e=>{let t=ii.fromXyz(ai.fromRgb(e));return[t.J,t.C,t.h]},[ci,li]=(()=>{let e={k_l:1,c1:.007,c2:.0228},t=Math.PI,n=64/t/5,r=1/(5*n+1),i=.2*r**4*(5*n)+.1*(1-r**4)**2*(5*n)**(1/3);return[n=>{let[r,a,o]=n,s=a*i**.25,c=(1+100*e.c1)*r/(1+e.c1*r);c/=e.k_l;let l=1/e.c2*Math.log(1+e.c2*s),u=l*Math.cos(t/180*o),d=l*Math.sin(t/180*o);return[c,u,d]},n=>{let[r,a,o]=n,s=Math.sqrt(a*a+o*o),c=(Math.exp(s*e.c2)-1)/e.c2,l=(180/t*Math.atan2(o,a)+360)%360,u=c/i**.25;return[r/(1+e.c1*(100-r)),u,l]}]})(),ui=e=>oi(li(e)),di=e=>ci(si(e)),fi=console;fi.color=(e,t=``)=>{let n=K(e).luminance();fi.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?`#000`:`#fff`}`)},fi.ramp=(e,t=1)=>{fi.log(`%c `,`font-size: 1px;line-height: 16px;background: ${K.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};var pi=(e,t,n,r,i,a,o=.1)=>{if(e===n||t===r)return!0;let s=(r-t)/(n-e),c=(a+i/s-t+s*e)/(s+1/s),l=a+i/s-c/s;return(i-c)**2+(a-l)**2{let i=(t[0]+n[0])/2,a=e(i);return pi(...t,...n,i,a,r)?null:[i,a]},hi=(e,t,n,r=.1)=>{let i=(n-t)/10,a=[];for(let r=t;rMath.round(e*10**t)/10**t,_i=(e,t=1,n=90,r=.005)=>{let i=hi(t=>e(t).gl()[0],0,t,r),a=hi(t=>e(t).gl()[1],0,t,r),o=hi(t=>e(t).gl()[2],0,t,r);return`linear-gradient(${n}deg, ${Array.from(new Set([...i.map(e=>gi(e[0])),...a.map(e=>gi(e[0])),...o.map(e=>gi(e[0]))].sort((e,t)=>e-t))).map(t=>`${e(t).hex()} ${gi(t*100)}%`).join()});`},vi=e=>{e.Color.prototype.jch=function(){return si(this._rgb.slice(0,3).map(e=>e/255))},e.jch=(...t)=>new e.Color(...oi(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.jab=function(){return di(this._rgb.slice(0,3).map(e=>e/255))},e.jab=(...t)=>new e.Color(...ui(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.hsluv=function(){return ni(this._rgb.slice(0,3).map(e=>e/255))},e.hsluv=(...t)=>new e.Color(...ri(t).map(e=>Math.floor(e*255)),`rgb`);let t=e.interpolate,n={jch:si,jab:di,hsluv:ni},r=(e,t,n)=>(Math.abs(e-t)>360/2&&(e>t?t+=360:e+=360),((1-n)*e+n*t)%360);e.interpolate=(i,a,o=.5,s=`lrgb`)=>{if(n[s]){typeof i!=`object`&&(i=new e.Color(i)),typeof a!=`object`&&(a=new e.Color(a));let t=n[s](i.gl()),c=n[s](a.gl()),l=Number.isNaN(i.hsl()[0]),u=Number.isNaN(a.hsl()[0]),d,f,p;switch(s){case`hsluv`:t[1]<1e-10&&(t[0]=c[0]),t[1]===0&&(t[1]=c[1]),c[1]<1e-10&&(c[0]=t[0]),c[1]===0&&(c[1]=t[1]),d=r(t[0],c[0],o),f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o;break;case`jch`:l&&(t[2]=c[2]),u&&(c[2]=t[2]),d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=r(t[2],c[2],o);break;default:d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o}return e[s](d,f,p).alpha(i.alpha()+o*(a.alpha()-i.alpha()))}return t(i,a,o,s)},e.getCSSGradient=_i},X={mainTRC:2.4,get mainTRCencode(){return 1/this.mainTRC},sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1,mFactor:1.9468554433171,get mFactInv(){return 1/this.mFactor},mOffsetIn:.0387393816571401,mExpAdj:.283343396420869,get mExp(){return this.mExpAdj/this.blkClmp},mOffsetOut:.312865795870758};function yi(e,t,n=-1){let r=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)r[1])return 0;let i=0,a=0,o=`BoW`;return e=e>X.blkThrs?e:e+(X.blkThrs-e)**+X.blkClmp,t=t>X.blkThrs?t:t+(X.blkThrs-t)**+X.blkClmp,Math.abs(t-e)e?(i=(t**+X.normBG-e**+X.normTXT)*X.scaleBoW,a=i-X.loClip?0:i+X.loWoBoffset),n<0?a*100:n==0?Math.round(Math.abs(a)*100)+``+o+``:Number.isInteger(n)?(a*100).toFixed(n):0)}function bi(e=[0,0,0]){function t(e){return(e/255)**X.mainTRC}return X.sRco*t(e[0])+X.sGco*t(e[1])+X.sBco*t(e[2])}var xi=(e,t,n,r,i,a,o,s,c)=>{let l=1-c,u=l*l,d=u*l,f=c*c*c;return{x:d*e+u*3*c*n+l*3*c*c*i+f*o,y:d*t+u*3*c*r+l*3*c*c*a+f*s}},Si=(e,t)=>{let n=[],r={x:+e[0],y:+e[1]};for(let i=0,a=e.length;a-2*!t>i;i+=2){let o=[{x:+e[i-2],y:+e[i-1]},{x:+e[i],y:+e[i+1]},{x:+e[i+2],y:+e[i+3]},{x:+e[i+4],y:+e[i+5]}];t?i?a-4===i?o[3]={x:+e[0],y:+e[1]}:a-2===i&&(o[2]={x:+e[0],y:+e[1]},o[3]={x:+e[2],y:+e[3]}):o[0]={x:+e[a-2],y:+e[a-1]}:a-4===i?o[3]=o[2]:i||(o[0]={x:+e[i],y:+e[i+1]}),n.push([r.x,r.y,(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y]),r=o[2]}return n},Ci=(e,t,n,r,i,a,o,s)=>{let c=e,l=t,u=0;for(let d=1;d<5;d++){let{x:f,y:p}=xi(e,t,n,r,i,a,o,s,d/5);u+=Math.hypot(f-c,p-l),c=f,l=p}return u+=Math.hypot(o-c,s-l),u},wi=(e,t,n,r,i,a,o,s)=>{let c=Math.floor(Ci(e,t,n,r,i,a,o,s)*.75),l=[],u=0;for(let d=0;d<=c;d++){let f=xi(e,t,n,r,i,a,o,s,d/c),p=Math.round(f.x);if(l[p]=f.y,p-u>1){let e=l[u],t=l[p];for(let n=u+1;nl[Math.round(e)]||null},Ti={CAM02:`jab`,CAM02p:`jch`,HEX:`hex`,HSL:`hsl`,HSLuv:`hsluv`,HSV:`hsv`,LAB:`lab`,LCH:`lch`,RGB:`rgb`,OKLAB:`oklab`,OKLCH:`oklch`};function Z(e,t=0){let n=10**t;return Math.round(e*n)/n}function Ei(e,t){let n;return n=e>1?(e-1)*t+1:e<-1?(e+1)*t-1:1,Z(n,2)}function Di(e){return K(String(e)).jch()}function Oi(e){return K(String(e)).hsluv()}function ki(e,t,n){let r=[[],[],[]];if(e.forEach((e,n)=>r.forEach((r,i)=>r.push(t[n],e[i]))),n===`hcl`){let e=r[1];for(let t=1;t{let t=[];for(let n=1;n{e[t]=e[n]}),t.length=0;break}if(t.length){let n=K(`#ccc`).jch()[2];t.forEach(t=>{e[t]=n})}t.length=0;for(let n=e.length-1;n>0;n-=2)if(Number.isNaN(e[n]))t.push(n);else{t.forEach(t=>{e[t]=e[n]});break}for(let t=1;tSi(e).map(e=>wi(...e)));return e=>{let t=i.map(t=>{for(let n=0;nr*t**e+i}function ji({swatches:e,colorKeys:t,colorspace:n,colorSpace:r=n??`LAB`,shift:i=1,fullScale:a=!0,smooth:o=!1,distributeLightness:s=`linear`,sortColor:c=!0,asFun:l=!1}={}){n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead.");let u=Ti[r];if(!u)throw Error(`Colorspace “${r}” not supported`);if(!t)throw Error(`Colorkeys missing: returned “${t}”`);let d;if(a)d=t.map(t=>e-e*(K(t).jch()[0]/100)).sort((e,t)=>e-t).concat(e),d.unshift(0);else{let n=t.map(e=>K(e).jch()[0]/100),r=Math.min(...n),i=Math.max(...n);d=n.map(t=>t===0||isNaN((t-r)/(i-r))?0:e-(t-r)/(i-r)*e).sort((e,t)=>e-t)}let f=Ai(i,[1,e],[1,e]);if(f=d.map(e=>Math.max(0,f(e))),d=f,s===`polynomial`){let t=e=>Math.sqrt(Math.sqrt((e**2.25+e**4)/2));d=f.map(t=>t/e).map(n=>t(n)*e)}let p=t.map((e,t)=>({colorKeys:Di(e),index:t})).sort((e,t)=>t.colorKeys[0]-e.colorKeys[0]).map(e=>t[e.index]),m=[],h;if(a){let e=u===`lch`?K.lch(...K(`#fff`).lch()):`#ffffff`,t=u===`lch`?K.lch(...K(`#000`).lch()):`#000000`;m=[e,...p,t]}else m=c?p:t;let g;if(o){let t=m;if(m=m.map(e=>K(String(e))[u]()),u===`hcl`&&m.forEach(e=>{e[1]=Number.isNaN(e[1])?0:e[1]}),u===`jch`)for(let e=0;eh(t))}else h=K.scale(m.map(e=>typeof e==`object`&&e.constructor===K.Color?e:String(e))).domain(d).mode(u);return l?h:(!o||o===!1?h.colors(e):g).filter(e=>e!=null)}function Mi(e,t){let n=[],r={};return Object.keys(e).forEach(n=>{r[e[n][t]]=e[n]}),Object.keys(r).forEach(e=>n.push(r[e])),n}function Ni(e){return Number.isNaN(e)?0:e}function Pi(e,t,n=!1){if(!e)throw Error(`Cannot convert color value of “${e}”`);if(!Ti[t])throw Error(`Cannot convert to colorspace “${t}”`);let r=Ti[t],i=K(String(e))[r]();if(t===`HSL`&&i.pop(),t===`HEX`){if(n){let t=K(String(e)).rgb();return{r:t[0],g:t[1],b:t[2]}}return i}let a={},o=i.map(Ni);o=o.map((e,t)=>{let i=Z(e),o=t;r===`hsluv`&&(o+=2);let s=r.charAt(o);return r===`jch`&&s===`c`&&(s=`C`),a[s===`j`?`J`:s]=i,r in{lab:1,lch:1,jab:1,jch:1}?n||(s===`l`||s===`j`)&&(i+=`%`):r!==`hsluv`&&(s===`s`||s===`l`||s===`v`)&&(a[s]=Z(e,2),n||(i=Z(e*100),i+=`%`)),i});let s=`${r}(${o.join(`, `)})`;return n?a:s}function Fi(e,t,n){let r=[e,t,n].map(e=>(e/=255,e<=.03928?e/12.92:((e+.055)/1.055)**2.4));return r[0]*.2126+r[1]*.7152+r[2]*.0722}function Ii(e,t,n,r=`wcag2`){if(n===void 0){let e=K.rgb(...t).hsluv()[2];n=Z(e/100,2)}if(r===`wcag2`){let r=Fi(e[0],e[1],e[2]),i=Fi(t[0],t[1],t[2]),a=(r+.05)/(i+.05),o=(i+.05)/(r+.05);return n<.5?a>=1?a:-o:a<1?o:a===1?a:-a}else if(r===`wcag3`)return n<.5?yi(bi(e),bi(t))*-1:yi(bi(e),bi(t));else throw Error(`Contrast calculation method ${r} unsupported; use 'wcag2' or 'wcag3'`)}function Li(e,t){if(!e)throw Error(`Array undefined`);if(!Array.isArray(e))throw Error(`Passed object is not an array`);let n=t===`wcag2`?0:1;return Math.min(...e.filter(e=>e>=n))}function Ri(e,t){if(!e)throw Error(`Ratios undefined`);e=e.sort((e,t)=>e-t);let n=Li(e,t),r=e.indexOf(n),i=[],a=e.slice(0,r),o=e.slice(r,e.length);for(let e=0;ee-t),i}var zi=(e,t,n,r,i)=>{let a=3e3,o=ji({swatches:a,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),s={},c=e=>{if(s[e])return s[e];let r=Ii(K(o(e)).rgb(),t,n,i);return s[e]=r,r},l=e=>{let t=c(0).01&&o;)o--,n/=2,iu.push(o(l(+e)))),u},Q=class{constructor({name:e,colorKeys:t,colorspace:n,colorSpace:r=n??`RGB`,ratios:i,smooth:a=!1,output:o=`HEX`,saturation:s=100}){if(n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),this._name=e,this._colorKeys=t,this._modifiedKeys=t,this._colorspace=r,this._ratios=i,this._smooth=a,this._output=o,this._saturation=s,!this._name)throw Error(`Color missing name`);if(!this._colorKeys)throw Error(`Color Keys are undefined`);if(!Ti[this._colorspace])throw Error(`Colorspace “${r}” not supported`);if(!Ti[this._output])throw Error(`Output “${this._output}” not supported`);for(let e=0;e{let n=K(`${t}`).oklch(),r=n[1]*(this._saturation/100),i=K.oklch(n[0],r,n[2]),a=K.rgb(i).hex();e.push(a)}),this._modifiedKeys=e,this._generateColorScale()}_generateColorScale(){this._colorScale=ji({swatches:3e3,colorKeys:this._modifiedKeys,colorSpace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}},Bi=class extends Q{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){Q.prototype._generateColorScale.call(this);let e=ji({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});e.push(...this.colorKeys);let t=Mi(e.map((e,t)=>({value:Math.round(Oi(e)[2]),index:t})),`value`).map(t=>e[t.index]);return t.length>=101&&(t.length=100,t.push(`#ffffff`)),this._backgroundColorScale=t.map(e=>Pi(e,this._output)),this._backgroundColorScale}},Vi=class{constructor({colors:e,backgroundColor:t,lightness:n,contrast:r=1,saturation:i=100,output:a=`HEX`,formula:o=`wcag2`}){if(this._output=a,this._colors=e,this._lightness=n,this._saturation=i,this._formula=o,this._setBackgroundColor(t),this._setBackgroundColorValue(),this._contrast=r,!this._colors)throw Error(`No colors are defined`);if(!this._backgroundColor)throw Error(`Background color is undefined`);if(e.forEach(e=>{if(!e.ratios)throw Error(`Color ${e.name}'s ratios are undefined`)}),!Ti[this._output])throw Error(`Output “${a}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(e){this._formula=e,this._findContrastColors()}get formula(){return this._formula}set contrast(e){this._contrast=e,this._findContrastColors()}get contrast(){return this._contrast}set lightness(e){this._lightness=e,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(e){this._saturation=e,this._updateColorSaturation(e),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(e){this._setBackgroundColor(e),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(e){this._colors=e,this._findContrastColors()}get colors(){return this._colors}set addColor(e){this._colors.push(e),this._findContrastColors()}set removeColor(e){this._colors=this._colors.filter(t=>t.name!==e.name),this._findContrastColors()}set updateColor(e){if(Array.isArray(e))for(let t=0;tn.name===e[t].color);n=n[0];let r=this._colors.indexOf(n),i=this._colors.filter(n=>n.name!==e[t].color);e[t].name&&(n.name=e[t].name),e[t].colorKeys&&(n.colorKeys=e[t].colorKeys),e[t].ratios&&(n.ratios=e[t].ratios),(e[t].colorSpace!==void 0||e[t].colorspace!==void 0)&&(e[t].colorspace!==void 0&&e[t].colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),n.colorSpace=e[t].colorSpace??e[t].colorspace),e[t].smooth&&(n.smooth=e[t].smooth),n._generateColorScale(),i.splice(r,0,n),this._colors=i}else{let t=this._colors.filter(t=>t.name===e.color);t=t[0];let n=this._colors.indexOf(t),r=this._colors.filter(t=>t.name!==e.color);e.name&&(t.name=e.name),e.colorKeys&&(t.colorKeys=e.colorKeys),e.ratios&&(t.ratios=e.ratios),(e.colorSpace!==void 0||e.colorspace!==void 0)&&(e.colorspace!==void 0&&e.colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),t.colorSpace=e.colorSpace??e.colorspace),e.smooth&&(t.smooth=e.smooth),t._generateColorScale(),r.splice(n,0,t),this._colors=r}this._findContrastColors()}set output(e){this._output=e,this._colors.forEach(e=>{e.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(e){if(typeof e==`string`){let t=new Bi({name:`background`,colorKeys:[e],output:`RGB`}),n=Z(K(String(e)).hsluv()[2]);this._backgroundColor=t,this._lightness=n,this._backgroundColorValue=t[this._lightness]}else{e.output=`RGB`;let t=e.backgroundColorScale[this._lightness];this._backgroundColor=e,this._backgroundColorValue=t}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(e){this._colors.map(t=>{t.saturation=e})}_findContrastColors(){let e=K(String(this._backgroundColorValue)).rgb(),t=this._lightness/100,n={background:Pi(this._backgroundColorValue,this._output)},r=[],i=[],a={...n};return r.push(n),this._colors.map(n=>{if(n.ratios!==void 0){let o,s=[],c={name:n.name,values:s},l;Array.isArray(n.ratios)?l=n.ratios:Array.isArray(n.ratios)||(o=Object.keys(n.ratios),l=Object.values(n.ratios)),l=l.map(e=>Ei(+e,this._contrast));let u=zi(n,e,t,l,this._formula).map(e=>Pi(e,this._output));for(let e=0;e{let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},Wi=(e,t,n)=>{let r=e/255,i=t/255,a=n/255,o=Math.min(r,i,a),s=Math.max(r,i,a),c=s-o,l=0,u=0,d=0;return l=c===0?0:s===r?(i-a)/c%6:s===i?(a-r)/c+2:(r-i)/c+4,l=Math.round(l*60),l<0&&(l+=360),d=(s+o)/2,u=c===0?0:c/(1-Math.abs(2*d-1)),u=+(u*100).toFixed(1),d=+(d*100).toFixed(1),[l,u,Math.round(d)]},Gi=(e,t,n,r)=>{let i=n/100,a=t*Math.min(i,1-i)/100,o=t=>{let n=(t+e/30)%12,r=i-a*Math.max(Math.min(n-3,9-n,1),-1);return Math.round(255*r).toString(16).padStart(2,`0`).toUpperCase()},s=o(0),c=o(8),l=o(4),u=((e,t,n)=>Math.min(Math.max(e,t),n))(r,0,1);return`#${s}${c}${l}${Math.round(u*255).toString(16).padStart(2,`0`).toUpperCase()}`},Ki=(e,t,n=1)=>{let r=Ui(e),i=Ui(t===`white`?`#FFFFFF`:t===`black`?`#000000`:t),a=r.map((e,t)=>[(e-i[t])/(255-i[t]),(e-i[t])/(0-i[t])]),o=Hi(Math.max(...a.flat().filter(e=>/^-?\d+\.?\d*$/.test(e)))),s=r.map((e,t)=>Math.round((e-i[t]+i[t]*o)/o));if(s.includes(NaN)){let e=Wi(r[0],r[1],r[2]);return{h:e[0],s:Math.round(e[1]*n),l:e[2],a:1}}let c=Wi(s[0],s[1],s[2]);return{h:c[0],s:Math.round(c[1]*n),l:c[2],a:o}},qi={backgroundColor:`gray`,colorSpace:`OKLCH`,colorSmoothing:!1,formula:`wcag2`,output:`HEX`,colors:{gray:[$(215,20,90),$(215,8,50),$(215,6,25)],red:[$(358,100,58),$(350,100,30)],orange:[$(32,100,48),$(12,100,30)],yellow:[$(50,100,50),$(25,100,20)],lime:[$(100,68,50),$(115,86,25)],green:[$(163,87,42),$(168,100,25)],cyan:[$(185,80,45),$(200,98,35)],blue:[$(212,98,46),$(222,95,25)],purple:[$(258,94,64),$(265,100,35)],fuchsia:[$(295,56,50),$(285,80,25)],pink:[$(334,90,50),$(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function $(e,t,n){return K.hsl(e,t/100,n/100).hex()}function Ji(e,t){let n=e.colorSpace,r=e.colorSmoothing,i=e.themes[t].ratios,a=new Bi({name:`gray`,colorKeys:e.colors.gray,colorspace:n,ratios:i,smooth:r}),o=new Q({name:`blue`,colorKeys:e.colors.blue,colorspace:n,ratios:i,smooth:r}),s=new Q({name:`cyan`,colorKeys:e.colors.cyan,colorspace:n,ratios:i,smooth:r}),c=new Q({name:`fuchsia`,colorKeys:e.colors.fuchsia,colorspace:n,ratios:i,smooth:r}),l=new Q({name:`green`,colorKeys:e.colors.green,colorspace:n,ratios:i,smooth:r}),u=new Q({name:`lime`,colorKeys:e.colors.lime,colorspace:n,ratios:i,smooth:r}),d=new Q({name:`orange`,colorKeys:e.colors.orange,colorspace:n,ratios:i,smooth:r}),f=new Q({name:`pink`,colorKeys:e.colors.pink,colorspace:n,ratios:i,smooth:r}),p=new Q({name:`purple`,colorKeys:e.colors.purple,colorspace:n,ratios:i,smooth:r}),m={gray:a,red:new Q({name:`red`,colorKeys:e.colors.red,colorspace:n,ratios:i,smooth:r}),orange:d,yellow:new Q({name:`yellow`,colorKeys:e.colors.yellow,colorspace:n,ratios:i,smooth:r}),lime:u,green:l,cyan:s,blue:o,purple:p,fuchsia:c,pink:f};return e.colors.custom&&(m.custom=new Q({name:`custom`,colorKeys:e.colors.custom,colorspace:n,ratios:i,smooth:r})),new Vi({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function Yi(e){let t={};for(let n of Object.keys(e.themes))t[n]=Ji(e,n);return t}function Xi(e){qi.colors.custom=[e];let t=Yi(qi);return Object.fromEntries(Object.entries(t).map(([e,t])=>{let n=t.find(e=>e&&e.name===`custom`),r=Object.fromEntries(n.values.map(({name:e,value:t})=>[e,t]));for(let[e,n]of Object.entries(r)){let i=Ki(n,t[0].background);r[`alpha${e.charAt(0).toUpperCase()+e.slice(1)}`]=Gi(i.h,i.s,i.l,i.a)}return[e,r]}))}return e.generateCustomColors=Xi,e.generateThemesJson=Yi,e.hslToHex=$,e.leonardoConfig=qi,e})({}); \ No newline at end of file diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt index c5ac159b5a..5851a758f0 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt @@ -229,9 +229,6 @@ object CompoundIcons { @Composable fun Filter(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_filter) } - @Composable fun Folder(): ImageVector { - return ImageVector.vectorResource(R.drawable.ic_compound_folder) - } @Composable fun Forward(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_forward) } @@ -771,7 +768,6 @@ object CompoundIcons { FileError(), Files(), Filter(), - Folder(), Forward(), FullScreen(), Grid(), @@ -1000,7 +996,6 @@ object CompoundIcons { R.drawable.ic_compound_file_error, R.drawable.ic_compound_files, R.drawable.ic_compound_filter, - R.drawable.ic_compound_folder, R.drawable.ic_compound_forward, R.drawable.ic_compound_full_screen, R.drawable.ic_compound_grid, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt index 1e3c97d179..f5a54bb7be 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt @@ -91,6 +91,8 @@ data class SemanticColors( val bgSubtleSecondaryLevel0: Color, /** Subtle background colour for success state elements. State: Rest. */ val bgSuccessSubtle: Color, + /** Accent borders for containers */ + val borderAccentPrimary: Color, /** accent border intended for keylines on message highlights */ val borderAccentSubtle: Color, /** High-contrast border for critical state. State: Hover. */ @@ -171,6 +173,8 @@ data class SemanticColors( val iconTertiary: Color, /** Translucent version of tertiary icon. Refer to it for intended use. */ val iconTertiaryAlpha: Color, + /** Used to separate core sections of the UI as well as containers */ + val separatorPrimary: Color, /** Accent text colour for plain actions. */ val textActionAccent: Color, /** Default text colour for plain actions. */ diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt index adeed8d5a3..35a1234854 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt @@ -61,6 +61,7 @@ val compoundColorsDark = SemanticColors( bgSubtleSecondary = DarkColorTokens.colorGray300, bgSubtleSecondaryLevel0 = DarkColorTokens.colorThemeBg, bgSuccessSubtle = DarkColorTokens.colorGreen200, + borderAccentPrimary = DarkColorTokens.colorGreen900, borderAccentSubtle = DarkColorTokens.colorGreen700, borderCriticalHovered = DarkColorTokens.colorRed1000, borderCriticalPrimary = DarkColorTokens.colorRed900, @@ -101,6 +102,7 @@ val compoundColorsDark = SemanticColors( iconSuccessPrimary = DarkColorTokens.colorGreen900, iconTertiary = DarkColorTokens.colorGray800, iconTertiaryAlpha = DarkColorTokens.colorAlphaGray800, + separatorPrimary = DarkColorTokens.colorGray400, textActionAccent = DarkColorTokens.colorGreen900, textActionPrimary = DarkColorTokens.colorGray1400, textBadgeAccent = DarkColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt index 9bab04f833..802e3d56b0 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt @@ -61,6 +61,7 @@ val compoundColorsHcDark = SemanticColors( bgSubtleSecondary = DarkHcColorTokens.colorGray300, bgSubtleSecondaryLevel0 = DarkHcColorTokens.colorThemeBg, bgSuccessSubtle = DarkHcColorTokens.colorGreen200, + borderAccentPrimary = DarkHcColorTokens.colorGreen900, borderAccentSubtle = DarkHcColorTokens.colorGreen700, borderCriticalHovered = DarkHcColorTokens.colorRed1000, borderCriticalPrimary = DarkHcColorTokens.colorRed900, @@ -101,6 +102,7 @@ val compoundColorsHcDark = SemanticColors( iconSuccessPrimary = DarkHcColorTokens.colorGreen900, iconTertiary = DarkHcColorTokens.colorGray800, iconTertiaryAlpha = DarkHcColorTokens.colorAlphaGray800, + separatorPrimary = DarkHcColorTokens.colorGray400, textActionAccent = DarkHcColorTokens.colorGreen900, textActionPrimary = DarkHcColorTokens.colorGray1400, textBadgeAccent = DarkHcColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt index 033efc63ef..166f9ddafc 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt @@ -61,6 +61,7 @@ val compoundColorsLight = SemanticColors( bgSubtleSecondary = LightColorTokens.colorGray300, bgSubtleSecondaryLevel0 = LightColorTokens.colorGray300, bgSuccessSubtle = LightColorTokens.colorGreen200, + borderAccentPrimary = LightColorTokens.colorGreen900, borderAccentSubtle = LightColorTokens.colorGreen700, borderCriticalHovered = LightColorTokens.colorRed1000, borderCriticalPrimary = LightColorTokens.colorRed900, @@ -101,6 +102,7 @@ val compoundColorsLight = SemanticColors( iconSuccessPrimary = LightColorTokens.colorGreen900, iconTertiary = LightColorTokens.colorGray800, iconTertiaryAlpha = LightColorTokens.colorAlphaGray800, + separatorPrimary = LightColorTokens.colorGray400, textActionAccent = LightColorTokens.colorGreen900, textActionPrimary = LightColorTokens.colorGray1400, textBadgeAccent = LightColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt index c1f677d156..8914b41bfc 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt @@ -61,6 +61,7 @@ val compoundColorsHcLight = SemanticColors( bgSubtleSecondary = LightHcColorTokens.colorGray300, bgSubtleSecondaryLevel0 = LightHcColorTokens.colorGray300, bgSuccessSubtle = LightHcColorTokens.colorGreen200, + borderAccentPrimary = LightHcColorTokens.colorGreen900, borderAccentSubtle = LightHcColorTokens.colorGreen700, borderCriticalHovered = LightHcColorTokens.colorRed1000, borderCriticalPrimary = LightHcColorTokens.colorRed900, @@ -101,6 +102,7 @@ val compoundColorsHcLight = SemanticColors( iconSuccessPrimary = LightHcColorTokens.colorGreen900, iconTertiary = LightHcColorTokens.colorGray800, iconTertiaryAlpha = LightHcColorTokens.colorAlphaGray800, + separatorPrimary = LightHcColorTokens.colorGray400, textActionAccent = LightHcColorTokens.colorGreen900, textActionPrimary = LightHcColorTokens.colorGray1400, textBadgeAccent = LightHcColorTokens.colorGreen1100, From 56f033e0ee4b51903940eef877060acae90ebd3a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 2 Apr 2026 09:25:30 +0200 Subject: [PATCH 0039/1083] Revert "Use Folder icon from Compound." This reverts commit f4adde627f003bed567d254b821a526db1f2b51d. --- .../android/features/viewfolder/impl/folder/ViewFolderView.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/folder/ViewFolderView.kt b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/folder/ViewFolderView.kt index dce5ffeae3..2a6b4031ef 100644 --- a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/folder/ViewFolderView.kt +++ b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/folder/ViewFolderView.kt @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Folder import androidx.compose.material.icons.outlined.SubdirectoryArrowLeft import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -111,7 +112,7 @@ private fun ItemRow( } is Item.Folder -> { ListItem( - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Folder())), + leadingContent = ListItemContent.Icon(IconSource.Vector(Icons.Outlined.Folder)), headlineContent = { Text( text = item.name, From e401619017741b94a4852d49a97c8e96ee0c9062 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 2 Apr 2026 09:37:15 +0200 Subject: [PATCH 0040/1083] Changer border color of InReplyTo to `separatorPrimary` --- .../messages/impl/timeline/components/TimelineItemEventRow.kt | 2 +- .../element/android/libraries/textcomposer/ComposerModeView.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 c9bc130905..0361eebc01 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 @@ -747,7 +747,7 @@ private fun MessageEventBubbleContent( } Box( modifier = talkbackCompatModifier - .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(6.dp)) + .border(1.dp, ElementTheme.colors.separatorPrimary, RoundedCornerShape(6.dp)) .background(ElementTheme.colors.bgCanvasDefault, RoundedCornerShape(6.dp)) .padding(4.dp) ) { diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt index 15aabdcbb0..08d89e25fb 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt @@ -134,7 +134,7 @@ private fun ReplyToModeView( modifier .clip(RoundedCornerShape(6.dp)) .background(ElementTheme.colors.bgCanvasDefault) - .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(6.dp)) + .border(1.dp, ElementTheme.colors.separatorPrimary, RoundedCornerShape(6.dp)) .padding(4.dp) ) { InReplyToView( From 13de580a51305cf8547452ffffb999d6efb76694 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 2 Apr 2026 07:52:20 +0000 Subject: [PATCH 0041/1083] Update screenshots --- libraries/compound/screenshots/Compound Icons - Dark.png | 4 ++-- libraries/compound/screenshots/Compound Icons - Light.png | 4 ++-- libraries/compound/screenshots/Compound Icons - Rtl.png | 4 ++-- .../compound/screenshots/Compound Vector Icons - Dark.png | 4 ++-- .../compound/screenshots/Compound Vector Icons - Light.png | 4 ++-- ....components_TimelineItemEventRowDisambiguated_Day_0_en.png | 4 ++-- ...omponents_TimelineItemEventRowDisambiguated_Night_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_1_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_0_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_1_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_0_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_1_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_0_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_0_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_10_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_11_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_2_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_3_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_4_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_5_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_6_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_7_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_8_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_9_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_0_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_10_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_11_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_1_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_2_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_3_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_4_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_5_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_6_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_7_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_8_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_9_en.png | 4 ++-- ...eatures.viewfolder.impl.folder_ViewFolderView_Day_1_en.png | 4 ++-- ...tures.viewfolder.impl.folder_ViewFolderView_Night_1_en.png | 4 ++-- ...raries.designsystem.theme.components_AllIcons_Icons_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Day_1_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Day_2_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Day_3_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Night_1_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Night_2_en.png | 4 ++-- .../libraries.textcomposer_ComposerModeView_Night_3_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png | 4 ++-- ...s.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png | 4 ++-- ...s.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png | 4 ++-- ...es.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png | 4 ++-- ...textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png | 4 ++-- ...textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png | 4 ++-- ....textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_0_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_10_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_11_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_1_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_2_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_3_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_4_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_5_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_6_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_7_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_8_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Day_9_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_0_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_10_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_11_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_1_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_2_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_3_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_4_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_5_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_6_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_7_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_8_en.png | 4 ++-- .../libraries.textcomposer_TextComposerReply_Night_9_en.png | 4 ++-- 96 files changed, 192 insertions(+), 192 deletions(-) diff --git a/libraries/compound/screenshots/Compound Icons - Dark.png b/libraries/compound/screenshots/Compound Icons - Dark.png index f140517dff..2e3fd0d04d 100644 --- a/libraries/compound/screenshots/Compound Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37f6acca46890e98087ece62e2716fa60791479fab02999406050517e3b79307 -size 240187 +oid sha256:7901fea2f578c8ed796160c9c08f417c61f4fb21580f958844fdf0cb794adf8a +size 239731 diff --git a/libraries/compound/screenshots/Compound Icons - Light.png b/libraries/compound/screenshots/Compound Icons - Light.png index c84421b6fa..6e1bfc80cd 100644 --- a/libraries/compound/screenshots/Compound Icons - Light.png +++ b/libraries/compound/screenshots/Compound Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2de5e6d24dcbe0baa75a69485f5a308466fa599625bcbdb0cb96e9bc5a1b708 -size 253233 +oid sha256:245f012d419817f6557d92a71729b3b70092f24f0eba37f2f1fc431ad27592be +size 252969 diff --git a/libraries/compound/screenshots/Compound Icons - Rtl.png b/libraries/compound/screenshots/Compound Icons - Rtl.png index 89be63840a..aa1b5d93a7 100644 --- a/libraries/compound/screenshots/Compound Icons - Rtl.png +++ b/libraries/compound/screenshots/Compound Icons - Rtl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae1cb46d82acbb23cc172f41e20a41bbe88c350ab53c20e5b2a91f2c16590fbf -size 254525 +oid sha256:2d15c52b21cc279d306fa187cd0c318820109b5ec66270e6447e1b02e800eeba +size 254206 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Dark.png b/libraries/compound/screenshots/Compound Vector Icons - Dark.png index 702fd9b425..a01fbf18b4 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a8a9b6e61758a40d01028a4edb4a4d21b845b83b3e0793ed0934e48f3d9eea0 -size 94637 +oid sha256:85ef188fa3a27e42f4beafc899c1f3e7e8bcfad980ed76af6a03f76d70d6a511 +size 93807 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Light.png b/libraries/compound/screenshots/Compound Vector Icons - Light.png index 76b1cc49bd..e227f1579c 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Light.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f29d225df71587fefe07ec8739b84f1a0469786c6b1d6778da0bad33d19574e -size 101183 +oid sha256:f6e38386e95dc0c50384f06fca122ce14851ceff8ffc7865e394c1b4fccc5db6 +size 100555 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png index c70050658f..0435f55de6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd81cbc3db5d329fcc1f0d4866c220af7488bb68929d0e75b983a170d15a7ab7 -size 380173 +oid sha256:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 +size 379511 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png index 57e2226f1f..f0b5506b89 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3be2bb0c8e344780d59b67a4ba23e50890b24a8b8ad1c48673e34403ff8db496 -size 378130 +oid sha256:04ea6c2947a21d3d4a3d43e9c4750c4f2a49056536a4da3f34c95df8353e9de3 +size 377990 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png index 662ccbf182..3ac59caeea 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da65fa129fdfe903f3e466f4e1dc6c70a6930e0388a3f6d3fb116e5b91411cc3 -size 365497 +oid sha256:1a94d5198e27338675c0e15df5874ba3272ee315b8d77291dc7ccc7c754ed1f4 +size 365082 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png index 11289371f2..86018764ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd797555bb72d7bc1b874df24ca5793df5550b235fe9a28d20aaa04bf5f3d0fb -size 370592 +oid sha256:8344427a0fe87cbf0883ff53a9ee4dcf90976a7011f6618d85961df48b2c53a9 +size 370228 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png index 64bcaa05f9..058a3992c3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be969a809f346799887fe031e139dcc47db8bc851ca4ccfae8dad4ad9dc523f7 -size 363498 +oid sha256:00fe1e676086766a3eac3e4457eff52c989789fc5d8d0df2624c019ed25ce9af +size 363322 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png index 33ea565e67..db4ea8296a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48c0af64a6aab3a28ac0493bb86cb92424555d6793a0a5c6cd446c25a20ce915 -size 368757 +oid sha256:2f0d24b8011564ee7a8b2f8c2e6a24eda668ee42d451d862f884acb7926aa06c +size 368529 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png index 1a345fdd13..94428abb56 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b4bef0095e989bd411426a2626155f1b75931f05c32d2632144f3c232f3aa93 -size 348379 +oid sha256:36d7cf2510d546d2b330b1d1b1674ce58df0558c547e443794a1e7b2222add87 +size 347897 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png index 7ef8d729ef..7ddac02717 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30db6503b7dde29553b5f806924565b1d60c13edeeaa982dd2ec7d2a5c8f1162 -size 364508 +oid sha256:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 +size 363909 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png index 72f5c9a9e5..bac23aab98 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15ad31eb2b457790913442d3186fae215f77f345470748cd64a345849b9de9d0 -size 346837 +oid sha256:e30686c7c037ef102717e0316543faf4d3ed2671c21eca96a667150daab380d6 +size 346614 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png index 5a6ad7fc23..b6e4650d9d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e72a79c374fc23a1325e1bd294584b8b7f0b312c804b932144bc2e5d8911bd9 -size 361950 +oid sha256:2cd357a1fbaa425eca95587bff2f768a45e773f983f75664875653ba1900e534 +size 361625 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png index ca682211d3..67490ba700 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:092a0d4c37d47c84c790a767b9acc77f38878876e609b986f80e5fb461e0a340 -size 370156 +oid sha256:f4431e2d9f30123949ea5676ce60f642234adcf9b5a33f2acc3f80ebf6609a66 +size 369730 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png index 51a93f68e5..f0dfbc3321 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:097fe6208d9cadc707e6866c151a2ab843550a9fab4d2cf4908514ceafc4e396 -size 355327 +oid sha256:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa +size 354751 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png index e60716fb3b..c4943b892c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f61a7a62c6fc96e23c8aaa793f5fff68e2197a067ad8f1614d1103e833b3230c -size 368585 +oid sha256:4c410e853089cc2c4a2c48a00dd9a8babc8095aed72bb4625057444710559c6c +size 368129 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png index 73be879502..68f8148879 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:091352ebd6bf2abfac5dfd99be5edc94159a5a45c1d3137c7271e0031116a254 -size 345649 +oid sha256:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c +size 345094 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png index 4ec235074c..8aa2cca147 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:842632747c13219ee6c7a50d9003c9e07c622393ae4b066e86eacf04f807b181 -size 358344 +oid sha256:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 +size 357743 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png index bc6cb62827..cececc229a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f43d615fd1aec05ee483d3047e99c1ecc89a6e5a7e56e6cf7e1ea4c108be413 -size 357473 +oid sha256:f0c6dafaa41849af00d5097a85bd88e3a054a0a9e41c0466a08e6ff8dd6102b2 +size 356857 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png index d39b6ec114..14a40a5676 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:898a1e8f0277d43a1127d99ec50687c24fe1154ceb290832a14fa5a43f12647a -size 365153 +oid sha256:a11044fe90227f1f316a1ade8587e545bb620e11cca76865fc2eb83cdb817fc5 +size 364655 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png index 0617c06d2f..133fd3903f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4cce6211c0a33407498145cb03a780d80553983146f487ba3e26f794ddf12369 -size 397594 +oid sha256:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb +size 397167 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png index 838c70dcdc..0041a870b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7e91b7aec4c43e2028a2e69a02f66e04f6a3188a42387013e3deb1faa7a108e -size 356627 +oid sha256:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 +size 356193 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png index 44e5341280..9fcf389708 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80c2e99ce6f851994da38077acc30ff386867f2093a8db4de3c1b82b0b6c1a8e -size 356307 +oid sha256:9daeee1aaa04247da3c8bb5aaae9947aab1ed2d2057995e53d6ebdb63e5cd356 +size 355848 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png index 6a0ee13891..d235670def 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4fd5470ac81fbdaf471e297c0f5bd9c6b9945e006ab88079568848befe1049d -size 365366 +oid sha256:a00bd766a00b7e7c6615fc53bf469b3ca5056a6c514c096431ae38d99d604306 +size 364845 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png index cede2d333e..b10f9741b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a75fb4510d405b29b120fa400d4f69a89965c11a2228b5cc2e772200a12227e1 -size 355912 +oid sha256:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 +size 355411 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png index ebe440bfdd..422c324695 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3f7e96bbbb4b3661514713514d7f6cb27c6634ba2621c22c0dd4ff730e5e24a -size 368043 +oid sha256:a1df8d22766981fc76d6d767dc3f40d98cadc7c51be20417b067b91af604232b +size 367884 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png index bd841f6f75..1d34761a9b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:449cc2fa5ce39163a5d5eea3430c7dc457579d41b0213b8b46a61acaa76b3ccc -size 353304 +oid sha256:f7d9b5fc0ff5d7828ad6f4dc0c9bd9520b4920553da97ed7b4e030ee844c0208 +size 353054 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png index 2867c5dfd4..c081fa16a5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4cb93499ea8f21d3fb79aa81b2746972f57a4732296bb421897e93a47ddf7d06 -size 366544 +oid sha256:6a92bcf5885322e11a706071969fb674b1f6e60e021af153aaa125baa4a602ae +size 366285 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png index 83d0f043e4..b6d1f07279 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6bb6a35c2e1d2090e6e6e5b3a1733d16fd433e63925082b2ea32293ecc639fd -size 343140 +oid sha256:4bee12a6bdb18fea5ac6997671bfcb903296da7278cf69b2456330066ca31dfb +size 342870 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png index e178f75d91..ceca184bd7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1067826b5b1e3220eef3ee3b9a8c9f77bebb248ba2378cc2e7029b86c585c48 -size 356339 +oid sha256:8e82011a72f36889c53ab61ed2b9947c7fb5f868c9b7010904fc10f4ca587082 +size 356082 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png index f43199a9d8..5cc5cfe4fc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:437f71e1845447b8f09905b4d97dd46677d8d8db669a317f8cba9ada6f5f1aa8 -size 355551 +oid sha256:6524cc87257cc9d3f135904f4e14594b56df695e71fe576418d2319c472d710b +size 355285 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png index 80db679074..e9d85990e8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffa5216fcff101f8ab1047ac9808f98749144e1b1197bc01905cd6ad251d31b7 -size 363081 +oid sha256:66d4b6ea4a697735bbb0fac936b89cde99c5077973ba828894bf50b5dae233b3 +size 362848 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png index b7a7e2020b..0eb106f4a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:222460ba0557c96c2ad0e8aab675a254f515281d06bf4a7b642ea7ef79d5171d -size 395589 +oid sha256:217ac95bf476c53d2dc6d3d0143b21312bf38b8ab86c8dfd4f9360582b584f9d +size 395476 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png index 75bb1086fe..ae8495618a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb0a738e57b657bda2454526dcd78a37d38839183a5feae99bf7f107c12ccded -size 354661 +oid sha256:08057fdc1e1184720b438ddd2a8753f00791baf2456cc30b45de8e6bdeb57e8e +size 354404 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png index a93768052e..40105c1498 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f98146a417290fcc741ef676fdb60f36822931358e943ad12faace7f96e995f -size 354422 +oid sha256:5ed24d190f10c079f8cf176404372d40eb25cc78ce595a22febc540315057b86 +size 354075 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png index c09d98903c..0cfd1dc985 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54c9d1f121d83f1a161f6483a6b4bbefa220c235ae88097ed4d03baf10bbcf9c -size 363289 +oid sha256:545c9e8933e420cc3f8fbba0fbd5162c946c65a20721faeb77c568596ca720cd +size 363045 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png index 0e2c06b0f3..c8306263a0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:932e5b29f2a64d70956470bee1be397775c6205f590081d3b90c98cf47845577 -size 353993 +oid sha256:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd +size 353705 diff --git a/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Day_1_en.png index 035b39c739..9b53e56d9f 100644 --- a/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cdaf746151224c1889c60232b55cb8c9d8b3c07cd341b1bb8ad6fb7abff97ed -size 9538 +oid sha256:a7983d27647e60d385703d5bb91763ab787ee69e0a0ef04acd13ca86d5d5b1ec +size 9560 diff --git a/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Night_1_en.png index 2a46e52aa3..ced849e58a 100644 --- a/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.viewfolder.impl.folder_ViewFolderView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:072d91aa19fa0c5ec80ca565e1529988598cd54afcf6f593c6dcf17882170d0c -size 9393 +oid sha256:c32280e645ff1459b179423f67077dfc75093f5e6c40fff659769d164f391aeb +size 9408 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png index e3cda24208..79992a9708 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca6ffe10dd122a2c2df99160b4e318e591ef6d3b10b6173d36f6c9959a93277f -size 114895 +oid sha256:30b39281fd597089c94c8ff1680297143989d6da97d6f5b15198be5f92469483 +size 114653 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png index a5db879ab2..1a6f5d660b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9775ee85b895e1eb6b58841a5232de980f44bf4a20c0f2e2bcab731f503fc762 -size 11000 +oid sha256:30ae0b86a9834a90990a42f6bad0fc9010b4109bfbbe85072f00d61b0664e6e2 +size 10926 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png index c186a409ad..1c65fadbf4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7ab6bf5d8255d61569c4400f5a911400f415a4e228de41e181ccb42e2742e47 -size 18637 +oid sha256:d6c87eb2b2da4afdadd949bd39e88389c34053adb19d34f8958f97ae1faf90da +size 18557 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png index c229dd85d8..42f4e1a941 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c54410a3733a3cecd1b161eb524e1809c270b8d2dd814c095eb73e013b486e0 -size 7840 +oid sha256:3c49dbe21e9c465adc1f12a57b87dcb06569936e80d047e0db77314cefce4691 +size 7756 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png index 609162f4bc..41e20b4266 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:793eea182afcb72be59a090d3c3e622edcd6f9509271bef2e75a2f45f47a8fe4 -size 10567 +oid sha256:7523f982565c692f9986d11bba14ecc51a3401700de5a752fe5d2b667d0ea236 +size 10560 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png index 874da23636..be3a01d3d2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e1cd401ab146d2d15e94a591625ab40440e32030f4acfd4ed9bd18dce01a1f0 -size 17814 +oid sha256:73769f2c3ced2e20f6a3a91cd8cd040c14e93a19c923d5784e2081cf4baf2d44 +size 17790 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png index c4e3bc9a39..90d85686d7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e47e98d0ace1eb50dfeb9935c27206abee28d42d0e092d410de4239dc6ac293 -size 7519 +oid sha256:ef3e1d6d11520f6475059032d53c9c0a6e80c133318a0ae44dfc67d9b69c31c1 +size 7494 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png index b51a04e421..df3af23261 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cf5e60d289daa62dff1c07469227acffd275a1e4a3534b60cbe37c89a2c4bb7 -size 72136 +oid sha256:2703da4167bd0198f9666c2160bf95e4c99ac718864ae67d277fbbb4fd50014f +size 71876 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png index 217b3181b7..6d8f6e1a3e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af4895f8222d984437a5d7427268d198345ad690161789d7bbb0340eeda916f7 -size 58660 +oid sha256:86f6e18357569284c223afb87195be656e6e6c90794e64ef6a13346c8de6c496 +size 58367 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png index 046d651b57..2704eb3847 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6049adcc9de51802804d0224bd7d5a7ee8ae2a754411e4ca5685df8028d51480 -size 71727 +oid sha256:05f9317281ed84751b9f168c4495e94d1f68a9f9e7946270402db59e259d1ac5 +size 71392 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png index 26ba390595..6cc38e5ad5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e339b203a782f7d73195b1cd6961c67dac8b313a6a965515e4bc2d2b83a2118d -size 80524 +oid sha256:be4cda10c2b416d70d020c46abb00e41a2802e5d71f2dc416c506cffae147af1 +size 80226 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png index 0a18ae1074..a74e2710c8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22cf555cb18cea56f2e6bd9f91dbf70353916f196ceba84b11ea017b9e95d794 -size 61511 +oid sha256:3d29017d9dca92779074b963ba29681bb6cc83728a15ba2f55846c8fb2751d1d +size 61119 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png index 063006fb88..f3472de5f0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de1e98fb04a4188e2c6b795a3cf0b21129d0e99f8ea2748137e9f8122d413c6a -size 60353 +oid sha256:a8d1701f1be6087e93d15bbeed97659e57e0d58b9d5087fad0253d5d3dd60194 +size 59972 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png index 9bfef2c6a2..be14ebd9b2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1861fe30f2c653911cfe193d69c21affea73f458132d6a1b6381aa504d4cce74 -size 67327 +oid sha256:d2d984f17ca414c523d6a2cdcf9fc4f82c0759b22b72b60e8f5bb28776350a72 +size 66958 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png index dcc6b6c915..c0ee61b312 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b5f1d42f06c4c5949f1fb1d216c7af45c4606a782178c21b58d0a0e7504a333 -size 89006 +oid sha256:eeb25a0b7738b0a8b12a2fbdcfc469dcfc2c893ebfa4a50a3047491f817ff981 +size 88665 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png index df1c374209..05cb3a4a89 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7074c637e0a3e9320f86a4f417931d59c2d5e199996e8e533f692a82ab0d8d2 -size 59581 +oid sha256:f1f008fc8bc035bf9256e19e831691d3ac7c3347e83aaed2ae8d4b7a7f5b4213 +size 59285 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png index 442ea4ff99..63622b0027 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0f084ce1bca37f796e7f50d78a4f03485b77fa742efd688d6b8accc2b41f5e9 -size 59734 +oid sha256:e9294ee360463d72968ef89eeed7ff52c80da29e4a59f36f00422f1fe3cb7d9f +size 59350 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png index 4e4fd5476c..62268cf4f8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20f92a0cbc8a60bb057b131e17300653ce21367627f611193b6b9ddeba5d4b37 -size 66908 +oid sha256:5dd13cfda2b0f029a46477cbe9f8db1e3a191890072665adda02ec0750cddcd6 +size 66535 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png index c5324db3d6..da1080256f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a0be3b08f1923c223eb433cda9d8c1bd86ba2dff1bce31e069b29953b13a084 -size 59085 +oid sha256:9b32f9442e9088eec377f74127c99002aaf2c5668b0550047dd7b1c9e73ad619 +size 58783 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png index 8fb1c22b45..9e1047504c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17bc1cac4537bd0b9a2dcd91838ff7c20de7e6076dbb9b174ad801af76f234f8 -size 69080 +oid sha256:24baa66c2fced922b328987b51c1045af7111fb3c7e4bafdc46046eae61d0f87 +size 68773 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png index c6b221f461..70a49794e7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:caceabb04420f3675940e3b95ec685cb2b02c69d87fd19843640a5e882dfa1ca -size 56124 +oid sha256:e343b71b9f170fa7879510544cfc95af1ba15ebc128bc5d78afd49d10c70dc66 +size 55802 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png index b5e644918e..c04c1cae02 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d46716354df7925d15345b61d8e16d80c0b3552b687a896004f4174286ad18ef -size 68625 +oid sha256:d76f37cc5bd2d6ee9b7c87bfe7b656b0095ce6ded4d07cdc48d255039aed3520 +size 68313 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png index c2bbd56d35..98a5dfd03c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a0b4ad61421f6b142e51200fb40df935027962145fa09b9871a11cdfdea8c0f -size 77316 +oid sha256:d24998e960d2d4d36c1ef0f589e9094d972203016b0a923268c1894bd09f267f +size 76999 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png index 3bb5259f05..ba691c8f65 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89b7d536f86c72378714e4fab14b24671a86726abdcd63a1e15abcefde6a6abb -size 58721 +oid sha256:62592587ff02f0d36cb40f0b59fa3e7c6925cd42622ac76c4d561f6df999eba9 +size 58404 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png index 4af97d2cc8..7ee8d6355c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d314aa8f8572a099c4aa0f96de8dfade75c57edee4732c3d1300e5356c0bed20 -size 57649 +oid sha256:fc54d34649b067af6e0daa7d2e1c8661572fe0139ea9aed209b28c3a99f44f12 +size 57353 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png index 918c7fa1b5..80a0c981fb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf3bc1027fdbbb194d1a0120123872f0ce75c41c43d5c73c72908ddbffaaebb1 -size 64314 +oid sha256:10f02c7de0575dc30c65cafa4adeb265d6ea1e487db240f1d4052be138a8b0b0 +size 64014 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png index c5eb73aa1c..3c4f0dff27 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92273288bdfe895fe0664533f60e322893ece33d271259303e35d9358fbae5df -size 85238 +oid sha256:a196fe9e7c551fa7cc1145c9f8df12c5905678fae285884b71e7ea15cea1bf5b +size 85088 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png index 4449d490db..616dacf9a0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d04a904fb5f98c075ed844668a06af29d03e7d1adf8bab7706d1cea39abcceb6 -size 57003 +oid sha256:60b3b04167249a6283dccae1450645853df5e05ac7a31f419c674be0594dd413 +size 56710 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png index ff54d6d0c5..256094a264 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:896b4497818ded4ce18ad6089fd436160f87189d79da1cb63ea652818de10041 -size 57009 +oid sha256:d303c75fe252ee9d3fb0bd91131ed44b731ea6fbe120dc1379aeac4c4d43c467 +size 56693 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png index 6d72c0f7cc..9aa831dde8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:256349593b50a7e1f40db6c032aa39a640136934eadde8883936b0b1885f81b0 -size 63867 +oid sha256:81d23de4f3afac7993f42ea8030f6a2392768b343761408d6737382492443267 +size 63586 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png index f05bee7bd5..3c59d53b44 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25b5d39992361966545a3c04b3de7b20569a1e12800b3ecf38e090ceb2afa7c9 -size 56567 +oid sha256:7c3a1636c58e8243f971f69ea3575e75a12526863f1304a32f65fc2991fd403f +size 56250 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png index d9d7e2913e..93c1f0a9ce 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bfb2c4674cd8bd0bcd434a2790f3e121dbc6a6c39e41d0417c80cdfb44be91ae -size 73627 +oid sha256:8eb6049cc99813238995f936022fd9fd5a43d1e917bfc69ab1069fe3da456cb5 +size 73316 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png index 7891573b3d..fe7b50f2e8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be931ad71b0562cd96456124c987ed79709f3ec7c55d736f4f71da1fdb036309 -size 56863 +oid sha256:611527e8c0bce7a9fb48b5eff42170cb9da5f40cf020c78209dee84615d300ba +size 56514 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png index 2e5b1dc647..dd8f8d2a66 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3f24723f76f444a6503ee01399298ae4258a190cd6657dd1bf5308ea528d55f -size 72035 +oid sha256:77b28be1b95709082e0302cca5b65c2d57ab48786e6a22facb8c86116f058b11 +size 71667 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png index 584285c1be..be45e720dd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfb33cec43d32917cb8f59e012244fa0c8824421cbedac516e002862f28f93db -size 83506 +oid sha256:31875ed4c6d9443418899de47eeb5b61d2246d8321e83579681cfa152ff4a056 +size 83174 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png index 7414d959a4..e7efad21d5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:94d01e112a860c145c6c09d1d3a9bf948fe73e7b939d7f602704a3b4853de9f5 -size 60076 +oid sha256:5cc4f388f677bf04259344b5bfc9033ef6a4a76ad161012abcd0239ef520a8d8 +size 59670 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png index b6e7b4e2a5..638e2761d7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b064ba533e8bfa225f0548fc6e13d811a0ab0dddcd500cfbb72ed199a268c1b9 -size 59202 +oid sha256:e57a614424396e36229d7877a0bb222a51e9e955a42e180acc1d43c048684da2 +size 58787 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png index c223cabf8f..6c510542bb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e0cdd88f5776e92aa0063c09f4c7c1c099d2b8cb0f4a13066925c1ca105b37a -size 66800 +oid sha256:4546f32ff1eeae0a923d473491926a6037eddf59c0c88c516c504b9875874c8a +size 66402 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png index 042c2792ce..d472874510 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa0e313a3d429ddfba85b62f4d855489cb5cca62bc6693dcaa33f4d0ac622b85 -size 101888 +oid sha256:acd25c00d9127c2c78f48b22296a5ab33f1e16ec5698c93dd29adc9172467aac +size 101706 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png index d1b0e795b5..48f0ad6881 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e3210208348505b93f4d673977f237bd7859b054699c1d66ece28591d20640b -size 58145 +oid sha256:d066e82aba5742c7e84a260de0e4578bb3bc8faac097225271cfdb14cd52f5f0 +size 57816 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png index a014be7a5a..f8f0337792 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0c9e887cd48c5aee046649a2ca5949abe763363659e29dd523869dc615e98f2 -size 58186 +oid sha256:2c037b4de113387ac7e28d256d28ce9308be184b4ebff988ed96760623acfafd +size 57776 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png index 4f07ac8b8f..6278391831 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5febf4de05a7794160b567dec3b00e818a6e3d4d7830d3dba97f72498aa5a3c -size 67172 +oid sha256:81883325e2e450c33f38b3143c43a3fa3d659a210ff6e9ef40de71b1d0522f50 +size 66781 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png index 2d5e2c39da..07c20262cd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f213b779238ac8536e4f0115d8de444a21c3b8ce31aac8aebd5415d8f80504a4 -size 57501 +oid sha256:b6b5808bdde620cac3fe980aee1f8162a854965113d99d074442a2baa818d712 +size 57198 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png index 362033d451..c41f41d043 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27cc53e2336c9ccf90d97d2aed98f94f83315dcb9fe4bd489958b8df2366262c -size 70207 +oid sha256:7174f340d6e16be525da9a06270f07abc7496fc6c41a5670a71bd1b23f4a72c2 +size 69957 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png index aa712c48ec..5d3b894ebc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd6c1a82daedd923982d81956924eeaa37857d54dee55f31fda4520071b4f66b -size 53675 +oid sha256:dbb0c22089c063c18042c8778c1b69edb441af8071f7dfb9a3ffdaeab4ba4c71 +size 53340 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png index 804b238d8d..61a6581ec4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffce97ff7f1d6a2641d761aad6457883babe333075a454b5860d266719bdb3f9 -size 68525 +oid sha256:e9a561ca3aa61371cc1bd0c1b51508469a0343de3bd8f404055041591c60d42f +size 68231 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png index ec221ef43a..7c25276223 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58718344783197c680e18a7a3c97a3531293b6e2442ca5701d4605ecb567e70a -size 79724 +oid sha256:c739add59dd40303652319c0b789ec4d0d2224cc097598ef717e8fb101031ad7 +size 79471 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png index 8369183006..a3fcdfc5f0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d84207a6b1bf4815d2515974c721a0ba26fb406a31e96f3566b90e548c7bf49 -size 57077 +oid sha256:61d30aca9b213938462659c2dcb8bc8ef10b28821f8492715003262f4cae142c +size 56761 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png index 7cd4c1a580..e10bdbdf26 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2056d90bbf2676fae7d88b326c496aae95a1c31924c8b5d13ca363f486c72968 -size 56206 +oid sha256:a84be2101e96ab4e7566e4fe1af14243466c7dba7e540fb7502acbbf70d33aaa +size 55835 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png index 6b23cf2db8..29ac8cd6f3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bca7347130b0b449ef2c917359753660446e4be7d2d4a13323489c63dbf28a4 -size 63589 +oid sha256:9f168b3af0e3679a2d7a5f2baddc1523c1afe9dc433d25c267572097d9ab7d15 +size 63284 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png index f388e96dac..f405aa34cb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fffdb6a8f159af3104d9f2e8edbc11395854f6ac6a558e303d20c79ea91857b -size 98128 +oid sha256:41799e15fad757a976b278d5d722fc755dcfdda3ad0880a1f4058a337b96d470 +size 97907 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png index 37890657c9..9b72a8c4fd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534628991ee750aa4f4b4e3edda1ea26cf648eb74d06610d4207266b659d4421 -size 55083 +oid sha256:c3d27473a9375edc590aeedf8dcb188e1c23785a8f8c62900aa439c33f86ca13 +size 54772 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png index cb402d830b..7a87bb30d2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9de6ef77a1d574da317c3d1c3258f3068e79613387d0bc32e925f516338da9e9 -size 55092 +oid sha256:52a125268370bb369c53271f204b5f942da75f01639a39ae6b935d3f3ab4ef00 +size 54705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png index 06a6ee8488..d0e908caff 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:350c89c3491e08a80f9910121140d56f2cf28fdc0b8f6ced380d1ec34b116c52 -size 63975 +oid sha256:56d531df665ae3baa6400b0fc83b1fe756ec0f452ddd2423457ed26ea18aed98 +size 63628 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png index e698f48771..29df858167 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8659bbb89e5c26caea7f1d759e1c9bbd6ecedc525dcc2cb6b1cc844c835aeec1 -size 54455 +oid sha256:d4e66a9e00b7aa05294522055cf6a89e68d409496c1a24ef0b6d841221f6883b +size 54122 From 860def39656d51c54849ae41ddf868e0d2acdf11 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 2 Apr 2026 11:10:47 +0200 Subject: [PATCH 0042/1083] Tentative fix for `ForegroundServiceStartNotAllowedException` (#6509) * Tentative fix for `ForegroundServiceStartNotAllowedException` When failing to start the service in foreground, don't crash. This is a helper to speed up the scheduling by keeping the CPU awake, not a critical part that should succeed * Simplify `DefaultPushHandlingWakeLock` It seems like restarting the service from background won't work in some cases, so don't try it. --- .../push/impl/push/DefaultPushHandlingWakeLock.kt | 12 ------------ .../push/impl/push/FetchPushForegroundService.kt | 8 +++++++- 2 files changed, 7 insertions(+), 13 deletions(-) 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 index 9713110042..27a921c219 100644 --- 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 @@ -14,7 +14,6 @@ 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 java.util.concurrent.atomic.AtomicInteger import kotlin.time.Duration @ContributesBinding(AppScope::class) @@ -22,24 +21,13 @@ import kotlin.time.Duration class DefaultPushHandlingWakeLock( @ApplicationContext private val context: Context, ) : PushHandlingWakeLock { - private val count = AtomicInteger(0) - override fun lock(time: Duration) { Timber.d("Acquiring wakelock for push handling, starting service.") FetchPushForegroundService.startIfNeeded(context) - - count.incrementAndGet() } override suspend fun unlock() { Timber.d("Releasing wakelock used for push handling.") FetchPushForegroundService.stop(context) - if (count.decrementAndGet() <= 0) { - Timber.d("No more wakelock needed for push handling, stopping service.") - count.set(0) - } else { - Timber.d("Wakelock still needed for push handling, restarting service | count: ${count.get()}.") - FetchPushForegroundService.startIfNeeded(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 6dc6bdfa0e..da5dc80707 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 @@ -145,7 +145,13 @@ class FetchPushForegroundService : Service() { fun start(context: Context) { val intent = Intent(context, FetchPushForegroundService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(intent) + 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) } From 68ad2bf7a96e32f5c37faa8b50ba1600abd7d41d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:39:06 +0200 Subject: [PATCH 0043/1083] fix(deps): update dependency androidx.compose:compose-bom to v2026.03.01 (#6511) 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 9f8878440b..c03363c97d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ camera = "1.5.3" work = "2.11.2" # Compose -compose_bom = "2026.03.00" +compose_bom = "2026.03.01" # Coroutines coroutines = "1.10.2" From 068b5b95a2f681d80684bcb53b5a4ca7971d6fc4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:39:31 +0200 Subject: [PATCH 0044/1083] fix(deps): update dependency org.jetbrains.kotlinx:kover-gradle-plugin to v0.9.8 (#6513) 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 c03363c97d..743b244f28 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -64,7 +64,7 @@ detekt = "1.23.8" # See https://github.com/pinterest/ktlint/releases/ ktlint = "1.8.0" androidx-test-ext-junit = "1.3.0" -kover = "0.9.7" +kover = "0.9.8" [libraries] # Project From 19070771d287bb163421329dd5d57408d7385773 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:45:46 +0200 Subject: [PATCH 0045/1083] fix(deps): update dependency androidx.browser:browser to v1.10.0 (#6515) 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 743b244f28..0ac571c344 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -102,7 +102,7 @@ androidx_javascriptengine = "androidx.javascriptengine:javascriptengine:1.0.0" androidx_workmanager_runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "work" } androidx_recyclerview = "androidx.recyclerview:recyclerview:1.4.0" -androidx_browser = "androidx.browser:browser:1.9.0" +androidx_browser = "androidx.browser:browser:1.10.0" androidx_lifecycle_runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" } androidx_lifecycle_process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle" } androidx_splash = "androidx.core:core-splashscreen:1.2.0" From 3634b5593c3b3eb580afb11b5b2a014a4b5eb86d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:38:43 +0200 Subject: [PATCH 0046/1083] fix(deps): update dependency io.element.android:emojibase-bindings to v1.5.3 (#6493) 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 0ac571c344..015b50531c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -226,7 +226,7 @@ sentry = "io.sentry:sentry-android:8.36.0" matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" # Emojibase -matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.2" +matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.3" sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" # Di From 4ad495d36c6ccde088848a2ac90c7db62e963421 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 2 Apr 2026 16:15:32 +0200 Subject: [PATCH 0047/1083] Add support for slash commands (under Feature Flag) (#6482) * Add support for slash commands * Update screenshots * Rename module `slash` to `slashcommands` * Rename `SlashCommand` to `SlashCommandService` * Introduce MsgType in order to send text message with a different msgtype value. * Format file and add parameter names, add default values and cleanup * Add isSupported parameter to filter out unsupported yet commands. * Slash commands: disable suggestions if the feature is disabled. * Fix sending shrug command. * Add missing test on SuggestionsProcessor * Add tests on MessageComposerPresenter about slash command. * Fix import ordering * Add missing tests on CommandExecutor * Add missing tests in MarkdownTextEditorStateTest * Slash commands: Improve code when sending message with prefix. * Slash commands: Add support for /unflip --------- Co-authored-by: ElementBot --- .../android/appnav/LoggedInFlowNode.kt | 14 +- .../room/joined/JoinedRoomLoadedFlowNode.kt | 9 + .../FakeJoinedRoomLoadedFlowNodeCallback.kt | 1 + .../impl/share/ShareLocationPresenterTest.kt | 3 + .../messages/api/MessagesEntryPoint.kt | 1 + features/messages/impl/build.gradle.kts | 2 + .../messages/impl/MessagesFlowNode.kt | 10 +- .../messages/impl/MessagesNavigator.kt | 2 + .../features/messages/impl/MessagesNode.kt | 11 +- .../messagecomposer/MessageComposerEvent.kt | 1 + .../MessageComposerPresenter.kt | 87 +++- .../messagecomposer/MessageComposerState.kt | 2 + .../MessageComposerStateProvider.kt | 3 + .../messagecomposer/MessageComposerView.kt | 7 + .../suggestions/SuggestionsPickerView.kt | 80 +++- .../suggestions/SuggestionsProcessor.kt | 18 +- .../impl/threads/ThreadedMessagesNode.kt | 11 +- .../impl/DefaultMessagesEntryPointTest.kt | 1 + .../messages/impl/FakeMessagesNavigator.kt | 10 + ...essageComposerPresenterSlashCommandTest.kt | 323 +++++++++++++ .../MessageComposerPresenterTest.kt | 48 +- .../suggestions/SuggestionsProcessorTest.kt | 72 ++- .../impl/timeline/TimelineControllerTest.kt | 5 +- .../preferences/api/PreferencesEntryPoint.kt | 3 + .../impl/DefaultPreferencesEntryPoint.kt | 1 + .../preferences/impl/PreferencesFlowNode.kt | 6 +- .../roomdetails/api/RoomDetailsEntryPoint.kt | 1 + .../roomdetails/impl/RoomDetailsFlowNode.kt | 4 + .../impl/DefaultRoomDetailsEntryPointTest.kt | 1 + .../features/share/impl/SharePresenterTest.kt | 4 +- .../libraries/featureflag/api/FeatureFlags.kt | 7 + .../matrix/api/core/RoomIdOrAlias.kt | 10 + .../libraries/matrix/api/mxc/MxcTools.kt | 15 + .../libraries/matrix/api/timeline/MsgType.kt | 19 + .../libraries/matrix/api/timeline/Timeline.kt | 3 + .../matrix/impl/timeline/RustTimeline.kt | 19 +- .../matrix/impl/util/MessageEventContent.kt | 46 +- .../matrix/test/timeline/FakeTimeline.kt | 14 +- ...otificationBroadcastReceiverHandlerTest.kt | 22 +- libraries/slashcommands/api/build.gradle.kts | 17 + .../libraries/slashcommands/api/ChatEffect.kt | 13 + .../slashcommands/api/MessagePrefix.kt | 15 + .../slashcommands/api/SlashCommand.kt | 71 +++ .../slashcommands/api/SlashCommandService.kt | 41 ++ .../api/SlashCommandSuggestion.kt | 14 + libraries/slashcommands/impl/build.gradle.kts | 35 ++ .../libraries/slashcommands/impl/Command.kt | 233 ++++++++++ .../slashcommands/impl/CommandExecutor.kt | 214 +++++++++ .../slashcommands/impl/CommandParser.kt | 430 ++++++++++++++++++ .../impl/DefaultSlashCommandService.kt | 80 ++++ .../impl/rainbow/RainbowGenerator.kt | 113 +++++ .../slashcommands/impl/rainbow/RgbColor.kt | 21 + .../impl/src/main/res/values/temporary.xml | 47 ++ .../slashcommands/impl/CommandExecutorTest.kt | 359 +++++++++++++++ .../slashcommands/impl/CommandParserTest.kt | 224 +++++++++ .../impl/DefaultSlashCommandServiceTest.kt | 165 +++++++ libraries/slashcommands/test/build.gradle.kts | 19 + .../test/FakeSlashCommandService.kt | 45 ++ libraries/textcomposer/impl/build.gradle.kts | 1 + .../mentions/ResolvedSuggestion.kt | 5 + .../model/MarkdownTextEditorState.kt | 20 +- .../impl/model/MarkdownTextEditorStateTest.kt | 37 +- .../kotlin/extension/DependencyHandleScope.kt | 1 + ...estions_SuggestionsPickerView_Day_0_en.png | 4 +- ...tions_SuggestionsPickerView_Night_0_en.png | 4 +- 65 files changed, 3038 insertions(+), 86 deletions(-) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MsgType.kt create mode 100644 libraries/slashcommands/api/build.gradle.kts create mode 100644 libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/ChatEffect.kt create mode 100644 libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/MessagePrefix.kt create mode 100644 libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt create mode 100644 libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandService.kt create mode 100644 libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandSuggestion.kt create mode 100644 libraries/slashcommands/impl/build.gradle.kts create mode 100644 libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt create mode 100644 libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt create mode 100644 libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt create mode 100644 libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt create mode 100644 libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RainbowGenerator.kt create mode 100644 libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RgbColor.kt create mode 100644 libraries/slashcommands/impl/src/main/res/values/temporary.xml create mode 100644 libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt create mode 100644 libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt create mode 100644 libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt create mode 100644 libraries/slashcommands/test/build.gradle.kts create mode 100644 libraries/slashcommands/test/src/main/kotlin/io/element/android/libraries/slashcommands/test/FakeSlashCommandService.kt 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..44c1060e10 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -422,6 +422,10 @@ class LoggedInFlowNode( override fun navigateToGlobalNotificationSettings() { backstack.push(NavTarget.Settings(PreferencesEntryPoint.InitialTarget.NotificationSettings)) } + + override fun navigateToDeveloperSettings() { + backstack.push(NavTarget.Settings(PreferencesEntryPoint.InitialTarget.DeveloperSettings)) + } } val inputs = RoomFlowNode.Inputs( roomIdOrAlias = navTarget.roomIdOrAlias, @@ -744,11 +748,11 @@ private class AttachRoomOperation( } } + // Always create a new element, otherwise we wouldn't be navigating to the target event id or child node BackStackElement( - key = NavKey(roomTarget), - fromState = CREATED, - targetState = ACTIVE, - operation = this - ) + key = NavKey(roomTarget), + fromState = CREATED, + targetState = ACTIVE, + operation = this + ) } else { // Otherwise, just push the new node to the end of the backstack Push(roomTarget).invoke(currentElements) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index d0d3df590d..febd15e9c2 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -85,6 +85,7 @@ class JoinedRoomLoadedFlowNode( fun navigateToRoom(roomId: RoomId, serverNames: List) fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun navigateToGlobalNotificationSettings() + fun navigateToDeveloperSettings() } data class Inputs( @@ -145,6 +146,10 @@ class JoinedRoomLoadedFlowNode( callback.navigateToGlobalNotificationSettings() } + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } + override fun navigateToRoom(roomId: RoomId, serverNames: List) { callback.navigateToRoom(roomId, serverNames) } @@ -252,6 +257,10 @@ class JoinedRoomLoadedFlowNode( override fun navigateToRoom(roomId: RoomId) { callback.navigateToRoom(roomId, emptyList()) } + + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } } val params = MessagesEntryPoint.Params( MessagesEntryPoint.InitialTarget.Messages(navTarget.focusedEventId) diff --git a/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt b/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt index 40778ae353..2f17071870 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt @@ -16,4 +16,5 @@ class FakeJoinedRoomLoadedFlowNodeCallback : JoinedRoomLoadedFlowNode.Callback { override fun navigateToRoom(roomId: RoomId, serverNames: List) = lambdaError() override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() override fun navigateToGlobalNotificationSettings() = lambdaError() + override fun navigateToDeveloperSettings() = lambdaError() } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index 92c27d9f21..46bc4a55df 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -6,6 +6,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.element.android.features.location.impl.share import app.cash.molecule.RecompositionMode @@ -37,6 +39,7 @@ 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.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule diff --git a/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/MessagesEntryPoint.kt b/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/MessagesEntryPoint.kt index a23e337d2a..3eecd54f3e 100644 --- a/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/MessagesEntryPoint.kt +++ b/features/messages/api/src/main/kotlin/io/element/android/features/messages/api/MessagesEntryPoint.kt @@ -38,6 +38,7 @@ interface MessagesEntryPoint : FeatureEntryPoint { fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean) fun navigateToRoom(roomId: RoomId) + fun navigateToDeveloperSettings() } data class Params(val initialTarget: InitialTarget) : NodeInputs diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 01482d0df5..6ff7f7e322 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -53,6 +53,7 @@ dependencies { implementation(projects.libraries.preferences.api) implementation(projects.libraries.recentemojis.api) implementation(projects.libraries.roomselect.api) + implementation(projects.libraries.slashcommands.api) implementation(projects.libraries.audio.api) implementation(projects.libraries.voiceplayer.api) implementation(projects.libraries.voicerecorder.api) @@ -104,4 +105,5 @@ dependencies { testImplementation(projects.features.poll.test) testImplementation(projects.libraries.eventformatter.test) testImplementation(projects.libraries.recentemojis.test) + testImplementation(projects.libraries.slashcommands.test) } 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..d3dd21de67 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 @@ -293,6 +293,10 @@ class MessagesFlowNode( override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) { backstack.push(NavTarget.Thread(threadRootId, focusedEventId)) } + + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } } val inputs = MessagesNode.Inputs(focusedEventId = navTarget.focusedEventId) createNode(buildContext, listOf(callback, inputs)) @@ -502,6 +506,10 @@ class MessagesFlowNode( override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) { backstack.push(NavTarget.Thread(threadRootId, focusedEventId)) } + + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } } createNode(buildContext, listOf(inputs, callback)) } @@ -567,7 +575,7 @@ class MessagesFlowNode( assetType = event.content.assetType, ) NavTarget.LocationViewer( - mode = mode + mode = mode ).takeIf { locationService.isServiceAvailable() } } else -> null diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt index 2ec5c0bcbf..e475f579c3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt @@ -23,6 +23,8 @@ interface MessagesNavigator { fun navigateToEditPoll(eventId: EventId) fun navigateToPreviewAttachments(attachments: ImmutableList, inReplyToEventId: EventId?) fun navigateToRoom(roomId: RoomId, eventId: EventId?, serverNames: List) + fun navigateToMember(userId: UserId) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) + fun navigateToDeveloperSettings() fun close() } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index 0c0b3e5448..20cdc51035 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -105,7 +105,7 @@ class MessagesNode( private val timelineController = TimelineController(room, room.liveTimeline) private val presenter = presenterFactory.create( navigator = this, - composerPresenter = messageComposerPresenterFactory.create(timelineController, this), + composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = false), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), actionListPresenter = actionListPresenterFactory.create( postProcessor = TimelineItemActionPostProcessor.Default, @@ -130,6 +130,7 @@ class MessagesNode( fun navigateToRoomDetails() fun navigateToPinnedMessagesList() fun navigateToKnockRequestsList() + fun navigateToDeveloperSettings() } override fun onBuilt() { @@ -222,10 +223,18 @@ class MessagesNode( } } + override fun navigateToMember(userId: UserId) { + callback.navigateToRoomMemberDetails(userId) + } + override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) { callback.navigateToThread(threadRootId, focusedEventId) } + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } + private fun displaySameRoomToast() { context.toast(CommonStrings.screen_room_permalink_same_room_android) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvent.kt index ae82c60f2a..982ca7dfd7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvent.kt @@ -36,4 +36,5 @@ sealed interface MessageComposerEvent { data class SuggestionReceived(val suggestion: Suggestion?) : MessageComposerEvent data class InsertSuggestion(val resolvedSuggestion: ResolvedSuggestion) : MessageComposerEvent data object SaveDraft : MessageComposerEvent + data object ClearSlashError : MessageComposerEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index ed22a5e2ee..90b91691a9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -15,6 +15,7 @@ import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf @@ -33,12 +34,14 @@ import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.location.api.LocationService import io.element.android.features.messages.impl.MessagesNavigator import io.element.android.features.messages.impl.attachments.Attachment +import io.element.android.features.messages.impl.attachments.Attachment.Media import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError import io.element.android.features.messages.impl.draft.ComposerDraftService import io.element.android.features.messages.impl.messagecomposer.suggestions.RoomAliasSuggestionsDataSource import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.TextPillificationHelper +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.mimetype.MimeTypes @@ -68,6 +71,9 @@ import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.push.api.notifications.conversations.NotificationConversationService +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.api.SlashCommandService +import io.element.android.libraries.slashcommands.api.message import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MarkdownTextEditorState @@ -104,6 +110,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes class MessageComposerPresenter( @Assisted private val navigator: MessagesNavigator, @Assisted private val timelineController: TimelineController, + @Assisted private val isInThread: Boolean, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val room: JoinedRoom, private val mediaPickerProvider: PickerProvider, @@ -125,10 +132,15 @@ class MessageComposerPresenter( private val suggestionsProcessor: SuggestionsProcessor, private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider, private val notificationConversationService: NotificationConversationService, + private val slashCommandService: SlashCommandService, ) : Presenter { @AssistedFactory interface Factory { - fun create(timelineController: TimelineController, navigator: MessagesNavigator): MessageComposerPresenter + fun create( + timelineController: TimelineController, + navigator: MessagesNavigator, + isInThread: Boolean, + ): MessageComposerPresenter } private val mediaSender = mediaSenderFactory.create(timelineMode = timelineController.mainTimelineMode()) @@ -218,6 +230,8 @@ class MessageComposerPresenter( } ) + val slashCommandAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } + LaunchedEffect(Unit) { val draft = draftService.loadDraft( roomId = room.roomId, @@ -246,12 +260,13 @@ class MessageComposerPresenter( sessionCoroutineScope.sendMessage( markdownTextEditorState = markdownTextEditorState, richTextEditorState = richTextEditorState, + slashCommandAction = slashCommandAction, ) } is MessageComposerEvent.SendUri -> { val inReplyToEventId = (messageComposerContext.composerMode as? MessageComposerMode.Reply)?.eventId sessionCoroutineScope.sendAttachment( - attachment = Attachment.Media( + attachment = Media( localMedia = localMediaFactory.createFromUri( uri = event.uri, mimeType = null, @@ -340,6 +355,9 @@ class MessageComposerPresenter( val link = permalinkBuilder.permalinkForRoomAlias(suggestion.roomAlias).getOrNull() ?: return@launch richTextEditorState.insertMentionAtSuggestion(text = text, link = link) } + is ResolvedSuggestion.Command -> { + richTextEditorState.replaceSuggestion(suggestion.command.command) + } } } else if (markdownTextEditorState.currentSuggestion != null) { markdownTextEditorState.insertSuggestion( @@ -354,6 +372,9 @@ class MessageComposerPresenter( val draft = createDraftFromState(markdownTextEditorState, richTextEditorState) sessionCoroutineScope.updateDraft(draft, isVolatile = false) } + MessageComposerEvent.ClearSlashError -> { + slashCommandAction.value = AsyncAction.Uninitialized + } } } @@ -385,6 +406,7 @@ class MessageComposerPresenter( suggestions = suggestions.toImmutableList(), resolveMentionDisplay = resolveMentionDisplay, resolveAtRoomMentionDisplay = resolveAtRoomMentionDisplay, + slashCommandAction = slashCommandAction.value, eventSink = ::handleEvent, ) } @@ -422,6 +444,7 @@ class MessageComposerPresenter( roomAliasSuggestions = roomAliasSuggestions, currentUserId = currentUserId, canSendRoomMention = ::canSendRoomMention, + isInThread = isInThread, ) suggestions.clear() suggestions.addAll(result) @@ -433,9 +456,69 @@ class MessageComposerPresenter( private fun CoroutineScope.sendMessage( markdownTextEditorState: MarkdownTextEditorState, richTextEditorState: RichTextEditorState, + slashCommandAction: MutableState>, ) = launch { val message = currentComposerMessage(markdownTextEditorState, richTextEditorState, withMentions = true) val capturedMode = messageComposerContext.composerMode + + val slashCommand = if (capturedMode is MessageComposerMode.Normal) { + slashCommandService.parse( + textMessage = message.markdown, + formattedMessage = message.html, + isInThreadTimeline = isInThread, + ) + } else { + SlashCommand.NotACommand + } + + when (slashCommand) { + is SlashCommand.NotACommand -> Unit + is SlashCommand.Error -> { + slashCommandAction.value = AsyncAction.Failure(Exception(slashCommand.message())) + return@launch + } + is SlashCommand.SlashCommandNavigation -> { + when (slashCommand) { + is SlashCommand.ShowUser -> { + navigator.navigateToMember(slashCommand.userId) + } + SlashCommand.DevTools -> { + navigator.navigateToDeveloperSettings() + } + } + resetComposer(markdownTextEditorState, richTextEditorState, fromEdit = capturedMode is MessageComposerMode.Edit) + return@launch + } + is SlashCommand.SlashCommandSendMessage -> { + timelineController.invokeOnCurrentTimeline { + slashCommandService.proceedSendMessage(slashCommand, this) + .onFailure { cause -> + Timber.e(cause, "Failed to proceed with admin slash command") + slashCommandAction.value = AsyncAction.Failure(cause) + } + .onSuccess { + // Reset composer + resetComposer(markdownTextEditorState, richTextEditorState, fromEdit = capturedMode is MessageComposerMode.Edit) + } + } + return@launch + } + is SlashCommand.SlashCommandAdmin -> { + slashCommandAction.value = AsyncAction.Loading + slashCommandService.proceedAdmin(slashCommand) + .onFailure { cause -> + Timber.e(cause, "Failed to proceed with admin slash command") + slashCommandAction.value = AsyncAction.Failure(cause) + } + .onSuccess { + // Reset composer + resetComposer(markdownTextEditorState, richTextEditorState, fromEdit = capturedMode is MessageComposerMode.Edit) + slashCommandAction.value = AsyncAction.Uninitialized + } + return@launch + } + } + // Reset composer right away resetComposer(markdownTextEditorState, richTextEditorState, fromEdit = capturedMode is MessageComposerMode.Edit) when (capturedMode) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt index 424e8c07b9..f3fdb3d59a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt @@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.runtime.Stable +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.TextEditorState @@ -26,5 +27,6 @@ data class MessageComposerState( val suggestions: ImmutableList, val resolveMentionDisplay: (String, String) -> TextDisplay, val resolveAtRoomMentionDisplay: () -> TextDisplay, + val slashCommandAction: AsyncAction, val eventSink: (MessageComposerEvent) -> Unit, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt index a06bf30dad..ef9cd7933b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt @@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.TextEditorState @@ -32,6 +33,7 @@ fun aMessageComposerState( showAttachmentSourcePicker: Boolean = false, canShareLocation: Boolean = true, suggestions: ImmutableList = persistentListOf(), + slashCommandAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (MessageComposerEvent) -> Unit = {}, ) = MessageComposerState( textEditorState = textEditorState, @@ -43,5 +45,6 @@ fun aMessageComposerState( suggestions = suggestions, resolveMentionDisplay = { _, _ -> TextDisplay.Plain }, resolveAtRoomMentionDisplay = { TextDisplay.Plain }, + slashCommandAction = slashCommandAction, eventSink = eventSink, ) 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..d387bc8765 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 @@ -22,6 +22,7 @@ import io.element.android.features.messages.api.timeline.voicemessages.composer. import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerState import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerStateProvider import io.element.android.features.messages.api.timeline.voicemessages.composer.aVoiceMessageComposerState +import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.textcomposer.TextComposer @@ -115,6 +116,12 @@ internal fun MessageComposerView( onTyping = ::onTyping, onSelectRichContent = ::sendUri, ) + + AsyncActionView( + async = state.slashCommandAction, + onSuccess = {}, + onErrorDismiss = { state.eventSink(MessageComposerEvent.ClearSlashError) }, + ) } @PreviewsDayNight diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt index e9e38e1730..678ef2ba56 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.components.avatar.AvatarType.Room import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -40,6 +41,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.ui.model.getAvatarData +import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -63,6 +65,7 @@ fun SuggestionsPickerView( is ResolvedSuggestion.AtRoom -> "@room" is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value is ResolvedSuggestion.Alias -> suggestion.roomId.value + is ResolvedSuggestion.Command -> suggestion.command.command } } ) { @@ -91,54 +94,81 @@ private fun SuggestionItemView( modifier: Modifier = Modifier, ) { Row( - modifier = modifier.clickable { onSelectSuggestion(suggestion) }, - horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = modifier + .clickable { onSelectSuggestion(suggestion) } + .padding(horizontal = 16.dp), ) { val avatarSize = AvatarSize.Suggestion val avatarData = when (suggestion) { is ResolvedSuggestion.AtRoom -> roomAvatar?.copy(size = avatarSize) ?: AvatarData(roomId, roomName, null, avatarSize) is ResolvedSuggestion.Member -> suggestion.roomMember.getAvatarData(avatarSize) is ResolvedSuggestion.Alias -> suggestion.getAvatarData(avatarSize) + is ResolvedSuggestion.Command -> null } val avatarType = when (suggestion) { - is ResolvedSuggestion.Alias -> AvatarType.Room() + is ResolvedSuggestion.Alias -> Room() ResolvedSuggestion.AtRoom, is ResolvedSuggestion.Member -> AvatarType.User + is ResolvedSuggestion.Command -> null } val title = when (suggestion) { is ResolvedSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title) is ResolvedSuggestion.Member -> suggestion.roomMember.displayName is ResolvedSuggestion.Alias -> suggestion.roomName + is ResolvedSuggestion.Command -> suggestion.command.command + } + val details = when (suggestion) { + is ResolvedSuggestion.AtRoom, + is ResolvedSuggestion.Member, + is ResolvedSuggestion.Alias -> null + is ResolvedSuggestion.Command -> suggestion.command.parameters } val subtitle = when (suggestion) { is ResolvedSuggestion.AtRoom -> "@room" is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value is ResolvedSuggestion.Alias -> suggestion.roomAlias.value + is ResolvedSuggestion.Command -> suggestion.command.description + } + if (avatarData != null && avatarType != null) { + Avatar( + avatarData = avatarData, + avatarType = avatarType, + modifier = Modifier.padding(top = 12.dp, bottom = 12.dp, end = 16.dp), + ) } - Avatar( - avatarData = avatarData, - avatarType = avatarType, - modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp), - ) Column( modifier = Modifier .fillMaxWidth() - .padding(end = 16.dp, top = 8.dp, bottom = 8.dp) + .padding(top = 8.dp, bottom = 8.dp) .align(Alignment.CenterVertically), ) { - title?.let { - Text( - text = it, - style = ElementTheme.typography.fontBodyLgRegular, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + title?.let { + Text( + text = it, + style = ElementTheme.typography.fontBodyLgRegular, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + details?.let { + Text( + text = it, + style = ElementTheme.typography.fontBodyMdRegular, + maxLines = 1, + color = ElementTheme.colors.textSecondary, + overflow = TextOverflow.Ellipsis, + ) + } } Text( text = subtitle, style = ElementTheme.typography.fontBodySmRegular, color = ElementTheme.colors.textSecondary, - maxLines = 1, + maxLines = 2, overflow = TextOverflow.Ellipsis, ) } @@ -174,7 +204,21 @@ internal fun SuggestionsPickerViewPreview() { roomId = RoomId("!room:matrix.org"), roomName = "My room", roomAvatarUrl = null, - ) + ), + ResolvedSuggestion.Command( + command = SlashCommandSuggestion( + command = "/noparam", + parameters = null, + description = "A slash command without parameters", + ) + ), + ResolvedSuggestion.Command( + command = SlashCommandSuggestion( + command = "/withparam", + parameters = " [reason]", + description = "A slash command with parameters", + ) + ), ), onSelectSuggestion = {} ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt index 789a027cf7..010aff5d4b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessor.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.slashcommands.api.SlashCommandService import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType @@ -23,7 +24,9 @@ import io.element.android.libraries.textcomposer.model.SuggestionType * This class is responsible for processing suggestions when `@`, `/` or `#` are type in the composer. */ @Inject -class SuggestionsProcessor { +class SuggestionsProcessor( + private val slashCommandService: SlashCommandService, +) { /** * Process the suggestion. * @param suggestion The current suggestion input @@ -31,6 +34,7 @@ class SuggestionsProcessor { * @param roomAliasSuggestions The available room alias suggestions * @param currentUserId The current user id * @param canSendRoomMention Should return true if the current user can send room mentions + * @param isInThread Whether the composer is in a thread or not, used to filter slash commands suggestions * @return The list of suggestions to display */ suspend fun process( @@ -39,6 +43,7 @@ class SuggestionsProcessor { roomAliasSuggestions: List, currentUserId: UserId, canSendRoomMention: suspend () -> Boolean, + isInThread: Boolean, ): List { suggestion ?: return emptyList() return when (suggestion.type) { @@ -69,7 +74,16 @@ class SuggestionsProcessor { ) } } - SuggestionType.Command, + SuggestionType.Command -> { + // Command suggestions are valid only if this is the beginning of the message + if (suggestion.start == 0) { + slashCommandService.getSuggestions(suggestion.text, isInThread).map { + ResolvedSuggestion.Command(it) + } + } else { + emptyList() + } + } SuggestionType.Emoji, is SuggestionType.Custom -> { // Clear suggestions diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 23bcbe99bd..4bb3471660 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -112,7 +112,7 @@ class ThreadedMessagesNode( this.timelineController = timelineController return presenterFactory.create( navigator = this, - composerPresenter = messageComposerPresenterFactory.create(timelineController, this), + composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = true), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), // TODO add special processor for threaded timeline actionListPresenter = actionListPresenterFactory.create( @@ -136,6 +136,7 @@ class ThreadedMessagesNode( fun navigateToEditPoll(eventId: EventId) fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) + fun navigateToDeveloperSettings() } override fun onBuilt() { @@ -233,10 +234,18 @@ class ThreadedMessagesNode( callback.handlePermalinkClick(permalinkData) } + override fun navigateToMember(userId: UserId) { + callback.navigateToRoomMemberDetails(userId) + } + override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) { callback.navigateToThread(threadRootId, focusedEventId) } + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } + override fun close() = navigateUp() @Composable diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt index a1db09dfda..dc50fca2c3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -93,6 +93,7 @@ class DefaultMessagesEntryPointTest { override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() override fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean) = lambdaError() override fun navigateToRoom(roomId: RoomId) = lambdaError() + override fun navigateToDeveloperSettings() = lambdaError() } val initialTarget = MessagesEntryPoint.InitialTarget.Messages(focusedEventId = AN_EVENT_ID) val params = MessagesEntryPoint.Params(initialTarget) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt index 68d2cd824b..44d82f1a7c 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt @@ -24,6 +24,8 @@ class FakeMessagesNavigator( private val onEditPollClickLambda: (eventId: EventId) -> Unit = { _ -> lambdaError() }, private val onPreviewAttachmentLambda: (attachments: ImmutableList, inReplyToEventId: EventId?) -> Unit = { _, _ -> lambdaError() }, private val onNavigateToRoomLambda: (roomId: RoomId, threadId: EventId?, serverNames: List) -> Unit = { _, _, _ -> lambdaError() }, + private val navigateToMemberLambda: (userId: UserId) -> Unit = { lambdaError() }, + private val navigateToDeveloperSettingsLambda: () -> Unit = { lambdaError() }, private val onOpenThreadLambda: (threadRootId: ThreadId, focusedEventId: EventId?) -> Unit = { _, _ -> lambdaError() }, private val closeLambda: () -> Unit = { lambdaError() }, ) : MessagesNavigator { @@ -51,10 +53,18 @@ class FakeMessagesNavigator( onNavigateToRoomLambda(roomId, eventId, serverNames) } + override fun navigateToMember(userId: UserId) { + navigateToMemberLambda(userId) + } + override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) { onOpenThreadLambda(threadRootId, focusedEventId) } + override fun navigateToDeveloperSettings() { + navigateToDeveloperSettingsLambda() + } + override fun close() { closeLambda() } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt new file mode 100644 index 0000000000..116a1cfb5d --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt @@ -0,0 +1,323 @@ +/* + * 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.messages.impl.messagecomposer + +import android.net.Uri +import app.cash.turbine.ReceiveTurbine +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.LocationService +import io.element.android.features.location.test.FakeLocationService +import io.element.android.features.messages.impl.FakeMessagesNavigator +import io.element.android.features.messages.impl.MessagesNavigator +import io.element.android.features.messages.impl.draft.ComposerDraftService +import io.element.android.features.messages.impl.draft.FakeComposerDraftService +import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor +import io.element.android.features.messages.impl.timeline.TimelineController +import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter +import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper +import io.element.android.features.messages.impl.utils.TextPillificationHelper +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder +import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.A_FAILURE_REASON +import io.element.android.libraries.matrix.test.A_MESSAGE +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder +import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.mediapickers.api.PickerProvider +import io.element.android.libraries.mediapickers.test.FakePickerProvider +import io.element.android.libraries.mediaupload.api.MediaOptimizationConfig +import io.element.android.libraries.mediaupload.api.MediaPreProcessor +import io.element.android.libraries.mediaupload.api.MediaSenderFactory +import io.element.android.libraries.mediaupload.impl.DefaultMediaSender +import io.element.android.libraries.mediaupload.test.FakeMediaOptimizationConfigProvider +import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory +import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.permissions.test.FakePermissionsPresenter +import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory +import io.element.android.libraries.preferences.api.store.SessionPreferencesStore +import io.element.android.libraries.preferences.api.store.VideoCompressionPreset +import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore +import io.element.android.libraries.push.test.notifications.conversations.FakeNotificationConversationService +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.api.SlashCommandService +import io.element.android.libraries.slashcommands.test.FakeSlashCommandService +import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider +import io.element.android.libraries.textcomposer.mentions.MentionSpanTheme +import io.element.android.libraries.textcomposer.model.MessageComposerMode +import io.element.android.services.analytics.test.FakeAnalyticsService +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 io.mockk.mockk +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class MessageComposerPresenterSlashCommandTest { + @get:Rule + val warmUpRule = WarmUpRule() + + private val pickerProvider = FakePickerProvider().apply { + givenResult(mockk()) // Uri is not available in JVM, so the only way to have a non-null Uri is using Mockk + } + private val mediaPreProcessor = FakeMediaPreProcessor() + private val snackbarDispatcher = SnackbarDispatcher() + private val mockMediaUrl: Uri = mockk("localMediaUri") + private val localMediaFactory = FakeLocalMediaFactory(mockMediaUrl) + private val analyticsService = FakeAnalyticsService() + private val notificationConversationService = FakeNotificationConversationService() + + @Test + fun `present - initial state`() = runTest { + val presenter = createPresenter() + presenter.test { + val initialState = awaitFirstItem() + assertThat(initialState.isFullScreen).isFalse() + assertThat(initialState.textEditorState.messageHtml()).isEmpty() + assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal) + assertThat(initialState.showAttachmentSourcePicker).isFalse() + assertThat(initialState.canShareLocation).isTrue() + } + } + + @Test + fun `present - slash command error sets failure`() = runTest { + val presenter = createPresenter( + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.ErrorUnknownSlashCommand(A_FAILURE_REASON) } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + val errorState = awaitItem() + assertThat(errorState.slashCommandAction.isFailure()).isTrue() + assertThat(errorState.slashCommandAction.errorOrNull()?.message).isEqualTo(A_FAILURE_REASON) + // Composer should not be reset when command is an error + assertThat(errorState.textEditorState.messageHtml()).isEqualTo(A_MESSAGE) + // Close the error + errorState.eventSink(MessageComposerEvent.ClearSlashError) + val finalState = awaitItem() + assertThat(finalState.slashCommandAction.isUninitialized()).isTrue() + } + } + + @Test + fun `present - slash command navigation ShowUser navigates to member and resets composer`() = runTest { + val navigateToMember = lambdaRecorder {} + val navigator = FakeMessagesNavigator(navigateToMemberLambda = navigateToMember) + val presenter = createPresenter( + navigator = navigator, + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.ShowUser(A_USER_ID) } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + advanceUntilIdle() + // navigation should be invoked and composer reset + navigateToMember.assertions().isCalledOnce().with(value(A_USER_ID)) + assertThat(initialState.textEditorState.messageHtml()).isEmpty() + } + } + + @Test + fun `present - slash command navigation DevTools navigates to developer settings and resets composer`() = runTest { + val navigateToDev = lambdaRecorder { } + val navigator = FakeMessagesNavigator(navigateToDeveloperSettingsLambda = navigateToDev) + val presenter = createPresenter( + navigator = navigator, + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.DevTools } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + advanceUntilIdle() + navigateToDev.assertions().isCalledOnce() + assertThat(initialState.textEditorState.messageHtml()).isEmpty() + } + } + + @Test + fun `present - slash command send message proceeds and resets composer`() = runTest { + val presenter = createPresenter( + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.SendPlainText(A_MESSAGE) }, + proceedSendMessageResult = { _, _ -> Result.success(Unit) } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + advanceUntilIdle() + // Composer reset after successful slash send + assertThat(initialState.textEditorState.messageHtml()).isEmpty() + // Ensure no failure + assertThat(initialState.slashCommandAction.isFailure()).isFalse() + } + } + + @Test + fun `present - slash command send message failure sets failure state`() = runTest { + val presenter = createPresenter( + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.SendPlainText("A_MESSAGE") }, + proceedSendMessageResult = { _, _ -> Result.failure(Exception(A_FAILURE_REASON)) } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + val failureState = awaitItem() + assertThat(failureState.slashCommandAction.isFailure()).isTrue() + assertThat(failureState.slashCommandAction.errorOrNull()?.message).isEqualTo(A_FAILURE_REASON) + // Clear the error + failureState.eventSink(MessageComposerEvent.ClearSlashError) + val finalState = awaitItem() + assertThat(finalState.slashCommandAction.isUninitialized()).isTrue() + } + } + + @Test + fun `present - slash command admin proceeds and resets state on success`() = runTest { + val presenter = createPresenter( + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.BanUser(A_USER_ID, null) }, + proceedAdminResult = { _ -> Result.success(Unit) } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + val loadingState = awaitItem() + assertThat(loadingState.slashCommandAction.isLoading()).isTrue() + val successState = awaitItem() + // After success, state should be Uninitialized + assertThat(successState.slashCommandAction.isUninitialized()).isTrue() + assertThat(successState.textEditorState.messageHtml()).isEmpty() + } + } + + @Test + fun `present - slash command admin proceeds and emit failure on error`() = runTest { + val presenter = createPresenter( + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.BanUser(A_USER_ID, null) }, + proceedAdminResult = { _ -> Result.failure(Exception(A_FAILURE_REASON)) } + ) + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.textEditorState.setHtml(A_MESSAGE) + initialState.eventSink(MessageComposerEvent.SendMessage) + val loadingState = awaitItem() + assertThat(loadingState.slashCommandAction.isLoading()).isTrue() + val failureState = awaitItem() + assertThat(failureState.slashCommandAction.isFailure()).isTrue() + assertThat(failureState.slashCommandAction.errorOrNull()?.message).isEqualTo(A_FAILURE_REASON) + // Clear error + failureState.eventSink(MessageComposerEvent.ClearSlashError) + val finalState = awaitItem() + assertThat(finalState.slashCommandAction.isUninitialized()).isTrue() + } + } + + private fun TestScope.createPresenter( + room: JoinedRoom = FakeJoinedRoom( + typingNoticeResult = { Result.success(Unit) } + ), + timeline: Timeline = room.liveTimeline, + navigator: MessagesNavigator = FakeMessagesNavigator(), + pickerProvider: PickerProvider = this@MessageComposerPresenterSlashCommandTest.pickerProvider, + locationService: LocationService = FakeLocationService(true), + sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), + mediaPreProcessor: MediaPreProcessor = this@MessageComposerPresenterSlashCommandTest.mediaPreProcessor, + snackbarDispatcher: SnackbarDispatcher = this@MessageComposerPresenterSlashCommandTest.snackbarDispatcher, + permissionPresenter: PermissionsPresenter = FakePermissionsPresenter(), + permalinkBuilder: PermalinkBuilder = FakePermalinkBuilder(), + permalinkParser: PermalinkParser = FakePermalinkParser(), + mentionSpanProvider: MentionSpanProvider = MentionSpanProvider( + permalinkParser = permalinkParser, + mentionSpanFormatter = FakeMentionSpanFormatter(), + mentionSpanTheme = MentionSpanTheme(A_USER_ID) + ), + textPillificationHelper: TextPillificationHelper = FakeTextPillificationHelper(), + isRichTextEditorEnabled: Boolean = true, + draftService: ComposerDraftService = FakeComposerDraftService(), + mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + isInThread: Boolean = false, + slashCommandService: SlashCommandService = FakeSlashCommandService(), + ) = MessageComposerPresenter( + navigator = navigator, + sessionCoroutineScope = this, + isInThread = isInThread, + room = room, + mediaPickerProvider = pickerProvider, + sessionPreferencesStore = sessionPreferencesStore, + localMediaFactory = localMediaFactory, + mediaSenderFactory = MediaSenderFactory { timelineMode -> + DefaultMediaSender( + preProcessor = mediaPreProcessor, + room = room, + timelineMode = timelineMode, + mediaOptimizationConfigProvider = { + MediaOptimizationConfig( + compressImages = true, + videoCompressionPreset = VideoCompressionPreset.STANDARD + ) + } + ) + }, + snackbarDispatcher = snackbarDispatcher, + analyticsService = analyticsService, + locationService = locationService, + messageComposerContext = DefaultMessageComposerContext(), + richTextEditorStateFactory = TestRichTextEditorStateFactory(), + roomAliasSuggestionsDataSource = FakeRoomAliasSuggestionsDataSource(), + permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionPresenter), + permalinkParser = permalinkParser, + permalinkBuilder = permalinkBuilder, + timelineController = TimelineController(room, timeline), + draftService = draftService, + mentionSpanProvider = mentionSpanProvider, + pillificationHelper = textPillificationHelper, + suggestionsProcessor = SuggestionsProcessor(slashCommandService = slashCommandService), + mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, + notificationConversationService = notificationConversationService, + slashCommandService = slashCommandService, + ).apply { + isTesting = true + showTextFormatting = isRichTextEditorEnabled + } + + private suspend fun ReceiveTurbine.awaitFirstItem(): T { + skipItems(1) + return awaitItem() + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index e16236f109..7a2cc1110a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -31,6 +31,7 @@ import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.matrix.api.core.EventId @@ -46,6 +47,7 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType +import io.element.android.libraries.matrix.api.timeline.MsgType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.TimelineException import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId @@ -89,6 +91,9 @@ import io.element.android.libraries.preferences.api.store.SessionPreferencesStor import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore import io.element.android.libraries.push.test.notifications.conversations.FakeNotificationConversationService +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.api.SlashCommandService +import io.element.android.libraries.slashcommands.test.FakeSlashCommandService import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider import io.element.android.libraries.textcomposer.mentions.MentionSpanTheme import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion @@ -144,6 +149,7 @@ class MessageComposerPresenterTest { assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal) assertThat(initialState.showAttachmentSourcePicker).isFalse() assertThat(initialState.canShareLocation).isTrue() + assertThat(initialState.slashCommandAction).isEqualTo(AsyncAction.Uninitialized) } } @@ -374,10 +380,13 @@ class MessageComposerPresenterTest { val presenter = createPresenter( room = FakeJoinedRoom( liveTimeline = FakeTimeline().apply { - sendMessageLambda = { _, _, _ -> Result.success(Unit) } + sendMessageLambda = { _, _, _, _, _ -> Result.success(Unit) } }, typingNoticeResult = { Result.success(Unit) } ), + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.NotACommand } + ), ) moleculeFlow(RecompositionMode.Immediate) { val state = presenter.present() @@ -409,10 +418,13 @@ class MessageComposerPresenterTest { isRichTextEditorEnabled = false, room = FakeJoinedRoom( liveTimeline = FakeTimeline().apply { - sendMessageLambda = { _, _, _ -> Result.success(Unit) } + sendMessageLambda = { _, _, _, _, _ -> Result.success(Unit) } }, typingNoticeResult = { Result.success(Unit) } ), + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.NotACommand } + ), ) moleculeFlow(RecompositionMode.Immediate) { val state = presenter.present() @@ -602,7 +614,7 @@ class MessageComposerPresenterTest { @Test fun `present - reply message`() = runTest { - val replyMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List, _: Boolean -> + val replyMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List, _: Boolean, _: MsgType -> Result.success(Unit) } val timeline = FakeTimeline().apply { @@ -633,7 +645,7 @@ class MessageComposerPresenterTest { assert(replyMessageLambda) .isCalledOnce() - .with(any(), value(A_REPLY), value(A_REPLY), any(), value(false)) + .with(any(), value(A_REPLY), value(A_REPLY), any(), value(false), value(MsgType.MSG_TYPE_TEXT)) assertThat(analyticsService.capturedEvents).containsExactly( Composer( @@ -967,7 +979,12 @@ class MessageComposerPresenterTest { ) givenRoomInfo(aRoomInfo(isDirect = false)) } - val presenter = createPresenter(room) + val presenter = createPresenter( + room = room, + slashCommandService = FakeSlashCommandService( + getSuggestionsResult = { _, _ -> emptyList() }, + ), + ) presenter.test { val initialState = awaitItem() @@ -1086,13 +1103,13 @@ class MessageComposerPresenterTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - send messages with intentional mentions`() = runTest { - val replyMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List, _: Boolean -> + val replyMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List, _: Boolean, _: MsgType -> Result.success(Unit) } val editMessageLambda = lambdaRecorder { _: EventOrTransactionId, _: String, _: String?, _: List -> Result.success(Unit) } - val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List -> + val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List, _: MsgType, _: Boolean -> Result.success(Unit) } val timeline = FakeTimeline().apply { @@ -1104,7 +1121,12 @@ class MessageComposerPresenterTest { liveTimeline = timeline, typingNoticeResult = { Result.success(Unit) } ) - val presenter = createPresenter(room = room) + val presenter = createPresenter( + room = room, + slashCommandService = FakeSlashCommandService( + parseResult = { _, _, _ -> SlashCommand.NotACommand } + ), + ) presenter.test { val initialState = awaitFirstItem() @@ -1122,7 +1144,7 @@ class MessageComposerPresenterTest { advanceUntilIdle() sendMessageResult.assertions().isCalledOnce() - .with(value(A_MESSAGE), any(), value(listOf(IntentionalMention.User(A_USER_ID)))) + .with(value(A_MESSAGE), any(), value(listOf(IntentionalMention.User(A_USER_ID))), value(MsgType.MSG_TYPE_TEXT), value(false)) // Check intentional mentions on reply sent initialState.eventSink(MessageComposerEvent.SetMode(aReplyMode())) @@ -1139,7 +1161,7 @@ class MessageComposerPresenterTest { assert(replyMessageLambda) .isCalledOnce() - .with(any(), any(), any(), value(listOf(IntentionalMention.User(A_USER_ID_2))), value(false)) + .with(any(), any(), any(), value(listOf(IntentionalMention.User(A_USER_ID_2))), value(false), value(MsgType.MSG_TYPE_TEXT)) // Check intentional mentions on edit message skipItems(1) @@ -1512,9 +1534,12 @@ class MessageComposerPresenterTest { isRichTextEditorEnabled: Boolean = true, draftService: ComposerDraftService = FakeComposerDraftService(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + isInThread: Boolean = false, + slashCommandService: SlashCommandService = FakeSlashCommandService(), ) = MessageComposerPresenter( navigator = navigator, sessionCoroutineScope = this, + isInThread = isInThread, room = room, mediaPickerProvider = pickerProvider, sessionPreferencesStore = sessionPreferencesStore, @@ -1545,9 +1570,10 @@ class MessageComposerPresenterTest { draftService = draftService, mentionSpanProvider = mentionSpanProvider, pillificationHelper = textPillificationHelper, - suggestionsProcessor = SuggestionsProcessor(), + suggestionsProcessor = SuggestionsProcessor(slashCommandService = slashCommandService), mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, notificationConversationService = notificationConversationService, + slashCommandService = slashCommandService, ).apply { isTesting = true showTextFormatting = isRichTextEditorEnabled diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt index daba41fb3c..6283d7236a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsProcessorTest.kt @@ -17,6 +17,8 @@ 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.room.aRoomMember import io.element.android.libraries.matrix.test.room.aRoomSummary +import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion +import io.element.android.libraries.slashcommands.test.FakeSlashCommandService import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import io.element.android.libraries.textcomposer.model.Suggestion import io.element.android.libraries.textcomposer.model.SuggestionType @@ -27,10 +29,13 @@ import org.junit.Test class SuggestionsProcessorTest { private fun aMentionSuggestion(text: String) = Suggestion(0, 1, SuggestionType.Mention, text) private fun aRoomSuggestion(text: String) = Suggestion(0, 1, SuggestionType.Room, text) - private val aCommandSuggestion = Suggestion(0, 1, SuggestionType.Command, "") private val aCustomSuggestion = Suggestion(0, 1, SuggestionType.Custom("*"), "") - private val suggestionsProcessor = SuggestionsProcessor() + private val suggestionsProcessor = SuggestionsProcessor( + slashCommandService = FakeSlashCommandService( + getSuggestionsResult = { _, _ -> emptyList() }, + ), + ) @Test fun `processing null suggestion will return empty suggestion`() = runTest { @@ -40,18 +45,59 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @Test - fun `processing Command will return empty suggestion`() = runTest { - val result = suggestionsProcessor.process( - suggestion = aCommandSuggestion, + fun `processing Command will return suggestions from the slash service`() = runTest { + val suggestionsProcessorWithCommand = SuggestionsProcessor( + slashCommandService = FakeSlashCommandService( + getSuggestionsResult = { _, _ -> + listOf( + SlashCommandSuggestion( + command = "aCommand", + parameters = null, + description = "A description", + ), + ) + }, + ), + ) + val result = suggestionsProcessorWithCommand.process( + suggestion = Suggestion(0, 1, SuggestionType.Command, ""), roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())), roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, + ) + assertThat(result).isNotEmpty() + } + + @Test + fun `processing Command will return empty list if start of suggestion is not 0`() = runTest { + val suggestionsProcessorWithCommand = SuggestionsProcessor( + slashCommandService = FakeSlashCommandService( + getSuggestionsResult = { _, _ -> + listOf( + SlashCommandSuggestion( + command = "aCommand", + parameters = null, + description = "A description", + ), + ) + }, + ), + ) + val result = suggestionsProcessorWithCommand.process( + suggestion = Suggestion(1, 2, SuggestionType.Command, ""), + roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())), + roomAliasSuggestions = emptyList(), + currentUserId = A_USER_ID, + canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -64,6 +110,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -76,6 +123,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -88,6 +136,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -100,6 +149,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -120,6 +170,7 @@ class SuggestionsProcessorTest { ), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( @@ -149,6 +200,7 @@ class SuggestionsProcessorTest { ), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( @@ -178,6 +230,7 @@ class SuggestionsProcessorTest { ), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -198,6 +251,7 @@ class SuggestionsProcessorTest { ), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( @@ -227,6 +281,7 @@ class SuggestionsProcessorTest { ), currentUserId = A_USER_ID, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -240,6 +295,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID_2, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( @@ -257,6 +313,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = UserId("@alice:server.org"), canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -270,6 +327,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID_2, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -283,6 +341,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID_2, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEmpty() } @@ -296,6 +355,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID_2, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( @@ -313,6 +373,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID_2, canSendRoomMention = { true }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( @@ -331,6 +392,7 @@ class SuggestionsProcessorTest { roomAliasSuggestions = emptyList(), currentUserId = A_USER_ID_2, canSendRoomMention = { false }, + isInThread = false, ) assertThat(result).isEqualTo( listOf( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt index 034c952f3d..bc36766bac 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt @@ -12,6 +12,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.MsgType 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.A_UNIQUE_ID @@ -154,10 +155,10 @@ class TimelineControllerTest { @Test fun `test invokeOnCurrentTimeline use the detached timeline and not the live timeline`() = runTest { - val lambdaForDetached = lambdaRecorder { _: String, _: String?, _: List -> + val lambdaForDetached = lambdaRecorder { _: String, _: String?, _: List, _: MsgType, _: Boolean -> Result.success(Unit) } - val lambdaForLive = lambdaRecorder(ensureNeverCalled = true) { _: String, _: String?, _: List -> + val lambdaForLive = lambdaRecorder(ensureNeverCalled = true) { _: String, _: String?, _: List, _: MsgType, _: Boolean -> Result.success(Unit) } val liveTimeline = FakeTimeline(name = "live").apply { diff --git a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt index 5a59d9be8a..04b471a498 100644 --- a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt +++ b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt @@ -28,6 +28,9 @@ interface PreferencesEntryPoint : FeatureEntryPoint { @Parcelize data object NotificationTroubleshoot : InitialTarget + + @Parcelize + data object DeveloperSettings : InitialTarget } data class Params(val initialElement: InitialTarget) : NodeInputs diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt index 4348b33756..57c561400c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt @@ -34,4 +34,5 @@ internal fun PreferencesEntryPoint.InitialTarget.toNavTarget() = when (this) { is PreferencesEntryPoint.InitialTarget.Root -> PreferencesFlowNode.NavTarget.Root is PreferencesEntryPoint.InitialTarget.NotificationSettings -> PreferencesFlowNode.NavTarget.NotificationSettings PreferencesEntryPoint.InitialTarget.NotificationTroubleshoot -> PreferencesFlowNode.NavTarget.TroubleshootNotifications + PreferencesEntryPoint.InitialTarget.DeveloperSettings -> PreferencesFlowNode.NavTarget.DeveloperSettings } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index c646923c77..15718ca0f0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -192,7 +192,11 @@ class PreferencesFlowNode( } override fun onDone() { - backstack.pop() + if (backstack.canPop()) { + backstack.pop() + } else { + navigateUp() + } } } createNode(buildContext, listOf(developerSettingsCallback)) diff --git a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt index 928c08324d..07e10c65ef 100644 --- a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt +++ b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt @@ -39,6 +39,7 @@ interface RoomDetailsEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun navigateToGlobalNotificationSettings() + fun navigateToDeveloperSettings() fun navigateToRoom(roomId: RoomId, serverNames: List) fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun startForwardEventFlow(eventId: EventId, fromPinnedEvents: Boolean) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index e1024c611f..c3ae902ba9 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -388,6 +388,10 @@ class RoomDetailsFlowNode( override fun navigateToRoom(roomId: RoomId) { callback.navigateToRoom(roomId, emptyList()) } + + override fun navigateToDeveloperSettings() { + callback.navigateToDeveloperSettings() + } } return messagesEntryPoint.createNode( parentNode = this, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt index 5042f942b6..bcf25b2aac 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -69,6 +69,7 @@ class DefaultRoomDetailsEntryPointTest { } val callback = object : RoomDetailsEntryPoint.Callback { override fun navigateToGlobalNotificationSettings() = lambdaError() + override fun navigateToDeveloperSettings() = lambdaError() override fun navigateToRoom(roomId: RoomId, serverNames: List) = lambdaError() override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() override fun startForwardEventFlow(eventId: EventId, fromPinnedEvents: Boolean) = lambdaError() diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt index fee1278fce..fd2c8ff194 100644 --- a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt @@ -76,7 +76,7 @@ class SharePresenterTest { fun `present - on room selected ok`() = runTest { val joinedRoom = FakeJoinedRoom( liveTimeline = FakeTimeline().apply { - sendMessageLambda = { _, _, _ -> Result.success(Unit) } + sendMessageLambda = { _, _, _, _, _ -> Result.success(Unit) } }, ) val matrixClient = FakeMatrixClient().apply { @@ -103,7 +103,7 @@ class SharePresenterTest { fun `present - send text ok`() = runTest { val joinedRoom = FakeJoinedRoom( liveTimeline = FakeTimeline().apply { - sendMessageLambda = { _, _, _ -> Result.success(Unit) } + sendMessageLambda = { _, _, _, _, _ -> Result.success(Unit) } }, ) val matrixClient = FakeMatrixClient().apply { 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 9fe21a10c3..a8e59e5c6d 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 @@ -169,4 +169,11 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + SlashCommand( + key = "feature.slash_command", + title = "Parse slash commands in the message composer", + description = "Allow parsing slash commands in the message composer and perform action.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomIdOrAlias.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomIdOrAlias.kt index 4ac480e064..462ec0535c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomIdOrAlias.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/RoomIdOrAlias.kt @@ -27,6 +27,16 @@ sealed interface RoomIdOrAlias : Parcelable { is Id -> roomId.value is Alias -> roomAlias.value } + + companion object { + fun from(id: String): RoomIdOrAlias? { + return when { + MatrixPatterns.isRoomId(id) -> Id(RoomId(id)) + MatrixPatterns.isRoomAlias(id) -> Alias(RoomAlias(id)) + else -> null + } + } + } } fun RoomId.toRoomIdOrAlias() = RoomIdOrAlias.Id(this) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt index 306ab8354b..09ceaa4712 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt @@ -17,3 +17,18 @@ interface MxcTools { */ fun mxcUri2FilePath(mxcUri: String): String? } + +/** + * "mxc" scheme, including "://". So "mxc://". + */ +const val MATRIX_CONTENT_URI_SCHEME = "mxc://" + +/** + * Return true if the String starts with "mxc://". + */ +fun String.isMxcUrl() = startsWith(MATRIX_CONTENT_URI_SCHEME) + +/** + * Remove the "mxc://" prefix. No op if the String is not a Mxc URL. + */ +fun String.removeMxcPrefix() = removePrefix(MATRIX_CONTENT_URI_SCHEME) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MsgType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MsgType.kt new file mode 100644 index 0000000000..b8d3933663 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MsgType.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.timeline + +enum class MsgType { + MSG_TYPE_TEXT, + MSG_TYPE_EMOTE, + + // For future support + MSG_TYPE_SNOW, + + // For future support + MSG_TYPE_CONFETTI, +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt index 500d9f3191..fe73230dce 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt @@ -69,6 +69,8 @@ interface Timeline : AutoCloseable { body: String, htmlBody: String?, intentionalMentions: List, + msgType: MsgType = MsgType.MSG_TYPE_TEXT, + asPlainText: Boolean = false, ): Result suspend fun editMessage( @@ -90,6 +92,7 @@ interface Timeline : AutoCloseable { htmlBody: String?, intentionalMentions: List, fromNotification: Boolean = false, + msgType: MsgType = MsgType.MSG_TYPE_TEXT, ): Result suspend fun sendImage( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 3996155871..8a184311de 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.MsgType import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.TimelineException @@ -271,8 +272,16 @@ class RustTimeline( body: String, htmlBody: String?, intentionalMentions: List, + msgType: MsgType, + asPlainText: Boolean, ): Result = withContext(dispatcher) { - MessageEventContent.from(body, htmlBody, intentionalMentions).use { content -> + MessageEventContent.from( + body = body, + htmlBody = htmlBody, + intentionalMentions = intentionalMentions, + msgType = msgType, + asPlainText = asPlainText, + ).use { content -> runCatchingExceptions { inner.send(content) } @@ -337,9 +346,15 @@ class RustTimeline( htmlBody: String?, intentionalMentions: List, fromNotification: Boolean, + msgType: MsgType, ): Result = withContext(dispatcher) { runCatchingExceptions { - val msg = MessageEventContent.from(body, htmlBody, intentionalMentions) + val msg = MessageEventContent.from( + body = body, + htmlBody = htmlBody, + intentionalMentions = intentionalMentions, + msgType = msgType, + ) inner.sendReply( msg = msg, eventId = repliedToEventId.value, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt index 3e320116c6..f1c0019f17 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt @@ -9,20 +9,54 @@ package io.element.android.libraries.matrix.impl.util import io.element.android.libraries.matrix.api.room.IntentionalMention +import io.element.android.libraries.matrix.api.timeline.MsgType import io.element.android.libraries.matrix.impl.room.map +import org.matrix.rustcomponents.sdk.MessageContent +import org.matrix.rustcomponents.sdk.MessageType import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation +import org.matrix.rustcomponents.sdk.TextMessageContent +import org.matrix.rustcomponents.sdk.contentWithoutRelationFromMessage import org.matrix.rustcomponents.sdk.messageEventContentFromHtml +import org.matrix.rustcomponents.sdk.messageEventContentFromHtmlAsEmote import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown +import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdownAsEmote /** * Creates a [RoomMessageEventContentWithoutRelation] from a body, an html body and a list of mentions. */ object MessageEventContent { - fun from(body: String, htmlBody: String?, intentionalMentions: List): RoomMessageEventContentWithoutRelation { - return if (htmlBody != null) { - messageEventContentFromHtml(body, htmlBody) - } else { - messageEventContentFromMarkdown(body) - }.withMentions(intentionalMentions.map()) + fun from( + body: String, + htmlBody: String?, + intentionalMentions: List, + msgType: MsgType = MsgType.MSG_TYPE_TEXT, + asPlainText: Boolean = false, + ): RoomMessageEventContentWithoutRelation { + return when { + asPlainText -> contentWithoutRelationFromMessage( + MessageContent( + msgType = MessageType.Text( + TextMessageContent( + body = body, + formatted = null, + ) + ), + body = body, + isEdited = false, + mentions = null, + ) + ) + htmlBody != null -> if (msgType == MsgType.MSG_TYPE_EMOTE) { + messageEventContentFromHtmlAsEmote(body, htmlBody) + } else { + messageEventContentFromHtml(body, htmlBody) + } + else -> if (msgType == MsgType.MSG_TYPE_EMOTE) { + messageEventContentFromMarkdownAsEmote(body) + } else { + messageEventContentFromMarkdown(body) + } + } + .withMentions(intentionalMentions.map()) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt index 4451de6276..fcc7057dbe 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.MsgType import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId @@ -64,7 +65,9 @@ class FakeTimeline( body: String, htmlBody: String?, intentionalMentions: List, - ) -> Result = { _, _, _ -> + msgType: MsgType, + asPlainText: Boolean, + ) -> Result = { _, _, _, _, _ -> lambdaError() } @@ -76,8 +79,10 @@ class FakeTimeline( body: String, htmlBody: String?, intentionalMentions: List, + msgType: MsgType, + asPlainText: Boolean, ): Result = simulateLongTask { - sendMessageLambda(body, htmlBody, intentionalMentions) + sendMessageLambda(body, htmlBody, intentionalMentions, msgType, asPlainText) } var redactEventLambda: (eventOrTransactionId: EventOrTransactionId, reason: String?) -> Result = { _, _ -> @@ -134,7 +139,8 @@ class FakeTimeline( htmlBody: String?, intentionalMentions: List, fromNotification: Boolean, - ) -> Result = { _, _, _, _, _ -> + msgType: MsgType, + ) -> Result = { _, _, _, _, _, _ -> lambdaError() } @@ -144,12 +150,14 @@ class FakeTimeline( htmlBody: String?, intentionalMentions: List, fromNotification: Boolean, + msgType: MsgType, ): Result = replyMessageLambda( repliedToEventId, body, htmlBody, intentionalMentions, fromNotification, + msgType, ) var sendImageLambda: ( diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt index a52eb16b07..2cf666d92a 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.RoomInfo +import io.element.android.libraries.matrix.api.timeline.MsgType import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_MESSAGE @@ -341,9 +342,9 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test send reply`() = runTest { - val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } + val sendMessage = lambdaRecorder, MsgType, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } val replyMessage = - lambdaRecorder, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } + lambdaRecorder, Boolean, MsgType, Result> { _, _, _, _, _, _ -> Result.success(Unit) } val liveTimeline = FakeTimeline().apply { sendMessageLambda = sendMessage replyMessageLambda = replyMessage @@ -375,7 +376,13 @@ class NotificationBroadcastReceiverHandlerTest { advanceUntilIdle() sendMessage.assertions() .isCalledOnce() - .with(value(A_MESSAGE), value(null), value(emptyList())) + .with( + value(A_MESSAGE), + value(null), + value(emptyList()), + value(MsgType.MSG_TYPE_TEXT), + value(false), + ) onNotifiableEventsReceivedResult.assertions() .isCalledOnce() replyMessage.assertions() @@ -384,7 +391,7 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test send reply blank message`() = runTest { - val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } + val sendMessage = lambdaRecorder, MsgType, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } val liveTimeline = FakeTimeline().apply { sendMessageLambda = sendMessage } @@ -408,9 +415,9 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test send reply to thread`() = runTest { - val sendMessage = lambdaRecorder, Result> { _, _, _ -> Result.success(Unit) } + val sendMessage = lambdaRecorder, MsgType, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } val replyMessage = - lambdaRecorder, Boolean, Result> { _, _, _, _, _ -> Result.success(Unit) } + lambdaRecorder, Boolean, MsgType, Result> { _, _, _, _, _, _ -> Result.success(Unit) } val liveTimeline = FakeTimeline().apply { sendMessageLambda = sendMessage replyMessageLambda = replyMessage @@ -453,7 +460,8 @@ class NotificationBroadcastReceiverHandlerTest { value(A_MESSAGE), value(null), value(emptyList()), - value(true) + value(true), + value(MsgType.MSG_TYPE_TEXT), ) } diff --git a/libraries/slashcommands/api/build.gradle.kts b/libraries/slashcommands/api/build.gradle.kts new file mode 100644 index 0000000000..8cec0e65af --- /dev/null +++ b/libraries/slashcommands/api/build.gradle.kts @@ -0,0 +1,17 @@ +/* + * 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. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.slashcommands.api" +} + +dependencies { + implementation(projects.libraries.matrix.api) +} diff --git a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/ChatEffect.kt b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/ChatEffect.kt new file mode 100644 index 0000000000..7b31ffb3b7 --- /dev/null +++ b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/ChatEffect.kt @@ -0,0 +1,13 @@ +/* + * 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.slashcommands.api + +enum class ChatEffect { + CONFETTI, + SNOWFALL +} diff --git a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/MessagePrefix.kt b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/MessagePrefix.kt new file mode 100644 index 0000000000..713458c720 --- /dev/null +++ b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/MessagePrefix.kt @@ -0,0 +1,15 @@ +/* + * 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.slashcommands.api + +enum class MessagePrefix { + Shrug, + TableFlip, + Unflip, + Lenny, +} diff --git a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt new file mode 100644 index 0000000000..770543e548 --- /dev/null +++ b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt @@ -0,0 +1,71 @@ +/* + * 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.slashcommands.api + +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.libraries.matrix.api.core.UserId + +/** + * Represent a slash command. + */ +sealed interface SlashCommand { + // This is not a Slash command + data object NotACommand : SlashCommand + + // Slash command types: + sealed interface Error : SlashCommand + sealed interface SlashCommandSendMessage : SlashCommand + sealed interface SlashCommandAdmin : SlashCommand + sealed interface SlashCommandNavigation : SlashCommand + + // Errors + data class ErrorEmptySlashCommand(val message: String) : Error + data class ErrorCommandNotSupportedInThreads(val message: String) : Error + + // Unknown/Unsupported slash command + data class ErrorUnknownSlashCommand(val message: String) : Error + + // A slash command is detected, but there is an error + data class ErrorSyntax(val message: String) : Error + + // Valid commands: + data class SendPlainText(val message: CharSequence) : SlashCommandSendMessage + data class SendEmote(val message: CharSequence) : SlashCommandSendMessage + data class SendRainbow(val message: CharSequence) : SlashCommandSendMessage + data class SendRainbowEmote(val message: CharSequence) : SlashCommandSendMessage + data class BanUser(val userId: UserId, val reason: String?) : SlashCommandAdmin + data class UnbanUser(val userId: UserId, val reason: String?) : SlashCommandAdmin + data class IgnoreUser(val userId: UserId) : SlashCommandAdmin + data class UnignoreUser(val userId: UserId) : SlashCommandAdmin + data class SetUserPowerLevel(val userId: UserId, val powerLevel: Int?) : SlashCommandAdmin + data class ChangeRoomName(val name: String) : SlashCommandAdmin + data class Invite(val userId: UserId, val reason: String?) : SlashCommandAdmin + data class JoinRoom(val roomIdOrAlias: RoomIdOrAlias, val reason: String?) : SlashCommandAdmin + data class ChangeTopic(val topic: String) : SlashCommandAdmin + data class RemoveUser(val userId: UserId, val reason: String?) : SlashCommandAdmin + data class ChangeDisplayName(val displayName: String) : SlashCommandAdmin + data class ChangeDisplayNameForRoom(val displayName: String) : SlashCommandAdmin + data class ChangeRoomAvatar(val url: String) : SlashCommandAdmin + data class ChangeAvatarForRoom(val url: String) : SlashCommandAdmin + data class SendSpoiler(val message: String) : SlashCommandSendMessage + data class SendWithPrefix(val prefix: MessagePrefix, val message: CharSequence) : SlashCommandSendMessage + data object DiscardSession : SlashCommandAdmin + data class SendChatEffect(val chatEffect: ChatEffect, val message: String) : SlashCommandSendMessage + data object LeaveRoom : SlashCommandAdmin + data class UpgradeRoom(val newVersion: String) : SlashCommandAdmin + + data object DevTools : SlashCommandNavigation + data class ShowUser(val userId: UserId) : SlashCommandNavigation +} + +fun SlashCommand.Error.message() = when (this) { + is SlashCommand.ErrorEmptySlashCommand -> message + is SlashCommand.ErrorCommandNotSupportedInThreads -> message + is SlashCommand.ErrorUnknownSlashCommand -> message + is SlashCommand.ErrorSyntax -> message +} diff --git a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandService.kt b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandService.kt new file mode 100644 index 0000000000..9dfca26078 --- /dev/null +++ b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandService.kt @@ -0,0 +1,41 @@ +/* + * 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.slashcommands.api + +import io.element.android.libraries.matrix.api.timeline.Timeline + +interface SlashCommandService { + suspend fun getSuggestions( + text: String, + isInThread: Boolean, + ): List + + /** + * Parse the message and return a SlashCommand. + */ + suspend fun parse( + textMessage: CharSequence, + formattedMessage: String?, + isInThreadTimeline: Boolean, + ): SlashCommand + + /** + * Proceed a SlashCommandSendMessage. + */ + suspend fun proceedSendMessage( + slashCommand: SlashCommand.SlashCommandSendMessage, + timeline: Timeline, + ): Result + + /** + * Proceed a SlashCommandAdmin. + */ + suspend fun proceedAdmin( + slashCommand: SlashCommand.SlashCommandAdmin, + ): Result +} diff --git a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandSuggestion.kt b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandSuggestion.kt new file mode 100644 index 0000000000..5a826d5fbd --- /dev/null +++ b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommandSuggestion.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.slashcommands.api + +data class SlashCommandSuggestion( + val command: String, + val parameters: String?, + val description: String, +) diff --git a/libraries/slashcommands/impl/build.gradle.kts b/libraries/slashcommands/impl/build.gradle.kts new file mode 100644 index 0000000000..34dc2e42b2 --- /dev/null +++ b/libraries/slashcommands/impl/build.gradle.kts @@ -0,0 +1,35 @@ +import extension.setupDependencyInjection +import extension.testCommonDependencies + +/* + * 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. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.slashcommands.impl" +} + +setupDependencyInjection() + +dependencies { + implementation(projects.libraries.androidutils) + implementation(projects.libraries.preferences.api) + implementation(projects.libraries.core) + implementation(projects.libraries.matrix.api) + api(projects.libraries.slashcommands.api) + implementation(projects.libraries.di) + implementation(projects.libraries.featureflag.api) + implementation(projects.services.toolbox.api) + + testCommonDependencies(libs) + testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.preferences.test) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.services.toolbox.test) +} diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt new file mode 100644 index 0000000000..0b7b58a15f --- /dev/null +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt @@ -0,0 +1,233 @@ +/* + * 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.slashcommands.impl + +import androidx.annotation.StringRes + +/** + * Defines the command line operations. + * The user can write these messages to perform some actions. + * The list will be displayed in this order. + */ +enum class Command( + val command: String, + val aliases: List? = null, + val parameters: String? = null, + @StringRes val description: Int, + val isAllowedInThread: Boolean = true, + val isSupported: Boolean = true, + val isDevCommand: Boolean = false, +) { + CRASH_APP( + command = "/crash", + description = R.string.slash_command_description_crash_application, + isDevCommand = true, + ), + EMOTE( + command = "/me", + parameters = "", + description = R.string.slash_command_description_emote, + ), + BAN_USER( + command = "/ban", + parameters = " [reason]", + description = R.string.slash_command_description_ban_user, + ), + UNBAN_USER( + command = "/unban", + parameters = " [reason]", + description = R.string.slash_command_description_unban_user, + ), + IGNORE_USER( + command = "/ignore", + parameters = " [reason]", + description = R.string.slash_command_description_ignore_user, + ), + UNIGNORE_USER( + command = "/unignore", + parameters = "", + description = R.string.slash_command_description_unignore_user, + ), + SET_USER_POWER_LEVEL( + command = "/op", + parameters = " []", + description = R.string.slash_command_description_op_user, + isAllowedInThread = false, + isSupported = false, + ), + RESET_USER_POWER_LEVEL( + command = "/deop", + parameters = "", + description = R.string.slash_command_description_deop_user, + isAllowedInThread = false, + isSupported = false, + ), + ROOM_NAME( + command = "/roomname", + parameters = "", + description = R.string.slash_command_description_room_name, + isAllowedInThread = false, + ), + INVITE( + command = "/invite", + parameters = " [reason]", + description = R.string.slash_command_description_invite_user, + ), + JOIN_ROOM( + command = "/join", + aliases = listOf("/j", "/goto"), + parameters = " [reason]", + description = R.string.slash_command_description_join_room, + isAllowedInThread = false, + isSupported = false, + ), + TOPIC( + command = "/topic", + parameters = "", + description = R.string.slash_command_description_topic, + isAllowedInThread = false, + ), + REMOVE_USER( + command = "/remove", + aliases = listOf("/kick"), + parameters = " [reason]", + description = R.string.slash_command_description_remove_user, + ), + CHANGE_DISPLAY_NAME( + command = "/nick", + parameters = "", + description = R.string.slash_command_description_nick, + ), + CHANGE_DISPLAY_NAME_FOR_ROOM( + command = "/myroomnick", + aliases = listOf("/roomnick"), + parameters = "", + description = R.string.slash_command_description_nick_for_room, + isAllowedInThread = false, + isSupported = false, + ), + ROOM_AVATAR( + command = "/roomavatar", + parameters = "", + description = R.string.slash_command_description_room_avatar, + isAllowedInThread = false, + // Dev command since user has to know the mxc url + isDevCommand = true, + isSupported = false, + ), + CHANGE_AVATAR_FOR_ROOM( + command = "/myroomavatar", + parameters = "", + description = R.string.slash_command_description_avatar_for_room, + isAllowedInThread = false, + // Dev command since user has to know the mxc url + isDevCommand = true, + isSupported = false, + ), + RAINBOW( + command = "/rainbow", + parameters = "", + description = R.string.slash_command_description_rainbow, + ), + RAINBOW_EMOTE( + command = "/rainbowme", + parameters = "", + description = R.string.slash_command_description_rainbow_emote, + ), + DEVTOOLS( + command = "/devtools", + description = R.string.slash_command_description_devtools, + isDevCommand = true, + ), + SPOILER( + command = "/spoiler", + parameters = "", + description = R.string.slash_command_description_spoiler, + ), + SHRUG( + command = "/shrug", + parameters = "", + description = R.string.slash_command_description_shrug, + ), + LENNY( + command = "/lenny", + parameters = "", + description = R.string.slash_command_description_lenny, + ), + PLAIN( + command = "/plain", + parameters = "", + description = R.string.slash_command_description_plain, + ), + WHOIS( + command = "/whois", + parameters = "", + description = R.string.slash_command_description_whois, + ), + DISCARD_SESSION( + command = "/discardsession", + description = R.string.slash_command_description_discard_session, + isAllowedInThread = false, + isSupported = false, + ), + CONFETTI( + command = "/confetti", + parameters = "", + description = R.string.slash_command_confetti, + isAllowedInThread = false, + isSupported = false, + ), + SNOWFALL( + command = "/snowfall", + parameters = "", + description = R.string.slash_command_snow, + isAllowedInThread = false, + isSupported = false, + ), + LEAVE_ROOM( + command = "/leave", + aliases = listOf("/part"), + description = R.string.slash_command_description_leave_room, + isAllowedInThread = false, + isDevCommand = true, + ), + UPGRADE_ROOM( + command = "/upgraderoom", + parameters = "newVersion", + description = R.string.slash_command_description_upgrade_room, + isAllowedInThread = false, + isDevCommand = true, + isSupported = false, + ), + TABLE_FLIP( + command = "/tableflip", + parameters = "", + description = R.string.slash_command_description_table_flip, + ), + UNFLIP( + command = "/unflip", + parameters = "", + description = R.string.slash_command_description_unflip, + ); + + val allAliases = listOf(command) + aliases.orEmpty() + + /** + * Checks if the input command matches any of the command aliases, ignoring case. + * Do not exclude not supported commands so that user can discover that the command is not supported. + * Used for whole command parsing. + */ + fun matches(inputCommand: CharSequence) = allAliases.any { it.contentEquals(inputCommand, true) } + + /** + * Checks if the input is a prefix of any of the command aliases, ignoring the first character (the slash), and excluding not supported command. + * Used for suggestions. + */ + fun startsWith(input: CharSequence) = isSupported && + allAliases.any { it.startsWith(input, 1, true) } +} diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt new file mode 100644 index 0000000000..0acd3af6f8 --- /dev/null +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt @@ -0,0 +1,214 @@ +/* + * 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.slashcommands.impl + +import dev.zacsweers.metro.Inject +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.timeline.MsgType +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.slashcommands.api.MessagePrefix +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.impl.rainbow.RainbowGenerator +import io.element.android.services.toolbox.api.strings.StringProvider + +@Inject +class CommandExecutor( + private val matrixClient: MatrixClient, + private val joinedRoom: JoinedRoom, + private val rainbowGenerator: RainbowGenerator, + private val stringProvider: StringProvider, +) { + suspend fun proceedSendMessage( + slashCommand: SlashCommand.SlashCommandSendMessage, + timeline: Timeline, + ): Result { + return when (slashCommand) { + is SlashCommand.SendChatEffect -> sendChatEffect() + is SlashCommand.SendEmote -> sendEmote(slashCommand, timeline) + is SlashCommand.SendWithPrefix -> sendPrefixedMessage(slashCommand.prefix, slashCommand.message, timeline) + is SlashCommand.SendPlainText -> sendPlainText(slashCommand, timeline) + is SlashCommand.SendRainbow -> sendRainbow(slashCommand, timeline) + is SlashCommand.SendRainbowEmote -> sendRainbowEmote(slashCommand, timeline) + is SlashCommand.SendSpoiler -> sendSpoiler(slashCommand, timeline) + } + } + + suspend fun proceedAdmin( + slashCommand: SlashCommand.SlashCommandAdmin, + ): Result { + return when (slashCommand) { + is SlashCommand.BanUser -> banUser(slashCommand) + is SlashCommand.ChangeAvatarForRoom -> changeAvatarForRoom() + is SlashCommand.ChangeDisplayName -> changeDisplayName(slashCommand) + is SlashCommand.ChangeDisplayNameForRoom -> changeDisplayNameForRoom() + is SlashCommand.ChangeRoomAvatar -> changeRoomAvatar() + is SlashCommand.ChangeRoomName -> changeRoomName(slashCommand) + is SlashCommand.ChangeTopic -> changeTopic(slashCommand) + is SlashCommand.DiscardSession -> discardSession() + is SlashCommand.IgnoreUser -> ignoreUser(slashCommand) + is SlashCommand.Invite -> invite(slashCommand) + is SlashCommand.JoinRoom -> joinRoom(slashCommand) + is SlashCommand.LeaveRoom -> leaveRoom(joinedRoom) + is SlashCommand.RemoveUser -> removeUser(slashCommand) + is SlashCommand.SetUserPowerLevel -> setUserPowerLevel() + is SlashCommand.UnbanUser -> unbanUser(slashCommand) + is SlashCommand.UnignoreUser -> unignoreUser(slashCommand) + is SlashCommand.UpgradeRoom -> upgradeRoom() + } + } + + private fun upgradeRoom(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private suspend fun unignoreUser(slashCommand: SlashCommand.UnignoreUser): Result { + return matrixClient.unignoreUser(slashCommand.userId) + } + + private suspend fun unbanUser(slashCommand: SlashCommand.UnbanUser): Result { + return joinedRoom.unbanUser(slashCommand.userId, slashCommand.reason) + } + + private fun setUserPowerLevel(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private suspend fun sendSpoiler(slashCommand: SlashCommand.SendSpoiler, timeline: Timeline): Result { + val text = "[${stringProvider.getString(R.string.common_spoiler)}](${slashCommand.message})" + val formattedText = "${slashCommand.message}" + return timeline.sendMessage( + body = text, + htmlBody = formattedText, + intentionalMentions = emptyList(), + ) + } + + private suspend fun sendRainbowEmote(slashCommand: SlashCommand.SendRainbowEmote, timeline: Timeline): Result { + val message = slashCommand.message.toString() + return timeline.sendMessage( + body = message, + htmlBody = rainbowGenerator.generate(message), + msgType = MsgType.MSG_TYPE_EMOTE, + intentionalMentions = emptyList(), + ) + } + + private suspend fun sendRainbow(slashCommand: SlashCommand.SendRainbow, timeline: Timeline): Result { + val message = slashCommand.message.toString() + return timeline.sendMessage( + body = message, + htmlBody = rainbowGenerator.generate(message), + intentionalMentions = emptyList(), + ) + } + + private suspend fun sendPlainText(slashCommand: SlashCommand.SendPlainText, timeline: Timeline): Result { + return timeline.sendMessage( + body = slashCommand.message.toString(), + htmlBody = null, + intentionalMentions = emptyList(), + asPlainText = true, + ) + } + + private suspend fun sendEmote(slashCommand: SlashCommand.SendEmote, timeline: Timeline): Result { + val message = slashCommand.message.toString() + return timeline.sendMessage( + body = message, + htmlBody = null, + msgType = MsgType.MSG_TYPE_EMOTE, + intentionalMentions = emptyList(), + ) + } + + private fun sendChatEffect(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private suspend fun removeUser(slashCommand: SlashCommand.RemoveUser): Result { + return joinedRoom.kickUser(slashCommand.userId, slashCommand.reason) + } + + private suspend fun leaveRoom( + room: JoinedRoom, + ): Result { + return room.leave() + } + + private suspend fun joinRoom(slashCommand: SlashCommand.JoinRoom): Result { + return matrixClient.joinRoomByIdOrAlias(slashCommand.roomIdOrAlias, emptyList()) + .map {} + } + + private suspend fun invite(slashCommand: SlashCommand.Invite): Result { + return joinedRoom.inviteUserById(slashCommand.userId) + } + + private suspend fun ignoreUser(slashCommand: SlashCommand.IgnoreUser): Result { + return matrixClient.ignoreUser(slashCommand.userId) + } + + private fun discardSession(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private suspend fun changeTopic(slashCommand: SlashCommand.ChangeTopic): Result { + return joinedRoom.setTopic(slashCommand.topic) + } + + private suspend fun changeRoomName(slashCommand: SlashCommand.ChangeRoomName): Result { + return joinedRoom.setName(slashCommand.name) + } + + private fun changeRoomAvatar(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private fun changeDisplayNameForRoom(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private suspend fun changeDisplayName(slashCommand: SlashCommand.ChangeDisplayName): Result { + return matrixClient.setDisplayName(slashCommand.displayName) + } + + private fun changeAvatarForRoom(): Result { + return Result.failure(Exception("Not yet implemented")) + } + + private suspend fun banUser(slashCommand: SlashCommand.BanUser): Result { + return joinedRoom.banUser(slashCommand.userId, slashCommand.reason) + } + + private suspend fun sendPrefixedMessage( + prefix: MessagePrefix, + message: CharSequence, + timeline: Timeline, + ): Result { + val sequence = buildString { + append(prefix.toMarkdown()) + if (message.isNotEmpty()) { + append(" ") + append(message) + } + } + return timeline.sendMessage( + body = sequence, + htmlBody = null, + intentionalMentions = emptyList(), + ) + } +} + +private fun MessagePrefix.toMarkdown() = when (this) { + MessagePrefix.Shrug -> "¯\\\\_(ツ)\\_/¯" + MessagePrefix.TableFlip -> "(╯°□°)╯︵ ┻━┻" + MessagePrefix.Unflip -> "┬──┬ ノ( ゜-゜ノ)" + MessagePrefix.Lenny -> "( ͡° ͜ʖ ͡°)" +} diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt new file mode 100644 index 0000000000..85a045f50c --- /dev/null +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt @@ -0,0 +1,430 @@ +/* + * 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.slashcommands.impl + +import dev.zacsweers.metro.Inject +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.core.MatrixPatterns +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.mxc.isMxcUrl +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.slashcommands.api.ChatEffect +import io.element.android.libraries.slashcommands.api.MessagePrefix +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.services.toolbox.api.strings.StringProvider +import kotlinx.coroutines.flow.first +import timber.log.Timber + +@Inject +class CommandParser( + private val appPreferencesStore: AppPreferencesStore, + private val featureFlagService: FeatureFlagService, + private val stringProvider: StringProvider, +) { + /** + * Convert the text message into a Slash command. + * + * @param textMessage the text message in plain text + * @param formattedMessage the text messaged in HTML format + * @param isInThreadTimeline true if the user is currently typing in a thread + * @return a parsed slash command (ok or error) + */ + suspend fun parseSlashCommand( + textMessage: CharSequence, + formattedMessage: String?, + isInThreadTimeline: Boolean, + ): SlashCommand { + if (!featureFlagService.isFeatureEnabled(FeatureFlags.SlashCommand)) { + return SlashCommand.NotACommand + } + // check if it has the Slash marker + val message = formattedMessage ?: textMessage + return if (!message.startsWith("/")) { + SlashCommand.NotACommand + } else { + // "/" only + if (message.length == 1) { + return SlashCommand.ErrorEmptySlashCommand( + stringProvider.getString(R.string.slash_command_unrecognized, "/") + ) + } + // Exclude "//" + if ("/" == message.substring(1, 2)) { + return SlashCommand.NotACommand + } + val (messageParts, message) = extractMessage(message.toString()) + ?: return SlashCommand.ErrorEmptySlashCommand( + stringProvider.getString(R.string.slash_command_unrecognized, "/") + ) + val slashCommand = messageParts.first() + getNotSupportedByThreads(isInThreadTimeline, slashCommand)?.let { + return SlashCommand.ErrorCommandNotSupportedInThreads( + stringProvider.getString( + R.string.slash_command_not_supported_in_threads, + it.command, + ) + ) + } + when { + Command.PLAIN.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.SendPlainText(message = message) + } else { + syntaxError(Command.PLAIN) + } + } + Command.CHANGE_DISPLAY_NAME.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.ChangeDisplayName(displayName = message) + } else { + syntaxError(Command.CHANGE_DISPLAY_NAME) + } + } + Command.CHANGE_DISPLAY_NAME_FOR_ROOM.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.ChangeDisplayNameForRoom(displayName = message) + } else { + syntaxError(Command.CHANGE_DISPLAY_NAME_FOR_ROOM) + } + } + Command.ROOM_AVATAR.matches(slashCommand) -> { + if (messageParts.size == 2) { + val url = messageParts[1] + if (url.isMxcUrl()) { + SlashCommand.ChangeRoomAvatar(url) + } else { + syntaxError(Command.ROOM_AVATAR) + } + } else { + syntaxError(Command.ROOM_AVATAR) + } + } + Command.CHANGE_AVATAR_FOR_ROOM.matches(slashCommand) -> { + if (messageParts.size == 2) { + val url = messageParts[1] + + if (url.isMxcUrl()) { + SlashCommand.ChangeAvatarForRoom(url) + } else { + syntaxError(Command.CHANGE_AVATAR_FOR_ROOM) + } + } else { + syntaxError(Command.CHANGE_AVATAR_FOR_ROOM) + } + } + Command.TOPIC.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.ChangeTopic(topic = message) + } else { + syntaxError(Command.TOPIC) + } + } + Command.EMOTE.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.SendEmote(message) + } else { + syntaxError(Command.EMOTE) + } + } + Command.RAINBOW.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.SendRainbow(message) + } else { + syntaxError(Command.RAINBOW) + } + } + Command.RAINBOW_EMOTE.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.SendRainbowEmote(message) + } else { + syntaxError(Command.RAINBOW_EMOTE) + } + } + Command.JOIN_ROOM.matches(slashCommand) -> { + if (messageParts.size >= 2) { + val id = messageParts[1] + val roomIdOrAlias = RoomIdOrAlias.from(id) + if (roomIdOrAlias != null) { + SlashCommand.JoinRoom( + RoomIdOrAlias.Id(RoomId(id)), + trimParts(textMessage, messageParts.take(2)) + ) + } else { + syntaxError(Command.JOIN_ROOM) + } + } else { + syntaxError(Command.JOIN_ROOM) + } + } + Command.ROOM_NAME.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.ChangeRoomName(name = message) + } else { + syntaxError(Command.ROOM_NAME) + } + } + Command.INVITE.matches(slashCommand) -> { + if (messageParts.size >= 2) { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.Invite( + userId = userId, + reason = trimParts(textMessage, messageParts.take(2)) + ) + } + ?: syntaxError(Command.INVITE) + } else { + syntaxError(Command.INVITE) + } + } + Command.REMOVE_USER.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.RemoveUser( + userId = userId, + reason = trimParts(textMessage, messageParts.take(2)) + ) + } + ?: syntaxError(Command.REMOVE_USER) + } + Command.BAN_USER.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.BanUser( + userId = userId, + reason = trimParts(textMessage, messageParts.take(2)) + ) + } + ?: syntaxError(Command.BAN_USER) + } + Command.UNBAN_USER.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.UnbanUser( + userId = userId, + reason = trimParts(textMessage, messageParts.take(2)) + ) + } + ?: syntaxError(Command.UNBAN_USER) + } + Command.IGNORE_USER.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.IgnoreUser( + userId = userId, + ) + } + ?: syntaxError(Command.IGNORE_USER) + } + Command.UNIGNORE_USER.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.UnignoreUser( + userId = userId, + ) + } + ?: syntaxError(Command.UNIGNORE_USER) + } + Command.SET_USER_POWER_LEVEL.matches(slashCommand) -> { + if (messageParts.size == 3) { + val userId = parseUserId(messageParts) + if (userId != null) { + val powerLevelsAsString = messageParts[2] + try { + val powerLevelsAsInt = Integer.parseInt(powerLevelsAsString) + SlashCommand.SetUserPowerLevel( + userId = userId, + powerLevel = powerLevelsAsInt + ) + } catch (_: Exception) { + syntaxError(Command.SET_USER_POWER_LEVEL) + } + } else { + syntaxError(Command.SET_USER_POWER_LEVEL) + } + } else { + syntaxError(Command.SET_USER_POWER_LEVEL) + } + } + Command.RESET_USER_POWER_LEVEL.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.SetUserPowerLevel( + userId = userId, + powerLevel = null + ) + } + ?: syntaxError(Command.SET_USER_POWER_LEVEL) + } + Command.DEVTOOLS.matches(slashCommand) -> { + if (messageParts.size == 1) { + SlashCommand.DevTools + } else { + syntaxError(Command.DEVTOOLS) + } + } + Command.SPOILER.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.SendSpoiler(message) + } else { + syntaxError(Command.SPOILER) + } + } + Command.SHRUG.matches(slashCommand) -> { + SlashCommand.SendWithPrefix(MessagePrefix.Shrug, message) + } + Command.LENNY.matches(slashCommand) -> { + SlashCommand.SendWithPrefix(MessagePrefix.Lenny, message) + } + Command.TABLE_FLIP.matches(slashCommand) -> { + SlashCommand.SendWithPrefix(MessagePrefix.TableFlip, message) + } + Command.UNFLIP.matches(slashCommand) -> { + SlashCommand.SendWithPrefix(MessagePrefix.Unflip, message) + } + Command.DISCARD_SESSION.matches(slashCommand) -> { + if (messageParts.size == 1) { + SlashCommand.DiscardSession + } else { + syntaxError(Command.DISCARD_SESSION) + } + } + Command.WHOIS.matches(slashCommand) -> { + parseUserId(messageParts) + ?.let { userId -> + SlashCommand.ShowUser( + userId = userId, + ) + } + ?: syntaxError(Command.WHOIS) + } + Command.CONFETTI.matches(slashCommand) -> { + SlashCommand.SendChatEffect(ChatEffect.CONFETTI, message) + } + Command.SNOWFALL.matches(slashCommand) -> { + SlashCommand.SendChatEffect(ChatEffect.SNOWFALL, message) + } + Command.LEAVE_ROOM.matches(slashCommand) -> { + if (messageParts.size == 1) { + SlashCommand.LeaveRoom + } else { + syntaxError(Command.LEAVE_ROOM) + } + } + Command.UPGRADE_ROOM.matches(slashCommand) -> { + if (message.isNotEmpty()) { + SlashCommand.UpgradeRoom(newVersion = message) + } else { + syntaxError(Command.UPGRADE_ROOM) + } + } + Command.CRASH_APP.matches(slashCommand) && appPreferencesStore.isDeveloperModeEnabledFlow().first() -> { + error("Application crashed from user demand") + } + else -> { + // Unknown command + SlashCommand.ErrorUnknownSlashCommand( + stringProvider.getString(R.string.slash_command_unrecognized, slashCommand) + ) + } + } + } + } + + private fun parseUserId(messageParts: List): UserId? { + val str = messageParts.getOrNull(1) ?: return null + return when { + MatrixPatterns.isUserId(str) -> str + str == " { + // Rich text editor mode + messageParts.getOrNull(2)?.let { html -> + // html must match "href="https://matrix.to/#/@user:domain.org">@user:domain.org" + val regex = "href=\"https://matrix.to/#/([^\"]+)\">([^<]+)".toRegex() + val matchResult = regex.find(html) + val userId = matchResult?.groupValues?.getOrNull(1) + userId?.takeIf { + userId == matchResult.groupValues.getOrNull(2) && MatrixPatterns.isUserId(it) + } + } + } + else -> { + // Can be markdown format like "[@user:domain.org](https://matrix.to/#/@user:domain.org)" + val regex = "\\[([^\\]]+)]\\(https://matrix.to/#/([^\\]]+)\\)".toRegex() + val matchResult = regex.find(str) + val userId = matchResult?.groupValues?.getOrNull(1) + userId?.takeIf { + userId == matchResult.groupValues.getOrNull(2) && MatrixPatterns.isUserId(it) + } + } + } + ?.let(::UserId) + } + + private fun syntaxError(command: Command) = SlashCommand.ErrorSyntax( + stringProvider.getString( + R.string.slash_command_parameters_error, + command.command, + buildString { + append(command.command) + if (command.parameters != null) { + append(" ${command.parameters}") + } + }, + ) + ) + + private fun extractMessage(message: String): Pair, String>? { + val messageParts = try { + message.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() } + } catch (e: Exception) { + Timber.e(e, "## parseSlashCommand() : split failed") + null + } + + // test if the string cut fails + if (messageParts.isNullOrEmpty()) { + return null + } + + val slashCommand = messageParts.first() + val trimmedMessage = message.substring(slashCommand.length).trim() + + return messageParts to trimmedMessage + } + + private val notSupportedThreadsCommands: List by lazy { + Command.entries.filter { + !it.isAllowedInThread + } + } + + /** + * Checks whether the current command is not supported by threads. + * @param isInThreadTimeline if its true we are in a thread timeline + * @param slashCommand the slash command that will be checked + * @return The command that is not supported + */ + private fun getNotSupportedByThreads(isInThreadTimeline: Boolean, slashCommand: String): Command? { + return if (isInThreadTimeline) { + notSupportedThreadsCommands.firstOrNull { + it.command == slashCommand + } + } else { + null + } + } + + private fun trimParts(message: CharSequence, messageParts: List): String? { + val partsSize = messageParts.sumOf { it.length } + val gapsNumber = messageParts.size - 1 + return message.substring(partsSize + gapsNumber).trim().takeIf { it.isNotEmpty() } + } +} diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt new file mode 100644 index 0000000000..ba2786c944 --- /dev/null +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt @@ -0,0 +1,80 @@ +/* + * 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.slashcommands.impl + +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.api.SlashCommandService +import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion +import io.element.android.services.toolbox.api.strings.StringProvider +import kotlinx.coroutines.flow.first + +@ContributesBinding(RoomScope::class) +class DefaultSlashCommandService( + private val commandParser: CommandParser, + private val commandExecutor: CommandExecutor, + private val stringProvider: StringProvider, + private val appPreferencesStore: AppPreferencesStore, + private val featureFlagService: FeatureFlagService, +) : SlashCommandService { + override suspend fun getSuggestions( + text: String, + isInThread: Boolean, + ): List { + if (!featureFlagService.isFeatureEnabled(FeatureFlags.SlashCommand)) return emptyList() + val isDeveloperModeEnabled = appPreferencesStore.isDeveloperModeEnabledFlow().first() + return Command.entries.filter { + it.startsWith(text) + }.filter { + !isInThread || it.isAllowedInThread + }.filter { + !it.isDevCommand || isDeveloperModeEnabled + }.map { + SlashCommandSuggestion( + command = it.command, + parameters = it.parameters, + description = stringProvider.getString(it.description), + ) + } + } + + override suspend fun parse( + textMessage: CharSequence, + formattedMessage: String?, + isInThreadTimeline: Boolean, + ): SlashCommand { + return commandParser.parseSlashCommand( + textMessage = textMessage, + formattedMessage = formattedMessage, + isInThreadTimeline = isInThreadTimeline, + ) + } + + override suspend fun proceedSendMessage( + slashCommand: SlashCommand.SlashCommandSendMessage, + timeline: Timeline, + ): Result { + return commandExecutor.proceedSendMessage( + slashCommand = slashCommand, + timeline = timeline, + ) + } + + override suspend fun proceedAdmin( + slashCommand: SlashCommand.SlashCommandAdmin, + ): Result { + return commandExecutor.proceedAdmin( + slashCommand = slashCommand, + ) + } +} diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RainbowGenerator.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RainbowGenerator.kt new file mode 100644 index 0000000000..594b51cbf6 --- /dev/null +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RainbowGenerator.kt @@ -0,0 +1,113 @@ +/* + * 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.slashcommands.impl.rainbow + +import dev.zacsweers.metro.Inject +import kotlin.math.cos +import kotlin.math.pow +import kotlin.math.roundToInt +import kotlin.math.sin + +/** + * Inspired from React-Sdk + * Ref: https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/utils/colour.js + */ +@Inject +class RainbowGenerator { + fun generate(text: String): String { + val split = text.splitEmoji() + val frequency = 2 * Math.PI / split.size + + return split + .mapIndexed { idx, letter -> + // Do better than React-Sdk: Avoid adding font color for spaces + if (letter == " ") { + "$letter" + } else { + val (a, b) = generateAB(idx * frequency, 1f) + val dashColor = labToRGB(75, a, b).toDashColor() + "$letter" + } + } + .joinToString(separator = "") + } + + private fun generateAB(hue: Double, chroma: Float): Pair { + val a = chroma * 127 * cos(hue) + val b = chroma * 127 * sin(hue) + + return Pair(a, b) + } + + private fun labToRGB(l: Int, a: Double, b: Double): RgbColor { + // Convert CIELAB to CIEXYZ (D65) + var y = (l + 16) / 116.0 + val x = adjustXYZ(y + a / 500) * 0.9505 + val z = adjustXYZ(y - b / 200) * 1.0890 + + y = adjustXYZ(y) + + // Linear transformation from CIEXYZ to RGB + val red = 3.24096994 * x - 1.53738318 * y - 0.49861076 * z + val green = -0.96924364 * x + 1.8759675 * y + 0.04155506 * z + val blue = 0.05563008 * x - 0.20397696 * y + 1.05697151 * z + + return RgbColor(adjustRGB(red), adjustRGB(green), adjustRGB(blue)) + } + + private fun adjustXYZ(value: Double): Double { + if (value > 0.2069) { + return value.pow(3) + } + return 0.1284 * value - 0.01771 + } + + private fun gammaCorrection(value: Double): Double { + // Non-linear transformation to sRGB + if (value <= 0.0031308) { + return 12.92 * value + } + return 1.055 * value.pow(1 / 2.4) - 0.055 + } + + private fun adjustRGB(value: Double): Int { + return (gammaCorrection(value) + .coerceIn(0.0, 1.0) * 255) + .roundToInt() + } +} + +/** + * Same as split, but considering emojis. + */ +private fun CharSequence.splitEmoji(): List { + val result = mutableListOf() + var index = 0 + while (index < length) { + val firstChar = get(index) + if (firstChar.code == 0x200e) { + // Left to right mark. What should I do with it? + } else if (firstChar.code in 0xD800..0xDBFF && index + 1 < length) { + // We have the start of a surrogate pair + val secondChar = get(index + 1) + if (secondChar.code in 0xDC00..0xDFFF) { + // We have an emoji + result.add("$firstChar$secondChar") + index++ + } else { + // Not sure what we have here... + result.add("$firstChar") + } + } else { + // Regular char + result.add("$firstChar") + } + index++ + } + return result +} diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RgbColor.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RgbColor.kt new file mode 100644 index 0000000000..c425d81d73 --- /dev/null +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/rainbow/RgbColor.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.slashcommands.impl.rainbow + +data class RgbColor( + val r: Int, + val g: Int, + val b: Int +) + +fun RgbColor.toDashColor(): String { + return listOf(r, g, b) + .joinToString(separator = "", prefix = "#") { + it.toString(16).padStart(2, '0') + } +} diff --git a/libraries/slashcommands/impl/src/main/res/values/temporary.xml b/libraries/slashcommands/impl/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..0a8f2a0034 --- /dev/null +++ b/libraries/slashcommands/impl/src/main/res/values/temporary.xml @@ -0,0 +1,47 @@ + + + Command error + Unrecognized command: %1$s + The command \"%1$s\" needs more parameters, or some parameters are incorrect.The syntax is\n\n%2$s + The command \"%1$s\" is recognized but not supported in threads. + Displays action + Crash the application. + Bans user with given id + Unbans user with given id + Ignores a user, hiding their messages from you + Stops ignoring a user, showing their messages going forward + Define the power level of a user + Deops user with given id + Sets the room name + Sends the given message colored as a rainbow + Sends the given emote colored as a rainbow + Invites user with given id to current room + Joins room with given address + Sends the given message as a spoiler + Set the room topic + Removes user with given id from this room + Changes your display nickname + Sends the given message with confetti + Sends the given message with snowfall + Sends a message as plain text, without interpreting it as markdown + Changes your display nickname in the current room only + Changes the avatar of the current room + Changes your avatar in this current room only + Open the developer tools screen + Displays information about a user + Prepends ¯\\_(ツ)_/¯ to a plain-text message + Prepends ( ͡° ͜ʖ ͡°) to a plain-text message + Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message + Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message + Forces the current outbound group session in an encrypted room to be discarded + Only supported in encrypted rooms + Leave the current room + Upgrades a room to a new version + + Spoiler + diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt new file mode 100644 index 0000000000..497f45c96f --- /dev/null +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt @@ -0,0 +1,359 @@ +/* + * 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.slashcommands.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.libraries.matrix.api.timeline.MsgType +import io.element.android.libraries.matrix.test.AN_AVATAR_URL +import io.element.android.libraries.matrix.test.A_MESSAGE +import io.element.android.libraries.matrix.test.A_USER_ID +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.room.FakeBaseRoom +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.timeline.FakeTimeline +import io.element.android.libraries.slashcommands.api.ChatEffect +import io.element.android.libraries.slashcommands.api.MessagePrefix +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.impl.rainbow.RainbowGenerator +import io.element.android.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.test.strings.FakeStringProvider +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class CommandExecutorTest { + @Test + fun `send plain text delegates to timeline with plain flag`() = runTest { + val timeline = FakeTimeline() + var capturedBody: String? = null + var capturedHtml: String? = "initial" + var capturedAsPlainText = false + timeline.sendMessageLambda = { body, htmlBody, _, _, asPlainText -> + capturedBody = body + capturedHtml = htmlBody + capturedAsPlainText = asPlainText + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendPlainText("hello"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("hello") + assertThat(capturedHtml).isNull() + assertThat(capturedAsPlainText).isTrue() + } + + @Test + fun `send emote delegates to timeline as emote`() = runTest { + val timeline = FakeTimeline() + var msgType: MsgType? = null + timeline.sendMessageLambda = { _, _, _, type, _ -> + msgType = type + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendEmote("yay"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(msgType).isEqualTo(MsgType.MSG_TYPE_EMOTE) + } + + @Test + fun `send lenny prefixes message`() = runTest { + val timeline = FakeTimeline() + var capturedBody: String? = null + timeline.sendMessageLambda = { body, _, _, _, _ -> + capturedBody = body + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendWithPrefix(MessagePrefix.Lenny, "fun"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("( ͡° ͜ʖ ͡°) fun") + } + + @Test + fun `send table flip prefixes message`() = runTest { + val timeline = FakeTimeline() + var capturedBody: String? = null + timeline.sendMessageLambda = { body, _, _, _, _ -> + capturedBody = body + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendWithPrefix(MessagePrefix.TableFlip, "wow"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("(╯°□°)╯︵ ┻━┻ wow") + } + + @Test + fun `send unflip prefixes message`() = runTest { + val timeline = FakeTimeline() + var capturedBody: String? = null + timeline.sendMessageLambda = { body, _, _, _, _ -> + capturedBody = body + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendWithPrefix(MessagePrefix.Unflip, "keep cool"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("┬──┬ ノ( ゜-゜ノ) keep cool") + } + + @Test + fun `send shrug prefixes message`() = runTest { + val timeline = FakeTimeline() + var capturedBody: String? = null + timeline.sendMessageLambda = { body, _, _, _, _ -> + capturedBody = body + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendWithPrefix(MessagePrefix.Shrug, "wow"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("¯\\\\_(ツ)\\_/¯ wow") + } + + @Test + fun `send rainbow provides html body`() = runTest { + val timeline = FakeTimeline() + var capturedHtml: String? = null + var capturedBody: String? = null + var capturedMsgType: MsgType? = null + timeline.sendMessageLambda = { body, htmlBody, _, msgType, _ -> + capturedBody = body + capturedHtml = htmlBody + capturedMsgType = msgType + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendRainbow("a nice rainbow"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("a nice rainbow") + assertThat(capturedHtml).isNotNull() + assertThat(capturedHtml!!.contains(" + capturedBody = body + capturedHtml = htmlBody + capturedMsgType = msgType + Result.success(Unit) + } + val sut = createCommandExecutor() + val res = sut.proceedSendMessage(SlashCommand.SendRainbowEmote("a nice rainbow"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("a nice rainbow") + assertThat(capturedHtml).isNotNull() + assertThat(capturedHtml!!.contains(" + capturedBody = body + capturedHtml = htmlBody + Result.success(Unit) + } + val stringProvider = FakeStringProvider(defaultResult = "SPOILER") + val sut = createCommandExecutor( + stringProvider = stringProvider, + ) + val res = sut.proceedSendMessage(SlashCommand.SendSpoiler("secret"), timeline) + assertThat(res.isSuccess).isTrue() + assertThat(capturedBody).isEqualTo("[SPOILER](secret)") + assertThat(capturedHtml).isEqualTo("secret") + } + + @Test + fun `send chat effect is not supported`() = runTest { + val sut = createCommandExecutor() + val res = sut.proceedSendMessage( + SlashCommand.SendChatEffect(ChatEffect.CONFETTI, A_MESSAGE), + FakeTimeline() + ) + assertThat(res.isFailure).isTrue() + } + + @Test + fun `admin commands call underlying client and room APIs`() = runTest { + var kicked = false + var banned = false + var unbanned = false + var invited = false + var ignored = false + var unignored = false + var left = false + var topicSet = false + var nameSet = false + var joined = false + + val joinedRoom = FakeJoinedRoom( + kickUserResult = { _, _ -> + kicked = true + Result.success(Unit) + }, + banUserResult = { _, _ -> + banned = true + Result.success(Unit) + }, + unBanUserResult = { _, _ -> + unbanned = true + Result.success(Unit) + }, + inviteUserResult = { _ -> + invited = true + Result.success(Unit) + }, + setTopicResult = { _ -> + topicSet = true + Result.success(Unit) + }, + setNameResult = { _ -> + nameSet = true + Result.success(Unit) + }, + baseRoom = FakeBaseRoom( + leaveRoomLambda = { + left = true + Result.success(Unit) + }, + ) + ) + val matrixClient = FakeMatrixClient( + ignoreUserResult = { _ -> + ignored = true + Result.success(Unit) + }, + unIgnoreUserResult = { _ -> + unignored = true + Result.success(Unit) + }, + ).apply { + joinRoomByIdOrAliasLambda = { _, _ -> + joined = true + Result.success(null) + } + } + val sut = createCommandExecutor( + matrixClient = matrixClient, + joinedRoom = joinedRoom, + ) + val kickRes = sut.proceedAdmin(SlashCommand.RemoveUser(A_USER_ID, null)) + assertThat(kicked).isTrue() + assertThat(kickRes.isSuccess).isTrue() + val banRes = sut.proceedAdmin(SlashCommand.BanUser(A_USER_ID, "reason")) + assertThat(banned).isTrue() + assertThat(banRes.isSuccess).isTrue() + val unbanRes = sut.proceedAdmin(SlashCommand.UnbanUser(A_USER_ID, null)) + assertThat(unbanned).isTrue() + assertThat(unbanRes.isSuccess).isTrue() + val inviteRes = sut.proceedAdmin(SlashCommand.Invite(A_USER_ID, null)) + assertThat(invited).isTrue() + assertThat(inviteRes.isSuccess).isTrue() + val ignoreRes = sut.proceedAdmin(SlashCommand.IgnoreUser(A_USER_ID)) + assertThat(ignoreRes.isSuccess).isTrue() + assertThat(ignored).isTrue() + val unignoreRes = sut.proceedAdmin(SlashCommand.UnignoreUser(A_USER_ID)) + assertThat(unignoreRes.isSuccess).isTrue() + assertThat(unignored).isTrue() + val leaveRes = sut.proceedAdmin(SlashCommand.LeaveRoom) + assertThat(leaveRes.isSuccess).isTrue() + assertThat(left).isTrue() + val topicRes = sut.proceedAdmin(SlashCommand.ChangeTopic("t")) + assertThat(topicRes.isSuccess).isTrue() + assertThat(topicSet).isTrue() + val nameRes = sut.proceedAdmin(SlashCommand.ChangeRoomName("n")) + assertThat(nameRes.isSuccess).isTrue() + assertThat(nameSet).isTrue() + val joinRes = sut.proceedAdmin( + SlashCommand.JoinRoom( + roomIdOrAlias = RoomIdOrAlias.Id( + RoomId("!room:domain") + ), + reason = null, + ) + ) + assertThat(joinRes.isSuccess).isTrue() + assertThat(joined).isTrue() + } +} + +fun createCommandExecutor( + matrixClient: FakeMatrixClient = FakeMatrixClient(), + joinedRoom: FakeJoinedRoom = FakeJoinedRoom(), + rainbowGenerator: RainbowGenerator = RainbowGenerator(), + stringProvider: StringProvider = FakeStringProvider(), +) = CommandExecutor( + matrixClient = matrixClient, + joinedRoom = joinedRoom, + rainbowGenerator = rainbowGenerator, + stringProvider = stringProvider, +) diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt new file mode 100644 index 0000000000..0887847a40 --- /dev/null +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt @@ -0,0 +1,224 @@ +/* + * 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.slashcommands.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore +import io.element.android.libraries.slashcommands.api.ChatEffect +import io.element.android.libraries.slashcommands.api.MessagePrefix +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.test.strings.FakeStringProvider +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class CommandParserTest { + @Test + fun parseSlashCommandEmpty() = runTest { + test("/", SlashCommand.ErrorEmptySlashCommand("A string/")) + } + + @Test + fun parseSlashCommandUnknown() = runTest { + test("/unknown", SlashCommand.ErrorUnknownSlashCommand("A string/unknown")) + test("/unknown with param", SlashCommand.ErrorUnknownSlashCommand("A string/unknown")) + } + + @Test + fun parseSlashCommandNotACommand() = runTest { + test("", SlashCommand.NotACommand) + test("test", SlashCommand.NotACommand) + test("// test", SlashCommand.NotACommand) + } + + @Test + fun parseSlashCommandEmote() = runTest { + test("/me test", SlashCommand.SendEmote("test")) + test("/me", SlashCommand.ErrorSyntax("A string/me, /me ")) + } + + @Test + fun parseSlashCommandRemove() = runTest { + // Nominal + test("/remove $A_USER_ID", SlashCommand.RemoveUser(A_USER_ID, null)) + // With a reason + test("/remove $A_USER_ID a reason", SlashCommand.RemoveUser(A_USER_ID, "a reason")) + // Trim the reason + test("/remove $A_USER_ID a reason ", SlashCommand.RemoveUser(A_USER_ID, "a reason")) + // Alias + test("/kick $A_USER_ID", SlashCommand.RemoveUser(A_USER_ID, null)) + // Error + test("/remove", SlashCommand.ErrorSyntax("A string/remove, /remove [reason]")) + } + + @Test + fun parseSlashCommandRemoveMarkdown() = runTest { + // Nominal + test( + "/remove [@user:domain.org](https://matrix.to/#/@user:domain.org)", + SlashCommand.RemoveUser(UserId("@user:domain.org"), null) + ) + test( + "/remove [@user:domain.org](https://matrix.to/#/@user:domain.org) reason", + SlashCommand.RemoveUser(UserId("@user:domain.org"), "reason") + ) + } + + @Test + fun parseSlashCommandPlainAndNick() = runTest { + test("/plain hello", SlashCommand.SendPlainText("hello")) + test("/plain", SlashCommand.ErrorSyntax("A string/plain, /plain ")) + + test("/nick John", SlashCommand.ChangeDisplayName("John")) + test("/nick", SlashCommand.ErrorSyntax("A string/nick, /nick ")) + } + + @Test + fun parseSlashCommandRoomNickAndAvatars() = runTest { + test("/myroomnick Roomy", SlashCommand.ChangeDisplayNameForRoom("Roomy")) + test("/roomavatar mxc://matrix.org/abc", SlashCommand.ChangeRoomAvatar("mxc://matrix.org/abc")) + test("/roomavatar http://notmxc", SlashCommand.ErrorSyntax("A string/roomavatar, /roomavatar ")) + test("/myroomavatar mxc://matrix.org/abc", SlashCommand.ChangeAvatarForRoom("mxc://matrix.org/abc")) + } + + @Test + fun parseSlashCommandTopicAndRainbow() = runTest { + test("/topic New topic", SlashCommand.ChangeTopic("New topic")) + test("/topic", SlashCommand.ErrorSyntax("A string/topic, /topic ")) + + test("/rainbow yay", SlashCommand.SendRainbow("yay")) + test("/rainbow", SlashCommand.ErrorSyntax("A string/rainbow, /rainbow ")) + + test("/rainbowme yay", SlashCommand.SendRainbowEmote("yay")) + test("/rainbowme", SlashCommand.ErrorSyntax("A string/rainbowme, /rainbowme ")) + } + + @Test + fun parseSlashCommandJoinAndRoomName() = runTest { + // valid join + test( + "/join !roomId:domain reason", + SlashCommand.JoinRoom( + RoomIdOrAlias.Id(RoomId("!roomId:domain")), + "reason" + ) + ) + + // invalid join + test("/join notavalid", SlashCommand.ErrorSyntax("A string/join, /join [reason]")) + + test("/roomname My Room", SlashCommand.ChangeRoomName("My Room")) + test("/roomname", SlashCommand.ErrorSyntax("A string/roomname, /roomname ")) + } + + @Test + fun parseSlashCommandInviteBanEtc() = runTest { + test("/invite $A_USER_ID", SlashCommand.Invite(A_USER_ID, null)) + test("/invite", SlashCommand.ErrorSyntax("A string/invite, /invite [reason]")) + + test("/ban $A_USER_ID bad", SlashCommand.BanUser(A_USER_ID, "bad")) + test("/unban $A_USER_ID", SlashCommand.UnbanUser(A_USER_ID, null)) + + test("/ignore $A_USER_ID", SlashCommand.IgnoreUser(A_USER_ID)) + test("/unignore $A_USER_ID", SlashCommand.UnignoreUser(A_USER_ID)) + } + + @Test + fun parseSlashCommandPowerLevels() = runTest { + test("/op $A_USER_ID 50", SlashCommand.SetUserPowerLevel(A_USER_ID, 50)) + test("/op $A_USER_ID notnumber", SlashCommand.ErrorSyntax("A string/op, /op []")) + test("/deop $A_USER_ID", SlashCommand.SetUserPowerLevel(A_USER_ID, null)) + } + + @Test + fun parseSlashCommandDevtoolsAndSpoiler() = runTest { + test("/devtools", SlashCommand.DevTools) + test("/devtools extra", SlashCommand.ErrorSyntax("A string/devtools, /devtools")) + + test("/spoiler secret", SlashCommand.SendSpoiler("secret")) + test("/spoiler", SlashCommand.ErrorSyntax("A string/spoiler, /spoiler ")) + } + + @Test + fun parseSlashCommandEmojisAndSession() = runTest { + test("/shrug hello", SlashCommand.SendWithPrefix(MessagePrefix.Shrug, "hello")) + test("/shrug", SlashCommand.SendWithPrefix(MessagePrefix.Shrug, "")) + + test("/lenny fun", SlashCommand.SendWithPrefix(MessagePrefix.Lenny, "fun")) + test("/tableflip wow", SlashCommand.SendWithPrefix(MessagePrefix.TableFlip, "wow")) + test("/unflip be safe", SlashCommand.SendWithPrefix(MessagePrefix.Unflip, "be safe")) + + test("/discardsession", SlashCommand.DiscardSession) + test("/discardsession extra", SlashCommand.ErrorSyntax("A string/discardsession, /discardsession")) + } + + @Test + fun parseSlashCommandWhoisAndEffectsAndLeave() = runTest { + test("/whois $A_USER_ID", SlashCommand.ShowUser(A_USER_ID)) + + test("/confetti party", SlashCommand.SendChatEffect(ChatEffect.CONFETTI, "party")) + test("/snowfall snow", SlashCommand.SendChatEffect(ChatEffect.SNOWFALL, "snow")) + + test("/leave", SlashCommand.LeaveRoom) + test("/leave now", SlashCommand.ErrorSyntax("A string/leave, /leave")) + } + + @Test + fun parseSlashCommandUpgradeAndCrashAndFeatureFlagAndThreads() = runTest { + test("/upgraderoom 9", SlashCommand.UpgradeRoom("9")) + test("/upgraderoom", SlashCommand.ErrorSyntax("A string/upgraderoom, /upgraderoom newVersion")) + + // Crash only when developer mode enabled + val cpDev = createCommandParser(appPreferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = true)) + try { + cpDev.parseSlashCommand("/crash", null, false) + org.junit.Assert.fail("Expected crash to throw") + } catch (_: IllegalStateException) { + // expected + } + + // Feature flag disabled + val cpFF = createCommandParser(featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.SlashCommand.key to false))) + val res = cpFF.parseSlashCommand("/me test", null, false) + assertThat(res).isEqualTo(SlashCommand.NotACommand) + + // Not supported in threads (e.g. /join) + val cpThread = createCommandParser() + val threadRes = cpThread.parseSlashCommand("/join !roomId:domain", null, true) + assertThat(threadRes).isInstanceOf(SlashCommand.ErrorCommandNotSupportedInThreads::class.java) + assertThat((threadRes as SlashCommand.ErrorCommandNotSupportedInThreads).message).isEqualTo("A string/join") + } + + private suspend fun test(message: String, expectedResult: SlashCommand) { + val commandParser = createCommandParser() + val result = commandParser.parseSlashCommand(message, null, false) + assertThat(result).isEqualTo(expectedResult) + } +} + +internal fun createCommandParser( + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.SlashCommand.key to true, + ), + ), + stringProvider: StringProvider = FakeStringProvider(), +) = CommandParser( + appPreferencesStore = appPreferencesStore, + featureFlagService = featureFlagService, + stringProvider = stringProvider, +) diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt new file mode 100644 index 0000000000..243f25666c --- /dev/null +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt @@ -0,0 +1,165 @@ +/* + * 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.slashcommands.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.room.IntentionalMention +import io.element.android.libraries.matrix.api.timeline.MsgType +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.room.FakeBaseRoom +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.timeline.FakeTimeline +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.impl.rainbow.RainbowGenerator +import io.element.android.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.test.strings.FakeStringProvider +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultSlashCommandServiceTest { + @Test + fun `getSuggestions filters by text and maps to suggestions`() = runTest { + val stringProvider = FakeStringProvider(defaultResult = "desc") + val prefs = InMemoryAppPreferencesStore(isDeveloperModeEnabled = false) + val sut = createDefaultSlashCommandService( + commandParser = CommandParser( + appPreferencesStore = prefs, + featureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.SlashCommand.key to true, + ) + ), + stringProvider = stringProvider, + ), + stringProvider = stringProvider, + appPreferencesStore = prefs, + ) + val res = sut.getSuggestions("ra", isInThread = true) + // Expect commands starting with "/ra" (case-insensitive) and that are allowed in threads + assertThat(res).isNotEmpty() + assertThat(res.first().description).isEqualTo("desc") + } + + @Test + fun `getSuggestions hides dev commands when developer mode disabled`() = runTest { + val stringProvider = FakeStringProvider() + val prefs = InMemoryAppPreferencesStore(isDeveloperModeEnabled = false) + val sut = createDefaultSlashCommandService(appPreferencesStore = prefs, stringProvider = stringProvider) + val all = sut.getSuggestions("crash", isInThread = true) + assertThat(all).isEmpty() + } + + @Test + fun `getSuggestions returns empty list when the feature is enabled`() = runTest { + val sut = createDefaultSlashCommandService(isFeatureEnabled = true) + val all = sut.getSuggestions("me", isInThread = false) + assertThat(all).isNotEmpty() + } + + @Test + fun `getSuggestions returns empty list when the feature is disabled`() = runTest { + val sut = createDefaultSlashCommandService(isFeatureEnabled = false) + val all = sut.getSuggestions("me", isInThread = false) + assertThat(all).isEmpty() + } + + @Test + fun `getSuggestions for aliases`() = runTest { + val stringProvider = FakeStringProvider() + val prefs = InMemoryAppPreferencesStore(isDeveloperModeEnabled = false) + val sut = createDefaultSlashCommandService(appPreferencesStore = prefs, stringProvider = stringProvider) + val all = sut.getSuggestions("part", isInThread = true) + assertThat(all).isEmpty() + } + + @Test + fun `getSuggestions shows dev commands when developer mode enabled`() = runTest { + val stringProvider = FakeStringProvider() + val prefs = InMemoryAppPreferencesStore(isDeveloperModeEnabled = true) + val sut = createDefaultSlashCommandService(appPreferencesStore = prefs, stringProvider = stringProvider) + val all = sut.getSuggestions("crash", isInThread = true) + assertThat(all).isNotEmpty() + assertThat(all.first().command).isEqualTo("/crash") + } + + @Test + fun `parse delegates to commandParser`() = runTest { + val sut = createDefaultSlashCommandService() + val res = sut.parse("test", null, false) + assertThat(res).isEqualTo(SlashCommand.NotACommand) + } + + @Test + fun `proceedSendMessage delegate to commandExecutor`() = runTest { + val sendMessage = lambdaRecorder { _: String, _: String?, _: List, _: MsgType, _: Boolean -> + Result.success(Unit) + } + val sut = createDefaultSlashCommandService() + val sendRes = sut.proceedSendMessage( + slashCommand = SlashCommand.SendPlainText("hi"), + timeline = FakeTimeline().apply { + sendMessageLambda = sendMessage + }, + ) + assertThat(sendRes.isSuccess).isTrue() + sendMessage.assertions().isCalledOnce() + } + + @Test + fun `proceedAdmin delegates to commandExecutor`() = runTest { + val leaveRoomLambda = lambdaRecorder> { + Result.success(Unit) + } + val sut = createDefaultSlashCommandService( + commandExecutor = CommandExecutor( + matrixClient = FakeMatrixClient(), + joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + leaveRoomLambda = leaveRoomLambda + ), + ), + rainbowGenerator = RainbowGenerator(), + stringProvider = FakeStringProvider(), + ), + ) + val adminRes = sut.proceedAdmin(SlashCommand.LeaveRoom) + assertThat(adminRes.isSuccess).isTrue() + leaveRoomLambda.assertions().isCalledOnce() + } + + private fun createDefaultSlashCommandService( + isFeatureEnabled: Boolean = true, + featureFlagService: FeatureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.SlashCommand.key to isFeatureEnabled, + ), + ), + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), + stringProvider: StringProvider = FakeStringProvider(), + commandParser: CommandParser = createCommandParser( + featureFlagService = featureFlagService, + appPreferencesStore = appPreferencesStore, + stringProvider = stringProvider, + ), + commandExecutor: CommandExecutor = createCommandExecutor( + stringProvider = stringProvider, + ), + ) = DefaultSlashCommandService( + commandParser = commandParser, + commandExecutor = commandExecutor, + stringProvider = stringProvider, + appPreferencesStore = appPreferencesStore, + featureFlagService = featureFlagService, + ) +} diff --git a/libraries/slashcommands/test/build.gradle.kts b/libraries/slashcommands/test/build.gradle.kts new file mode 100644 index 0000000000..d8a54aa180 --- /dev/null +++ b/libraries/slashcommands/test/build.gradle.kts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.slashcommands.test" +} + +dependencies { + implementation(projects.libraries.slashcommands.api) + implementation(projects.libraries.matrix.api) + implementation(projects.tests.testutils) +} diff --git a/libraries/slashcommands/test/src/main/kotlin/io/element/android/libraries/slashcommands/test/FakeSlashCommandService.kt b/libraries/slashcommands/test/src/main/kotlin/io/element/android/libraries/slashcommands/test/FakeSlashCommandService.kt new file mode 100644 index 0000000000..319a8e647c --- /dev/null +++ b/libraries/slashcommands/test/src/main/kotlin/io/element/android/libraries/slashcommands/test/FakeSlashCommandService.kt @@ -0,0 +1,45 @@ +/* + * 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.slashcommands.test + +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.slashcommands.api.SlashCommand +import io.element.android.libraries.slashcommands.api.SlashCommandService +import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.simulateLongTask + +class FakeSlashCommandService( + private val getSuggestionsResult: (String, Boolean) -> List = { _, _ -> lambdaError() }, + private val parseResult: (CharSequence, String?, Boolean) -> SlashCommand = { _, _, _ -> lambdaError() }, + private val proceedSendMessageResult: (SlashCommand.SlashCommandSendMessage, Timeline) -> Result = { _, _ -> lambdaError() }, + private val proceedAdminResult: (SlashCommand.SlashCommandAdmin) -> Result = { lambdaError() }, +) : SlashCommandService { + override suspend fun getSuggestions(text: String, isInThread: Boolean): List = simulateLongTask { + getSuggestionsResult(text, isInThread) + } + + override suspend fun parse( + textMessage: CharSequence, + formattedMessage: String?, + isInThreadTimeline: Boolean, + ): SlashCommand = simulateLongTask { + parseResult(textMessage, formattedMessage, isInThreadTimeline) + } + + override suspend fun proceedSendMessage( + slashCommand: SlashCommand.SlashCommandSendMessage, + timeline: Timeline, + ): Result = simulateLongTask { + proceedSendMessageResult(slashCommand, timeline) + } + + override suspend fun proceedAdmin(slashCommand: SlashCommand.SlashCommandAdmin): Result = simulateLongTask { + proceedAdminResult(slashCommand) + } +} diff --git a/libraries/textcomposer/impl/build.gradle.kts b/libraries/textcomposer/impl/build.gradle.kts index a339890201..41e20582e0 100644 --- a/libraries/textcomposer/impl/build.gradle.kts +++ b/libraries/textcomposer/impl/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.testtags) implementation(projects.libraries.uiUtils) + implementation(projects.libraries.slashcommands.api) releaseApi(libs.matrix.richtexteditor) releaseApi(libs.matrix.richtexteditor.compose) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt index d91735fb83..f9fd6a2b6d 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/ResolvedSuggestion.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion @Immutable sealed interface ResolvedSuggestion { @@ -32,4 +33,8 @@ sealed interface ResolvedSuggestion { size = size, ) } + + data class Command( + val command: SlashCommandSuggestion, + ) : ResolvedSuggestion } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt index ba7e3c50c0..90e5368951 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/model/MarkdownTextEditorState.kt @@ -61,21 +61,29 @@ class MarkdownTextEditorState( } is ResolvedSuggestion.Member -> { val currentText = SpannableStringBuilder(text.value()) - val mentionSpan = mentionSpanProvider.createUserMentionSpan(resolvedSuggestion.roomMember.userId) + val userId = resolvedSuggestion.roomMember.userId + val mentionSpan = mentionSpanProvider.createUserMentionSpan(userId) currentText.replace(suggestion.start, suggestion.end, "@ ") val end = suggestion.start + 1 currentText.setSpan(mentionSpan, suggestion.start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - this.text.update(currentText, true) - this.selection = IntRange(end + 1, end + 1) + text.update(currentText, true) + selection = IntRange(end + 1, end + 1) } is ResolvedSuggestion.Alias -> { val currentText = SpannableStringBuilder(text.value()) - val mentionSpan = mentionSpanProvider.createRoomMentionSpan(resolvedSuggestion.roomAlias.toRoomIdOrAlias()) + val roomAlias = resolvedSuggestion.roomAlias + val mentionSpan = mentionSpanProvider.createRoomMentionSpan(roomAlias.toRoomIdOrAlias()) currentText.replace(suggestion.start, suggestion.end, "# ") val end = suggestion.start + 1 currentText.setSpan(mentionSpan, suggestion.start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - this.text.update(currentText, true) - this.selection = IntRange(end + 1, end + 1) + text.update(currentText, true) + selection = IntRange(end + 1, end + 1) + } + is ResolvedSuggestion.Command -> { + // Just insert the command text + text.update("${resolvedSuggestion.command.command} ", true) + val length = resolvedSuggestion.command.command.length + 1 + selection = IntRange(length, length) } } } diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt index 04b700925e..6e57ce68cb 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/model/MarkdownTextEditorStateTest.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion import io.element.android.libraries.textcomposer.impl.mentions.aMentionSpanProvider import io.element.android.libraries.textcomposer.mentions.MentionSpan import io.element.android.libraries.textcomposer.mentions.MentionType @@ -42,6 +43,7 @@ class MarkdownTextEditorStateTest { val mentionSpanProvider = aMentionSpanProvider() state.insertSuggestion(suggestion, mentionSpanProvider) assertThat(state.getMentions()).isEmpty() + assertThat(state.text.value().toString()).isEqualTo("Hello @") } @Test @@ -53,6 +55,7 @@ class MarkdownTextEditorStateTest { val permalinkParser = FakePermalinkParser(result = { PermalinkData.RoomLink(A_ROOM_ALIAS.toRoomIdOrAlias()) }) val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) state.insertSuggestion(suggestion, mentionSpanProvider) + assertThat(state.text.value().toString()).isEqualTo("Hello # ") } @Test @@ -64,6 +67,19 @@ class MarkdownTextEditorStateTest { val permalinkParser = FakePermalinkParser(result = { PermalinkData.RoomLink(A_ROOM_ALIAS.toRoomIdOrAlias()) }) val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) state.insertSuggestion(suggestion, mentionSpanProvider) + assertThat(state.text.value().toString()).isEqualTo("Hello # ") + } + + @Test + fun `insertSuggestion - command`() { + val state = aMarkdownTextEditorState(initialText = "/rai", initialFocus = true).apply { + currentSuggestion = Suggestion(start = 0, end = 3, type = SuggestionType.Command, text = "/rainbow") + } + val suggestion = aSlashCommandSuggestion() + val permalinkParser = FakePermalinkParser(result = { PermalinkData.RoomLink(A_ROOM_ALIAS.toRoomIdOrAlias()) }) + val mentionSpanProvider = aMentionSpanProvider(permalinkParser = permalinkParser) + state.insertSuggestion(suggestion, mentionSpanProvider) + assertThat(state.text.value().toString()).isEqualTo("/rainbow ") } @Test @@ -74,6 +90,7 @@ class MarkdownTextEditorStateTest { val mentionSpanProvider = aMentionSpanProvider() state.insertSuggestion(mention, mentionSpanProvider) assertThat(state.getMentions()).isEmpty() + assertThat(state.text.value().toString()).isEqualTo("Hello @") } @Test @@ -91,6 +108,7 @@ class MarkdownTextEditorStateTest { val mentions = state.getMentions() assertThat(mentions).isNotEmpty() assertThat((mentions.firstOrNull() as? IntentionalMention.User)?.userId).isEqualTo(member.userId) + assertThat(state.text.value().toString()).isEqualTo("Hello @ ") } @Test @@ -107,15 +125,14 @@ class MarkdownTextEditorStateTest { val mentions = state.getMentions() assertThat(mentions).isNotEmpty() assertThat(mentions.firstOrNull()).isInstanceOf(IntentionalMention.Room::class.java) + assertThat(state.text.value().toString()).isEqualTo("Hello @ ") } @Test fun `getMessageMarkdown - when there are no MentionSpans returns the same text`() { val text = "No mentions here" val state = aMarkdownTextEditorState(initialText = text, initialFocus = true) - val markdown = state.getMessageMarkdown(FakePermalinkBuilder()) - assertThat(markdown).isEqualTo(text) } @@ -128,19 +145,17 @@ class MarkdownTextEditorStateTest { ) val state = aMarkdownTextEditorState(initialText = text, initialFocus = true) state.text.update(aMarkdownTextWithMentions(), needsDisplaying = false) - val markdown = state.getMessageMarkdown(permalinkBuilder = permalinkBuilder) - assertThat(markdown).isEqualTo( "Hello [@alice:matrix.org](https://matrix.to/#/@alice:matrix.org) and everyone in @room" + " and a room [#room:domain.org](https://matrix.to/#/#room:domain.org)" ) + assertThat(state.text.value().toString()).isEqualTo("Hello @ and everyone in @ and a room #room:domain.org") } @Test fun `getMentions - when there are no MentionSpans returns empty list of mentions`() { val state = aMarkdownTextEditorState(initialText = "Hello @", initialFocus = true) - assertThat(state.getMentions()).isEmpty() } @@ -148,9 +163,7 @@ class MarkdownTextEditorStateTest { fun `getMentions - when there are MentionSpans returns a list of mentions`() { val state = aMarkdownTextEditorState(initialText = "Hello @", initialFocus = true) state.text.update(aMarkdownTextWithMentions(), needsDisplaying = false) - val mentions = state.getMentions() - assertThat(mentions).isNotEmpty() assertThat((mentions.firstOrNull() as? IntentionalMention.User)?.userId?.value).isEqualTo("@alice:matrix.org") assertThat(mentions.lastOrNull()).isInstanceOf(IntentionalMention.Room::class.java) @@ -184,4 +197,14 @@ class MarkdownTextEditorStateTest { roomAvatarUrl = null ) } + + private fun aSlashCommandSuggestion(): ResolvedSuggestion.Command { + return ResolvedSuggestion.Command( + command = SlashCommandSuggestion( + command = "/rainbow", + parameters = "param", + description = "Make the text colorful 🌈", + ), + ) + } } diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index e7cc47d7b8..8a5dfa2c4a 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -106,6 +106,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:session-storage:impl")) implementation(project(":libraries:mediapickers:impl")) implementation(project(":libraries:mediaupload:impl")) + implementation(project(":libraries:slashcommands:impl")) implementation(project(":libraries:usersearch:impl")) implementation(project(":libraries:textcomposer:impl")) implementation(project(":libraries:accountselect:impl")) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png index 6e14838915..986547c8c5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31e730519a460ebc21ebee0d24c429ea22bceb164bd99080fe23b2c1c010577f -size 22488 +oid sha256:d2acf7cae297e8be76765b392dc07a36692a9e597b8f205de31a04dcf8b6bdca +size 37918 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png index b83a34aa0d..d333d2439d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:426d109d550f6298f9375c4a8406210b7d2c52a590678e5c21d4a0ac2864202d -size 22560 +oid sha256:47b4d158df0f83631d099c072b8b3d95a57d539fb9e8d7e6802f6a90a3b78284 +size 37904 From 104ae4752a831ac4be23ff8d767d4087e32857c3 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Thu, 2 Apr 2026 17:28:55 +0400 Subject: [PATCH 0048/1083] 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 0049/1083] 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 0050/1083] 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 350d8bc61f7f8abf45b35abea7365df966c5756f Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 3 Apr 2026 10:41:57 +0100 Subject: [PATCH 0051/1083] Fix a missing : in build-rust-sdk (#6522) This prevented us providing a build target argument. --- tools/sdk/build-rust-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sdk/build-rust-sdk b/tools/sdk/build-rust-sdk index b3b57f7e98..2012af8741 100755 --- a/tools/sdk/build-rust-sdk +++ b/tools/sdk/build-rust-sdk @@ -41,7 +41,7 @@ sdkArg="" ## Argument parsing -TEMP=$(getopt -o 'rs:b:at:h' --long 'remote,sdk:,branch:,build-app,target-arch,help' -- "$@") +TEMP=$(getopt -o 'rs:b:at:h' --long 'remote,sdk:,branch:,build-app,target-arch:,help' -- "$@") if [ $? -ne 0 ]; then echo 'Terminating...' >&2 From 67671126f2e24658c425c0cd3551db76e9c7cc81 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 14:56:48 +0200 Subject: [PATCH 0052/1083] fix(deps): update core to v1.18.0 (#6328) 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 015b50531c..769c3b0854 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ ksp = "2.3.6" firebaseAppDistribution = "5.2.1" # AndroidX -core = "1.17.0" +core = "1.18.0" datastore = "1.2.1" constraintlayout = "2.2.1" constraintlayout_compose = "1.1.1" From 4e0165458a3c15b90ddc45786c5337490f08b1f9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 3 Apr 2026 18:21:37 +0200 Subject: [PATCH 0053/1083] 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 c96544be947f393521df6dad45a3aad54234a3fe Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 3 Apr 2026 18:22:35 +0200 Subject: [PATCH 0054/1083] Setting version for the release 26.04.1 --- enterprise | 1 - plugins/src/main/kotlin/Versions.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 160000 enterprise diff --git a/enterprise b/enterprise deleted file mode 160000 index cdde60c158..0000000000 --- a/enterprise +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cdde60c158ecd0987a3ba6fd79a4617551aff463 diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 4fbc3fb20c..62ccf66ab3 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 4 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** From 6e7bf8bbc3d9a870ce2a79e7bf7ed9239c3cb93c Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 3 Apr 2026 18:22:42 +0200 Subject: [PATCH 0055/1083] Adding fastlane file for version 26.04.1 --- fastlane/metadata/android/en-US/changelogs/202604010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202604010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202604010.txt b/fastlane/metadata/android/en-US/changelogs/202604010.txt new file mode 100644 index 0000000000..a4b397f1bb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202604010.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 5e6a6af409f7108d7e847fcae409b3a98bf5b456 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Sun, 5 Apr 2026 12:03:50 +0400 Subject: [PATCH 0056/1083] 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 0057/1083] 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 0058/1083] 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 a4a350fd17559d64606453a47eaab3cc56ba49a3 Mon Sep 17 00:00:00 2001 From: ganfra Date: Sun, 5 Apr 2026 10:56:38 +0200 Subject: [PATCH 0059/1083] Changelog for version 26.04.1 --- CHANGES.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 37c4e23d0a..830edde763 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,26 @@ +Changes in Element X v26.04.1 +============================= + +## What's Changed +### ✨ Features +* Add support for slash commands (under Feature Flag) by @bmarty in https://github.com/element-hq/element-x-android/pull/6482 +### Dependency upgrades +* chore(deps): update gradle/actions action to v6 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6489 +* fix(deps): update dependency androidx.work:work-runtime-ktx to v2.11.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6479 +* fix(deps): update dependency net.zetetic:sqlcipher-android to v4.14.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6460 +* fix(deps): update metro to v0.12.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6503 +* fix(deps): update dependency androidx.compose:compose-bom to v2026.03.01 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6511 +* fix(deps): update dependency org.jetbrains.kotlinx:kover-gradle-plugin to v0.9.8 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6513 +* fix(deps): update dependency androidx.browser:browser to v1.10.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6515 +* fix(deps): update dependency io.element.android:emojibase-bindings to v1.5.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6493 +* fix(deps): update core to v1.18.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6328 +### Others +* Tentative fix for `ForegroundServiceStartNotAllowedException` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6509 +* Fix a missing : in build-rust-sdk by @andybalaam in https://github.com/element-hq/element-x-android/pull/6522 + + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.04.0...v26.04.1 + Changes in Element X v26.04.0 ============================= From d87dea3cb96de58d2960e34cc65d913637ddd2b4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Apr 2026 12:18:42 +0200 Subject: [PATCH 0060/1083] Restore enterprise submodule. (#6541) --- enterprise | 1 + 1 file changed, 1 insertion(+) create mode 160000 enterprise diff --git a/enterprise b/enterprise new file mode 160000 index 0000000000..cdde60c158 --- /dev/null +++ b/enterprise @@ -0,0 +1 @@ +Subproject commit cdde60c158ecd0987a3ba6fd79a4617551aff463 From 15437912e1a9154be51050cbd27e7ba37900aa53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:26:43 +0200 Subject: [PATCH 0061/1083] fix(deps): update dependency io.element.android:element-call-embedded to v0.19.0 (#6538) 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 769c3b0854..ca5f42c118 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -233,7 +233,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.18.0" +element_call_embedded = "io.element.android:element-call-embedded:0.19.0" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From 503449f7379d095bb2d09e1ddf044ecf52053e5a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Apr 2026 14:28:05 +0200 Subject: [PATCH 0062/1083] Setting version for the release 26.04.2 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 62ccf66ab3..f46abc71bf 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 4 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 1 +private const val versionReleaseNumber = 2 object Versions { /** From 5f5738892c486093f9112c86410475c0fd9eb697 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Apr 2026 14:28:43 +0200 Subject: [PATCH 0063/1083] Adding fastlane file for version 26.04.2 --- fastlane/metadata/android/en-US/changelogs/202604020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202604020.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202604020.txt b/fastlane/metadata/android/en-US/changelogs/202604020.txt new file mode 100644 index 0000000000..a4b397f1bb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202604020.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 596e5c61929e0c58d815ac9a725dc2031ffc4387 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Apr 2026 15:29:06 +0200 Subject: [PATCH 0064/1083] Changelog for version 26.04.2 --- CHANGES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 830edde763..a3d7870288 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,14 @@ +Changes in Element X v26.04.2 +============================= + +## What's Changed +### 🐛 Bugfixes +* Restore enterprise submodule. by @bmarty in https://github.com/element-hq/element-x-android/pull/6541 +### Dependency upgrades +* fix(deps): update dependency io.element.android:element-call-embedded to v0.19.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6538 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.04.1...v26.04.2 + Changes in Element X v26.04.1 ============================= From 6ad85d4dfc25accc544b9f45f7222439c4bd9862 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:02:12 +0200 Subject: [PATCH 0065/1083] Sync Strings (#6537) * Sync Strings from Localazy * Sync strings. --------- Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> Co-authored-by: Benoit Marty --- .../src/main/res/values-lt/translations.xml | 4 +- .../src/main/res/values-lt/translations.xml | 10 +- .../src/main/res/values-cs/translations.xml | 4 +- .../src/main/res/values-cs/translations.xml | 6 +- .../src/main/res/values-cs/translations.xml | 4 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 5 + .../src/main/res/values-ko/translations.xml | 5 + .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-cs/translations.xml | 4 +- .../src/main/res/values-hu/translations.xml | 4 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-sv/translations.xml | 2 +- .../src/main/res/values-lt/translations.xml | 26 +- .../src/main/res/values-cs/translations.xml | 26 +- .../src/main/res/values-hu/translations.xml | 26 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-sv/translations.xml | 10 +- .../src/main/res/values-sv/translations.xml | 2 +- .../src/main/res/values-lt/translations.xml | 2 +- .../src/main/res/values-lt/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 27 +- .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 9 +- .../src/main/res/values-ko/translations.xml | 5 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-sv/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 10 +- .../src/main/res/values-hu/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 4 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-sv/translations.xml | 2 +- .../src/main/res/values-lt/translations.xml | 8 +- .../src/main/res/values-ko/translations.xml | 1 + .../src/main/res/values-lt/translations.xml | 5 + .../src/main/res/values-cs/translations.xml | 36 +- .../src/main/res/values-fi/translations.xml | 7 + .../src/main/res/values-fr/translations.xml | 8 + .../src/main/res/values-hu/translations.xml | 22 +- .../src/main/res/values-ko/translations.xml | 39 +- .../src/main/res/values-lt/translations.xml | 5 +- .../src/main/res/values-sv/translations.xml | 4 +- .../src/main/res/values/localazy.xml | 7 + ....impl.share_ShareLocationView_Day_5_de.png | 4 +- ...estions_SuggestionsPickerView_Day_0_de.png | 4 +- screenshots/html/data.js | 2029 +++++++++-------- 46 files changed, 1253 insertions(+), 1139 deletions(-) create mode 100644 features/location/impl/src/main/res/values-cs/translations.xml create mode 100644 features/location/impl/src/main/res/values-hu/translations.xml create mode 100644 features/location/impl/src/main/res/values-ko/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-lt/translations.xml diff --git a/features/analytics/api/src/main/res/values-lt/translations.xml b/features/analytics/api/src/main/res/values-lt/translations.xml index 08dd155332..004b20d79d 100644 --- a/features/analytics/api/src/main/res/values-lt/translations.xml +++ b/features/analytics/api/src/main/res/values-lt/translations.xml @@ -1,7 +1,7 @@ - "Dalinkitės anoniminiais naudojimo duomenimis ir padėkite mums nustatyti problemas." + "Bendrinkite anoniminius naudojimo duomenis, kad padėtumėte mums nustatyti problemas." "Galite perskaityti visas mūsų sąlygas %1$s." "čia" - "Dalytis analitiniais duomenimis" + "Bendrinti analitinius duomenis" diff --git a/features/analytics/impl/src/main/res/values-lt/translations.xml b/features/analytics/impl/src/main/res/values-lt/translations.xml index 11f2cbc74e..4f7c70dd6d 100644 --- a/features/analytics/impl/src/main/res/values-lt/translations.xml +++ b/features/analytics/impl/src/main/res/values-lt/translations.xml @@ -1,10 +1,10 @@ - "Mes nekaupsime ir neprofiliuosime jokių asmens duomenų" - "Dalinkitės anoniminiais naudojimo duomenimis ir padėkite mums nustatyti problemas." + "Mes neįrašysime ar neprofiliuosime jokių asmeninių duomenų." + "Bendrinkite anoniminius naudojimo duomenis, kad padėtumėte mums nustatyti problemas." "Galite perskaityti visas mūsų sąlygas %1$s." "čia" - "Tai galite bet kada išjungti" - "Mes nesidalinsime Jūsų duomenimis su trečiosiomis šalimis" - "Padėkite pagerinti %1$s" + "Tai galite išjungti bet kuriuo metu." + "Mes nebendrinsime jūsų duomenų su trečiosiomis šalimis." + "Padėkite patobulinti „%1$s“" diff --git a/features/ftue/impl/src/main/res/values-cs/translations.xml b/features/ftue/impl/src/main/res/values-cs/translations.xml index 30d6998ac6..0937e7ed14 100644 --- a/features/ftue/impl/src/main/res/values-cs/translations.xml +++ b/features/ftue/impl/src/main/res/values-cs/translations.xml @@ -2,8 +2,8 @@ "Nemůžete potvrdit?" "Vytvoření nového klíče pro obnovení" - "Ověřte toto zařízení a nastavte zabezpečené zasílání zpráv." - "Potvrďte, že jste to vy" + "Vyberte způsob ověření pro nastavení zabezpečeného zasílání zpráv." + "Potvrďte svou digitální identitu" "Použít jiné zařízení" "Použít klíč pro obnovení" "Nyní můžete bezpečně číst nebo odesílat zprávy, a kdokoli, s kým chatujete, může tomuto zařízení důvěřovat." diff --git a/features/home/impl/src/main/res/values-cs/translations.xml b/features/home/impl/src/main/res/values-cs/translations.xml index 16f9e6b801..0276db1fbe 100644 --- a/features/home/impl/src/main/res/values-cs/translations.xml +++ b/features/home/impl/src/main/res/values-cs/translations.xml @@ -5,9 +5,9 @@ "Nepřicházejí vám oznámení?" "Váš zvuk oznámení byl aktualizován – je jasnější, rychlejší a méně rušivý." "Aktualizovali jsme vaše zvuky" - "Vygenerujte nový klíč pro obnovení, který lze použít k obnovení historie šifrovaných zpráv v případě, že ztratíte přístup ke svým zařízením." - "Nastavení obnovy" - "Nastavení obnovy" + "Vaše chaty jsou automaticky zálohovány pomocí koncového šifrování. Chcete-li tuto zálohu obnovit a zachovat si svou digitální identitu v případě, že ztratíte přístup ke všem svým zařízením, budete potřebovat svůj klíč pro obnovení." + "Získat klíč pro obnovení" + "Zálohujte své chaty" "Potvrďte klíč pro obnovení, abyste zachovali přístup k úložišti klíčů a historii zpráv." "Zadejte klíč pro obnovení" "Zapomněli jste klíč pro obnovení?" diff --git a/features/location/impl/src/main/res/values-cs/translations.xml b/features/location/impl/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..99deeba029 --- /dev/null +++ b/features/location/impl/src/main/res/values-cs/translations.xml @@ -0,0 +1,4 @@ + + + "Zvolte, jak dlouho chcete sdílet svou aktuální polohu." + diff --git a/features/location/impl/src/main/res/values-fr/translations.xml b/features/location/impl/src/main/res/values-fr/translations.xml index 46689488e1..043c180dbc 100644 --- a/features/location/impl/src/main/res/values-fr/translations.xml +++ b/features/location/impl/src/main/res/values-fr/translations.xml @@ -1,4 +1,5 @@ + "Votre historique de localisation en direct sera enregistré dans le salon et visible par les membres après la fin de la session." "Choisissez la durée pendant laquelle vous partagerez votre position en direct." diff --git a/features/location/impl/src/main/res/values-hu/translations.xml b/features/location/impl/src/main/res/values-hu/translations.xml new file mode 100644 index 0000000000..b89965485f --- /dev/null +++ b/features/location/impl/src/main/res/values-hu/translations.xml @@ -0,0 +1,5 @@ + + + "Az élő helymeghatározás története a szobában lesz tárolva, és a munkamenet befejezése után is látható marad a tagok számára." + "Válassza ki, mennyi ideig szeretné megosztani az aktuális tartózkodási helyét." + diff --git a/features/location/impl/src/main/res/values-ko/translations.xml b/features/location/impl/src/main/res/values-ko/translations.xml new file mode 100644 index 0000000000..e283d20b9c --- /dev/null +++ b/features/location/impl/src/main/res/values-ko/translations.xml @@ -0,0 +1,5 @@ + + + "실시간 위치 기록은 대화방에 저장되며, 공유 종료 후에도 멤버들이 확인할 수 있습니다." + "실시간 위치를 공유할 시간을 선택해 주세요." + diff --git a/features/location/impl/src/main/res/values/localazy.xml b/features/location/impl/src/main/res/values/localazy.xml index 04538049db..ac2ff4b2a0 100644 --- a/features/location/impl/src/main/res/values/localazy.xml +++ b/features/location/impl/src/main/res/values/localazy.xml @@ -1,4 +1,5 @@ + "Your live location history will be stored in the room and visible to members after the session ends." "Choose how long to share your live location." diff --git a/features/lockscreen/impl/src/main/res/values-cs/translations.xml b/features/lockscreen/impl/src/main/res/values-cs/translations.xml index fce1142f2c..f54d16f42b 100644 --- a/features/lockscreen/impl/src/main/res/values-cs/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-cs/translations.xml @@ -23,7 +23,7 @@ Vyberte si něco zapamatovatelného. Pokud tento kód PIN zapomenete, budete z a "Zadejte stejný PIN dvakrát" "PIN kódy se neshodují." "Abyste mohli pokračovat, budete se muset znovu přihlásit a vytvořit nový PIN" - "Jste odhlášeni" + "Toto zařízení se odstraňuje" "Máte %1$d pokus pro odemknutí" "Máte %1$d pokusy pro odemknutí" @@ -36,5 +36,5 @@ Vyberte si něco zapamatovatelného. Pokud tento kód PIN zapomenete, budete z a "Použijte biometrické údaje" "Použít PIN" - "Odhlašování…" + "Odebírání zařízení…" diff --git a/features/lockscreen/impl/src/main/res/values-hu/translations.xml b/features/lockscreen/impl/src/main/res/values-hu/translations.xml index 3a65239697..470324b2ba 100644 --- a/features/lockscreen/impl/src/main/res/values-hu/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-hu/translations.xml @@ -23,7 +23,7 @@ Válasszon valami megjegyezhetőt. Ha elfelejti a PIN-kódot, akkor ki lesz jele "Adja meg a PIN-kódját kétszer" "A PIN-kódok nem egyeznek" "A folytatáshoz újra be kell jelentkeznie, és létre kell hoznia egy új PIN-kódot" - "Kijelentkeztetésre kerül" + "Ez az eszköz eltávolításra kerül" "%1$d próbálkozása van a feloldáshoz" "%1$d próbálkozása van a feloldáshoz" @@ -34,5 +34,5 @@ Válasszon valami megjegyezhetőt. Ha elfelejti a PIN-kódot, akkor ki lesz jele "Biometrikus adatok használata" "PIN-kód használata" - "Kijelentkezés…" + "Eszköz eltávolítása…" diff --git a/features/lockscreen/impl/src/main/res/values-ru/translations.xml b/features/lockscreen/impl/src/main/res/values-ru/translations.xml index d0441fb253..cb71dfc88c 100644 --- a/features/lockscreen/impl/src/main/res/values-ru/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-ru/translations.xml @@ -36,5 +36,5 @@ "Использовать биометрию" "Использовать PIN-код" - "Выполняется выход…" + "Удаление устройства…" diff --git a/features/lockscreen/impl/src/main/res/values-sv/translations.xml b/features/lockscreen/impl/src/main/res/values-sv/translations.xml index a559e4c909..021fa67fb3 100644 --- a/features/lockscreen/impl/src/main/res/values-sv/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-sv/translations.xml @@ -34,5 +34,5 @@ Välj något minnesvärt. Om du glömmer den här PIN-koden loggas du ut från a "Använd biometri" "Använd PIN-kod" - "Loggar ut …" + "Tar bort enhet …" 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 35e82d5a58..f8f243f29d 100644 --- a/features/login/impl/src/main/res/values-lt/translations.xml +++ b/features/login/impl/src/main/res/values-lt/translations.xml @@ -4,17 +4,29 @@ "Pagrindinio serverio adresas" "Įveskite paieškos terminą arba domeno adresą." "Ieškokite bendrovės, bendruomenės arba privataus serverio." - "Rasti paskyros teikėją" + "Raskite paskyros teikėją" "Čia bus saugomi Jūsų pokalbiai - panašiai kaip el. pašto paslaugų teikėjas saugo Jūsų el. laiškus." "Ketinate prisijungti prie %s" "Čia bus saugomi Jūsų pokalbiai - panašiai kaip el. pašto paslaugų teikėjas saugo Jūsų el. laiškus." "Ketinate sukurti paskyrą teikėjoje %s" - "Kita" - "Naudokite skirtingą paskyros teikėją, pavyzdžiui, savo privatų serverį arba darbo paskyrą." + "Matrix.org – tai didelis nemokamas serveris viešajame „Matrix“ tinkle saugiam ir decentralizuotam bendravimui, kurį valdo „Matrix.org“ fondas." + "Kitas" + "Naudokite kitą paskyros teikėją, pavyzdžiui, savo privatų serverį arba darbo paskyrą." "Keisti paskyros teikėją" - "Nepavyko pasiekti šio serverio. Patikrinkite, ar teisingai įvedėte serverio URL. Jei URL yra teisingas, susisiekite su serverio administracija dėl tolimesnės pagalbos." - "Serverio URL" - "Koks yra Jūsų serverio adresas?" + "„Google Play“" + "„Element Pro“ programa privaloma teikėjoje %1$s. Atsisiųskite ją iš parduotuvės." + "„Element Pro“ privaloma" + "Nepavyko pasiekti šio pagrindinio serverio. Patikrinkite, ar teisingai įvedėte serverio URL. Jei URL yra teisingas, susisiekite su serverio administratoriumi dėl tolimesnės pagalbos." + "Serveris nepasiekiamas dėl problemos .labai-zinomame faile: +%1$s" + "Pasirinktas paskyros teikėjas nepalaiko slankiojo sinchronizavimo. Norint naudoti „%1$s“, reikia atnaujinti serverį." + "„%1$s“ neleidžiama prisijungti prie %2$s." + "Ši programa sukonfigūruota, kad leistų %1$s." + "Paskyros teikėjas %1$s neleidžiamas." + "Pagrindinio serverio URL" + "Įveskite domeno adresą." + "Koks yra jūsų serverio adresas?" + "Pasirinkite savo serverį" "Kurti paskyrą" "Ši paskyra buvo išjungta." "Neteisingas vartotojo vardas ir (arba) slaptažodis" @@ -31,7 +43,7 @@ "Kurti paskyrą" "Sveiki atvykę į sparčiausią „%1$s“ kada nors. Pagerintas spartai ir paprastumui." "Sveiki atvykę į „%1$s“. Pagerintas spartai ir paprastumui." - "Būkite savo elemente" + "Būkite savo stichijoje" "Keisti paskyros teikėją" "Privatus serveris “Element” darbuotojams." "Matrix yra atviras tinklas, skirtas saugiam, decentralizuotam bendravimui." diff --git a/features/logout/impl/src/main/res/values-cs/translations.xml b/features/logout/impl/src/main/res/values-cs/translations.xml index e2c2a68fd5..e19512c017 100644 --- a/features/logout/impl/src/main/res/values-cs/translations.xml +++ b/features/logout/impl/src/main/res/values-cs/translations.xml @@ -1,18 +1,18 @@ - "Opravdu se chcete odhlásit?" - "Odhlásit se" - "Odhlásit se" - "Odhlašování…" - "Chystáte se odhlásit z poslední relace. Pokud se nyní odhlásíte, ztratíte přístup ke svým šifrovaným zprávám." - "Vypnuli jste zálohování" - "Když jste přešli do režimu offline, vaše klíče se ještě stále zálohovaly. Znovu se připojte, aby bylo možné před odhlášením zálohovat vaše klíče." + "Opravdu chcete odstranit toto zařízení?" + "Odebrat toto zařízení" + "Odebrat toto zařízení" + "Odebírání zařízení…" + "Toto je vaše jediné zařízení. Pokud ho odstraníte, budete potřebovat klíč pro obnovení, abyste si při příštím přihlášení ověřili svou digitální identitu a obnovili šifrované chaty." + "Chystáte se ztratit přístup ke svým šifrovaným chatům" + "Vaše klíče se stále zálohovaly, když jste byli offline. Před odpojením tohoto zařízení se znovu připojte, aby se vaše klíče mohly zálohovat." "Vaše klíče jsou stále zálohovány" - "Před odhlášením prosím počkejte na dokončení." + "Před odstraněním tohoto zařízení počkejte, až se proces dokončí." "Vaše klíče jsou stále zálohovány" - "Odhlásit se" - "Chystáte se odhlásit z poslední relace. Pokud se nyní odhlásíte, ztratíte přístup ke svým šifrovaným zprávám." - "Obnovení není nastaveno" - "Chystáte se odhlásit z poslední relace. Pokud se nyní odhlásíte, můžete ztratit přístup k šifrovaným zprávám." - "Uložili jste si klíč pro obnovení?" + "Odebrat toto zařízení" + "Toto je vaše jediné zařízení. Pokud ho odstraníte, budete potřebovat klíč pro obnovení, abyste si při příštím přihlášení ověřili svou digitální identitu a obnovili šifrované chaty." + "Chystáte se ztratit přístup ke svým šifrovaným chatům" + "Toto je vaše jediné zařízení. Pokud ho odstraníte, budete potřebovat klíč pro obnovení, abyste si při příštím přihlášení ověřili svou digitální identitu a obnovili šifrované chaty." + "Před odebráním tohoto zařízení se ujistěte, že máte přístup ke klíči pro obnovení" diff --git a/features/logout/impl/src/main/res/values-hu/translations.xml b/features/logout/impl/src/main/res/values-hu/translations.xml index 2cf2b89e4a..e7eb8de99e 100644 --- a/features/logout/impl/src/main/res/values-hu/translations.xml +++ b/features/logout/impl/src/main/res/values-hu/translations.xml @@ -1,18 +1,18 @@ - "Biztos, hogy kijelentkezik?" - "Kijelentkezés" - "Kijelentkezés" - "Kijelentkezés…" - "Arra készül, hogy kijelentkezzen az utolsó munkamenetéből is. Ha most kijelentkezik, akkor elveszti a hozzáférését a titkosított üzeneteihez." - "Kikapcsolta a biztonsági mentést" - "A kulcsai mentése során bontotta a kapcsolatot. Kapcsolódjon újra, hogy a kulcsai továbbra is mentésre kerüljenek mielőtt kijelentkezik." + "Biztosan eltávolítja ezt az eszközt?" + "Eszköz eltávolítása" + "Eszköz eltávolítása" + "Eszköz eltávolítása…" + "Ez az egyetlen eszköze. Ha eltávolítja, a következő bejelentkezéskor szüksége lesz egy helyreállítási kulcsra a digitális személyazonossága megerősítéséhez és a titkosított csevegések helyreállításához." + "Hamarosan elveszíti a hozzáférését a titkosított csevegéseihez" + "A kulcsok biztonsági mentése még folyamatban volt, amikor megszűnt a hálózati kapcsolat. Csatlakozzon újra, hogy a kulcsok biztonsági mentése megtörténhessen, mielőtt eltávolítja ezt az eszközt." "A kulcsai mentése még folyamatban van" - "Kijelentkezés előtt várja meg a befejezését." + "Várja meg, amíg ez befejeződik, mielőtt eltávolítja ezt az eszközt." "A kulcsai mentése még folyamatban van" - "Kijelentkezés" - "Arra készül, hogy kijelentkezzen az utolsó munkamenetéből is. Ha most kijelentkezik, akkor elveszti a hozzáférését a titkosított üzeneteihez." - "A helyreállítás nincs beállítva" - "Arra készül, hogy kijelentkezzen az utolsó munkamenetéből is. Ha most kijelentkezik, akkor elveszítheti a hozzáférését a titkosított üzeneteihez." - "Mentette a helyreállítási kulcsát?" + "Eszköz eltávolítása" + "Ez az egyetlen eszköze. Ha eltávolítja, a következő bejelentkezéskor szüksége lesz egy helyreállítási kulcsra a digitális személyazonossága megerősítéséhez és a titkosított csevegések helyreállításához." + "Hamarosan elveszíti a hozzáférését a titkosított csevegéseihez" + "Ez az egyetlen eszköze. Ha eltávolítja, a következő bejelentkezéskor szüksége lesz egy helyreállítási kulcsra a digitális személyazonossága megerősítéséhez és a titkosított csevegések helyreállításához." + "Az eszköz eltávolítása előtt győződjön meg arról, hogy hozzáfér a helyreállítási kulcshoz" diff --git a/features/logout/impl/src/main/res/values-ru/translations.xml b/features/logout/impl/src/main/res/values-ru/translations.xml index f7ed9216c0..efb0d3d645 100644 --- a/features/logout/impl/src/main/res/values-ru/translations.xml +++ b/features/logout/impl/src/main/res/values-ru/translations.xml @@ -3,7 +3,7 @@ "Вы уверены, что вы хотите выйти?" "Удалить это устройство" "Удалить это устройство" - "Выполняется выход…" + "Удаление устройства…" "Вы собираетесь выйти из последнего сеанса. Если вы выйдете из системы сейчас, вы потеряете доступ к зашифрованным сообщениям." "Вы отключили резервное копирование" "Когда вы перешли в автономный режим, резервное копирование ваших ключей продолжалось. Повторно подключитесь, чтобы перед выходом из системы можно было создать резервную копию ключей." diff --git a/features/logout/impl/src/main/res/values-sv/translations.xml b/features/logout/impl/src/main/res/values-sv/translations.xml index fdf0e5102e..c35a0455f9 100644 --- a/features/logout/impl/src/main/res/values-sv/translations.xml +++ b/features/logout/impl/src/main/res/values-sv/translations.xml @@ -1,16 +1,16 @@ - "Är du säker på att du vill logga ut?" - "Logga ut" - "Logga ut" - "Loggar ut …" + "Är du säker på att du vill ta bort den här enheten?" + "Ta bort den här enheten" + "Ta bort den här enheten" + "Tar bort enhet …" "Du är på väg att logga ut ur din senaste session. Om du loggar ut nu kommer du att förlora åtkomsten till dina krypterade meddelanden." "Du har stängt av säkerhetskopiering" "Dina nycklar säkerhetskopierades fortfarande när du gick offline. Anslut igen så att dina nycklar kan säkerhetskopieras innan du loggar ut." "Dina nycklar säkerhetskopieras fortfarande" "Vänta tills detta är klart innan du loggar ut." "Dina nycklar säkerhetskopieras fortfarande" - "Logga ut" + "Ta bort den här enheten" "Du är på väg att logga ut ur din sista session. Om du loggar ut nu förlorar du åtkomsten till dina krypterade meddelanden." "Återställning inte inställd" "Du är på väg att logga ut från din senaste session. Om du loggar ut nu kan du förlora åtkomsten till dina krypterade meddelanden." diff --git a/features/messages/impl/src/main/res/values-sv/translations.xml b/features/messages/impl/src/main/res/values-sv/translations.xml index 21d2cd5fe2..2e10fd3166 100644 --- a/features/messages/impl/src/main/res/values-sv/translations.xml +++ b/features/messages/impl/src/main/res/values-sv/translations.xml @@ -33,7 +33,7 @@ "Spela in video" "Bilaga" "Foto- och videobibliotek" - "Plats" + "Dela plats" "Omröstning" "Textformatering" "Meddelandehistoriken är för närvarande otillgänglig." diff --git a/features/rageshake/api/src/main/res/values-lt/translations.xml b/features/rageshake/api/src/main/res/values-lt/translations.xml index 49762d57ca..88c49aca3c 100644 --- a/features/rageshake/api/src/main/res/values-lt/translations.xml +++ b/features/rageshake/api/src/main/res/values-lt/translations.xml @@ -2,6 +2,6 @@ "%1$s nulūžo paskutinį kartą, kai buvo naudojama. Ar norėtumėte su mumis pasidalyti strigčių ataskaita?" "Atrodo, kad nusivylęs purtote telefoną. Ar norėtumėte atidaryti pranešimo apie klaidas ekraną?" - "Rageshake" + "Gerai pakratyti" "Aptikimo riba" diff --git a/features/rageshake/impl/src/main/res/values-lt/translations.xml b/features/rageshake/impl/src/main/res/values-lt/translations.xml index c45c982ba5..cc79a5055e 100644 --- a/features/rageshake/impl/src/main/res/values-lt/translations.xml +++ b/features/rageshake/impl/src/main/res/values-lt/translations.xml @@ -10,6 +10,6 @@ "Siųsti gedimų žurnalus" "Leisti žurnalus" "Siųsti ekrano nuotrauką" - "Prie žinutės bus pridėti žurnalai, kad įsitikintumėme, jog viskas veikia tinkamai. Jei norite išsiųsti savo žinutę be žurnalų, išjunkite šį nustatymą." + "Žurnalai bus įtraukti į jūsų žinutę, kad būtų užtikrinta, jog viskas veikia tinkamai. Kad išsiųstumėte žinutę be žurnalų, išjunkite šį nustatymą." "%1$s nulūžo paskutinį kartą, kai buvo naudojama. Ar norėtumėte su mumis pasidalyti strigčių ataskaita?" diff --git a/features/securebackup/impl/src/main/res/values-cs/translations.xml b/features/securebackup/impl/src/main/res/values-cs/translations.xml index 3669da34ee..171900cede 100644 --- a/features/securebackup/impl/src/main/res/values-cs/translations.xml +++ b/features/securebackup/impl/src/main/res/values-cs/translations.xml @@ -2,16 +2,17 @@ "Vypnout zálohování" "Zapnout zálohování" - "Bezpečně uložte svou kryptografickou identitu a klíče zpráv na serveru. To vám umožní zobrazit historii zpráv na všech nových zařízeních. %1$s." + "To vám umožní zobrazit historii chatu na všech nových zařízeních a je to nutné pro zálohování chatů a digitální identity. %1$s ." "Úložiště klíčů" - "Pro nastavení obnovení musí být zapnuto úložiště klíčů." + "Pro zálohování chatů musí být zapnuto ukládání klíčů." "Nahrát klíče z tohoto zařízení" "Povolit ukládání klíčů" "Změnit klíč pro obnovení" - "Obnovte svou kryptografickou identitu a historii zpráv pomocí klíče pro obnovení, pokud jste ztratili všechna stávající zařízení." + "Vaše chaty jsou automaticky zálohovány pomocí koncového šifrování. Chcete-li tuto zálohu obnovit a zachovat si svou digitální identitu v případě, že ztratíte přístup ke všem svým zařízením, budete potřebovat svůj klíč pro obnovení." "Zadejte klíč pro obnovení" "Vaše úložiště klíčů je momentálně nesynchronizované." - "Nastavení obnovy" + "Získat klíč pro obnovení" + "Vaše chaty jsou automaticky zálohovány pomocí koncového šifrování. Chcete-li tuto zálohu obnovit a zachovat si svou digitální identitu v případě, že ztratíte přístup ke všem svým zařízením, budete potřebovat svůj klíč pro obnovení." "Otevřít %1$s na stolním počítači" "Znovu se přihlaste ke svému účtu" "Když budete vyzváni k ověření vašeho zařízení, vyberte %1$s" @@ -23,12 +24,12 @@ "Podrobnosti o vašem účtu, kontaktech, preferencích a seznamu chatu budou zachovány" "Ztratíte svou stávající historii zpráv" "Budete muset znovu ověřit všechna stávající zařízení a kontakty" - "Obnovte svou identitu pouze v případě, že nemáte přístup k jinému přihlášenému zařízení a ztratili jste klíč pro obnovení." - "Obnovte svou identitu v případě, že nemůžete potvrdit jiným způsobem" - "Vypnout" - "Pokud se odhlásíte ze všech zařízení, přijdete o zašifrované zprávy." - "Opravdu chcete vypnout zálohování?" - "Vypnutím zálohování odstraníte zálohu aktuálního šifrovacího klíče a vypnete další bezpečnostní funkce. V tomto případě budete:" + "Digitální identitu resetujte pouze v případě, že nemáte přístup k jinému ověřenému zařízení a nemáte klíč pro obnovení." + "Nelze potvrdit? Budete muset resetovat svou digitální identitu." + "Smazat" + "Pokud odeberete všechna zařízení, ztratíte svou šifrovanou historii chatu a budete muset resetovat svou digitální identitu." + "Opravdu chcete smazat úložiště klíčů?" + "Smazáním úložiště klíčů odstraníte ze serveru klíče digitální identity a zpráv a vypnete následující bezpečnostní funkce:" "Nemít v nových zařízeních šifrovanou historii zpráv" "Ztratíte přístup k šifrovaným zprávám, pokud jste všude odhlášeni z %1$s" "Opravdu chcete vypnout zálohování?" @@ -58,12 +59,12 @@ "Vygenerovat klíč pro obnovení" "Toto s nikým nesdílejte!" "Nastavení obnovení bylo úspěšné" - "Nastavení obnovy" + "Získat klíč pro obnovení" "Ano, resetovat nyní" "Tento proces je nevratný." - "Opravdu chcete obnovit svou identitu?" + "Opravdu chcete resetovat svou digitální identitu?" "Došlo k neznámé chybě. Zkontrolujte, zda je heslo k účtu správné a zkuste to znovu." "Zadejte…" - "Potvrďte, že chcete obnovit svou identitu." + "Potvrďte, že chcete resetovat svou digitální identitu." "Pro pokračování zadejte heslo k účtu" diff --git a/features/securebackup/impl/src/main/res/values-fi/translations.xml b/features/securebackup/impl/src/main/res/values-fi/translations.xml index f7d09bb6ca..7cbe0f1af6 100644 --- a/features/securebackup/impl/src/main/res/values-fi/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fi/translations.xml @@ -12,6 +12,7 @@ "Anna palautusavain" "Avainten säilytys ei ole tällä hetkellä synkronoitu." "Hanki palautusavain" + "Keskustelusi varmuuskopioidaan automaattisesti päästä päähän -salauksella. Jotta voit palauttaa tämän varmuuskopion ja säilyttää digitaalisen identiteettisi, kun menetät pääsyn kaikkiin laitteisiisi, tarvitset palautusavaimesi." "Avaa %1$s tietokoneella" "Kirjaudu tilillesi uudelleen" "Kun sinua pyydetään vahvistamaan laitteesi, valitse %1$s" diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml index cf7ab1cb0c..a5d910e76b 100644 --- a/features/securebackup/impl/src/main/res/values-hu/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml @@ -12,6 +12,7 @@ "Adja meg a helyreállítási kulcsot" "A kulcstároló jelenleg nincs szinkronizálva." "Helyreállítási kulcs beszerzése" + "A csevegésekről automatikusan készül biztonsági mentés végpontok közötti titkosítással. A biztonsági mentés helyreállításához és digitális személyazonossága megőrzéséhez szüksége lesz a helyreállítási kulcsára, ha elveszíti a hozzáférést az összes eszközéhez." "Nyissa meg az %1$set egy asztali eszközön" "Jelentkezzen be újra a fiókjába" "Amikor az eszköz ellenőrzését kéri, válassza ezt a lehetőséget: %1$s" @@ -23,11 +24,11 @@ "A fiókadatok, a kapcsolatok, a beállítások és a csevegéslista megmarad" "Elveszíti meglévő üzenetelőzményeit" "Újból ellenőriznie kell az összes meglévő eszközét és csevegőpartnerét" - "Csak akkor állítsa alaphelyzetbe a személyazonosságát, ha nem fér hozzá másik bejelentkezett eszközhöz, és elvesztette a helyreállítási kulcsot." + "Csak akkor állítsa alaphelyzetbe a személyazonosságát, ha nem fér hozzá más bejelentkezett eszközhöz, és elveszítette a helyreállítási kulcsát." "Nem tudja megerősíteni? Alaphelyzetbe kell állítania a digitális személyazonosságát." - "Kikapcsolás" - "Ha kijelentkezik az összes eszközéről, akkor elveszti a titkosított üzeneteit." - "Biztos, hogy kikapcsolja a biztonsági mentéseket?" + "Törlés" + "Ha eltávolítja az összes eszközét, elveszíti titkosított csevegési előzményeit, és újra be kell állítania digitális személyazonosságát." + "Biztosan törölni szeretné a kulcstárolót?" "A kulcstároló törlése eltávolítja a digitális személyazonosságát és az üzenetkulcsait a kiszolgálóról, és kikapcsolja a következő biztonsági funkciókat:" "Nem lesznek meg a titkosított üzenetek előzményei az új eszközein" "Elveszti a hozzáférését a titkosított üzeneteihez, ha mindenhol kilép az %1$sből" diff --git a/features/securebackup/impl/src/main/res/values-ko/translations.xml b/features/securebackup/impl/src/main/res/values-ko/translations.xml index d2aec9c27d..182ae8d59a 100644 --- a/features/securebackup/impl/src/main/res/values-ko/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ko/translations.xml @@ -4,14 +4,15 @@ "백업 활성화" "이 설정을 통해 새로운 기기에서도 대화 기록을 확인할 수 있으며, 대화 및 디지털 신원 백업을 위해 반드시 필요합니다. %1$s." "키 저장소" - "복구 설정을 하려면 키 저장을 켜야 합니다." + "대화 내용을 백업하려면 키 저장소를 켜야 합니다." "이 장치에서 키 업로드" "키 저장 허용" "복구 키 변경" - "기존의 모든 기기를 분실한 경우, 복구 키를 사용하여 암호화 ID와 메시지 기록을 복구할 수 있습니다." + "대화 내용은 종단간 암호화 기술로 자동 백업됩니다. 모든 기기를 사용할 수 없는 상황에서 백업을 복구하고 디지털 신원을 유지하려면 복구 키가 반드시 필요합니다." "복구 키를 입력하세요" "현재 키 저장소가 동기화되지 않았습니다." "복구 키 가져오기" + "대화 내용은 종단간 암호화로 자동 백업됩니다. 모든 기기를 사용할 수 없는 상황에서 백업을 복구하고 디지털 신원을 유지하려면 복구 키가 반드시 필요합니다." "데스크톱 장치에서 %1$s 을 엽니다." "계정에 다시 로그인하세요" "장치를 확인하라는 메시지가 표시되면, %1$s 을 선택하세요" 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 35da59cdb9..bcc44c29ae 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -28,7 +28,7 @@ "Не можете подтвердить? Вам потребуется сбросить личность вашей учетной записи." "Удалить" "Вы потеряете зашифрованные сообщения, если выйдете из всех устройств." - "Вы действительно хотите отключить резервное копирование?" + "Вы уверены, что хотите удалить хранилище ключей?" "Удаление хранилища ключей приведёт к удалению вашей криптографической личности и ключей сообщений с сервера, а также отключению следующих функций безопасности:" "Нет зашифрованной истории сообщений на новых устройствах" "Вы потеряете доступ к зашифрованным сообщениям, если выйдете из %1$s везде" diff --git a/features/space/impl/src/main/res/values-sv/translations.xml b/features/space/impl/src/main/res/values-sv/translations.xml index 794d7db626..f4427c384d 100644 --- a/features/space/impl/src/main/res/values-sv/translations.xml +++ b/features/space/impl/src/main/res/values-sv/translations.xml @@ -1,6 +1,7 @@ "Välj ägare" + "Välj de rum du vill lämna och som du inte är ensam administratör för:" "Lämna %1$s?" "Lämna utrymmet" "Roller och behörigheter" diff --git a/features/verifysession/impl/src/main/res/values-cs/translations.xml b/features/verifysession/impl/src/main/res/values-cs/translations.xml index 5d0b28bc0a..3c3e68e1f0 100644 --- a/features/verifysession/impl/src/main/res/values-cs/translations.xml +++ b/features/verifysession/impl/src/main/res/values-cs/translations.xml @@ -2,8 +2,8 @@ "Nemůžete potvrdit?" "Vytvoření nového klíče pro obnovení" - "Ověřte toto zařízení a nastavte zabezpečené zasílání zpráv." - "Potvrďte, že jste to vy" + "Vyberte způsob ověření pro nastavení zabezpečeného zasílání zpráv." + "Potvrďte svou digitální identitu" "Použít jiné zařízení" "Použít klíč pro obnovení" "Nyní můžete bezpečně číst nebo odesílat zprávy, a kdokoli, s kým chatujete, může tomuto zařízení důvěřovat." @@ -17,7 +17,7 @@ "Potvrďte, že níže uvedená čísla odpovídají číslům zobrazeným na vaší druhé relaci." "Porovnejte čísla" "Nyní můžete bezpečně číst nebo odesílat zprávy na svém druhém zařízení." - "Nyní můžete důvěřovat identitě tohoto uživatele při odesílání nebo přijímání zpráv." + "Nyní můžete při odesílání nebo přijímání zpráv důvěřovat digitální identitě tohoto uživatele." "Zařízení ověřeno" "Zadejte klíč pro obnovení" "Buď vypršel časový limit požadavku, požadavek byl zamítnut, nebo došlo k nesouladu ověření." @@ -42,7 +42,7 @@ "Otevřete aplikaci na jiném ověřeném zařízení" "Pro větší bezpečnost ověřte tohoto uživatele porovnáním sady emotikonů na svých zařízeních. Proveďte to pomocí důvěryhodného způsobu komunikace." "Ověřte tohoto uživatele?" - "Pro větší bezpečnost chce jiný uživatel ověřit vaši identitu. Zobrazí se vám sada emotikonů k porovnání." + "Z důvodu zvýšené bezpečnosti chce jiný uživatel ověřit vaši digitální identitu. Zobrazí se vám sada emodži, které je třeba porovnat." "Na druhém zařízení byste měli vidět vyskakovací okno. Začněte s ověrením tam." "Spusťte ověření na druhém zařízení" "Spusťte ověření na druhém zařízení" @@ -50,5 +50,5 @@ "Po přijetí budete moci pokračovat v ověřování." "Pro pokračování přijměte požadavek na zahájení ověření v jiné relaci." "Čekání na přijetí žádosti" - "Odhlašování…" + "Odebírání zařízení…" diff --git a/features/verifysession/impl/src/main/res/values-hu/translations.xml b/features/verifysession/impl/src/main/res/values-hu/translations.xml index b7617168ee..666ff26af1 100644 --- a/features/verifysession/impl/src/main/res/values-hu/translations.xml +++ b/features/verifysession/impl/src/main/res/values-hu/translations.xml @@ -50,5 +50,5 @@ "Az elfogadása után folytathatja az ellenőrzést." "A folytatáshoz fogadja el az ellenőrzési folyamat indítási kérését a másik munkamenetében." "Várakozás a kérés elfogadására" - "Kijelentkezés…" + "Eszköz eltávolítása…" diff --git a/features/verifysession/impl/src/main/res/values-ko/translations.xml b/features/verifysession/impl/src/main/res/values-ko/translations.xml index 262a4d3052..493ac0d685 100644 --- a/features/verifysession/impl/src/main/res/values-ko/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ko/translations.xml @@ -17,7 +17,7 @@ "아래 숫자가 다른 세션에 표시된 숫자와 일치하는지 확인하세요." "숫자 비교" "이제 다른 기기에서도 안전하게 메시지를 읽거나 보낼 수 있습니다." - "이제 메시지를 보내거나 받을 때 이 사용자의 신원을 신뢰할 수 있습니다." + "이제 메시지를 주고받을 때 이 사용자의 디지털 신원을 신뢰할 수 있습니다." "기기 검증됨" "복구 키를 입력하세요" "요청이 시간 초과되었거나, 요청이 거부되었거나, 검증 불일치가 발생했습니다." @@ -42,7 +42,7 @@ "다른 검증된 장치에서 앱을 실행하세요" "보안을 강화하려면, 기기에 표시된 이모티콘을 비교하여 이 사용자를 확인하세요. 신뢰할 수 있는 통신 수단을 사용하여 확인하시기 바랍니다." "이 사용자를 검증하시겠습니까?" - "추가 보안 위해 다른 사용자가 귀하의 신원을 확인하고자 합니다. 비교할 이모티콘 세트가 표시됩니다." + "보안 강화를 위해 상대방이 귀하의 디지털 신원을 확인하려고 합니다. 화면에 표시되는 이모지 세트가 서로 일치하는지 비교해 주세요." "다른 기기에 팝업이 표시될 것입니다. 지금 그곳에서 확인을 시작하세요." "다른 장치에서 검증 시작" "다른 장치에서 검증 시작" diff --git a/features/verifysession/impl/src/main/res/values-ru/translations.xml b/features/verifysession/impl/src/main/res/values-ru/translations.xml index 8672229640..53d4196d9d 100644 --- a/features/verifysession/impl/src/main/res/values-ru/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ru/translations.xml @@ -50,5 +50,5 @@ "После принятия запроса вы сможете продолжить проверку." "Чтобы продолжить, примите запрос на запуск процесса подтверждения в другом сеансе." "Ожидание принятия запроса" - "Выполняется выход…" + "Удаление устройства…" diff --git a/features/verifysession/impl/src/main/res/values-sv/translations.xml b/features/verifysession/impl/src/main/res/values-sv/translations.xml index 100f4964da..9f4008d0a4 100644 --- a/features/verifysession/impl/src/main/res/values-sv/translations.xml +++ b/features/verifysession/impl/src/main/res/values-sv/translations.xml @@ -50,5 +50,5 @@ "När det har accepterats kommer du kunna fortsätta verifieringen." "Godkänn begäran om att starta verifieringsprocessen på din andra session för att fortsätta." "Väntar på att acceptera begäran" - "Loggar ut …" + "Tar bort enhet …" diff --git a/libraries/eventformatter/impl/src/main/res/values-lt/translations.xml b/libraries/eventformatter/impl/src/main/res/values-lt/translations.xml index 9fb1486d59..9a632b8f5a 100644 --- a/libraries/eventformatter/impl/src/main/res/values-lt/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-lt/translations.xml @@ -1,13 +1,13 @@ "(taip pat buvo pakeistas ir avataras)" - "%1$s pakeitė savo avatarą" - "Jūs pakeitėte savo avatarą" + "%1$s pakeitė savo pseudoportretą" + "Jūs pakeitėte savo pseudoportretą" "%1$s pakeitė savo slapyvardį iš %2$s į %3$s" "Jūs pakeitėte savo slapyvardį iš %1$s į %2$s" "%1$s pašalino savo slapyvardį (jis buvo %2$s)" "Jūs pašalinote savo slapyvardį (jis buvo %1$s)" - "%1$s pakeitė savo slapyvardį į %2$s" + "%1$s nustatė savo rodomą vardą į %2$s" "Jūs nustatėte savo slapyvardį į %1$s" "%1$s pakeitė kambario avatarą" "Jūs pakeitėte kambario avatarą" @@ -21,7 +21,7 @@ "%1$s priėmė kvietimą" "Priėmėte kvietimą" "Jūs pakvietėte %1$s" - "%1$s pakvietė Jus" + "%1$s pakvietė jus" "%1$s prisijungė prie kambario" "Jūs prisijungėte prie kambario" "%1$s prašo prisijungti" diff --git a/libraries/push/impl/src/main/res/values-ko/translations.xml b/libraries/push/impl/src/main/res/values-ko/translations.xml index 3aa015392f..f4399cda2b 100644 --- a/libraries/push/impl/src/main/res/values-ko/translations.xml +++ b/libraries/push/impl/src/main/res/values-ko/translations.xml @@ -16,6 +16,7 @@ "%d개의 새 메시지가 있습니다." + "📞 수신 전화" "📹 수신 전화" "** 전송 실패 - 방을 열여주세요" "참가하기" diff --git a/libraries/troubleshoot/impl/src/main/res/values-lt/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-lt/translations.xml new file mode 100644 index 0000000000..2befbbf398 --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-lt/translations.xml @@ -0,0 +1,5 @@ + + + "Vykdyti testus" + "Vykdyti testus dar kartą" + 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 f343571f1e..38d9ac3d8e 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -122,6 +122,7 @@ "Opustit prostor" "Načíst více" "Spravovat účet" + "Správa účtu a zařízení" "Spravovat zařízení" "Spravovat místnosti" "Zpráva" @@ -164,14 +165,15 @@ "Sdílet aktuální polohu" "Zobrazit" "Přihlásit se znovu" - "Odhlásit se" - "Přesto se odhlásit" + "Odebrat toto zařízení" + "Přesto toto zařízení odebrat" "Přeskočit" "Začít" "Zahájit chat" "Začít znovu" "Zahájit ověření" "Klepnutím načtete mapu" + "Zastavit" "Vyfotit" "Klepnutím zobrazíte možnosti" "Přeložit" @@ -192,6 +194,7 @@ "Pokročilá nastavení" "obrázek" "Analytika" + "Synchronizace oznámení…" "Opustili jste místnost" "Byli jste odhlášeni z relace" "Vzhled" @@ -225,6 +228,7 @@ "Prázdný soubor" "Šifrování" "Šifrování povoleno" + "Končí v %1$s" "Zadejte svůj PIN" "Chyba" "Došlo k chybě, nemusíte dostávat oznámení o nových zprávách. Vyřešte prosím problémy s oznámeními z nastavení. @@ -251,6 +255,8 @@ Důvod: %1$s." "Řádek zkopírován do schránky" "Odkaz zkopírován do schránky" "Připojit nové zařízení" + "Aktuální poloha" + "Sdílení aktuální polohy skončilo" "Načítání…" "Načítání dalších…" @@ -351,9 +357,10 @@ Důvod: %1$s." "Nastavení" "Sdílet prostor" "Noví členové vidí historii" + "Sdílená aktuální poloha" "Sdílená poloha" "Sdílený prostor" - "Odhlašování" + "Odebrání zařízení" "Něco se nepovedlo" "Narazili jsme na problém. Zkuste to prosím znovu." "Prostor" @@ -374,12 +381,13 @@ Důvod: %1$s." "Text" "Oznámení třetích stran" "Vlákno" + "Vlákna" "Téma" "O čem je tato místnost?" "Nelze dešifrovat" "Šifrováno nezabezpečeným zařízením" "Nemáte přístup k této zprávě" - "Ověřená identita odesílatele se změnila" + "Ověřená digitální identita odesílatele byla resetována" "Pozvánky nebylo možné odeslat jednomu nebo více uživatelům." "Nelze odeslat pozvánky" "Odemknout" @@ -404,16 +412,17 @@ Důvod: %1$s." "Hlasová zpráva" "Čekání…" "Čekání na dešifrovací klíč" + "Čekání na aktuální polohu…" "Kdokoli může vidět historii" "Vy" "%1$s (%2$s) sdílel(a) tuto zprávu v době, kdy jste nebyli v místnosti." "%1$s sdílel(a) tuto zprávu v době, kdy jste nebyli v místnosti." "Tato místnost byla nastavena tak, aby noví členové mohli číst historii. %1$s" - "Identita uživatele %1$s se změnila. %2$s" - "Identita uživatele %1$s %2$s se změnila. %3$s" + "Identita uživatele %1$s byla resetována. %2$s" + "Identita uživatele %1$s %2$s byla resetována. %3$s" "(%1$s)" - "Identita uživatele %1$s se změnila." - "Identita uživatele %1$s %2$s se změnila. %3$s" + "Identita uživatele %1$s byla resetována." + "Identita uživatele %1$s %2$s byla resetována. %3$s" "Zrušit ověření" "Povolit přístup" "Odkaz %1$s vás přesměruje na jinou stránku %2$s @@ -445,6 +454,7 @@ Opravdu chcete pokračovat?" "%1$s nemá přístup k vaší poloze. Zkuste to prosím později." "Nepodařilo se nahrát hlasovou zprávu." "Místnost již neexistuje nebo pozvánka již není platná." + "Pro přístup k funkcím založeným na poloze prosím povolte GPS." "Zpráva nebyla nalezena" "%1$s nemá oprávnění k přístupu k vaší poloze. Přístup můžete povolit v Nastavení." "%1$s nemá oprávnění k přístupu k vaší poloze. Povolit přístup níže." @@ -473,11 +483,11 @@ Opravdu chcete pokračovat?" "%1$d Připnutých zpráv" "Připnuté zprávy" - "Chystáte se přejít na svůj %1$s účet a obnovit svou identitu. Poté budete přesměrováni zpět do aplikace." - "Nemůžete to potvrdit? Přejděte na svůj účet a resetujte svou identitu." + "Chystáte se přejít na svůj účet %1$s, abyste resetovali svou digitální identitu. Poté budete přesměrováni zpět do aplikace." + "Nemůžete to potvrdit? Přejděte do svého účtu a resetujte svou digitální identitu." "Zrušit ověření a odeslat" "Ověření můžete zrušit a přesto odeslat tuto zprávu, nebo můžete prozatím zrušit a zkusit to znovu později po opětovném ověření %1$s." - "Vaše zpráva nebyla odeslána, protože ověřená identita uživatele %1$s se změnila" + "Vaše zpráva nebyla odeslána, protože byla resetována ověřená digitální identita %1$s" "Přesto odeslat zprávu" "%1$s používá jedno nebo více neověřených zařízení. Zprávu můžete přesto odeslat, nebo můžete prozatím zrušit a zkusit to znovu později poté, co %2$s ověří všechna svá zařízení." "Vaše zpráva nebyla odeslána, protože%1$s neověřil(a) všechna zařízení" @@ -509,7 +519,7 @@ Opravdu chcete pokračovat?" "Prostory" "Sdíleno %1$s" "Na mapě" - "Zpráva nebyla odeslána, protože ověřená identita uživatele %1$s se změnila." + "Zpráva nebyla odeslána, protože byla resetována ověřená digitální identita %1$s." "Zpráva nebyla odeslána, protože%1$s neověřil(a) všechna zařízení." "Zpráva nebyla odeslána, protože jste neověřili jedno nebo více zařízení." "Poloha" @@ -519,5 +529,5 @@ Opravdu chcete pokračovat?" "Pro přístup k historickým zprávám musíte toto zařízení ověřit" "Nemáte přístup k této zprávě" "Nelze dešifrovat zprávu" - "Tato zpráva byla zablokována buď proto, že jste neověřili své zařízení, nebo proto, že odesílatel potřebuje ověřit vaši identitu." + "Tato zpráva byla zablokována buď proto, že jste neověřili své zařízení, nebo proto, že odesílatel musí ověřit vaši digitální identitu." 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 182f403140..7be84a8716 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -374,6 +374,7 @@ Syy: %1$s." "Teksti" "Kolmannen osapuolen ilmoitukset" "Viestiketju" + "Viestiketjut" "Aihe" "Mistä tässä huoneessa on kyse?" "Salauksen purkaminen ei onnistunut" @@ -466,6 +467,12 @@ Haluatko varmasti jatkaa?" "Poista %1$s" "Asetukset" "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." 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 1dad21ff65..bec6d7f4ca 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -374,6 +374,7 @@ Raison : %1$s." "Texte" "Avis de tiers" "Fil de discussion" + "Fils de discussion" "Sujet" "De quoi s’agit-il dans ce salon ?" "Échec de déchiffrement" @@ -466,6 +467,13 @@ Raison : %1$s." "Supprimer %1$s" "Paramètres" "É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é" 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 bc4535dda1..9586b392e9 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -120,6 +120,7 @@ "Tér elhagyása" "Továbbiak betöltése" "Fiók kezelése" + "Fiók és eszközök kezelése" "Eszközök kezelése" "Szobák kezelése" "Üzenet" @@ -162,14 +163,15 @@ "Valós idejű hely megosztása" "Megjelenítés" "Jelentkezzen be újra" - "Kijelentkezés" - "Kijelentkezés mindenképp" + "Eszköz eltávolítása" + "Eszköz eltávolítása mindenképpen" "Kihagyás" "Indítás" "Csevegés indítása" "Újrakezdés" "Ellenőrzés elindítása" "Koppintson a térkép betöltéséhez" + "Leállítás" "Fénykép készítése" "Koppintson a beállításokért" "Fordítás" @@ -190,6 +192,7 @@ "Speciális beállítások" "egy kép" "Elemzések" + "Értesítések szinkronizálása…" "Elhagyta a szobát" "Ki lett jelentkeztetve a munkamenetből" "Megjelenítés" @@ -223,6 +226,7 @@ "Üres fájl" "Titkosítás" "Titkosítás engedélyezve" + "Vége: %1$s" "Adja meg a PIN-kódját" "Hiba" "Hiba történt, előfordulhat, hogy nem kap értesítést az új üzenetekről. Az értesítések hibaelhárítása a beállításokban található. @@ -249,6 +253,8 @@ Ok: %1$s." "A sor a vágólapra másolva" "Hivatkozás a vágólapra másolva" "Új eszköz összekapcsolása" + "Élő helymeghatározás" + "Élő pozíciómegosztás befejezve" "Betöltés…" "Továbbiak betöltése…" @@ -344,9 +350,10 @@ Ok: %1$s." "Beállítások" "Tér megosztása" "Az új tagok látják az előzményeket" + "Megosztott élő helymeghatározás" "Megosztott tartózkodási hely" "Megosztott tér" - "Kijelentkezés" + "Eszköz eltávolítása" "Valamilyen hiba történt" "Problémába ütköztünk. Próbálja újra." "Tér" @@ -366,6 +373,7 @@ Ok: %1$s." "Szöveg" "Harmadik felek nyilatkozatai" "Üzenetszál" + "Üzenetszálak" "Téma" "Miről szól ez a szoba?" "Nem lehet visszafejteni" @@ -396,6 +404,7 @@ Ok: %1$s." "Hangüzenet" "Várakozás…" "Várakozás erre az üzenetre" + "Várakozás az élő helymeghatározásra…" "Bárki láthatja az előzményeket" "Ön" "%1$s (%2$s) megosztotta ezt az üzenetet, mivel Ön nem volt a szobában, amikor elküldték." @@ -457,6 +466,13 @@ Biztos, hogy folytatja?" "Eltávolítás: %1$s" "Beállítások" "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" 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 a9d560b852..4174e4d15d 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -26,6 +26,7 @@ "일시중지" "음성 메시지, 지속 시간: %1$s, 현재 위치: %2$s" "PIN 필드" + "고정된 위치" "재생" "재생 속도" "투표" @@ -43,9 +44,11 @@ "%1$s 반응을 제거하세요" "방 아바타" "파일 보내기" + "발신자 위치" "제한 시간 내 인증이 필요합니다.1분 안에 확인해 주세요." "비밀번호 표시" "통화 시작" + "음성 통화 시작" "묘비 방" "사용자 아바타" "사용자 메뉴" @@ -115,6 +118,7 @@ "스페이스 떠나기" "더 불러오기" "계정 관리" + "계정 및 기기 관리" "기기 관리" "방 관리" "메시지" @@ -165,6 +169,7 @@ "다시 시작하다" "인증 시작" "탭해서 지도 불러오기" + "중지" "사진 찍기" "옵션을 보려면 탭하세요" "번역" @@ -185,6 +190,7 @@ "고급 설정" "이미지" "통계" + "알림 동기화 중…" "방을 떠남" "세션에서 로그아웃되었습니다." "외관" @@ -218,6 +224,7 @@ "빈 파일" "암호화" "암호화 활성화됨" + "%1$s에 종료" "PIN을 입력하세요" "오류" "오류가 발생했습니다, 새 메시지 알림을 받지 못할 수 있습니다. 설정에서 알림 문제를 해결하세요. @@ -244,6 +251,8 @@ "줄이 클립보드에 복사되었습니다." "링크가 클립보드에 복사됨" "새 기기 연결" + "실시간 위치" + "실시간 위치 공유 종료" "로딩 중…" "더 많은 내용이 로딩 중…" @@ -268,6 +277,7 @@ "오프라인" "오픈 소스 라이선스" "또는" + "기타 옵션" "비밀번호" "사람" "퍼머링크" @@ -333,6 +343,7 @@ "설정" "스페이스 공유" "새 멤버에게 대화 기록 공개" + "공유 중인 실시간 위치" "공유된 위치" "공유된 스페이스" "기기 제거" @@ -354,12 +365,13 @@ "글자" "제3자 고지" "스레드" + "스레드" "주제" "이 방은 어떤 곳인가요?" "해독 불가" "보안되지 않은 장치에서 전송됨" "이 메시지에 액세스할 수 없습니다" - "발신자의 검증된 신원이 재설정되었습니다." + "발신자의 인증된 디지털 신원이 재설정되었습니다" "한 명 이상의 사용자에게 초대를 보낼 수 없습니다." "초대를 보낼 수 없음" "잠금 해제" @@ -384,16 +396,17 @@ "음성 메시지" "대기 중…" "이 메시지를 기다리고 있습니다" + "실시간 위치 정보를 기다리는 중…" "누구나 대화 기록 보기 가능" "당신" "%1$s(%2$s)님이 이 메시지를 공유했습니다. 메시지 전송 당시 귀하가 방에 참여 중이 아니었기 때문입니다." "%1$s님이 이 메시지를 공유했습니다. 메시지 전송 당시 귀하가 방에 참여 중이 아니었기 때문입니다." "이 방은 새 멤버가 이전 대화 기록을 읽을 수 있도록 설정되었습니다. %1$s" - "%1$s 의 신원이 재설정되었습니다. %2$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 @@ -427,6 +440,7 @@ "%1$s가 위치에 접근할 수 없습니다. 나중에 다시 시도해 주세요." "음성 메시지 업로드에 실패했습니다." "해당 방이 더 이상 존재하지 않거나 초대장이 더 이상 유효하지 않습니다." + "위치 기반 기능을 사용하려면 GPS를 켜 주세요." "메시지를 찾을 수 없습니다" "%1$s에서 위치에 접근할 수 있는 권한이 없습니다. 설정에서 활성화가 가능합니다." "%1$s에서 위치에 접근할 수 있는 권한이 없습니다. 아래에서 허용해주세요." @@ -446,6 +460,14 @@ "%1$s 제거" "설정" "미디어 선택에 실패했습니다. 다시 시도해 주세요." + "Element Classic 열기" + "기기에서 Element Classic 앱을 열어 주세요" + "설정 > 보안 및 개인정보 보호로 이동하세요" + "암호화 키 관리에서 \'암호화된 메시지 복구\'를 선택하세요" + "안내에 따라 키 저장소를 활성화해 주세요" + "%1$s(으)로 돌아가기" + "%1$s(으)로 진행하기 전에 키 저장소를 활성화해 주세요." + "다시 오신 것을 환영합니다" "메시지를 누르고 \"%1$s\" 를 선택하여 여기에 포함합니다." "중요한 메시지를 고정하여 쉽게 찾을 수 있도록 합니다" @@ -456,7 +478,7 @@ "확인할 수 없나요? 계정 설정으로 이동하여 디지털 신원을 재설정하세요." "인증 철회 및 전송" "확인 절차를 철회하고 이 메시지를 보내거나, 지금 취소하고 나중에 %1$s 을 확인한 후 다시 시도할 수 있습니다." - "%1$s의 인증된 신원이 재설정되어 귀하의 메시지가 전송되지 않았습니다." + "%1$s님의 인증된 디지털 신원이 재설정되어 메시지를 전송하지 못했습니다." "아무튼 메시지 보내기" "%1$s 는 하나 이상의 확인되지 않은 장치를 사용하고 있습니다. 메시지를 보내거나, %2$s 이 모든 장치를 확인한 후에 다시 시도할 수 있습니다." "%1$s 이(가) 모든 기기를 확인하지 않았기 때문에 귀하의 메시지가 전송되지 않았습니다." @@ -480,12 +502,15 @@ "Google Maps에서 열기" "OpenStreetMap에서 열기" "선택한 위치 공유" + "공유 옵션" "당신이 스페이스를 만들거나 가입했습니다." "%1$s•%2$s" "스페이스를 생성하여 방을 체계적으로 관리해 보세요." "%1$s 스페이스" "스페이스" - "%1$s의 인증된 신원이 재설정되어 메시지가 전송되지 않았습니다." + "공유된 %1$s" + "지도에서 보기" + "%1$s님의 인증된 디지털 신원이 재설정되어 메시지를 보내지 못했습니다." "%1$s 이 모든 장치를 확인하지 않았기 때문에 메시지가 전송되지 않았습니다." "하나 이상의 기기를 확인하지 않았기 때문에 메시지가 전송되지 않았습니다." "위치" @@ -495,5 +520,5 @@ "이전 메시지에 액세스하려면 이 장치를 확인해야 합니다." "이 메시지에 액세스할 수 없습니다" "메시지를 해독할 수 없습니다." - "이 메시지는 귀하가 기기를 확인하지 않았거나 발신자가 귀하의 신원을 확인해야 하기 때문에 차단되었습니다." + "기기가 인증되지 않았거나, 발신자가 귀하의 디지털 신원을 확인해야 하므로 이 메시지가 차단되었습니다." 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 18eafdb13c..1ebbceedd5 100644 --- a/libraries/ui-strings/src/main/res/values-lt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-lt/translations.xml @@ -88,7 +88,7 @@ "Kūrėjo nustatymai" "Asmeninis pokalbis" "(redaguota)" - "Taisymas" + "Redagavimas" "* %1$s %2$s" "Šifravimas įjungtas" "Klaida" @@ -96,7 +96,7 @@ "Failas išsaugotas aplanke Atsisiuntimai" "Persiųsti žinutę" "GIF" - "Paveikslėlis" + "Vaizdas" "Šio Matrix ID nepavyksta rasti, todėl kvietimas gali būti negautas." "Paliekamas kambarys" "Nuoroda nukopijuota į iškarpinę" @@ -170,6 +170,7 @@ "%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-sv/translations.xml b/libraries/ui-strings/src/main/res/values-sv/translations.xml index 0969270a3c..dfcd514209 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -146,8 +146,8 @@ "Dela länk" "Visa" "Logga in igen" - "Logga ut" - "Logga ut ändå" + "Ta bort den här enheten" + "Ta bort den här enheten ändå" "Hoppa över" "Starta" "Starta chat" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 457aec7d80..0c1be935ef 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -467,6 +467,13 @@ Are you sure you want to continue?" "Remove %1$s" "Settings" "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" "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/de/features.location.impl.share_ShareLocationView_Day_5_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png index bdd4cde724..18dc2c74b7 100644 --- a/screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e17424dbbfb6a537bcd285ab3d4a4a8567a61cba89b17b7ac1caddbc26dfde6 -size 17320 +oid sha256:6edd90a847c7fc84c25545313f90ec41b8769d4a9b758476725f7ec5255fc167 +size 21838 diff --git a/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png index 057548a09c..ee068ebc52 100644 --- a/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fd7dc09638aef0559bd4b1c75800648d9f37c67d96fde244eb064a4374c67e8 -size 21574 +oid sha256:a237e342ba5bce3980d0f0164afe658993741ff8238e7cbdf9c73f7eb83f2f4c +size 36792 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 1ecfab0491..326e4ae318 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,87 +1,87 @@ // 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",20539,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20548,], ["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",20539,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20539,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20539,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20539,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20539,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20539,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20539,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20539,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20539,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20539,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20539,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20548,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20548,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20548,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20548,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20548,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20548,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20548,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20548,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20548,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20548,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20548,], ["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",20539,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20539,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20548,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20548,], ["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",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20548,], ["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",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20539,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20539,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20539,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20539,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20539,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20539,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20539,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20539,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20539,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20539,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20548,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20548,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20548,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20548,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20548,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20548,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20548,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20548,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20548,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20548,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20539,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20539,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20539,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20539,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20539,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20548,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20548,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20548,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20548,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20548,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20539,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20548,], ["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",20539,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20548,], ["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",20539,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20548,], ["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",20539,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20548,], ["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",20539,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20548,], ["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 +91,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","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20539,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20539,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20548,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20548,], ["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",20539,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20548,], ["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 +133,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",20539,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20548,], ["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",20539,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20539,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20539,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20539,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20539,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20539,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20539,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20548,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20548,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20548,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20548,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20548,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20548,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20548,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20539,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20539,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20539,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20539,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20539,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20548,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20548,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20548,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20548,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20548,], ["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 +159,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",20539,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20539,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20548,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20548,], ["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",20539,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20548,], ["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",20539,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20539,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20539,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20539,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20539,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20539,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20548,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20548,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20548,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20548,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20548,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20548,], ["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",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20539,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20539,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20539,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20548,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20548,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20548,], ["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",20539,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20539,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20539,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20539,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20539,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20548,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20548,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20548,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20548,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20548,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20539,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20548,], ["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",20539,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20539,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20539,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20539,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20539,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20539,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20539,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20539,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20548,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20548,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20548,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20548,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20548,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20548,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20548,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20548,], ["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",20539,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20539,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20539,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20539,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20539,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20539,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20539,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20548,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20548,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20548,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20548,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20548,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20548,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20548,], ["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","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20539,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20539,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20539,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20539,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20539,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20539,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20548,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20548,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20548,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20548,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20548,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20548,], ["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",20539,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20539,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20539,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20539,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20539,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20539,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20539,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20539,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20539,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20539,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20539,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20539,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20539,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20539,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20539,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20539,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20539,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20539,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20539,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20539,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20548,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20548,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20548,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20548,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20548,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20548,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20548,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20548,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20548,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20548,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20548,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20548,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20548,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20548,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20548,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20548,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20548,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20548,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20548,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20548,], ["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","",20539,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20539,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20539,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20539,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20539,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20539,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20539,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20548,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20548,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20548,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20548,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20548,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20548,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20548,], ["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",20539,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20539,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20539,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20548,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20548,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20548,], ["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",20539,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20548,], ["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",20539,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20539,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20539,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20539,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20539,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20539,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20539,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20539,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20539,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20539,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20548,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20548,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20548,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20548,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20548,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20548,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20548,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20548,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20548,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20548,], ["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 +308,19 @@ 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",20539,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20539,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20539,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20539,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20539,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20539,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20539,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20539,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20539,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20539,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20539,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20539,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20539,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20548,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20548,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20548,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20548,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20548,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20548,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20548,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20548,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20548,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20548,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20548,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20548,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20548,], ["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 +328,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",20539,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20539,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20548,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20548,], ["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",20539,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20539,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20539,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20539,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20539,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20539,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20539,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20539,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20539,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20539,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20548,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20548,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20548,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20548,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20548,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20548,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20548,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20548,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20548,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20548,], ["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,], @@ -366,50 +366,51 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FilledTextFieldValueLight_TextFields_en","",0,], ["libraries.designsystem.theme.components_FilledTextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.designsystem.theme.components_FloatingActionButton_Floating_Action_Buttons_en","",0,], +["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",20539,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20539,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20539,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20548,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20548,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20548,], ["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",20539,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20539,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20548,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20548,], ["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",20539,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20539,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20539,], -["features.home.impl.spaces_HomeSpacesView_Day_3_en","features.home.impl.spaces_HomeSpacesView_Night_3_en",20539,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20539,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20539,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20548,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20548,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20548,], +["features.home.impl.spaces_HomeSpacesView_Day_3_en","features.home.impl.spaces_HomeSpacesView_Night_3_en",20548,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20548,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20548,], ["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",20539,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20539,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20548,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20548,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20539,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20539,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20548,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20548,], ["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",20539,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20539,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20539,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20539,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20539,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20539,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20539,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20539,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20539,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20539,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20539,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20539,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20539,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20548,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20548,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20548,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20548,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20548,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20548,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20548,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20548,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20548,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20548,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20548,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20548,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20548,], ["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 +425,8 @@ export const screenshots = [ ["appicon.enterprise_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",20539,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20539,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20548,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20548,], ["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 +434,117 @@ 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",20539,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20548,], ["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",20539,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20548,], ["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",20539,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20539,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20548,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20548,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20539,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20539,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20548,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20548,], ["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",20539,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20539,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20539,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20548,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20548,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20548,], ["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",20539,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20539,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20539,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20548,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20548,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20548,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20548,], ["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",20539,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20539,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20539,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20539,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20539,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20539,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20539,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20539,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20548,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20548,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20548,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20548,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20548,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20548,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20548,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20548,], ["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",20539,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20539,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20539,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20539,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20539,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20548,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20548,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20548,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20548,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20539,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20539,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20548,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20548,], ["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",20539,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20539,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20539,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20539,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20539,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20539,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20539,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20539,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20548,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20548,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20548,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20548,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20548,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20548,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20548,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20548,], ["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",20539,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20539,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20539,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20539,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20539,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20539,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20548,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20548,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20548,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20548,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20548,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20548,], ["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",20539,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20548,], ["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,43 +599,43 @@ 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",20539,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20548,], ["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",20539,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20539,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20539,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20548,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20548,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20548,], ["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",20539,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20539,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20539,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20539,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20539,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20539,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20539,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20539,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20539,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20539,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20539,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20539,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20539,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20539,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20539,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20539,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20539,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20539,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20539,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20539,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20539,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20539,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20539,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20539,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20539,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20548,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20548,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20548,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20548,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20548,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20548,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20548,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20548,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20548,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20548,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20548,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20548,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20548,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20548,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20548,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20548,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20548,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20548,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20548,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20548,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20548,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20548,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20548,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20548,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20548,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20539,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20539,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20539,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20539,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20548,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20548,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20548,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20548,], ["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,], @@ -648,22 +649,22 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20539,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20539,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20548,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20548,], ["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",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20539,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20539,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20548,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20548,], ["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,], @@ -671,14 +672,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20539,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20539,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20548,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20548,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20539,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20548,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20539,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20548,], ["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 +693,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",20539,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20548,], ["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 +702,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",20539,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20548,], ["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,23 +711,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20539,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20539,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20539,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20539,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20539,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20539,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20539,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20539,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20539,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20539,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20539,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20539,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20539,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20539,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20539,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20548,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20548,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20548,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20548,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20548,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20548,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20548,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20548,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20548,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20548,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20548,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20548,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20548,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20548,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20548,], ["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",20539,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20548,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -737,112 +738,112 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20539,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20539,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20539,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20548,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20548,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20548,], ["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",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20539,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20539,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20548,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20548,], ["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",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20539,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20548,], ["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",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20539,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20539,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20548,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20548,], ["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",20539,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20539,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20539,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20539,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20539,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20539,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20548,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20548,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20548,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20548,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20548,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20548,], ["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",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20539,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20539,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20548,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20548,], ["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",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20539,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20539,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20539,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20539,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20539,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20539,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20548,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20548,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20548,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20548,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20548,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20548,], ["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",20539,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20539,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20539,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20539,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20539,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20548,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20548,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20548,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20548,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20548,], ["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",20539,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20539,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20539,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20539,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20539,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20539,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20539,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20539,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20539,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20539,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20539,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20548,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20548,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20548,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20548,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20548,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20548,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20548,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20548,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20548,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20548,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20548,], ["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 +857,215 @@ 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","",20539,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20539,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20539,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20539,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20548,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20548,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20548,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20548,], ["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","",20539,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20539,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20548,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20548,], ["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",20539,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20539,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20539,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20539,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20539,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20539,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20539,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20539,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20539,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20539,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20539,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20539,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20539,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20539,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20539,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20539,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20539,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20539,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20539,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20539,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20539,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20548,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20548,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20548,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20548,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20548,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20548,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20548,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20548,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20548,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20548,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20548,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20548,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20548,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20548,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20548,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20548,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20548,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20548,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20548,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20548,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20548,], ["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",20539,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20539,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20548,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20548,], ["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",20539,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20539,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20539,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20539,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20539,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20539,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20539,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20548,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20548,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20548,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20548,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20548,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20548,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20548,], ["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",20539,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20539,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20539,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20539,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20539,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20539,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20539,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20539,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20539,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20539,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20539,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20539,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20539,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20539,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20539,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20539,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20539,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20548,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20548,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20548,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20548,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20548,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20548,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20548,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20548,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20548,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20548,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20548,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20548,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20548,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20548,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20548,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20548,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20548,], ["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",20539,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20539,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20539,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20539,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20539,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20548,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20548,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20548,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20548,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20548,], ["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",20539,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20539,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20548,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20548,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20539,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20539,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20539,], -["features.roomdetails.impl_RoomDetails_0_en","",20539,], -["features.roomdetails.impl_RoomDetails_10_en","",20539,], -["features.roomdetails.impl_RoomDetails_11_en","",20539,], -["features.roomdetails.impl_RoomDetails_12_en","",20539,], -["features.roomdetails.impl_RoomDetails_13_en","",20539,], -["features.roomdetails.impl_RoomDetails_14_en","",20539,], -["features.roomdetails.impl_RoomDetails_15_en","",20539,], -["features.roomdetails.impl_RoomDetails_16_en","",20539,], -["features.roomdetails.impl_RoomDetails_17_en","",20539,], -["features.roomdetails.impl_RoomDetails_18_en","",20539,], -["features.roomdetails.impl_RoomDetails_19_en","",20539,], -["features.roomdetails.impl_RoomDetails_1_en","",20539,], -["features.roomdetails.impl_RoomDetails_20_en","",20539,], -["features.roomdetails.impl_RoomDetails_21_en","",20539,], -["features.roomdetails.impl_RoomDetails_22_en","",20539,], -["features.roomdetails.impl_RoomDetails_2_en","",20539,], -["features.roomdetails.impl_RoomDetails_3_en","",20539,], -["features.roomdetails.impl_RoomDetails_4_en","",20539,], -["features.roomdetails.impl_RoomDetails_5_en","",20539,], -["features.roomdetails.impl_RoomDetails_6_en","",20539,], -["features.roomdetails.impl_RoomDetails_7_en","",20539,], -["features.roomdetails.impl_RoomDetails_8_en","",20539,], -["features.roomdetails.impl_RoomDetails_9_en","",20539,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20539,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20539,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20539,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20539,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20539,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20539,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20539,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20539,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20539,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20548,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20548,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20548,], +["features.roomdetails.impl_RoomDetails_0_en","",20548,], +["features.roomdetails.impl_RoomDetails_10_en","",20548,], +["features.roomdetails.impl_RoomDetails_11_en","",20548,], +["features.roomdetails.impl_RoomDetails_12_en","",20548,], +["features.roomdetails.impl_RoomDetails_13_en","",20548,], +["features.roomdetails.impl_RoomDetails_14_en","",20548,], +["features.roomdetails.impl_RoomDetails_15_en","",20548,], +["features.roomdetails.impl_RoomDetails_16_en","",20548,], +["features.roomdetails.impl_RoomDetails_17_en","",20548,], +["features.roomdetails.impl_RoomDetails_18_en","",20548,], +["features.roomdetails.impl_RoomDetails_19_en","",20548,], +["features.roomdetails.impl_RoomDetails_1_en","",20548,], +["features.roomdetails.impl_RoomDetails_20_en","",20548,], +["features.roomdetails.impl_RoomDetails_21_en","",20548,], +["features.roomdetails.impl_RoomDetails_22_en","",20548,], +["features.roomdetails.impl_RoomDetails_2_en","",20548,], +["features.roomdetails.impl_RoomDetails_3_en","",20548,], +["features.roomdetails.impl_RoomDetails_4_en","",20548,], +["features.roomdetails.impl_RoomDetails_5_en","",20548,], +["features.roomdetails.impl_RoomDetails_6_en","",20548,], +["features.roomdetails.impl_RoomDetails_7_en","",20548,], +["features.roomdetails.impl_RoomDetails_8_en","",20548,], +["features.roomdetails.impl_RoomDetails_9_en","",20548,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20548,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20548,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20548,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20548,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20548,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20548,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20548,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20548,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20548,], ["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",20539,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20539,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20539,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20539,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20539,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20539,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20539,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20539,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20539,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20548,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20548,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20548,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20548,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20548,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20548,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20548,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20548,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20548,], ["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",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20539,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20539,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20539,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20548,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20548,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20548,], ["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",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20539,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20539,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20548,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20548,], ["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",20539,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20539,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20539,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20539,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20539,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20539,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20548,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20548,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20548,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20548,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20548,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20548,], ["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 +1088,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20539,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20539,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20548,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20548,], ["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",20539,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20548,], ["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 +1105,118 @@ 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",20539,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20539,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20539,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20548,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20548,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20548,], ["appicon.enterprise_RoundIcon_en","",0,], ["appicon.element_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",20539,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20539,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20539,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20539,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20539,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20539,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20539,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20539,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20548,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20548,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20548,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20548,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20548,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20548,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20548,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20548,], ["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","",20539,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20548,], ["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","",20539,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20539,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20539,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20539,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20539,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20539,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20539,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20539,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20539,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20539,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20539,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20539,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20539,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20539,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20539,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20548,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20548,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20548,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20548,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20548,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20548,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20548,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20548,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20548,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20548,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20548,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20548,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20548,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20548,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20548,], ["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 +1239,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",20539,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20539,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20539,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20539,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20539,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20539,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20539,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20539,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20542,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20542,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20542,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20542,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20542,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20542,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20542,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20548,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20548,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20548,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20548,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20548,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20548,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20548,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20548,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20548,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20548,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20548,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20548,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20548,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20548,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20548,], ["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",20539,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20539,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20539,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20539,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20539,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20539,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20539,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20539,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20539,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20548,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20548,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20548,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20548,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20548,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20548,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20548,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20548,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20548,], ["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 +1275,107 @@ 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",20539,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20548,], ["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",20539,], +["features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en","features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en",20548,], ["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",20539,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20539,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20539,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20548,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20548,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20548,], ["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",20539,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20548,], ["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",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20539,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20539,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20539,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20539,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20539,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20539,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20539,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20539,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20539,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20539,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20539,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20539,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20539,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20539,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20539,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20548,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20548,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20548,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20548,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20548,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20548,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20548,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20548,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20548,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20548,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20548,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20548,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20548,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20548,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20548,], ["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",20539,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20539,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20539,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20539,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20539,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20539,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20539,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20548,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20548,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20548,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20548,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20548,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20548,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20548,], ["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",20539,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20548,], ["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",20539,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20548,], ["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",20539,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20539,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20539,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20539,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20539,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20539,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20539,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20539,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20539,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20539,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20539,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20539,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20539,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20539,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20539,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20548,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20548,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20548,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20548,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20548,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20548,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20548,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20548,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20548,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20548,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20548,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20548,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20548,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20548,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20548,], ["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",20539,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20539,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20548,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20548,], ["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 +1387,16 @@ 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",20539,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20539,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20539,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20539,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20539,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20548,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20548,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20548,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20548,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20548,], ["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",20539,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20539,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20548,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20548,], ["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 +1406,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",20539,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20548,], ["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",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20548,], ["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 +1425,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",20539,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20548,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20548,], ["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",20539,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20539,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20548,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20548,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20548,], ["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",20539,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20548,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20548,], ["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 +1445,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",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20548,], ["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",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20548,], ["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",20539,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20548,], ["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","",20539,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20548,], ["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",20539,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20548,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20548,], ["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",20539,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20548,], ["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",20539,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20539,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20539,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20548,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20548,], ["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",20539,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20539,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20548,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20548,], ["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",20539,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20548,], ["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 +1489,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",20539,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20548,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20548,], ["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 +1505,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",20539,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20539,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20548,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20548,], ["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 +1529,85 @@ 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",20539,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20539,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20542,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20539,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20539,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20539,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20539,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20539,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20539,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20548,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20548,], ["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",20539,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20548,], ["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",20539,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20548,], ["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",20539,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20548,], ["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",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20539,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20539,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20548,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20548,], ["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",20539,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20539,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20539,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20539,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20539,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20539,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20548,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20548,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20548,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20548,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20548,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20548,], ["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","",20539,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20548,], ["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",20539,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20539,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20539,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20539,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20548,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20548,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20548,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20548,], ["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",20539,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20548,], ["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",20539,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20548,], ["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",20539,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20539,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20539,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20539,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20539,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20539,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20539,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20539,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20539,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20539,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20539,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20539,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20539,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20548,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20548,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20548,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20548,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20548,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20548,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20548,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20548,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20548,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20548,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20548,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20548,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20548,], ["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",20539,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20539,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20548,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20548,], ["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",20539,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20548,], ["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,], From d05cc0bcdfa29716ad64593cb68c075d7c99e33c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:10:54 +0200 Subject: [PATCH 0066/1083] fix(deps): update media3 to v1.10.0 (#6529) 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 ca5f42c118..2619d924fd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ constraintlayout = "2.2.1" constraintlayout_compose = "1.1.1" lifecycle = "2.10.0" activity = "1.13.0" -media3 = "1.9.3" +media3 = "1.10.0" camera = "1.5.3" work = "2.11.2" From 03262d220909a6537f98a5208a9e5a3040058f08 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:11:54 +0200 Subject: [PATCH 0067/1083] fix(deps): update dependency io.github.sergio-sastre.composablepreviewscanner:android to v0.8.2 (#6525) 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 2619d924fd..29ad2fd5e5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -168,7 +168,7 @@ test_truth = "com.google.truth:truth:1.4.5" test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.21" test_robolectric = "org.robolectric:robolectric:4.16.1" test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" } -test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.8.1" +test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.8.2" test_detekt_api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" } test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" } From 0921a7655fa6ce669bcb860f769915587525ae03 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:12:44 +0200 Subject: [PATCH 0068/1083] fix(deps): update metro to v0.12.1 (#6543) 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 29ad2fd5e5..a6fcae8d86 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.6.1" # DI -metro = "0.12.0" +metro = "0.12.1" # Auto service autoservice = "1.1.1" From a93c90058a5a617fd7d74f4572bc431efb82126a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:38:40 +0200 Subject: [PATCH 0069/1083] fix(deps): update kotlinpoet to v2.3.0 (#6528) 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 a6fcae8d86..2465b71a59 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ android_gradle_plugin = "8.13.2" # When updating this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.3.20" -kotlinpoet = "2.2.0" +kotlinpoet = "2.3.0" ksp = "2.3.6" firebaseAppDistribution = "5.2.1" From d38f483cd179a6beb26df032a8b6f2228f8f7741 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:11:15 +0200 Subject: [PATCH 0070/1083] fix(deps): update dependency io.sentry:sentry-android to v8.37.1 (#6508) 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 2465b71a59..a92784e4a9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -221,7 +221,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.39.0" -sentry = "io.sentry:sentry-android:8.36.0" +sentry = "io.sentry:sentry-android:8.37.1" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 523ede744a035caef438311c073bd926b0b5bbd1 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Wed, 8 Apr 2026 11:01:54 +0200 Subject: [PATCH 0071/1083] Fix portrait image metadata when uploading without media optimization (#6362) * fix(media): preserve image orientation metadata without optimization * style: linting --- .../impl/AndroidMediaPreProcessor.kt | 54 ++++++++++++++----- .../impl/AndroidMediaPreProcessorTest.kt | 25 +++++++++ 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessor.kt index 2b1883619e..2ab1cd0619 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessor.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessor.kt @@ -195,18 +195,16 @@ class AndroidMediaPreProcessor( file = file, mimeType = mimeType, ) - val imageInfo = contentResolver.openInputStream(uri).use { input -> - val bitmap = BitmapFactory.decodeStream(input, null, null)!! - ImageInfo( - width = bitmap.width.toLong(), - height = bitmap.height.toLong(), - mimetype = mimeType, - size = file.length(), - thumbnailInfo = thumbnailResult?.info, - thumbnailSource = null, - blurhash = thumbnailResult?.blurhash, - ) - } + val (width, height) = extractOrientedImageDimensions(file) + val imageInfo = ImageInfo( + width = width, + height = height, + mimetype = mimeType, + size = file.length(), + thumbnailInfo = thumbnailResult?.info, + thumbnailSource = null, + blurhash = thumbnailResult?.blurhash, + ) removeSensitiveImageMetadata(file) return MediaUploadInfo.Image( file = file, @@ -354,6 +352,23 @@ class AndroidMediaPreProcessor( return contentResolver.openInputStream(uri)?.use { createTmpFileWithInput(it) } ?: error("Could not copy the contents of $uri to a temporary file") } + + private fun extractOrientedImageDimensions(file: File): Pair { + val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } + BitmapFactory.decodeFile(file.path, options) + + val rawWidth = options.outWidth.toLong() + val rawHeight = options.outHeight.toLong() + val orientation = tryOrNull { + ExifInterface(file).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED) + } ?: ExifInterface.ORIENTATION_UNDEFINED + + return orientedImageDimensions( + rawWidth = rawWidth, + rawHeight = rawHeight, + orientation = orientation, + ) + } } private fun ImageCompressionResult.toImageInfo(mimeType: String, thumbnailResult: ThumbnailResult?) = ImageInfo( @@ -371,3 +386,18 @@ private fun MediaMetadataRetriever.extractDuration(): Duration { val durationInMs = extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L return durationInMs.milliseconds } + +internal fun orientedImageDimensions(rawWidth: Long, rawHeight: Long, orientation: Int): Pair { + return if (orientation.rotatesRightAngle()) { + rawHeight to rawWidth + } else { + rawWidth to rawHeight + } +} + +private fun Int.rotatesRightAngle(): Boolean { + return this == ExifInterface.ORIENTATION_ROTATE_90 || + this == ExifInterface.ORIENTATION_ROTATE_270 || + this == ExifInterface.ORIENTATION_TRANSPOSE || + this == ExifInterface.ORIENTATION_TRANSVERSE +} diff --git a/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessorTest.kt b/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessorTest.kt index f4b4e7d4a5..57726ac5a2 100644 --- a/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessorTest.kt +++ b/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/AndroidMediaPreProcessorTest.kt @@ -12,6 +12,7 @@ import android.content.Context import android.net.Uri import android.os.Build import androidx.core.net.toUri +import androidx.exifinterface.media.ExifInterface import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.file.TemporaryUriDeleter @@ -42,6 +43,30 @@ import kotlin.time.Duration @RunWith(RobolectricTestRunner::class) class AndroidMediaPreProcessorTest { + @Test + fun `orientedImageDimensions swaps width and height for 90 degree exif orientation`() { + val (width, height) = orientedImageDimensions( + rawWidth = 4032, + rawHeight = 2268, + orientation = ExifInterface.ORIENTATION_ROTATE_90, + ) + + assertThat(width).isEqualTo(2268) + assertThat(height).isEqualTo(4032) + } + + @Test + fun `orientedImageDimensions keeps width and height for upright exif orientation`() { + val (width, height) = orientedImageDimensions( + rawWidth = 4032, + rawHeight = 2268, + orientation = ExifInterface.ORIENTATION_NORMAL, + ) + + assertThat(width).isEqualTo(4032) + assertThat(height).isEqualTo(2268) + } + private suspend fun TestScope.process( asset: Asset, mediaOptimizationConfig: MediaOptimizationConfig, From dae308fcf74e878bf23e5e81fa333308c6fc3459 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 11:15:51 +0200 Subject: [PATCH 0072/1083] Fix crash, ensure that `super.onTimeout(startId)` is not called when the method is not available. --- .../libraries/push/impl/push/FetchPushForegroundService.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 da5dc80707..d54b7f5497 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 @@ -106,7 +106,7 @@ class FetchPushForegroundService : Service() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { coroutineScope.launch { delay(wakelockTimeout) - onTimeout(startId) + onTimeoutAction(calledByTheSystem = false) } } @@ -124,7 +124,11 @@ class FetchPushForegroundService : Service() { override fun onTimeout(startId: Int) { super.onTimeout(startId) + onTimeoutAction(calledByTheSystem = true) + } + private fun onTimeoutAction(calledByTheSystem: Boolean) { + Timber.d("onTimeoutAction, calledByTheSystem: $calledByTheSystem, isOnForeground: $isOnForeground") if (isOnForeground) { Timber.d("Wakelock timeout reached, stopping FetchPushForegroundService") coroutineScope.launch { pushHandlingWakeLock.unlock() } From 22a51bae5c10797c3542fae1dbaf17ca155107e8 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Wed, 8 Apr 2026 12:25:59 +0300 Subject: [PATCH 0073/1083] Fix Threads not tappable in pinned messages list (#6535) --- .../android/features/messages/impl/MessagesFlowNode.kt | 4 ++++ .../messages/impl/pinned/list/PinnedMessagesListEvent.kt | 2 ++ .../impl/pinned/list/PinnedMessagesListNavigator.kt | 2 ++ .../messages/impl/pinned/list/PinnedMessagesListNode.kt | 6 ++++++ .../impl/pinned/list/PinnedMessagesListPresenter.kt | 1 + .../messages/impl/pinned/list/PinnedMessagesListView.kt | 8 +++++++- .../impl/pinned/list/FakePinnedMessagesListNavigator.kt | 6 ++++++ 7 files changed, 28 insertions(+), 1 deletion(-) 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 d3dd21de67..f77f06fad3 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 @@ -432,6 +432,10 @@ class MessagesFlowNode( override fun handleForwardEventClick(eventId: EventId) { backstack.push(NavTarget.ForwardEvent(eventId = eventId, fromPinnedEvents = true)) } + + override fun navigateToThread(threadRootId: ThreadId) { + backstack.push(NavTarget.Thread(threadRootId, null)) + } } createNode(buildContext, plugins = listOf(callback)) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt index 6ad4fbefe6..73ba08b29d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt @@ -10,7 +10,9 @@ package io.element.android.features.messages.impl.pinned.list import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.libraries.matrix.api.core.ThreadId sealed interface PinnedMessagesListEvent { data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : PinnedMessagesListEvent + data class OpenThread(val threadRootId: ThreadId) : PinnedMessagesListEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt index a3728cb9f4..9633802f77 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt @@ -9,10 +9,12 @@ package io.element.android.features.messages.impl.pinned.list import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo interface PinnedMessagesListNavigator { fun viewInTimeline(eventId: EventId) fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) fun forwardEvent(eventId: EventId) + fun navigateToThread(threadRootId: ThreadId) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt index 292a77ba6a..cddc1831db 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt @@ -31,6 +31,7 @@ import io.element.android.libraries.androidutils.system.openUrlInExternalApp import io.element.android.libraries.architecture.callback import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser @@ -55,6 +56,7 @@ class PinnedMessagesListNode( fun handlePermalinkClick(data: PermalinkData.RoomLink) fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) fun handleForwardEventClick(eventId: EventId) + fun navigateToThread(threadRootId: ThreadId) } private val callback: Callback = callback() @@ -95,6 +97,10 @@ class PinnedMessagesListNode( callback.handleForwardEventClick(eventId) } + override fun navigateToThread(threadRootId: ThreadId) { + callback.navigateToThread(threadRootId) + } + @Composable override fun View(modifier: Modifier) { CompositionLocalProvider( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index f884cdac84..6cd037484d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -137,6 +137,7 @@ class PinnedMessagesListPresenter( fun handleEvent(event: PinnedMessagesListEvent) { when (event) { is PinnedMessagesListEvent.HandleAction -> sessionCoroutineScope.handleTimelineAction(event.action, event.event) + is PinnedMessagesListEvent.OpenThread -> navigator.navigateToThread(event.threadRootId) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index b125bdcf6f..b212549a22 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -30,6 +30,7 @@ import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.link.LinkEvent import io.element.android.features.messages.impl.link.LinkView +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.components.TimelineItemRow import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData @@ -235,7 +236,12 @@ private fun PinnedMessagesListLoaded( onReadReceiptClick = {}, onSwipeToReply = {}, onJoinCallClick = {}, - eventSink = {}, + eventSink = { timelineItemEvent -> + when (timelineItemEvent) { + is TimelineEvent.OpenThread -> state.eventSink(PinnedMessagesListEvent.OpenThread(timelineItemEvent.threadRootEventId)) + else -> Unit + } + }, eventContentView = { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentViewWrapper( event = event, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt index 479139a45b..69eaae3699 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt @@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.pinned.list import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo class FakePinnedMessagesListNavigator : PinnedMessagesListNavigator { @@ -26,4 +27,9 @@ class FakePinnedMessagesListNavigator : PinnedMessagesListNavigator { override fun forwardEvent(eventId: EventId) { onForwardEventClickLambda?.invoke(eventId) } + + var onOpenThreadLambda: ((ThreadId) -> Unit)? = null + override fun navigateToThread(threadRootId: ThreadId) { + onOpenThreadLambda?.invoke(threadRootId) + } } From 6cbd1b348617bcdbfcd70f3658ca24b6b9a0e684 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 12:11:29 +0200 Subject: [PATCH 0074/1083] fix(deps): update dependency org.maplibre.gl:android-sdk to v13.0.2 (#6546) 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 a92784e4a9..8a6f95bc7e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -207,7 +207,7 @@ vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" } telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" } statemachine = "com.freeletics.flowredux:compose:1.2.2" -maplibre = "org.maplibre.gl:android-sdk:13.0.1" +maplibre = "org.maplibre.gl:android-sdk:13.0.2" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_compose = "org.maplibre.compose:maplibre-compose:0.12.1" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" From 2a5e9956e439f5d07d663597b0a4ea5cdf477304 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 16:45:22 +0200 Subject: [PATCH 0075/1083] Reduce log level of activity lifecycle from warning to debug. (#6548) --- .../main/kotlin/io/element/android/x/MainActivity.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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..502518bf3c 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -52,7 +52,7 @@ class MainActivity : NodeActivity() { private lateinit var appBindings: AppBindings override fun onCreate(savedInstanceState: Bundle?) { - Timber.tag(loggerTag.value).w("onCreate, with savedInstanceState: ${savedInstanceState != null}") + Timber.tag(loggerTag.value).d("onCreate, with savedInstanceState: ${savedInstanceState != null}") installSplashScreen() super.onCreate(savedInstanceState) appBindings = bindings() @@ -108,7 +108,7 @@ class MainActivity : NodeActivity() { plugins = listOf( object : NodeReadyObserver { override fun init(node: MainNode) { - Timber.tag(loggerTag.value).w("onMainNodeInit") + Timber.tag(loggerTag.value).d("onMainNodeInit") mainNode = node mainNode.handleIntent(intent) } @@ -144,7 +144,7 @@ class MainActivity : NodeActivity() { */ override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - Timber.tag(loggerTag.value).w("onNewIntent") + Timber.tag(loggerTag.value).d("onNewIntent") // If the mainNode is not init yet, keep the intent for later. // It can happen when the activity is killed by the system. The methods are called in this order : // onCreate(savedInstanceState=true) -> onNewIntent -> onResume -> onMainNodeInit @@ -157,16 +157,16 @@ class MainActivity : NodeActivity() { override fun onPause() { super.onPause() - Timber.tag(loggerTag.value).w("onPause") + Timber.tag(loggerTag.value).d("onPause") } override fun onResume() { super.onResume() - Timber.tag(loggerTag.value).w("onResume") + Timber.tag(loggerTag.value).d("onResume") } override fun onDestroy() { super.onDestroy() - Timber.tag(loggerTag.value).w("onDestroy") + Timber.tag(loggerTag.value).d("onDestroy") } } From 9e61c6545c2bce9a68351e3e27fe8e4a005299b7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:48:53 +0000 Subject: [PATCH 0076/1083] Update codecov/codecov-action action to v6 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f4205758c1..56a342ddba 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -108,7 +108,7 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov - uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 + uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From d17992abe8d4bf99741eb36aef20916070b6ff0b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:15:04 +0200 Subject: [PATCH 0077/1083] Ensure Mark as fully read is not invoked several times. --- .../android/features/messages/impl/MessagesPresenter.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index d9c3d17afa..4b004b74d7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -250,8 +250,8 @@ class MessagesPresenter( is MessagesEvent.OnUserClicked -> { roomMemberModerationState.eventSink(RoomMemberModerationEvents.ShowActionsForUser(event.user)) } - is MessagesEvent.MarkAsFullyReadAndExit -> coroutineScope.launch { - if (!markingAsReadAndExiting.getAndSet(true)) { + is MessagesEvent.MarkAsFullyReadAndExit -> if (!markingAsReadAndExiting.getAndSet(true)) { + coroutineScope.launch { val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { Timber.w(it, "Failed to get latest event id to mark as fully read") navigator.close() @@ -263,7 +263,6 @@ class MessagesPresenter( } } navigator.close() - markingAsReadAndExiting.set(false) } } } From 5e3f3f31e8bcbafbb52b72cd391321eaac26b97e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:16:04 +0200 Subject: [PATCH 0078/1083] Improve code. --- .../android/features/messages/impl/MessagesPresenter.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 4b004b74d7..edb11ff389 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -254,8 +254,7 @@ class MessagesPresenter( coroutineScope.launch { val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { Timber.w(it, "Failed to get latest event id to mark as fully read") - navigator.close() - return@launch + null } latestEventId?.let { eventId -> sessionCoroutineScope.launch { From ef97d135cc415be6024d56c019b7da71f28ef583 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:29:29 +0200 Subject: [PATCH 0079/1083] Move AppErrorView to the `api` module so that `:appnav:root` does not have to depend on a `impl` module. --- appnav/build.gradle.kts | 2 +- .../main/kotlin/io/element/android/appnav/root/RootView.kt | 2 +- services/apperror/api/build.gradle.kts | 1 + .../io/element/android/services/apperror/api}/AppErrorView.kt | 4 +--- services/apperror/impl/build.gradle.kts | 4 +--- 5 files changed, 5 insertions(+), 8 deletions(-) rename services/apperror/{impl/src/main/kotlin/io/element/android/services/apperror/impl => api/src/main/kotlin/io/element/android/services/apperror/api}/AppErrorView.kt (86%) diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index ecac391216..d15129aa6c 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -51,7 +51,7 @@ dependencies { implementation(projects.features.linknewdevice.api) implementation(projects.features.share.api) - implementation(projects.services.apperror.impl) + implementation(projects.services.apperror.api) implementation(projects.services.appnavstate.api) implementation(projects.services.analytics.api) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt b/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt index 32c8e52084..19aa820433 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt @@ -22,7 +22,7 @@ import io.element.android.features.rageshake.api.detection.RageshakeDetectionVie import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.services.apperror.impl.AppErrorView +import io.element.android.services.apperror.api.AppErrorView @Composable fun RootView( diff --git a/services/apperror/api/build.gradle.kts b/services/apperror/api/build.gradle.kts index c0893bd7e8..62d3501655 100644 --- a/services/apperror/api/build.gradle.kts +++ b/services/apperror/api/build.gradle.kts @@ -16,4 +16,5 @@ android { dependencies { implementation(libs.coroutines.core) + implementation(projects.libraries.designsystem) } diff --git a/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt b/services/apperror/api/src/main/kotlin/io/element/android/services/apperror/api/AppErrorView.kt similarity index 86% rename from services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt rename to services/apperror/api/src/main/kotlin/io/element/android/services/apperror/api/AppErrorView.kt index 3794234c79..5a2a5110f5 100644 --- a/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt +++ b/services/apperror/api/src/main/kotlin/io/element/android/services/apperror/api/AppErrorView.kt @@ -6,14 +6,12 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.services.apperror.impl +package io.element.android.services.apperror.api import androidx.compose.runtime.Composable import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.services.apperror.api.AppErrorState -import io.element.android.services.apperror.api.aAppErrorState @Composable fun AppErrorView( diff --git a/services/apperror/impl/build.gradle.kts b/services/apperror/impl/build.gradle.kts index b72b54c198..75440dc5a3 100644 --- a/services/apperror/impl/build.gradle.kts +++ b/services/apperror/impl/build.gradle.kts @@ -10,7 +10,7 @@ import extension.testCommonDependencies */ plugins { - id("io.element.android-compose-library") + id("io.element.android-library") } setupDependencyInjection() @@ -22,8 +22,6 @@ android { dependencies { implementation(projects.libraries.core) implementation(projects.libraries.di) - implementation(projects.libraries.designsystem) - implementation(projects.libraries.uiStrings) implementation(projects.services.toolbox.api) implementation(libs.coroutines.core) From 0e85fec41a52280fa71876ebcee8000acd956244 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:34:44 +0200 Subject: [PATCH 0080/1083] Depend on `api` not `impl` module. --- features/call/impl/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/call/impl/build.gradle.kts b/features/call/impl/build.gradle.kts index e77c09e19a..2843e47870 100644 --- a/features/call/impl/build.gradle.kts +++ b/features/call/impl/build.gradle.kts @@ -73,7 +73,7 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.designsystem) implementation(projects.libraries.featureflag.api) - implementation(projects.libraries.matrix.impl) + implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixmedia.api) implementation(projects.libraries.network) implementation(projects.libraries.preferences.api) From 2a5fc3633d451b532b56161cba06d36a056a8ba8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:40:48 +0200 Subject: [PATCH 0081/1083] Move aCallNotificationData to the tests package of the main module, so that the test module does not have to depend on the impl module. --- .../features/call/impl/notifications}/CallNotificationData.kt | 3 +-- .../features/call/utils/DefaultActiveCallManagerTest.kt | 2 +- features/call/test/build.gradle.kts | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) rename features/call/{test/src/main/kotlin/io/element/android/features/call/test => impl/src/test/kotlin/io/element/android/features/call/impl/notifications}/CallNotificationData.kt (93%) diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt similarity index 93% rename from features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt rename to features/call/impl/src/test/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt index 387a77ef8b..1906aba551 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt @@ -6,9 +6,8 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.call.test +package io.element.android.features.call.impl.notifications -import io.element.android.features.call.impl.notifications.CallNotificationData 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 diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt index 5650eaa47f..f9f6206ec7 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt @@ -15,11 +15,11 @@ import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat import io.element.android.features.call.api.CallType import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator +import io.element.android.features.call.impl.notifications.aCallNotificationData import io.element.android.features.call.impl.utils.ActiveCall import io.element.android.features.call.impl.utils.CallState import io.element.android.features.call.impl.utils.DefaultActiveCallManager import io.element.android.features.call.impl.utils.DefaultCurrentCallService -import io.element.android.features.call.test.aCallNotificationData 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 diff --git a/features/call/test/build.gradle.kts b/features/call/test/build.gradle.kts index 76fbf9915e..f06c5ed16e 100644 --- a/features/call/test/build.gradle.kts +++ b/features/call/test/build.gradle.kts @@ -20,7 +20,6 @@ dependencies { implementation(projects.libraries.core) api(projects.features.call.api) - implementation(projects.features.call.impl) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.test) implementation(projects.tests.testutils) From ed2b43e0da84dda175f0e3007f96506652ca748b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:45:01 +0200 Subject: [PATCH 0082/1083] Remove useless dependencies. --- features/createroom/impl/build.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index 7201f7dc9c..13a195e940 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -39,7 +39,6 @@ dependencies { implementation(projects.libraries.mediaupload.api) implementation(projects.libraries.permissions.api) implementation(projects.libraries.previewutils) - implementation(projects.libraries.usersearch.impl) implementation(projects.services.analytics.api) implementation(libs.coil.compose) implementation(projects.libraries.featureflag.api) @@ -52,7 +51,6 @@ dependencies { testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.permissions.test) - testImplementation(projects.libraries.usersearch.test) testImplementation(projects.features.startchat.test) testImplementation(projects.libraries.featureflag.test) } From 54be642597d70aa57ed3d14d2a51371fc598e8d3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:46:50 +0200 Subject: [PATCH 0083/1083] Depend on `api` not `impl` module. --- features/invitepeople/impl/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/invitepeople/impl/build.gradle.kts b/features/invitepeople/impl/build.gradle.kts index e2025405ff..0c3f988659 100644 --- a/features/invitepeople/impl/build.gradle.kts +++ b/features/invitepeople/impl/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) implementation(projects.libraries.androidutils) - implementation(projects.libraries.usersearch.impl) + implementation(projects.libraries.usersearch.api) implementation(libs.coil.compose) implementation(projects.services.apperror.api) api(projects.features.invitepeople.api) From 5ad6ad08527098e06db229ff805e3da9613a2be8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:51:03 +0200 Subject: [PATCH 0084/1083] Depend on `api` not `impl` module. --- features/messages/test/build.gradle.kts | 2 +- ...akeDefaultVoiceMessageComposerPresenterFactory.kt | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/features/messages/test/build.gradle.kts b/features/messages/test/build.gradle.kts index 29c00ece73..b839f8de06 100644 --- a/features/messages/test/build.gradle.kts +++ b/features/messages/test/build.gradle.kts @@ -26,5 +26,5 @@ dependencies { implementation(projects.libraries.voicerecorder.test) implementation(projects.services.analytics.test) implementation(projects.tests.testutils) - implementation(projects.libraries.mediaupload.impl) + implementation(projects.libraries.mediaupload.api) } diff --git a/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/timeline/voicemessages/composer/FakeDefaultVoiceMessageComposerPresenterFactory.kt b/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/timeline/voicemessages/composer/FakeDefaultVoiceMessageComposerPresenterFactory.kt index 17de179b55..466bfba4fd 100644 --- a/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/timeline/voicemessages/composer/FakeDefaultVoiceMessageComposerPresenterFactory.kt +++ b/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/timeline/voicemessages/composer/FakeDefaultVoiceMessageComposerPresenterFactory.kt @@ -12,13 +12,10 @@ import io.element.android.features.messages.impl.voicemessages.composer.DefaultV import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.mediaplayer.test.FakeAudioFocus import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer import io.element.android.libraries.mediaupload.api.MediaSender -import io.element.android.libraries.mediaupload.impl.DefaultMediaSender -import io.element.android.libraries.mediaupload.test.FakeMediaOptimizationConfigProvider -import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.libraries.mediaupload.test.FakeMediaSender import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory import io.element.android.libraries.voicerecorder.test.FakeVoiceRecorder import io.element.android.services.analytics.test.FakeAnalyticsService @@ -26,12 +23,7 @@ import kotlinx.coroutines.CoroutineScope class FakeDefaultVoiceMessageComposerPresenterFactory( private val sessionCoroutineScope: CoroutineScope, - private val mediaSender: MediaSender = DefaultMediaSender( - preProcessor = FakeMediaPreProcessor(), - room = FakeJoinedRoom(), - timelineMode = Timeline.Mode.Live, - mediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), - ), + private val mediaSender: MediaSender = FakeMediaSender(), ) : DefaultVoiceMessageComposerPresenter.Factory { override fun create(timelineMode: Timeline.Mode): DefaultVoiceMessageComposerPresenter { return DefaultVoiceMessageComposerPresenter( From d206c7a0504fec45a03567aec9cee3742b2ed2cf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:51:57 +0200 Subject: [PATCH 0085/1083] Depend on `api` not `impl` module. --- features/migration/impl/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/migration/impl/build.gradle.kts b/features/migration/impl/build.gradle.kts index a37c3be882..1ba0953349 100644 --- a/features/migration/impl/build.gradle.kts +++ b/features/migration/impl/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { implementation(projects.features.migration.api) implementation(projects.libraries.architecture) implementation(projects.libraries.androidutils) - implementation(projects.libraries.preferences.impl) + implementation(projects.libraries.preferences.api) implementation(libs.androidx.datastore.preferences) implementation(projects.features.rageshake.api) implementation(projects.libraries.designsystem) From 5eeaa4ca72faca8a927da0226a89bd4489169b81 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 17:52:42 +0200 Subject: [PATCH 0086/1083] Depend on `api` not `impl` module. --- features/startchat/impl/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/startchat/impl/build.gradle.kts b/features/startchat/impl/build.gradle.kts index 6ab1a361e9..805dcc742b 100644 --- a/features/startchat/impl/build.gradle.kts +++ b/features/startchat/impl/build.gradle.kts @@ -38,7 +38,7 @@ dependencies { implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.mediaupload.api) implementation(projects.libraries.permissions.api) - implementation(projects.libraries.usersearch.impl) + implementation(projects.libraries.usersearch.api) implementation(projects.services.analytics.api) implementation(libs.coil.compose) implementation(projects.libraries.featureflag.api) From 035e52710183fc76466a7b480afc568c9dc79493 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 18:04:46 +0200 Subject: [PATCH 0087/1083] Depend on `api` not `impl` module. --- libraries/matrix/test/build.gradle.kts | 1 - .../libraries/matrix/test/mxc/FakeMxcTools.kt | 10 +++++++--- .../impl/DefaultVoiceMessageMediaRepoTest.kt | 14 +++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libraries/matrix/test/build.gradle.kts b/libraries/matrix/test/build.gradle.kts index ccb1a37a25..63836d857a 100644 --- a/libraries/matrix/test/build.gradle.kts +++ b/libraries/matrix/test/build.gradle.kts @@ -19,7 +19,6 @@ dependencies { api(projects.libraries.matrix.api) api(libs.coroutines.core) implementation(libs.coroutines.test) - implementation(projects.libraries.matrix.impl) implementation(projects.services.analytics.api) implementation(projects.tests.testutils) implementation(libs.kotlinx.collections.immutable) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/mxc/FakeMxcTools.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/mxc/FakeMxcTools.kt index c348cd351c..d49a1cc22d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/mxc/FakeMxcTools.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/mxc/FakeMxcTools.kt @@ -8,8 +8,12 @@ package io.element.android.libraries.matrix.test.mxc import io.element.android.libraries.matrix.api.mxc.MxcTools -import io.element.android.libraries.matrix.impl.mxc.DefaultMxcTools +import io.element.android.tests.testutils.lambda.lambdaError class FakeMxcTools( - private val delegate: MxcTools = DefaultMxcTools() -) : MxcTools by delegate + private val mxcUri2FilePathResult: (String) -> String? = { lambdaError() } +) : MxcTools { + override fun mxcUri2FilePath(mxcUri: String): String? { + return mxcUri2FilePathResult(mxcUri) + } +} diff --git a/libraries/voiceplayer/impl/src/test/kotlin/io/element/android/libraries/voiceplayer/impl/DefaultVoiceMessageMediaRepoTest.kt b/libraries/voiceplayer/impl/src/test/kotlin/io/element/android/libraries/voiceplayer/impl/DefaultVoiceMessageMediaRepoTest.kt index 5df259fb5b..fad530a3e8 100644 --- a/libraries/voiceplayer/impl/src/test/kotlin/io/element/android/libraries/voiceplayer/impl/DefaultVoiceMessageMediaRepoTest.kt +++ b/libraries/voiceplayer/impl/src/test/kotlin/io/element/android/libraries/voiceplayer/impl/DefaultVoiceMessageMediaRepoTest.kt @@ -32,6 +32,9 @@ class DefaultVoiceMessageMediaRepoTest { val repo = createDefaultVoiceMessageMediaRepo( temporaryFolder = temporaryFolder, matrixMediaLoader = matrixMediaLoader, + mxcUri2FilePathResult = { + "matrix.org/1234567890abcdefg" + }, ) repo.getMediaFile().let { result -> @@ -76,6 +79,9 @@ class DefaultVoiceMessageMediaRepoTest { val repo = createDefaultVoiceMessageMediaRepo( temporaryFolder = temporaryFolder, matrixMediaLoader = matrixMediaLoader, + mxcUri2FilePathResult = { + "matrix.org/1234567890abcdefg" + }, ) repo.getMediaFile().let { result -> @@ -98,6 +104,9 @@ class DefaultVoiceMessageMediaRepoTest { val repo = createDefaultVoiceMessageMediaRepo( temporaryFolder = temporaryFolder, matrixMediaLoader = matrixMediaLoader, + mxcUri2FilePathResult = { + "matrix.org/1234567890abcdefg" + }, ) repo.getMediaFile().let { result -> @@ -128,10 +137,13 @@ class DefaultVoiceMessageMediaRepoTest { private fun createDefaultVoiceMessageMediaRepo( temporaryFolder: TemporaryFolder, matrixMediaLoader: MatrixMediaLoader = FakeMatrixMediaLoader(), + mxcUri2FilePathResult: (String) -> String? = { null }, mxcUri: String = MXC_URI, ) = DefaultVoiceMessageMediaRepo( cacheDir = temporaryFolder.root, - mxcTools = FakeMxcTools(), + mxcTools = FakeMxcTools( + mxcUri2FilePathResult = mxcUri2FilePathResult, + ), matrixMediaLoader = matrixMediaLoader, mediaSource = MediaSource( url = mxcUri, From df73b4427912903592ec56c194e986c1147a9b46 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 18:10:32 +0200 Subject: [PATCH 0088/1083] Depend on `api` not `impl` module. --- .../impl/notifications/DefaultNotifiableEventResolverTest.kt | 1 - .../DefaultOnMissedCallNotificationHandlerTest.kt | 1 - .../impl}/notifications/FakeCallNotificationEventResolver.kt | 3 +-- .../android/libraries/push/impl/push/DefaultPushHandlerTest.kt | 2 +- .../workmanager/FakeSyncPendingNotificationsRequestBuilder.kt | 3 +-- libraries/push/test/build.gradle.kts | 1 - 6 files changed, 3 insertions(+), 8 deletions(-) rename libraries/push/{test/src/main/kotlin/io/element/android/libraries/push/test => impl/src/test/kotlin/io/element/android/libraries/push/impl}/notifications/FakeCallNotificationEventResolver.kt (87%) rename libraries/push/{test/src/main/kotlin/io/element/android/libraries/push/test => impl/src/test/kotlin/io/element/android/libraries/push/impl}/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt (78%) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 63b903a3f7..e732c350b2 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -56,7 +56,6 @@ import io.element.android.libraries.push.impl.notifications.model.FallbackNotifi import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEvent -import io.element.android.libraries.push.test.notifications.FakeCallNotificationEventResolver import io.element.android.services.toolbox.impl.strings.AndroidStringProvider import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP import io.element.android.services.toolbox.test.systemclock.FakeSystemClock diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandlerTest.kt index 9bba1c32d3..e9f6b76b7a 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandlerTest.kt @@ -18,7 +18,6 @@ import io.element.android.libraries.matrix.test.notification.FakeNotificationSer import io.element.android.libraries.matrix.test.notification.aNotificationData import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDataFactory import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent -import io.element.android.libraries.push.test.notifications.FakeCallNotificationEventResolver import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeCallNotificationEventResolver.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/FakeCallNotificationEventResolver.kt similarity index 87% rename from libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeCallNotificationEventResolver.kt rename to libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/FakeCallNotificationEventResolver.kt index f923d0c9fe..a1049683f5 100644 --- a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeCallNotificationEventResolver.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/FakeCallNotificationEventResolver.kt @@ -6,11 +6,10 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.push.test.notifications +package io.element.android.libraries.push.impl.notifications import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.notification.NotificationData -import io.element.android.libraries.push.impl.notifications.CallNotificationEventResolver import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import io.element.android.tests.testutils.lambda.lambdaError diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt index cc6e4674f9..a16568d400 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt @@ -26,8 +26,8 @@ import io.element.android.libraries.push.impl.history.PushHistoryService import io.element.android.libraries.push.impl.notifications.FakeNotificationResultProcessor import io.element.android.libraries.push.impl.test.DefaultTestPush import io.element.android.libraries.push.impl.troubleshoot.DiagnosticPushHandler +import io.element.android.libraries.push.impl.workmanager.FakeSyncPendingNotificationsRequestBuilder import io.element.android.libraries.push.impl.workmanager.SyncPendingNotificationsRequestBuilder -import io.element.android.libraries.push.test.workmanager.FakeSyncPendingNotificationsRequestBuilder import io.element.android.libraries.pushproviders.api.PushData import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStore diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt similarity index 78% rename from libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt rename to libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt index ef0e38991e..f2da936b87 100644 --- a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FakeSyncPendingNotificationsRequestBuilder.kt @@ -5,9 +5,8 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.push.test.workmanager +package io.element.android.libraries.push.impl.workmanager -import io.element.android.libraries.push.impl.workmanager.SyncPendingNotificationsRequestBuilder import io.element.android.libraries.workmanager.api.WorkManagerRequestWrapper class FakeSyncPendingNotificationsRequestBuilder( diff --git a/libraries/push/test/build.gradle.kts b/libraries/push/test/build.gradle.kts index 475d4a4ae5..9dedeb3996 100644 --- a/libraries/push/test/build.gradle.kts +++ b/libraries/push/test/build.gradle.kts @@ -18,7 +18,6 @@ dependencies { api(projects.libraries.push.api) api(projects.libraries.pushproviders.api) implementation(projects.libraries.designsystem) - implementation(projects.libraries.push.impl) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.workmanager.api) From 76f776a12272de36524ce04b079c4b5e4dd19806 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 20:45:07 +0000 Subject: [PATCH 0089/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.04.8 --- 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 8a6f95bc7e..66eda77269 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.03.31" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.8" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 5c5a5ad7fc384b87ef018daab31c1e11deea061c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Apr 2026 09:32:52 +0200 Subject: [PATCH 0090/1083] Fix tests --- appnav/build.gradle.kts | 3 +- .../appnav/JoinedRoomLoadedFlowNodeTest.kt | 8 ++--- .../android/appnav/RootPresenterTest.kt | 21 ++++++----- .../appnavstate/test/FakeActiveRoomsHolder.kt | 36 +++++++++++++++++++ 4 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeActiveRoomsHolder.kt diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index d15129aa6c..24a0355b3f 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -67,8 +67,7 @@ dependencies { testImplementation(projects.features.messages.test) testImplementation(projects.features.networkmonitor.test) testImplementation(projects.features.rageshake.test) - testImplementation(projects.services.appnavstate.impl) + testImplementation(projects.services.apperror.test) testImplementation(projects.services.appnavstate.test) testImplementation(projects.services.analytics.test) - testImplementation(projects.services.toolbox.test) } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/JoinedRoomLoadedFlowNodeTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/JoinedRoomLoadedFlowNodeTest.kt index 8d514a2c0f..6dffda9e42 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/JoinedRoomLoadedFlowNodeTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/JoinedRoomLoadedFlowNodeTest.kt @@ -43,7 +43,7 @@ import io.element.android.services.analytics.api.watchers.AnalyticsSendMessageWa import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.analytics.test.watchers.FakeAnalyticsSendMessageWatcher import io.element.android.services.appnavstate.api.ActiveRoomsHolder -import io.element.android.services.appnavstate.impl.DefaultActiveRoomsHolder +import io.element.android.services.appnavstate.test.FakeActiveRoomsHolder import io.element.android.services.appnavstate.test.FakeAppNavigationStateService import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest @@ -128,7 +128,7 @@ class JoinedRoomLoadedFlowNodeTest { roomDetailsEntryPoint: RoomDetailsEntryPoint = FakeRoomDetailsEntryPoint(), spaceEntryPoint: SpaceEntryPoint = FakeSpaceEntryPoint(), forwardEntryPoint: ForwardEntryPoint = FakeForwardEntryPoint(), - activeRoomsHolder: ActiveRoomsHolder = DefaultActiveRoomsHolder(), + activeRoomsHolder: ActiveRoomsHolder = FakeActiveRoomsHolder(), matrixClient: FakeMatrixClient = FakeMatrixClient(), ) = JoinedRoomLoadedFlowNode( buildContext = BuildContext.root(savedStateMap = null), @@ -213,7 +213,7 @@ class JoinedRoomLoadedFlowNodeTest { val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint() val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root()) - val activeRoomsHolder = DefaultActiveRoomsHolder() + val activeRoomsHolder = FakeActiveRoomsHolder() val roomFlowNode = createJoinedRoomLoadedFlowNode( plugins = listOf(inputs, FakeJoinedRoomLoadedFlowNodeCallback()), messagesEntryPoint = fakeMessagesEntryPoint, @@ -236,7 +236,7 @@ class JoinedRoomLoadedFlowNodeTest { val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint() val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Root()) - val activeRoomsHolder = DefaultActiveRoomsHolder().apply { + val activeRoomsHolder = FakeActiveRoomsHolder().apply { addRoom(room) } val roomFlowNode = createJoinedRoomLoadedFlowNode( diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt index 73d55135fb..9ba98a3f72 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt @@ -19,8 +19,7 @@ import io.element.android.libraries.matrix.test.FakeSdkMetadata import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.apperror.api.AppErrorState import io.element.android.services.apperror.api.AppErrorStateService -import io.element.android.services.apperror.impl.DefaultAppErrorStateService -import io.element.android.services.toolbox.test.strings.FakeStringProvider +import io.element.android.services.apperror.test.FakeAppErrorStateService import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -44,10 +43,16 @@ class RootPresenterTest { @Test fun `present - passes app error state`() = runTest { val presenter = createRootPresenter( - appErrorService = DefaultAppErrorStateService( - stringProvider = FakeStringProvider(), - ).apply { - showError("Bad news", "Something bad happened") + appErrorService = FakeAppErrorStateService().apply { + setAppErrorState( + AppErrorState.Error( + title = "Bad news", + body = "Something bad happened", + dismiss = { + setAppErrorState(AppErrorState.NoError) + } + ) + ) } ) moleculeFlow(RecompositionMode.Immediate) { @@ -65,9 +70,7 @@ class RootPresenterTest { } private fun createRootPresenter( - appErrorService: AppErrorStateService = DefaultAppErrorStateService( - stringProvider = FakeStringProvider(), - ), + appErrorService: AppErrorStateService = FakeAppErrorStateService(), ): RootPresenter { return RootPresenter( crashDetectionPresenter = { aCrashDetectionState() }, diff --git a/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeActiveRoomsHolder.kt b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeActiveRoomsHolder.kt new file mode 100644 index 0000000000..7561932fc2 --- /dev/null +++ b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeActiveRoomsHolder.kt @@ -0,0 +1,36 @@ +/* + * 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.services.appnavstate.test + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.services.appnavstate.api.ActiveRoomsHolder + +class FakeActiveRoomsHolder : ActiveRoomsHolder { + private var room: JoinedRoom? = null + + override fun addRoom(room: JoinedRoom) { + this.room = room + } + + override fun getActiveRoom(sessionId: SessionId): JoinedRoom? { + return room + } + + override fun getActiveRoomMatching(sessionId: SessionId, roomId: RoomId): JoinedRoom? { + return null + } + + override fun removeRoom(sessionId: SessionId, roomId: RoomId) { + room = null + } + + override fun clear(sessionId: SessionId) { + } +} From 85823b3e6264a30d41332b580644dc6d5af95d74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Apr 2026 14:45:15 +0200 Subject: [PATCH 0091/1083] Fix compilation issue: RoomAliases does not exist anymore. --- .../io/element/android/appconfig/TimelineConfig.kt | 1 - .../eventformatter/impl/StateContentFormatter.kt | 9 --------- .../impl/DefaultPinnedMessagesBannerFormatterTest.kt | 1 - .../impl/DefaultRoomLatestEventFormatterTest.kt | 1 - .../matrix/api/notification/NotificationData.kt | 1 - .../android/libraries/matrix/api/room/StateEventType.kt | 1 - .../matrix/api/timeline/item/event/OtherState.kt | 1 - .../TimelineEventToNotificationContentMapper.kt | 1 - .../android/libraries/matrix/impl/room/StateEventType.kt | 2 -- .../timeline/item/event/TimelineEventContentMapper.kt | 1 - .../libraries/matrix/impl/room/StateEventTypeTest.kt | 2 -- .../impl/notifications/DefaultNotifiableEventResolver.kt | 1 - .../notifications/DefaultNotifiableEventResolverTest.kt | 1 - 13 files changed, 23 deletions(-) diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt index d4fe7d1fc5..7e5f064ef4 100644 --- a/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/TimelineConfig.kt @@ -18,7 +18,6 @@ object TimelineConfig { */ val excludedEvents = listOf( StateEventType.CallMember, - StateEventType.RoomAliases, StateEventType.RoomCanonicalAlias, StateEventType.RoomGuestAccess, StateEventType.RoomHistoryVisibility, diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt index f9d38fd8a7..5abfa89ef0 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/StateContentFormatter.kt @@ -118,15 +118,6 @@ class StateContentFormatter( "PolicyRuleUser" } } - OtherState.RoomAliases -> when (renderingMode) { - RenderingMode.RoomList -> { - Timber.v("Filtering timeline item for room state change: $content") - null - } - RenderingMode.Timeline -> { - "RoomAliases" - } - } OtherState.RoomCanonicalAlias -> when (renderingMode) { RenderingMode.RoomList -> { Timber.v("Filtering timeline item for room state change: $content") diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt index e91bed409e..38334afad5 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt @@ -601,7 +601,6 @@ class DefaultPinnedMessagesBannerFormatterTest { OtherState.PolicyRuleRoom, OtherState.PolicyRuleServer, OtherState.PolicyRuleUser, - OtherState.RoomAliases, OtherState.RoomCanonicalAlias, OtherState.RoomGuestAccess, OtherState.RoomHistoryVisibility, diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt index 2345af8a33..e1e8717c4c 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt @@ -746,7 +746,6 @@ class DefaultRoomLatestEventFormatterTest { OtherState.PolicyRuleRoom, OtherState.PolicyRuleServer, OtherState.PolicyRuleUser, - OtherState.RoomAliases, OtherState.RoomCanonicalAlias, OtherState.RoomGuestAccess, OtherState.RoomHistoryVisibility, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt index 5dce175237..c58a458865 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt @@ -95,7 +95,6 @@ sealed interface NotificationContent { data object PolicyRuleRoom : StateEvent data object PolicyRuleServer : StateEvent data object PolicyRuleUser : StateEvent - data object RoomAliases : StateEvent data object RoomAvatar : StateEvent data object RoomCanonicalAlias : StateEvent data object RoomCreate : StateEvent diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt index 41d64afff1..705dd25122 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt @@ -13,7 +13,6 @@ sealed interface StateEventType { data object PolicyRuleServer : StateEventType data object PolicyRuleUser : StateEventType data object CallMember : StateEventType - data object RoomAliases : StateEventType data object RoomAvatar : StateEventType data object RoomCanonicalAlias : StateEventType data object RoomCreate : StateEventType diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt index ed3f53169f..8b4a7eaa13 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/OtherState.kt @@ -16,7 +16,6 @@ sealed interface OtherState { data object PolicyRuleRoom : OtherState data object PolicyRuleServer : OtherState data object PolicyRuleUser : OtherState - data object RoomAliases : OtherState data class RoomAvatar(val url: String?) : OtherState data object RoomCanonicalAlias : OtherState data object RoomCreate : OtherState diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt index 96c4bdf3c4..7e65a1cc5c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt @@ -49,7 +49,6 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent { StateEventContent.PolicyRuleRoom -> NotificationContent.StateEvent.PolicyRuleRoom StateEventContent.PolicyRuleServer -> NotificationContent.StateEvent.PolicyRuleServer StateEventContent.PolicyRuleUser -> NotificationContent.StateEvent.PolicyRuleUser - StateEventContent.RoomAliases -> NotificationContent.StateEvent.RoomAliases StateEventContent.RoomAvatar -> NotificationContent.StateEvent.RoomAvatar StateEventContent.RoomCanonicalAlias -> NotificationContent.StateEvent.RoomCanonicalAlias StateEventContent.RoomCreate -> NotificationContent.StateEvent.RoomCreate diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt index 76fea0beef..897d9a34cb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt @@ -16,7 +16,6 @@ fun StateEventType.map(): RustStateEventType = when (this) { StateEventType.PolicyRuleServer -> RustStateEventType.PolicyRuleServer StateEventType.PolicyRuleUser -> RustStateEventType.PolicyRuleUser StateEventType.CallMember -> RustStateEventType.CallMember - StateEventType.RoomAliases -> RustStateEventType.RoomAliases StateEventType.RoomAvatar -> RustStateEventType.RoomAvatar StateEventType.RoomCanonicalAlias -> RustStateEventType.RoomCanonicalAlias StateEventType.RoomCreate -> RustStateEventType.RoomCreate @@ -46,7 +45,6 @@ fun RustStateEventType.map(): StateEventType = when (this) { RustStateEventType.PolicyRuleServer -> StateEventType.PolicyRuleServer RustStateEventType.PolicyRuleUser -> StateEventType.PolicyRuleUser RustStateEventType.CallMember -> StateEventType.CallMember - RustStateEventType.RoomAliases -> StateEventType.RoomAliases RustStateEventType.RoomAvatar -> StateEventType.RoomAvatar RustStateEventType.RoomCanonicalAlias -> StateEventType.RoomCanonicalAlias RustStateEventType.RoomCreate -> StateEventType.RoomCreate 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 2145bd2a7d..d617df60db 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 @@ -223,7 +223,6 @@ private fun RustOtherState.map(): OtherState { RustOtherState.PolicyRuleRoom -> OtherState.PolicyRuleRoom RustOtherState.PolicyRuleServer -> OtherState.PolicyRuleServer RustOtherState.PolicyRuleUser -> OtherState.PolicyRuleUser - RustOtherState.RoomAliases -> OtherState.RoomAliases is RustOtherState.RoomAvatar -> OtherState.RoomAvatar(url) RustOtherState.RoomCanonicalAlias -> OtherState.RoomCanonicalAlias RustOtherState.RoomCreate -> OtherState.RoomCreate diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt index 428bb7db7a..93a8f0908f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt @@ -20,7 +20,6 @@ class StateEventTypeTest { assertThat(RustStateEventType.PolicyRuleRoom.map()).isEqualTo(StateEventType.PolicyRuleRoom) assertThat(RustStateEventType.PolicyRuleServer.map()).isEqualTo(StateEventType.PolicyRuleServer) assertThat(RustStateEventType.PolicyRuleUser.map()).isEqualTo(StateEventType.PolicyRuleUser) - assertThat(RustStateEventType.RoomAliases.map()).isEqualTo(StateEventType.RoomAliases) assertThat(RustStateEventType.RoomAvatar.map()).isEqualTo(StateEventType.RoomAvatar) assertThat(RustStateEventType.RoomCanonicalAlias.map()).isEqualTo(StateEventType.RoomCanonicalAlias) assertThat(RustStateEventType.RoomCreate.map()).isEqualTo(StateEventType.RoomCreate) @@ -47,7 +46,6 @@ class StateEventTypeTest { assertThat(StateEventType.PolicyRuleRoom.map()).isEqualTo(RustStateEventType.PolicyRuleRoom) assertThat(StateEventType.PolicyRuleServer.map()).isEqualTo(RustStateEventType.PolicyRuleServer) assertThat(StateEventType.PolicyRuleUser.map()).isEqualTo(RustStateEventType.PolicyRuleUser) - assertThat(StateEventType.RoomAliases.map()).isEqualTo(RustStateEventType.RoomAliases) assertThat(StateEventType.RoomAvatar.map()).isEqualTo(RustStateEventType.RoomAvatar) assertThat(StateEventType.RoomCanonicalAlias.map()).isEqualTo(RustStateEventType.RoomCanonicalAlias) assertThat(StateEventType.RoomCreate.map()).isEqualTo(RustStateEventType.RoomCreate) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt index cf76b26e64..64583bd1d4 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt @@ -302,7 +302,6 @@ class DefaultNotifiableEventResolver( NotificationContent.StateEvent.PolicyRuleRoom, NotificationContent.StateEvent.PolicyRuleServer, NotificationContent.StateEvent.PolicyRuleUser, - NotificationContent.StateEvent.RoomAliases, NotificationContent.StateEvent.RoomAvatar, NotificationContent.StateEvent.RoomCanonicalAlias, NotificationContent.StateEvent.RoomCreate, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 63b903a3f7..44ce65d4ac 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -835,7 +835,6 @@ class DefaultNotifiableEventResolverTest { testNoResults(NotificationContent.StateEvent.PolicyRuleRoom) testNoResults(NotificationContent.StateEvent.PolicyRuleServer) testNoResults(NotificationContent.StateEvent.PolicyRuleUser) - testNoResults(NotificationContent.StateEvent.RoomAliases) testNoResults(NotificationContent.StateEvent.RoomAvatar) testNoResults(NotificationContent.StateEvent.RoomCanonicalAlias) testNoResults(NotificationContent.StateEvent.RoomCreate) From 8033d0f2117f642d3a252d5f5137b2e73e81939d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 10:00:54 +0200 Subject: [PATCH 0092/1083] Update telephoto to v0.19.0 (#6558) 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 8a6f95bc7e..709173b5d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -47,7 +47,7 @@ showkase = "1.0.5" appyx = "1.7.1" sqldelight = "2.3.2" wysiwyg = "2.41.1" -telephoto = "0.18.0" +telephoto = "0.19.0" haze = "1.7.2" # Dependency analysis From b6ce6a95c0fe3c96bd1c37f82ae27ff5622edb19 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Apr 2026 10:54:54 +0200 Subject: [PATCH 0093/1083] Remove FF `SpaceSettings` --- .../impl/root/SecurityAndPrivacyPresenter.kt | 4 ---- .../impl/root/SecurityAndPrivacyState.kt | 3 +-- .../root/SecurityAndPrivacyStateProvider.kt | 2 -- .../root/SecurityAndPrivacyPresenterTest.kt | 19 ------------------ .../space/impl/root/SpacePresenter.kt | 10 ++-------- .../space/impl/root/SpacePresenterTest.kt | 20 +------------------ .../libraries/featureflag/api/FeatureFlags.kt | 7 ------- 7 files changed, 4 insertions(+), 61 deletions(-) diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt index 9230c1183a..48ab41a820 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenter.kt @@ -78,9 +78,6 @@ class SecurityAndPrivacyPresenter( val isKnockEnabled by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock) }.collectAsState(false) - val isSpaceSettingsEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.SpaceSettings) - }.collectAsState(false) val saveAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } val homeserverName = remember { matrixClient.userIdServerName() } @@ -248,7 +245,6 @@ class SecurityAndPrivacyPresenter( saveAction = saveAction.value, permissions = permissions, isSpace = roomInfo.isSpace, - isSpaceSettingsEnabled = isSpaceSettingsEnabled, selectableJoinedSpaces = selectableJoinedSpaces, spaceSelectionMode = spaceSelectionMode, eventSink = ::handleEvent, diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyState.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyState.kt index 6ec47ba183..26e77b3c70 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyState.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyState.kt @@ -29,7 +29,6 @@ data class SecurityAndPrivacyState( val homeserverName: String, val showEnableEncryptionConfirmation: Boolean, private val isKnockEnabled: Boolean, - private val isSpaceSettingsEnabled: Boolean, val saveAction: AsyncAction, val isSpace: Boolean, private val permissions: SecurityAndPrivacyPermissions, @@ -37,7 +36,7 @@ data class SecurityAndPrivacyState( private val spaceSelectionMode: SpaceSelectionMode, val eventSink: (SecurityAndPrivacyEvent) -> Unit ) { - val isSpaceMemberSelectable = isSpaceSettingsEnabled && spaceSelectionMode != SpaceSelectionMode.None + val isSpaceMemberSelectable = spaceSelectionMode != SpaceSelectionMode.None // Show SpaceMember option in two cases: // - SpaceMember is the current saved value diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyStateProvider.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyStateProvider.kt index 95cb45d641..19124302e3 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyStateProvider.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyStateProvider.kt @@ -138,7 +138,6 @@ fun aSecurityAndPrivacyState( isSpace: Boolean = false, selectableJoinedSpaces: Set = emptySet(), spaceSelectionMode: SpaceSelectionMode = SpaceSelectionMode.None, - isSpaceSettingsEnabled: Boolean = true, eventSink: (SecurityAndPrivacyEvent) -> Unit = {} ) = SecurityAndPrivacyState( editedSettings = editedSettings, @@ -151,6 +150,5 @@ fun aSecurityAndPrivacyState( isSpace = isSpace, selectableJoinedSpaces = selectableJoinedSpaces.toImmutableSet(), spaceSelectionMode = spaceSelectionMode, - isSpaceSettingsEnabled = isSpaceSettingsEnabled, eventSink = eventSink, ) diff --git a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenterTest.kt b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenterTest.kt index d2844c79f0..34b4222053 100644 --- a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenterTest.kt +++ b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyPresenterTest.kt @@ -416,11 +416,6 @@ class SecurityAndPrivacyPresenterTest { val presenter = createSecurityAndPrivacyPresenter( room = room, matrixClient = client, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.SpaceSettings.key to true, - ) - ) ) presenter.test { skipItems(1) @@ -461,11 +456,6 @@ class SecurityAndPrivacyPresenterTest { room = room, navigator = navigator, matrixClient = client, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.SpaceSettings.key to true, - ) - ) ) presenter.test { skipItems(1) @@ -587,7 +577,6 @@ class SecurityAndPrivacyPresenterTest { featureFlagService = FakeFeatureFlagService( initialState = mapOf( FeatureFlags.Knock.key to true, - FeatureFlags.SpaceSettings.key to true, ) ) ) @@ -633,7 +622,6 @@ class SecurityAndPrivacyPresenterTest { featureFlagService = FakeFeatureFlagService( initialState = mapOf( FeatureFlags.Knock.key to true, - FeatureFlags.SpaceSettings.key to true, ) ) ) @@ -859,9 +847,6 @@ class SecurityAndPrivacyPresenterTest { val presenter = createSecurityAndPrivacyPresenter( room = room, matrixClient = client, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.SpaceSettings.key to true) - ) ) presenter.test { skipItems(1) @@ -901,9 +886,6 @@ class SecurityAndPrivacyPresenterTest { val presenter = createSecurityAndPrivacyPresenter( room = room, matrixClient = client, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.SpaceSettings.key to true) - ) ) presenter.test { skipItems(1) @@ -975,7 +957,6 @@ class SecurityAndPrivacyPresenterTest { featureFlagService = FakeFeatureFlagService( initialState = mapOf( FeatureFlags.Knock.key to true, - FeatureFlags.SpaceSettings.key to true, ) ) ) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpacePresenter.kt index 807d139e6a..5ce6575493 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpacePresenter.kt @@ -29,8 +29,6 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.di.annotations.SessionCoroutineScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias @@ -66,7 +64,6 @@ class SpacePresenter( private val joinRoom: JoinRoom, private val acceptDeclineInvitePresenter: Presenter, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, - private val featureFlagService: FeatureFlagService, private val spaceService: SpaceService, ) : Presenter { private var children by mutableStateOf>(persistentListOf()) @@ -99,16 +96,13 @@ class SpacePresenter( val permissions by room.permissionsAsState(SpacePermissions.DEFAULT) { perms -> perms.spacePermissions() } - val isSpaceSettingsEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.SpaceSettings) - }.collectAsState(false) val roomInfo by room.roomInfoFlow.collectAsState() val canAccessSpaceSettings by remember { - derivedStateOf { isSpaceSettingsEnabled && permissions.settingsPermissions.hasAny(roomInfo.joinRule) } + derivedStateOf { permissions.settingsPermissions.hasAny(roomInfo.joinRule) } } val canEditSpaceGraph by remember { - derivedStateOf { isSpaceSettingsEnabled && permissions.canEditSpaceGraph } + derivedStateOf { permissions.canEditSpaceGraph } } val (joinActions, setJoinActions) = remember { mutableStateOf(emptyMap>()) } diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt index 1d38e2e0f7..e183de6f27 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt @@ -19,8 +19,6 @@ import io.element.android.features.invite.api.toInviteData import io.element.android.features.invite.test.InMemorySeenInvitesStore import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomIdOrAlias @@ -75,16 +73,7 @@ class SpacePresenterTest { } @Test - fun `present - canAccessSpaceSettings false when space settings ff is enabled but no permissions`() = runTest { - val presenter = createSpacePresenter(spaceSettingsEnabled = true) - presenter.test { - val state = awaitItem() - assertThat(state.canAccessSpaceSettings).isFalse() - } - } - - @Test - fun `present - canAccessSpaceSettings true when space settings ff is enabled and has permissions`() = runTest { + fun `present - canAccessSpaceSettings true when has permissions`() = runTest { val room = FakeBaseRoom( roomPermissions = FakeRoomPermissions( canSendState = { true } @@ -92,7 +81,6 @@ class SpacePresenterTest { ) val presenter = createSpacePresenter( room = room, - spaceSettingsEnabled = true, ) presenter.test { skipItems(1) @@ -627,7 +615,6 @@ class SpacePresenterTest { lambda = { _, _, _ -> Result.success(Unit) }, ), acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() }, - spaceSettingsEnabled: Boolean = false, spaceService: FakeSpaceService = FakeSpaceService(), ): SpacePresenter { return SpacePresenter( @@ -638,11 +625,6 @@ class SpacePresenterTest { joinRoom = joinRoom, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, sessionCoroutineScope = this, - featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.SpaceSettings.key to spaceSettingsEnabled, - ) - ), spaceService = spaceService, ) } 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 a8e59e5c6d..5a80354b07 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 @@ -77,13 +77,6 @@ enum class FeatureFlags( defaultValue = { true }, isFinished = false, ), - SpaceSettings( - key = "feature.spaceSettings", - title = "Space settings", - description = "Allow managing space settings such as details, permissions and privacy.", - defaultValue = { true }, - isFinished = false, - ), RoomListSpaceFilters( key = "feature.roomListSpaceFilters", title = "Room list space filters", From 64b0a7eef39548a8a8c53ebadfb284fb17e7cec6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Apr 2026 11:00:55 +0200 Subject: [PATCH 0094/1083] Remove FF `CreateSpaces` --- .../configureroom/ConfigureRoomPresenter.kt | 9 +-- .../features/home/impl/HomePresenter.kt | 6 -- .../android/features/home/impl/HomeState.kt | 1 - .../android/features/home/impl/HomeView.kt | 69 ++++++++----------- .../home/impl/spaces/HomeSpacesPresenter.kt | 5 -- .../home/impl/spaces/HomeSpacesState.kt | 1 - .../impl/spaces/HomeSpacesStateProvider.kt | 10 --- .../home/impl/spaces/HomeSpacesView.kt | 2 +- .../features/home/impl/HomePresenterTest.kt | 32 --------- .../impl/spaces/HomeSpacesPresenterTest.kt | 10 --- .../libraries/featureflag/api/FeatureFlags.kt | 7 -- 11 files changed, 33 insertions(+), 119 deletions(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index 38d6132e14..0d74ca05bf 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -84,7 +84,6 @@ class ConfigureRoomPresenter( @Composable override fun present(): ConfigureRoomState { - val canAddRoomToSpace by featureFlagService.isFeatureEnabledFlow(FeatureFlags.CreateSpaces).collectAsState(false) val cameraPermissionState = cameraPermissionPresenter.present() val createRoomConfig by dataStore.getCreateRoomConfigFlow().collectAsState() val homeserverName = remember { matrixClient.userIdServerName() } @@ -113,12 +112,8 @@ class ConfigureRoomPresenter( } var spaces by remember { mutableStateOf>(persistentListOf()) } - LaunchedEffect(canAddRoomToSpace) { - spaces = if (canAddRoomToSpace) { - matrixClient.spaceService.editableSpaces().getOrElse { emptyList() }.toImmutableList() - } else { - persistentListOf() - } + LaunchedEffect(Unit) { + spaces = matrixClient.spaceService.editableSpaces().getOrElse { emptyList() }.toImmutableList() val parentSpace = spaces.find { it.roomId == initialParentSpaceId } parentSpace?.let { dataStore.setParentSpace(parentSpace = parentSpace, updateVisibility = true) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt index 6878f4d53c..5985e33127 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt @@ -94,12 +94,6 @@ class HomePresenter( } } - LaunchedEffect(homeSpacesState.canCreateSpaces, homeSpacesState.spaceRooms.isEmpty()) { - // If the flag to create spaces is disabled and the last space is left, ensure that the Chat view is rendered. - if (!homeSpacesState.canCreateSpaces && homeSpacesState.spaceRooms.isEmpty()) { - currentHomeNavigationBarItemOrdinal = HomeNavigationBarItem.Chats.ordinal - } - } val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() return HomeState( currentUserAndNeighbors = currentUserAndNeighbors, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt index 934dac831e..ae59ef8eb9 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt @@ -34,5 +34,4 @@ data class HomeState( ) { val isBackHandlerEnabled = currentHomeNavigationBarItem != HomeNavigationBarItem.Chats || roomListState.spaceFiltersState is SpaceFiltersState.Selected val displayRoomListFilters = currentHomeNavigationBarItem == HomeNavigationBarItem.Chats && roomListState.displayFilters - val showNavigationBar = homeSpacesState.canCreateSpaces || homeSpacesState.spaceRooms.isNotEmpty() } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt index ddf8b1c499..6956ba6ba5 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt @@ -199,50 +199,41 @@ private fun HomeScaffold( ) }, floatingActionButton = { - if (state.showNavigationBar) { - val coroutineScope = rememberCoroutineScope() - HomeBottomBar( - currentHomeNavigationBarItem = state.currentHomeNavigationBarItem, - onItemClick = { item -> - // scroll to top if selecting the same item - if (item == state.currentHomeNavigationBarItem) { - val lazyListStateTarget = when (item) { - HomeNavigationBarItem.Chats -> roomsLazyListState - HomeNavigationBarItem.Spaces -> spacesLazyListState - } - coroutineScope.launch { - if (lazyListStateTarget.firstVisibleItemIndex > 10) { - lazyListStateTarget.scrollToItem(10) - } - // Also reset the scrollBehavior height offset as it's not triggered by programmatic scrolls - scrollBehavior.state.heightOffset = 0f - lazyListStateTarget.animateScrollToItem(0) - } - } else { - state.eventSink(HomeEvent.SelectHomeNavigationBarItem(item)) + val coroutineScope = rememberCoroutineScope() + HomeBottomBar( + currentHomeNavigationBarItem = state.currentHomeNavigationBarItem, + onItemClick = { item -> + // scroll to top if selecting the same item + if (item == state.currentHomeNavigationBarItem) { + val lazyListStateTarget = when (item) { + HomeNavigationBarItem.Chats -> roomsLazyListState + HomeNavigationBarItem.Spaces -> spacesLazyListState } - }, - floatingActionButton = when (state.currentHomeNavigationBarItem) { + coroutineScope.launch { + if (lazyListStateTarget.firstVisibleItemIndex > 10) { + lazyListStateTarget.scrollToItem(10) + } + // Also reset the scrollBehavior height offset as it's not triggered by programmatic scrolls + scrollBehavior.state.heightOffset = 0f + lazyListStateTarget.animateScrollToItem(0) + } + } else { + state.eventSink(HomeEvent.SelectHomeNavigationBarItem(item)) + } + }, + floatingActionButton = { + when (state.currentHomeNavigationBarItem) { HomeNavigationBarItem.Chats -> { - { - HomeFloatingActionButton(onStartChatClick, CommonStrings.action_create_room) - } + HomeFloatingActionButton(onStartChatClick, CommonStrings.action_create_room) } - HomeNavigationBarItem.Spaces -> if (state.homeSpacesState.canCreateSpaces) { - { - HomeFloatingActionButton(onCreateSpaceClick, CommonStrings.action_create_space) - } - } else { - // No FAB for spaces if we cannot create spaces - null + HomeNavigationBarItem.Spaces -> { + HomeFloatingActionButton(onCreateSpaceClick, CommonStrings.action_create_space) } - }, - ) - } else { - HomeFloatingActionButton(onStartChatClick, CommonStrings.action_create_room) - } + } + }, + ) }, - floatingActionButtonPosition = if (state.showNavigationBar) FabPosition.Center else FabPosition.End, + floatingActionButtonPosition = FabPosition.Center, content = { padding -> val contentPadding = PaddingValues( bottom = 96.dp, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt index 707ac73261..b758a1e593 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenter.kt @@ -15,8 +15,6 @@ import androidx.compose.runtime.remember import dev.zacsweers.metro.Inject import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import kotlinx.collections.immutable.persistentListOf @@ -29,11 +27,9 @@ import kotlinx.coroutines.flow.map class HomeSpacesPresenter( private val client: MatrixClient, private val seenInvitesStore: SeenInvitesStore, - private val featureFlagsService: FeatureFlagService, ) : Presenter { @Composable override fun present(): HomeSpacesState { - val canCreateSpaces by featureFlagsService.isFeatureEnabledFlow(FeatureFlags.CreateSpaces).collectAsState(false) val hideInvitesAvatar by client.rememberHideInvitesAvatar() val spaceRooms by remember { client.spaceService.topLevelSpacesFlow.map { it.toImmutableList() } @@ -52,7 +48,6 @@ class HomeSpacesPresenter( spaceRooms = spaceRooms, seenSpaceInvites = seenSpaceInvites, hideInvitesAvatar = hideInvitesAvatar, - canCreateSpaces = canCreateSpaces, // TODO enable once we can link to the screen to explore public spaces canExploreSpaces = false, eventSink = ::handleEvent, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt index 84b2dc7f52..e93f04291e 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesState.kt @@ -18,7 +18,6 @@ data class HomeSpacesState( val spaceRooms: ImmutableList, val seenSpaceInvites: ImmutableSet, val hideInvitesAvatar: Boolean, - val canCreateSpaces: Boolean, val canExploreSpaces: Boolean, val eventSink: (HomeSpacesEvents) -> Unit, ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt index a65f29cc2f..17f2cbad31 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesStateProvider.kt @@ -30,17 +30,9 @@ open class HomeSpacesStateProvider : PreviewParameterProvider { ), spaceRooms = aListOfSpaceRooms(), ), - aHomeSpacesState( - space = CurrentSpace.Space( - spaceRoom = aSpaceRoom(roomId = RoomId("!mySpace:example.com")) - ), - spaceRooms = aListOfSpaceRooms(), - canCreateSpaces = false, - ), aHomeSpacesState( space = CurrentSpace.Root, spaceRooms = emptyList(), - canCreateSpaces = true, ), ) } @@ -50,7 +42,6 @@ internal fun aHomeSpacesState( spaceRooms: List = aListOfSpaceRooms(), seenSpaceInvites: Set = emptySet(), hideInvitesAvatar: Boolean = false, - canCreateSpaces: Boolean = true, canExploreSpaces: Boolean = true, eventSink: (HomeSpacesEvents) -> Unit = {}, ) = HomeSpacesState( @@ -58,7 +49,6 @@ internal fun aHomeSpacesState( spaceRooms = spaceRooms.toImmutableList(), seenSpaceInvites = seenSpaceInvites.toImmutableSet(), hideInvitesAvatar = hideInvitesAvatar, - canCreateSpaces = canCreateSpaces, canExploreSpaces = canExploreSpaces, eventSink = eventSink, ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt index c563e6eb26..9125912bf0 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesView.kt @@ -55,7 +55,7 @@ fun HomeSpacesView( onExploreClick: () -> Unit, modifier: Modifier = Modifier, ) { - if (state.canCreateSpaces && state.spaceRooms.isEmpty()) { + if (state.spaceRooms.isEmpty()) { EmptySpaceHomeView( modifier = modifier.padding(contentPadding), onCreateSpaceClick = onCreateSpaceClick, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt index 4002844947..90cf160cc6 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt @@ -33,7 +33,6 @@ import io.element.android.libraries.matrix.test.sync.FakeSyncService import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData -import io.element.android.tests.testutils.MutablePresenter import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -79,7 +78,6 @@ class HomePresenterTest { MatrixUser(A_USER_ID, A_USER_NAME, AN_AVATAR_URL) ) assertThat(withUserState.showAvatarIndicator).isFalse() - assertThat(withUserState.showNavigationBar).isTrue() } } @@ -158,36 +156,6 @@ class HomePresenterTest { .with(value(Announcement.Space)) } } - - @Test - fun `present - NavigationBar is hidden when the last space is left when the user can't create new spaces`() = runTest { - val homeSpacesPresenter = MutablePresenter(aHomeSpacesState()) - val presenter = createHomePresenter( - sessionStore = InMemorySessionStore( - updateUserProfileResult = { _, _, _ -> }, - ), - homeSpacesPresenter = homeSpacesPresenter, - announcementService = FakeAnnouncementService( - showAnnouncementResult = {}, - ) - ) - presenter.test { - val initialState = awaitItem() - assertThat(initialState.currentHomeNavigationBarItem).isEqualTo(HomeNavigationBarItem.Chats) - assertThat(initialState.showNavigationBar).isTrue() - // User navigate to Spaces - initialState.eventSink(HomeEvent.SelectHomeNavigationBarItem(HomeNavigationBarItem.Spaces)) - val spaceState = awaitItem() - assertThat(spaceState.currentHomeNavigationBarItem).isEqualTo(HomeNavigationBarItem.Spaces) - // The last space is left - homeSpacesPresenter.updateState(aHomeSpacesState(spaceRooms = emptyList(), canCreateSpaces = false)) - skipItems(1) - val finalState = awaitItem() - // We are back to Chats - assertThat(finalState.currentHomeNavigationBarItem).isEqualTo(HomeNavigationBarItem.Chats) - assertThat(finalState.showNavigationBar).isFalse() - } - } } internal fun createHomePresenter( diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenterTest.kt index 43d3a8896d..c7608833ac 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spaces/HomeSpacesPresenterTest.kt @@ -11,9 +11,6 @@ package io.element.android.features.home.impl.spaces import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.test.InMemorySeenInvitesStore -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.tests.testutils.test @@ -26,25 +23,18 @@ class HomeSpacesPresenterTest { val presenter = createPresenter() presenter.test { val state = awaitItem() - // canCreateSpaces is initially false - assertThat(state.canCreateSpaces).isFalse() assertThat(state.space).isEqualTo(CurrentSpace.Root) assertThat(state.spaceRooms).isEmpty() assertThat(state.hideInvitesAvatar).isFalse() assertThat(state.seenSpaceInvites).isEmpty() - - // It'll eventually be true - assertThat(awaitItem().canCreateSpaces).isTrue() } } private fun createPresenter( client: MatrixClient = FakeMatrixClient(), seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), - featureFlagsService: FeatureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.CreateSpaces.key to true)), ) = HomeSpacesPresenter( client = client, seenInvitesStore = seenInvitesStore, - featureFlagsService = featureFlagsService, ) } 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 5a80354b07..d0683fe53e 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 @@ -70,13 +70,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - CreateSpaces( - key = "feature.createSpaces", - title = "Create spaces", - description = "Allow creating spaces.", - defaultValue = { true }, - isFinished = false, - ), RoomListSpaceFilters( key = "feature.roomListSpaceFilters", title = "Room list space filters", From 5eb9bed386595e204db08626af3c0f3ec21c889b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Apr 2026 11:33:08 +0200 Subject: [PATCH 0095/1083] Remove FF `RoomListSpaceFilters` --- .../spacefilters/SpaceFiltersPresenter.kt | 9 +--- .../spacefilters/SpaceFiltersPresenterTest.kt | 49 +------------------ .../libraries/featureflag/api/FeatureFlags.kt | 7 --- 3 files changed, 3 insertions(+), 62 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt index 9813732bdb..76fce9bfec 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt @@ -17,8 +17,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter import kotlinx.collections.immutable.persistentListOf @@ -27,20 +25,15 @@ import kotlinx.coroutines.flow.map @Inject class SpaceFiltersPresenter( - private val featureFlagService: FeatureFlagService, private val matrixClient: MatrixClient, ) : Presenter { @Composable override fun present(): SpaceFiltersState { - val isFeatureEnabled by featureFlagService - .isFeatureEnabledFlow(FeatureFlags.RoomListSpaceFilters) - .collectAsState(initial = false) - val availableFilters by remember { matrixClient.spaceService.spaceFiltersFlow.map { it.toImmutableList() } }.collectAsState(initial = persistentListOf()) - if (!isFeatureEnabled || availableFilters.isEmpty()) { + if (availableFilters.isEmpty()) { return SpaceFiltersState.Disabled } diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt index 278a268864..31a47d830f 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt @@ -8,8 +8,6 @@ package io.element.android.features.home.impl.spacefilters import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.spaces.FakeSpaceService @@ -21,26 +19,9 @@ import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class SpaceFiltersPresenterTest { - @Test - fun `present - when feature flag is disabled returns Disabled state`() = runTest { - val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to false) - ) - ) - presenter.test { - val state = awaitItem() - assertThat(state).isEqualTo(SpaceFiltersState.Disabled) - } - } - @Test fun `present - when available filters is empty returns Disabled state`() = runTest { - val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ) - ) + val presenter = createSpaceFiltersPresenter() presenter.test { val state = awaitLastSequentialItem() assertThat(state).isEqualTo(SpaceFiltersState.Disabled) @@ -48,15 +29,12 @@ class SpaceFiltersPresenterTest { } @Test - fun `present - when feature flag is enabled and filters exist returns Unselected state`() = runTest { + fun `present - when filters exist returns Unselected state`() = runTest { val spaceFilter = aSpaceServiceFilter(displayName = "Test Space") val spaceService = FakeSpaceService() val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -75,9 +53,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -99,9 +74,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -129,9 +101,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -159,9 +128,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -196,9 +162,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -224,9 +187,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -271,9 +231,6 @@ class SpaceFiltersPresenterTest { val matrixClient = FakeMatrixClient(spaceService = spaceService) val presenter = createSpaceFiltersPresenter( - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) - ), matrixClient = matrixClient, ) presenter.test { @@ -302,11 +259,9 @@ class SpaceFiltersPresenterTest { } private fun createSpaceFiltersPresenter( - featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), matrixClient: FakeMatrixClient = FakeMatrixClient(), ): SpaceFiltersPresenter { return SpaceFiltersPresenter( - featureFlagService = featureFlagService, matrixClient = matrixClient, ) } 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 d0683fe53e..5b65a32f61 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 @@ -70,13 +70,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - RoomListSpaceFilters( - key = "feature.roomListSpaceFilters", - title = "Room list space filters", - description = "Allow filtering the room list by space.", - defaultValue = { true }, - isFinished = false, - ), PrintLogsToLogcat( key = "feature.print_logs_to_logcat", title = "Print logs to logcat", From 8cbc03b9a256dd79caecca43854bcbe83cabc142 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Apr 2026 12:09:51 +0200 Subject: [PATCH 0096/1083] Fix test compilation issue. --- .../fixtures/factories/EventTimelineItem.kt | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/EventTimelineItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/EventTimelineItem.kt index 41823a0fbb..8689de3c9b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/EventTimelineItem.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/EventTimelineItem.kt @@ -14,10 +14,9 @@ import io.element.android.libraries.matrix.test.A_USER_ID import org.matrix.rustcomponents.sdk.EventOrTransactionId import org.matrix.rustcomponents.sdk.EventSendState import org.matrix.rustcomponents.sdk.EventTimelineItem -import org.matrix.rustcomponents.sdk.EventTimelineItemDebugInfo +import org.matrix.rustcomponents.sdk.LazyTimelineItemProvider import org.matrix.rustcomponents.sdk.ProfileDetails import org.matrix.rustcomponents.sdk.Receipt -import org.matrix.rustcomponents.sdk.ShieldState import org.matrix.rustcomponents.sdk.TimelineItemContent import uniffi.matrix_sdk_ui.EventItemOrigin @@ -26,37 +25,35 @@ internal fun aRustEventTimelineItem( eventOrTransactionId: EventOrTransactionId = EventOrTransactionId.EventId(AN_EVENT_ID.value), sender: String = A_USER_ID.value, senderProfile: ProfileDetails = ProfileDetails.Unavailable, + forwarder: String? = null, + forwarderProfile: ProfileDetails? = null, isOwn: Boolean = true, isEditable: Boolean = true, content: TimelineItemContent = aRustTimelineItemContentMsgLike(), + eventTypeRaw: String? = null, timestamp: ULong = 0uL, - debugInfo: EventTimelineItemDebugInfo = anEventTimelineItemDebugInfo(), localSendState: EventSendState? = null, + localCreatedAt: ULong? = null, readReceipts: Map = emptyMap(), origin: EventItemOrigin? = EventItemOrigin.SYNC, canBeRepliedTo: Boolean = true, - shieldsState: ShieldState = ShieldState.None, - localCreatedAt: ULong? = null, - forwarder: String? = null, - forwarderProfile: ProfileDetails? = null, + lazyProvider: LazyTimelineItemProvider = FakeFfiLazyTimelineItemProvider(), ) = EventTimelineItem( isRemote = isRemote, eventOrTransactionId = eventOrTransactionId, sender = sender, senderProfile = senderProfile, - timestamp = timestamp, - isOwn = isOwn, - isEditable = isEditable, - canBeRepliedTo = canBeRepliedTo, - content = content, - localSendState = localSendState, - readReceipts = readReceipts, - origin = origin, - localCreatedAt = localCreatedAt, - lazyProvider = FakeFfiLazyTimelineItemProvider( - debugInfo = debugInfo, - shieldsState = shieldsState, - ), forwarder = forwarder, forwarderProfile = forwarderProfile, + isOwn = isOwn, + isEditable = isEditable, + content = content, + eventTypeRaw = eventTypeRaw, + timestamp = timestamp, + localSendState = localSendState, + localCreatedAt = localCreatedAt, + readReceipts = readReceipts, + origin = origin, + canBeRepliedTo = canBeRepliedTo, + lazyProvider = lazyProvider, ) From 9e8c7afa1ce4e92a2c12f16f28e6a81b34ff0de7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 12:14:22 +0200 Subject: [PATCH 0097/1083] Update dependency net.zetetic:sqlcipher-android to v4.14.1 (#6552) 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 709173b5d7..b9548f371c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -200,7 +200,7 @@ matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } -sqlcipher = "net.zetetic:sqlcipher-android:4.14.0" +sqlcipher = "net.zetetic:sqlcipher-android:4.14.1" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" unifiedpush = "org.unifiedpush.android:connector:3.3.2" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" From 3ba0689cf847ea0383bac5055311030a344fb2b5 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 9 Apr 2026 10:18:06 +0000 Subject: [PATCH 0098/1083] Update screenshots --- .../features.home.impl.spaces_HomeSpacesView_Day_2_en.png | 4 ++-- .../features.home.impl.spaces_HomeSpacesView_Day_3_en.png | 3 --- .../features.home.impl.spaces_HomeSpacesView_Night_2_en.png | 4 ++-- .../features.home.impl.spaces_HomeSpacesView_Night_3_en.png | 3 --- 4 files changed, 4 insertions(+), 10 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_2_en.png index de86c4285d..03d7d97186 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d69d687090971ab7e9b87f959521109fbed48413ef217e1be3da8d7d985038b -size 38751 +oid sha256:ecd79d3f8c4efbb54efa6a5b8dee79274ae9957b01146025dab42a45fc328fc0 +size 24740 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_3_en.png deleted file mode 100644 index 03d7d97186..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Day_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ecd79d3f8c4efbb54efa6a5b8dee79274ae9957b01146025dab42a45fc328fc0 -size 24740 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_2_en.png index 07e9ef1e28..049aa93a8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2a6a7f3188eb9635ade7c0bbc2239257cfbe3166f4a6fb7917a1e5578f51d9e -size 37436 +oid sha256:0fd37517b8913e2bac3275f717aa15bed18055a7525e0404b25b43cb8bd8422d +size 23840 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_3_en.png deleted file mode 100644 index 049aa93a8a..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.spaces_HomeSpacesView_Night_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0fd37517b8913e2bac3275f717aa15bed18055a7525e0404b25b43cb8bd8422d -size 23840 From f037603928114b19775a1342ff65e1ad5cc13e27 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 9 Apr 2026 10:26:40 +0000 Subject: [PATCH 0099/1083] Update screenshots --- ...y_0_en.png => services.apperror.api_AppErrorView_Day_0_en.png} | 0 ...0_en.png => services.apperror.api_AppErrorView_Night_0_en.png} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/uitests/src/test/snapshots/images/{services.apperror.impl_AppErrorView_Day_0_en.png => services.apperror.api_AppErrorView_Day_0_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{services.apperror.impl_AppErrorView_Night_0_en.png => services.apperror.api_AppErrorView_Night_0_en.png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/services.apperror.api_AppErrorView_Day_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Day_0_en.png rename to tests/uitests/src/test/snapshots/images/services.apperror.api_AppErrorView_Day_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/services.apperror.api_AppErrorView_Night_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/services.apperror.impl_AppErrorView_Night_0_en.png rename to tests/uitests/src/test/snapshots/images/services.apperror.api_AppErrorView_Night_0_en.png From 9ba8798175e8ec8e812baf5a316207d594f1d8f2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Apr 2026 14:43:24 +0200 Subject: [PATCH 0100/1083] 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 1929973209712349c087aa99b59f8804999278d0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Apr 2026 12:53:53 +0200 Subject: [PATCH 0101/1083] Remove space announcement. Rework to keep the logic for fullscreen announcement. --- .../features/announcement/api/Announcement.kt | 9 +- .../announcement/impl/AnnouncementEvent.kt | 17 ++ .../impl/AnnouncementPresenter.kt | 40 +++- .../announcement/impl/AnnouncementState.kt | 11 +- .../impl/AnnouncementStateProvider.kt | 30 +++ .../impl/DefaultAnnouncementService.kt | 44 +--- .../impl/di/AnnouncementModule.kt | 29 --- .../fullscreen/FullscreenAnnouncementView.kt | 225 ++++++++++++++++++ .../impl/spaces/SpaceAnnouncementEvents.kt | 13 - .../impl/spaces/SpaceAnnouncementPresenter.kt | 40 ---- .../impl/spaces/SpaceAnnouncementState.kt | 13 - .../spaces/SpaceAnnouncementStateProvider.kt | 24 -- .../impl/spaces/SpaceAnnouncementView.kt | 158 ------------ .../impl/store/DefaultAnnouncementStore.kt | 6 +- .../impl/AnnouncementPresenterTest.kt | 14 +- .../impl/DefaultAnnouncementServiceTest.kt | 25 +- .../FullscreenAnnouncementViewTest.kt} | 36 +-- .../spaces/SpaceAnnouncementPresenterTest.kt | 41 ---- .../impl/store/InMemoryAnnouncementStore.kt | 8 +- .../features/home/impl/HomePresenter.kt | 8 +- .../features/home/impl/HomePresenterTest.kt | 13 - 21 files changed, 374 insertions(+), 430 deletions(-) create mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementEvent.kt create mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementStateProvider.kt delete mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/di/AnnouncementModule.kt create mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementView.kt delete mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementEvents.kt delete mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenter.kt delete mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementState.kt delete mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementStateProvider.kt delete mode 100644 features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt rename features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/{spaces/SpaceAnnouncementViewTest.kt => fullscreen/FullscreenAnnouncementViewTest.kt} (51%) delete mode 100644 features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenterTest.kt diff --git a/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt b/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt index 0bf35650a0..a83d167ee2 100644 --- a/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt +++ b/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt @@ -8,7 +8,10 @@ package io.element.android.features.announcement.api -enum class Announcement { - Space, - NewNotificationSound, +sealed interface Announcement { + sealed interface Fullscreen : Announcement { + data object Space : Fullscreen + } + + data object NewNotificationSound : Announcement } diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementEvent.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementEvent.kt new file mode 100644 index 0000000000..947a3ceeba --- /dev/null +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementEvent.kt @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 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.features.announcement.impl + +import io.element.android.features.announcement.api.Announcement + +sealed interface AnnouncementEvent { + data class Continue( + val announcement: Announcement.Fullscreen, + ) : AnnouncementEvent +} diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenter.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenter.kt index 508f1e44a0..bd45ddb956 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenter.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenter.kt @@ -12,12 +12,16 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import dev.zacsweers.metro.Inject import io.element.android.features.announcement.api.Announcement import io.element.android.features.announcement.impl.store.AnnouncementStatus import io.element.android.features.announcement.impl.store.AnnouncementStore import io.element.android.libraries.architecture.Presenter +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch @Inject class AnnouncementPresenter( @@ -25,13 +29,39 @@ class AnnouncementPresenter( ) : Presenter { @Composable override fun present(): AnnouncementState { - val showSpaceAnnouncement by remember { - announcementStore.announcementStatusFlow(Announcement.Space).map { - it == AnnouncementStatus.Show + val coroutineScope = rememberCoroutineScope() + + val fullscreenAnnouncementToShow by remember { + combine( + flowOf(Unit), + announcementStore.announcementStatusFlow(Announcement.Fullscreen.Space).map { + it == AnnouncementStatus.Show + }, + // Add other announcements here when needed + ) { _, showFullscreenSpace -> + when { + showFullscreenSpace -> Announcement.Fullscreen.Space + else -> { + null + } + } } - }.collectAsState(false) + }.collectAsState(null) + + fun handle(event: AnnouncementEvent) { + when (event) { + is AnnouncementEvent.Continue -> coroutineScope.launch { + announcementStore.setAnnouncementStatus( + announcement = event.announcement, + status = AnnouncementStatus.Shown, + ) + } + } + } + return AnnouncementState( - showSpaceAnnouncement = showSpaceAnnouncement, + announcement = fullscreenAnnouncementToShow, + eventSink = ::handle, ) } } diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt index e762dd607f..3ef47d6ed0 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt @@ -8,12 +8,9 @@ package io.element.android.features.announcement.impl -data class AnnouncementState( - val showSpaceAnnouncement: Boolean, -) +import io.element.android.features.announcement.api.Announcement -fun anAnnouncementState( - showSpaceAnnouncement: Boolean = false, -) = AnnouncementState( - showSpaceAnnouncement = showSpaceAnnouncement, +data class AnnouncementState( + val announcement: Announcement.Fullscreen? = null, + val eventSink: (AnnouncementEvent) -> Unit, ) diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementStateProvider.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementStateProvider.kt new file mode 100644 index 0000000000..2412fee167 --- /dev/null +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementStateProvider.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 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.features.announcement.impl + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.announcement.api.Announcement + +open class AnnouncementStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + anAnnouncementState(), + anAnnouncementState( + announcement = Announcement.Fullscreen.Space, + ), + ) +} + +fun anAnnouncementState( + announcement: Announcement.Fullscreen? = null, + eventSink: (AnnouncementEvent) -> Unit = {}, +) = AnnouncementState( + announcement = announcement, + eventSink = eventSink, +) diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementService.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementService.kt index 0e5c30178c..adb81db61a 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementService.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementService.kt @@ -8,35 +8,28 @@ package io.element.android.features.announcement.impl -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.features.announcement.api.Announcement import io.element.android.features.announcement.api.AnnouncementService -import io.element.android.features.announcement.impl.spaces.SpaceAnnouncementState -import io.element.android.features.announcement.impl.spaces.SpaceAnnouncementView +import io.element.android.features.announcement.impl.fullscreen.FullscreenAnnouncementView import io.element.android.features.announcement.impl.store.AnnouncementStatus import io.element.android.features.announcement.impl.store.AnnouncementStore -import io.element.android.libraries.architecture.Presenter import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOf @ContributesBinding(AppScope::class) class DefaultAnnouncementService( private val announcementStore: AnnouncementStore, - private val announcementPresenter: Presenter, - private val spaceAnnouncementPresenter: Presenter, + private val announcementPresenter: AnnouncementPresenter, ) : AnnouncementService { override suspend fun showAnnouncement(announcement: Announcement) { when (announcement) { - Announcement.Space -> showSpaceAnnouncement() + is Announcement.Fullscreen -> showFullscreenAnnouncement(announcement) Announcement.NewNotificationSound -> { announcementStore.setAnnouncementStatus(Announcement.NewNotificationSound, AnnouncementStatus.Show) } @@ -49,13 +42,10 @@ class DefaultAnnouncementService( override fun announcementsToShowFlow(): Flow> { return combine( - announcementStore.announcementStatusFlow(Announcement.Space), + flowOf(Unit), announcementStore.announcementStatusFlow(Announcement.NewNotificationSound), - ) { spaceAnnouncementStatus, newNotificationSoundStatus -> + ) { _, newNotificationSoundStatus -> buildList { - if (spaceAnnouncementStatus == AnnouncementStatus.Show) { - add(Announcement.Space) - } if (newNotificationSoundStatus == AnnouncementStatus.Show) { add(Announcement.NewNotificationSound) } @@ -63,27 +53,19 @@ class DefaultAnnouncementService( } } - private suspend fun showSpaceAnnouncement() { - val currentValue = announcementStore.announcementStatusFlow(Announcement.Space).first() + private suspend fun showFullscreenAnnouncement(announcement: Announcement.Fullscreen) { + val currentValue = announcementStore.announcementStatusFlow(announcement).first() if (currentValue == AnnouncementStatus.NeverShown) { - announcementStore.setAnnouncementStatus(Announcement.Space, AnnouncementStatus.Show) + announcementStore.setAnnouncementStatus(announcement, AnnouncementStatus.Show) } } @Composable override fun Render(modifier: Modifier) { val announcementState = announcementPresenter.present() - Box(modifier = modifier.fillMaxSize()) { - AnimatedVisibility( - visible = announcementState.showSpaceAnnouncement, - enter = fadeIn(), - exit = fadeOut(), - ) { - val spaceAnnouncementState = spaceAnnouncementPresenter.present() - SpaceAnnouncementView( - state = spaceAnnouncementState, - ) - } - } + FullscreenAnnouncementView( + state = announcementState, + modifier = modifier, + ) } } diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/di/AnnouncementModule.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/di/AnnouncementModule.kt deleted file mode 100644 index 4cfc073271..0000000000 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/di/AnnouncementModule.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.di - -import dev.zacsweers.metro.AppScope -import dev.zacsweers.metro.BindingContainer -import dev.zacsweers.metro.Binds -import dev.zacsweers.metro.ContributesTo -import io.element.android.features.announcement.impl.AnnouncementPresenter -import io.element.android.features.announcement.impl.AnnouncementState -import io.element.android.features.announcement.impl.spaces.SpaceAnnouncementPresenter -import io.element.android.features.announcement.impl.spaces.SpaceAnnouncementState -import io.element.android.libraries.architecture.Presenter - -@ContributesTo(AppScope::class) -@BindingContainer -interface AnnouncementModule { - @Binds - fun bindAnnouncementPresenter(presenter: AnnouncementPresenter): Presenter - - @Binds - fun bindSpaceAnnouncementPresenter(presenter: SpaceAnnouncementPresenter): Presenter -} diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementView.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementView.kt new file mode 100644 index 0000000000..c544fd4914 --- /dev/null +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementView.kt @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 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.features.announcement.impl.fullscreen + +import androidx.activity.compose.BackHandler +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +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 +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.announcement.api.Announcement +import io.element.android.features.announcement.impl.AnnouncementEvent +import io.element.android.features.announcement.impl.AnnouncementState +import io.element.android.features.announcement.impl.AnnouncementStateProvider +import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule +import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem +import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism +import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.components.BigIcon +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +/** + * Ref: https://www.figma.com/design/kcnHxunG1LDWXsJhaNuiHz/ER-145--Spaces-on-Element-X?node-id=4593-40181 + */ +@Composable +fun FullscreenAnnouncementView( + state: AnnouncementState, + modifier: Modifier = Modifier, +) { + // Ensure that the content stays visible during the exit animation + var fullscreenAnnouncement by remember { mutableStateOf(null) } + if (state.announcement != null) { + fullscreenAnnouncement = state.announcement + } + Box(modifier = modifier.fillMaxSize()) { + AnimatedVisibility( + visible = state.announcement != null, + enter = fadeIn(), + exit = fadeOut(), + ) { + fullscreenAnnouncement?.let { + FullscreenAnnouncementView( + announcement = it, + eventSink = state.eventSink, + ) + } + } + } +} + +@Composable +private fun FullscreenAnnouncementView( + announcement: Announcement.Fullscreen, + eventSink: (AnnouncementEvent) -> Unit, + modifier: Modifier = Modifier +) { + fun onContinue() { + eventSink(AnnouncementEvent.Continue(announcement)) + } + + BackHandler(onBack = ::onContinue) + HeaderFooterPage( + modifier = modifier, + isScrollable = true, + contentPadding = PaddingValues(top = 24.dp, start = 16.dp, end = 16.dp, bottom = 24.dp), + header = { + FullscreenAnnouncementHeader(announcement) + }, + content = { + FullscreenAnnouncementContent( + modifier = Modifier.padding(horizontal = 8.dp), + announcement = announcement, + ) + }, + footer = { + FullscreenAnnouncementFooter( + onContinue = ::onContinue, + ) + } + ) +} + +@Composable +private fun FullscreenAnnouncementHeader( + announcement: Announcement.Fullscreen, + modifier: Modifier = Modifier, +) { + IconTitleSubtitleMolecule( + modifier = modifier.padding(top = 16.dp, bottom = 16.dp), + title = announcement.title(), + showBetaLabel = true, + subTitle = announcement.subtitle(), + iconStyle = BigIcon.Style.Default( + vectorIcon = announcement.icon(), + usePrimaryTint = true, + ), + ) +} + +@Composable +private fun FullscreenAnnouncementContent( + announcement: Announcement.Fullscreen, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.fillMaxSize(), + ) { + InfoListOrganism( + modifier = Modifier.fillMaxWidth(), + items = announcement.items(), + textStyle = ElementTheme.typography.fontBodyLgMedium, + iconTint = ElementTheme.colors.iconSecondary, + iconSize = 24.dp + ) + announcement.notice()?.let { notice -> + Text( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp), + text = notice, + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + } + } +} + +@Composable +private fun FullscreenAnnouncementFooter( + onContinue: () -> Unit, +) { + ButtonColumnMolecule( + modifier = Modifier.padding(bottom = 8.dp) + ) { + Button( + text = stringResource(id = CommonStrings.action_continue), + onClick = onContinue, + modifier = Modifier.fillMaxWidth(), + ) + } +} + +@Composable +private fun Announcement.Fullscreen.title() = when (this) { + Announcement.Fullscreen.Space -> "Introducing Spaces" +} + +@Composable +private fun Announcement.Fullscreen.subtitle() = when (this) { + Announcement.Fullscreen.Space -> "Welcome to the beta version of Spaces! With this first version you can:" +} + +@Composable +private fun Announcement.Fullscreen.icon() = when (this) { + Announcement.Fullscreen.Space -> CompoundIcons.SpaceSolid() +} + +@Composable +private fun Announcement.Fullscreen.items(): ImmutableList = when (this) { + Announcement.Fullscreen.Space -> persistentListOf( + InfoListItem( + message = "View spaces you\'ve created or joined", + iconVector = CompoundIcons.VisibilityOn(), + ), + InfoListItem( + message = "Accept or decline invites to spaces", + iconVector = CompoundIcons.Email(), + ), + InfoListItem( + message = "Discover any rooms you can join in your spaces", + iconVector = CompoundIcons.Search(), + ), + InfoListItem( + message = "Join public spaces", + iconVector = CompoundIcons.Explore(), + ), + InfoListItem( + message = "Leave any spaces you’ve joined", + iconVector = CompoundIcons.Leave(), + ), + ) +} + +@Composable +private fun Announcement.Fullscreen.notice(): String? = when (this) { + Announcement.Fullscreen.Space -> "Filtering, creating and managing spaces is coming soon." +} + +@PreviewsDayNight +@Composable +internal fun FullscreenAnnouncementViewPreview(@PreviewParameter(AnnouncementStateProvider::class) state: AnnouncementState) = ElementPreview { + FullscreenAnnouncementView( + state = state, + ) +} diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementEvents.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementEvents.kt deleted file mode 100644 index 3b968d09a6..0000000000 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementEvents.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.spaces - -sealed interface SpaceAnnouncementEvents { - data object Continue : SpaceAnnouncementEvents -} diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenter.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenter.kt deleted file mode 100644 index 7c4bc7b5eb..0000000000 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenter.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.spaces - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope -import dev.zacsweers.metro.Inject -import io.element.android.features.announcement.api.Announcement -import io.element.android.features.announcement.impl.store.AnnouncementStatus -import io.element.android.features.announcement.impl.store.AnnouncementStore -import io.element.android.libraries.architecture.Presenter -import kotlinx.coroutines.launch - -@Inject -class SpaceAnnouncementPresenter( - private val announcementStore: AnnouncementStore, -) : Presenter { - @Composable - override fun present(): SpaceAnnouncementState { - val localCoroutineScope = rememberCoroutineScope() - - fun handleEvent(event: SpaceAnnouncementEvents) { - when (event) { - SpaceAnnouncementEvents.Continue -> localCoroutineScope.launch { - announcementStore.setAnnouncementStatus(Announcement.Space, AnnouncementStatus.Shown) - } - } - } - - return SpaceAnnouncementState( - eventSink = ::handleEvent, - ) - } -} diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementState.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementState.kt deleted file mode 100644 index 9407fad872..0000000000 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementState.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.spaces - -data class SpaceAnnouncementState( - val eventSink: (SpaceAnnouncementEvents) -> Unit -) diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementStateProvider.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementStateProvider.kt deleted file mode 100644 index 27f48cc7ed..0000000000 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementStateProvider.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.spaces - -import androidx.compose.ui.tooling.preview.PreviewParameterProvider - -open class SpaceAnnouncementStateProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - aSpaceAnnouncementState(), - ) -} - -fun aSpaceAnnouncementState( - eventSink: (SpaceAnnouncementEvents) -> Unit = {}, -) = SpaceAnnouncementState( - eventSink = eventSink, -) diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt deleted file mode 100644 index 3fe6ec4456..0000000000 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementView.kt +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.spaces - -import androidx.activity.compose.BackHandler -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -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 -import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.announcement.impl.R -import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule -import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule -import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem -import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism -import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage -import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.ui.strings.CommonStrings -import kotlinx.collections.immutable.persistentListOf - -/** - * Ref: https://www.figma.com/design/kcnHxunG1LDWXsJhaNuiHz/ER-145--Spaces-on-Element-X?node-id=4593-40181 - */ -@Composable -fun SpaceAnnouncementView( - state: SpaceAnnouncementState, - modifier: Modifier = Modifier, -) { - val eventSink = state.eventSink - - fun onContinue() { - eventSink(SpaceAnnouncementEvents.Continue) - } - - BackHandler(onBack = ::onContinue) - HeaderFooterPage( - modifier = modifier, - isScrollable = true, - contentPadding = PaddingValues(top = 24.dp, start = 16.dp, end = 16.dp, bottom = 24.dp), - header = { - SpaceAnnouncementHeader() - }, - content = { - SpaceAnnouncementContent( - modifier = Modifier.padding(horizontal = 8.dp), - ) - }, - footer = { - SpaceAnnouncementFooter( - onContinue = ::onContinue, - ) - } - ) -} - -@Composable -private fun SpaceAnnouncementHeader( - modifier: Modifier = Modifier, -) { - IconTitleSubtitleMolecule( - modifier = modifier.padding(top = 16.dp, bottom = 16.dp), - title = stringResource(id = R.string.screen_space_announcement_title), - showBetaLabel = true, - subTitle = stringResource(id = R.string.screen_space_announcement_subtitle), - iconStyle = BigIcon.Style.Default( - vectorIcon = CompoundIcons.SpaceSolid(), - usePrimaryTint = true, - ), - ) -} - -@Composable -private fun SpaceAnnouncementContent( - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier.fillMaxSize(), - ) { - InfoListOrganism( - modifier = Modifier.fillMaxWidth(), - items = persistentListOf( - InfoListItem( - message = stringResource(id = R.string.screen_space_announcement_item1), - iconVector = CompoundIcons.VisibilityOn(), - ), - InfoListItem( - message = stringResource(id = R.string.screen_space_announcement_item2), - iconVector = CompoundIcons.Email(), - ), - InfoListItem( - message = stringResource(id = R.string.screen_space_announcement_item3), - iconVector = CompoundIcons.Search(), - ), - InfoListItem( - message = stringResource(id = R.string.screen_space_announcement_item4), - iconVector = CompoundIcons.Explore(), - ), - InfoListItem( - message = stringResource(id = R.string.screen_space_announcement_item5), - iconVector = CompoundIcons.Leave(), - ), - ), - textStyle = ElementTheme.typography.fontBodyLgMedium, - iconTint = ElementTheme.colors.iconSecondary, - iconSize = 24.dp - ) - Text( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 16.dp), - text = stringResource(id = R.string.screen_space_announcement_notice), - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - } -} - -@Composable -private fun SpaceAnnouncementFooter( - onContinue: () -> Unit, -) { - ButtonColumnMolecule( - modifier = Modifier.padding(bottom = 8.dp) - ) { - Button( - text = stringResource(id = CommonStrings.action_continue), - onClick = onContinue, - modifier = Modifier.fillMaxWidth(), - ) - } -} - -@PreviewsDayNight -@Composable -internal fun SpaceAnnouncementViewPreview(@PreviewParameter(SpaceAnnouncementStateProvider::class) state: SpaceAnnouncementState) = ElementPreview { - SpaceAnnouncementView( - state = state, - ) -} diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt index ad166e4ef5..d24e9ed26e 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt @@ -17,7 +17,6 @@ import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFac import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -private val spaceAnnouncementKey = intPreferencesKey("spaceAnnouncement") private val newNotificationSoundKey = intPreferencesKey("newNotificationSound") @ContributesBinding(AppScope::class) @@ -35,9 +34,10 @@ class DefaultAnnouncementStore( override fun announcementStatusFlow(announcement: Announcement): Flow { val key = announcement.toKey() + // Announcement.Fullscreen.Space is disabled, consider it's shown // For NewNotificationSound, a migration will set it to Show on application upgrade (see AppMigration08) val defaultStatus = when (announcement) { - Announcement.Space -> AnnouncementStatus.NeverShown + Announcement.Fullscreen.Space -> AnnouncementStatus.Shown Announcement.NewNotificationSound -> AnnouncementStatus.Shown } return store.data.map { prefs -> @@ -52,6 +52,6 @@ class DefaultAnnouncementStore( } private fun Announcement.toKey() = when (this) { - Announcement.Space -> spaceAnnouncementKey + is Announcement.Fullscreen -> intPreferencesKey("fullscreen_" + this::class.simpleName) Announcement.NewNotificationSound -> newNotificationSoundKey } diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt index 18deb8b2fd..bcfd80942d 100644 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt +++ b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt @@ -23,25 +23,25 @@ class AnnouncementPresenterTest { val presenter = createAnnouncementPresenter() presenter.test { val state = awaitItem() - assertThat(state.showSpaceAnnouncement).isFalse() + assertThat(state.announcement).isNull() } } @Test - fun `present - showSpaceAnnouncement value depends on the value in the store`() = runTest { + fun `present - showFullscreen value depends on the value in the store`() = runTest { val store = InMemoryAnnouncementStore() val presenter = createAnnouncementPresenter( announcementStore = store, ) presenter.test { val state = awaitItem() - assertThat(state.showSpaceAnnouncement).isFalse() - store.setAnnouncementStatus(Announcement.Space, AnnouncementStatus.Show) + assertThat(state.announcement).isNull() + store.setAnnouncementStatus(Announcement.Fullscreen.Space, AnnouncementStatus.Show) val updatedState = awaitItem() - assertThat(updatedState.showSpaceAnnouncement).isTrue() - store.setAnnouncementStatus(Announcement.Space, AnnouncementStatus.Shown) + assertThat(updatedState.announcement).isEqualTo(Announcement.Fullscreen.Space) + store.setAnnouncementStatus(Announcement.Fullscreen.Space, AnnouncementStatus.Shown) val finalState = awaitItem() - assertThat(finalState.showSpaceAnnouncement).isFalse() + assertThat(finalState.announcement).isNull() } } } diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementServiceTest.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementServiceTest.kt index e16619129c..c72d147c1d 100644 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementServiceTest.kt +++ b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/DefaultAnnouncementServiceTest.kt @@ -11,31 +11,28 @@ package io.element.android.features.announcement.impl import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.announcement.api.Announcement -import io.element.android.features.announcement.impl.spaces.SpaceAnnouncementState -import io.element.android.features.announcement.impl.spaces.aSpaceAnnouncementState import io.element.android.features.announcement.impl.store.AnnouncementStatus import io.element.android.features.announcement.impl.store.AnnouncementStore import io.element.android.features.announcement.impl.store.InMemoryAnnouncementStore -import io.element.android.libraries.architecture.Presenter import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.Test class DefaultAnnouncementServiceTest { @Test - fun `when showing Space announcement, space announcement is set to show only if it was never shown`() = runTest { + fun `when showing Fullscreen announcement, Fullscreen announcement is set to show only if it was never shown`() = runTest { val announcementStore = InMemoryAnnouncementStore() val sut = createDefaultAnnouncementService( announcementStore = announcementStore, ) - assertThat(announcementStore.announcementStatusFlow(Announcement.Space).first()).isEqualTo(AnnouncementStatus.NeverShown) - sut.showAnnouncement(Announcement.Space) - assertThat(announcementStore.announcementStatusFlow(Announcement.Space).first()).isEqualTo(AnnouncementStatus.Show) + assertThat(announcementStore.announcementStatusFlow(Announcement.Fullscreen.Space).first()).isEqualTo(AnnouncementStatus.NeverShown) + sut.showAnnouncement(Announcement.Fullscreen.Space) + assertThat(announcementStore.announcementStatusFlow(Announcement.Fullscreen.Space).first()).isEqualTo(AnnouncementStatus.Show) // Simulate user close the announcement - sut.onAnnouncementDismissed(Announcement.Space) + sut.onAnnouncementDismissed(Announcement.Fullscreen.Space) // Entering again the space tab should not change the value - sut.showAnnouncement(Announcement.Space) - assertThat(announcementStore.announcementStatusFlow(Announcement.Space).first()).isEqualTo(AnnouncementStatus.Shown) + sut.showAnnouncement(Announcement.Fullscreen.Space) + assertThat(announcementStore.announcementStatusFlow(Announcement.Fullscreen.Space).first()).isEqualTo(AnnouncementStatus.Shown) } @Test @@ -62,11 +59,7 @@ class DefaultAnnouncementServiceTest { ) sut.announcementsToShowFlow().test { assertThat(awaitItem()).isEmpty() - announcementStore.setAnnouncementStatus(Announcement.Space, AnnouncementStatus.Show) - assertThat(awaitItem()).containsExactly(Announcement.Space) announcementStore.setAnnouncementStatus(Announcement.NewNotificationSound, AnnouncementStatus.Show) - assertThat(awaitItem()).containsExactly(Announcement.Space, Announcement.NewNotificationSound) - announcementStore.setAnnouncementStatus(Announcement.Space, AnnouncementStatus.Shown) assertThat(awaitItem()).containsExactly(Announcement.NewNotificationSound) announcementStore.setAnnouncementStatus(Announcement.NewNotificationSound, AnnouncementStatus.Shown) assertThat(awaitItem()).isEmpty() @@ -75,11 +68,9 @@ class DefaultAnnouncementServiceTest { private fun createDefaultAnnouncementService( announcementStore: AnnouncementStore = InMemoryAnnouncementStore(), - announcementPresenter: Presenter = Presenter { anAnnouncementState() }, - spaceAnnouncementPresenter: Presenter = Presenter { aSpaceAnnouncementState() }, + announcementPresenter: AnnouncementPresenter = AnnouncementPresenter(announcementStore), ) = DefaultAnnouncementService( announcementStore = announcementStore, announcementPresenter = announcementPresenter, - spaceAnnouncementPresenter = spaceAnnouncementPresenter, ) } diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementViewTest.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt similarity index 51% rename from features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementViewTest.kt rename to features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt index ad3d83f1b5..b69037e61a 100644 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementViewTest.kt +++ b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt @@ -6,12 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.announcement.impl.spaces +package io.element.android.features.announcement.impl.fullscreen import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.announcement.api.Announcement +import io.element.android.features.announcement.impl.AnnouncementEvent +import io.element.android.features.announcement.impl.AnnouncementState +import io.element.android.features.announcement.impl.anAnnouncementState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn @@ -22,39 +26,41 @@ import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) -class SpaceAnnouncementViewTest { +class FullscreenAnnouncementViewTest { @get:Rule val rule = createAndroidComposeRule() @Test - fun `clicking on back sends a SpaceAnnouncementEvents`() { - val eventsRecorder = EventsRecorder() - rule.setSpaceAnnouncementView( - aSpaceAnnouncementState( + fun `clicking on back sends a AnnouncementEvent`() { + val eventsRecorder = EventsRecorder() + rule.setFullscreenAnnouncementView( + anAnnouncementState( + announcement = Announcement.Fullscreen.Space, eventSink = eventsRecorder, ), ) rule.pressBackKey() - eventsRecorder.assertSingle(SpaceAnnouncementEvents.Continue) + eventsRecorder.assertSingle(AnnouncementEvent.Continue(Announcement.Fullscreen.Space)) } @Test - fun `clicking on Continue sends a SpaceAnnouncementEvents`() { - val eventsRecorder = EventsRecorder() - rule.setSpaceAnnouncementView( - aSpaceAnnouncementState( + fun `clicking on Continue sends a AnnouncementEvent`() { + val eventsRecorder = EventsRecorder() + rule.setFullscreenAnnouncementView( + anAnnouncementState( + announcement = Announcement.Fullscreen.Space, eventSink = eventsRecorder, ), ) rule.clickOn(CommonStrings.action_continue) - eventsRecorder.assertSingle(SpaceAnnouncementEvents.Continue) + eventsRecorder.assertSingle(AnnouncementEvent.Continue(Announcement.Fullscreen.Space)) } } -private fun AndroidComposeTestRule.setSpaceAnnouncementView( - state: SpaceAnnouncementState, +private fun AndroidComposeTestRule.setFullscreenAnnouncementView( + state: AnnouncementState, ) { setContent { - SpaceAnnouncementView( + FullscreenAnnouncementView( state = state, ) } diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenterTest.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenterTest.kt deleted file mode 100644 index 672f677407..0000000000 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/spaces/SpaceAnnouncementPresenterTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.announcement.impl.spaces - -import com.google.common.truth.Truth.assertThat -import io.element.android.features.announcement.api.Announcement -import io.element.android.features.announcement.impl.store.AnnouncementStatus -import io.element.android.features.announcement.impl.store.AnnouncementStore -import io.element.android.features.announcement.impl.store.InMemoryAnnouncementStore -import io.element.android.tests.testutils.test -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.test.runTest -import org.junit.Test - -class SpaceAnnouncementPresenterTest { - @Test - fun `present - when user continues, the store is updated`() = runTest { - val store = InMemoryAnnouncementStore() - val presenter = createSpaceAnnouncementPresenter( - announcementStore = store, - ) - presenter.test { - assertThat(store.announcementStatusFlow(Announcement.Space).first()).isEqualTo(AnnouncementStatus.NeverShown) - val state = awaitItem() - state.eventSink(SpaceAnnouncementEvents.Continue) - assertThat(store.announcementStatusFlow(Announcement.Space).first()).isEqualTo(AnnouncementStatus.Shown) - } - } -} - -private fun createSpaceAnnouncementPresenter( - announcementStore: AnnouncementStore = InMemoryAnnouncementStore(), -) = SpaceAnnouncementPresenter( - announcementStore = announcementStore, -) diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/store/InMemoryAnnouncementStore.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/store/InMemoryAnnouncementStore.kt index ab3e85124f..ed6dfec850 100644 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/store/InMemoryAnnouncementStore.kt +++ b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/store/InMemoryAnnouncementStore.kt @@ -14,10 +14,10 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow class InMemoryAnnouncementStore( - initialSpaceAnnouncementStatus: AnnouncementStatus = AnnouncementStatus.NeverShown, + initialFullscreenAnnouncementStatus: AnnouncementStatus = AnnouncementStatus.NeverShown, initialNewNotificationSoundAnnouncementStatus: AnnouncementStatus = AnnouncementStatus.NeverShown, ) : AnnouncementStore { - private val spaceAnnouncement = MutableStateFlow(initialSpaceAnnouncementStatus) + private val fullScreenAnnouncement = MutableStateFlow(initialFullscreenAnnouncementStatus) private val newNotificationSoundAnnouncement = MutableStateFlow(initialNewNotificationSoundAnnouncementStatus) override suspend fun setAnnouncementStatus(announcement: Announcement, status: AnnouncementStatus) { @@ -29,12 +29,12 @@ class InMemoryAnnouncementStore( } override suspend fun reset() { - spaceAnnouncement.value = AnnouncementStatus.NeverShown + fullScreenAnnouncement.value = AnnouncementStatus.NeverShown newNotificationSoundAnnouncement.value = AnnouncementStatus.NeverShown } private fun Announcement.toMutableStateFlow() = when (this) { - Announcement.Space -> spaceAnnouncement + is Announcement.Fullscreen -> fullScreenAnnouncement Announcement.NewNotificationSound -> newNotificationSoundAnnouncement } } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt index 5985e33127..1e49b1aa70 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt @@ -19,8 +19,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject -import io.element.android.features.announcement.api.Announcement -import io.element.android.features.announcement.api.AnnouncementService import io.element.android.features.home.impl.roomlist.RoomListState import io.element.android.features.home.impl.spaces.HomeSpacesState import io.element.android.features.logout.api.direct.DirectLogoutState @@ -47,7 +45,6 @@ class HomePresenter( private val logoutPresenter: Presenter, private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, private val sessionStore: SessionStore, - private val announcementService: AnnouncementService, ) : Presenter { private val currentUserWithNeighborsBuilder = CurrentUserWithNeighborsBuilder() @@ -82,10 +79,7 @@ class HomePresenter( fun handleEvent(event: HomeEvent) { when (event) { - is HomeEvent.SelectHomeNavigationBarItem -> coroutineState.launch { - if (event.item == HomeNavigationBarItem.Spaces) { - announcementService.showAnnouncement(Announcement.Space) - } + is HomeEvent.SelectHomeNavigationBarItem -> { currentHomeNavigationBarItemOrdinal = event.item.ordinal } is HomeEvent.SwitchToAccount -> coroutineState.launch { diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt index 90cf160cc6..371a718523 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt @@ -9,14 +9,11 @@ package io.element.android.features.home.impl import com.google.common.truth.Truth.assertThat -import io.element.android.features.announcement.api.Announcement -import io.element.android.features.announcement.api.AnnouncementService import io.element.android.features.home.impl.roomlist.aRoomListState import io.element.android.features.home.impl.spaces.HomeSpacesState import io.element.android.features.home.impl.spaces.aHomeSpacesState import io.element.android.features.logout.api.direct.aDirectLogoutState import io.element.android.features.rageshake.api.RageshakeFeatureAvailability -import io.element.android.features.rageshake.test.logs.FakeAnnouncementService import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.indicator.api.IndicatorService @@ -34,8 +31,6 @@ import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData 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.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest @@ -137,14 +132,10 @@ class HomePresenterTest { @Test fun `present - NavigationBar change`() = runTest { - val showAnnouncementResult = lambdaRecorder { } val presenter = createHomePresenter( sessionStore = InMemorySessionStore( updateUserProfileResult = { _, _, _ -> }, ), - announcementService = FakeAnnouncementService( - showAnnouncementResult = showAnnouncementResult, - ) ) presenter.test { val initialState = awaitItem() @@ -152,8 +143,6 @@ class HomePresenterTest { initialState.eventSink(HomeEvent.SelectHomeNavigationBarItem(HomeNavigationBarItem.Spaces)) val finalState = awaitItem() assertThat(finalState.currentHomeNavigationBarItem).isEqualTo(HomeNavigationBarItem.Spaces) - showAnnouncementResult.assertions().isCalledOnce() - .with(value(Announcement.Space)) } } } @@ -166,7 +155,6 @@ internal fun createHomePresenter( indicatorService: IndicatorService = FakeIndicatorService(), homeSpacesPresenter: Presenter = Presenter { aHomeSpacesState() }, sessionStore: SessionStore = InMemorySessionStore(), - announcementService: AnnouncementService = FakeAnnouncementService(), ) = HomePresenter( client = client, syncService = syncService, @@ -177,5 +165,4 @@ internal fun createHomePresenter( logoutPresenter = { aDirectLogoutState() }, rageshakeFeatureAvailability = rageshakeFeatureAvailability, sessionStore = sessionStore, - announcementService = announcementService, ) From 78d8eaaf344377a49f69285e10f32bff0a0f6df2 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 10 Apr 2026 13:07:24 +0000 Subject: [PATCH 0102/1083] Update screenshots --- ...ent.impl.fullscreen_FullscreenAnnouncementView_Day_0_en.png | 3 +++ ...nt.impl.fullscreen_FullscreenAnnouncementView_Day_1_en.png} | 0 ...t.impl.fullscreen_FullscreenAnnouncementView_Night_0_en.png | 3 +++ ....impl.fullscreen_FullscreenAnnouncementView_Night_1_en.png} | 0 4 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_0_en.png rename tests/uitests/src/test/snapshots/images/{features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png => features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en.png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_0_en.png rename tests/uitests/src/test/snapshots/images/{features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png => features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en.png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_0_en.png new file mode 100644 index 0000000000..1b6fb4bab8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96a867cb12498cbdc97957bee07855dfaa13602baddaf933aff2b666ef4c7650 +size 3642 diff --git a/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en.png rename to tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_0_en.png new file mode 100644 index 0000000000..d6fd8eeb70 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bb36ccd718f3fec5b04f1bc812dc7718b5ea7fa4619c8b031466297a8d016fd +size 3659 diff --git a/tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en.png rename to tests/uitests/src/test/snapshots/images/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en.png From bf1948185e312513fa36b22a2b6d8e5064513da2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 18:15:06 +0000 Subject: [PATCH 0103/1083] Update gradle/actions action to v6.1.0 --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/maestro-local.yml | 2 +- .github/workflows/nightlyReports.yml | 4 ++-- .github/workflows/quality.yml | 12 ++++++------ .github/workflows/recordScreenshots.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/sonar.yml | 2 +- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/tests.yml | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e5f16200a..c60a89e2f6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,7 +56,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug APKs diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 71195ff163..aa00b74c44 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -61,7 +61,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug Gplay Enterprise APK diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 8780cd7c7b..ae87dd6d50 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -23,7 +23,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index c5587f40c1..8903ed0e57 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -50,7 +50,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug APK diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 10d41f5d1a..33660b1184 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -43,7 +43,7 @@ jobs: java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: false @@ -85,7 +85,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Dependency analysis diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index a1c7bd3c70..9a191ba15b 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -74,7 +74,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 @@ -113,7 +113,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Konsist tests @@ -154,7 +154,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run compose tests @@ -188,7 +188,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Build Gplay Debug @@ -233,7 +233,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Detekt @@ -274,7 +274,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run Ktlint check diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 4bec9643c5..70bbbe5d0a 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -59,7 +59,7 @@ jobs: java-version: '21' # Add gradle cache, this should speed up the process - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Record screenshots diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b5514a72f0..73cba6c8f7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Create app bundle env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} @@ -87,7 +87,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Create Enterprise app bundle env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} @@ -131,7 +131,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 - name: Create APKs env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 347d99c0f7..40cf9d0058 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -50,7 +50,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Build debug code and test fixtures diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index e37076b9de..f45a926814 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -22,7 +22,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 56a342ddba..03882c7d44 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,7 +68,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' - name: Configure gradle - uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} From 7c3b9523df00e09fac5c6c3d9e9421590c5ca276 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Apr 2026 20:44:05 +0200 Subject: [PATCH 0104/1083] 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 0105/1083] 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 0106/1083] 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 24d1900694b2c65854ef6e9d06cb041f7ee02e1f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Apr 2026 18:55:37 +0200 Subject: [PATCH 0107/1083] Fix quality issues --- .../element/android/features/announcement/api/Announcement.kt | 4 ++++ .../android/features/announcement/impl/AnnouncementState.kt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt b/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt index a83d167ee2..1d6f357ca8 100644 --- a/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt +++ b/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt @@ -8,7 +8,11 @@ package io.element.android.features.announcement.api +import androidx.compose.runtime.Immutable + +@Immutable sealed interface Announcement { + @Immutable sealed interface Fullscreen : Announcement { data object Space : Fullscreen } diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt index 3ef47d6ed0..fb0732450d 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/AnnouncementState.kt @@ -11,6 +11,6 @@ package io.element.android.features.announcement.impl import io.element.android.features.announcement.api.Announcement data class AnnouncementState( - val announcement: Announcement.Fullscreen? = null, + val announcement: Announcement.Fullscreen?, val eventSink: (AnnouncementEvent) -> Unit, ) From 23c1112dcf7c0ef562ae8a5dd3bb2e9d7e098396 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 13 Apr 2026 00:48:40 +0000 Subject: [PATCH 0108/1083] Sync Strings from Localazy --- app/src/main/res/xml/locales_config.xml | 2 + .../src/main/res/values-ja/translations.xml | 6 + .../src/main/res/values-vi/translations.xml | 6 + .../src/main/res/values-ja/translations.xml | 7 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-ja/translations.xml | 10 + .../src/main/res/values-vi/translations.xml | 10 + .../src/main/res/values-ja/translations.xml | 11 + .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-ja/translations.xml | 8 + .../src/main/res/values-vi/translations.xml | 8 + .../src/main/res/values-it/translations.xml | 32 +- .../src/main/res/values-ja/translations.xml | 36 + .../src/main/res/values-vi/translations.xml | 11 + .../src/main/res/values-ja/translations.xml | 14 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-it/translations.xml | 4 +- .../src/main/res/values-ja/translations.xml | 15 + .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 10 + .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-it/translations.xml | 7 +- .../src/main/res/values-ja/translations.xml | 56 + .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 48 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-be/translations.xml | 2 + .../src/main/res/values-ja/translations.xml | 18 + .../src/main/res/values-vi/translations.xml | 17 + .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-ja/translations.xml | 11 + .../src/main/res/values-vi/translations.xml | 5 + .../impl/src/main/res/values/localazy.xml | 8 + .../src/main/res/values-be/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 34 + .../src/main/res/values-vi/translations.xml | 19 + .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-ja/translations.xml | 35 + .../src/main/res/values-vi/translations.xml | 29 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 10 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-it/translations.xml | 19 + .../src/main/res/values-ja/translations.xml | 57 + .../src/main/res/values-vi/translations.xml | 4 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-it/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 5 + .../src/main/res/values-ru/translations.xml | 5 + .../src/main/res/values-it/translations.xml | 4 +- .../src/main/res/values-ja/translations.xml | 36 + .../src/main/res/values-vi/translations.xml | 35 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-it/translations.xml | 2 + .../src/main/res/values-ja/translations.xml | 99 + .../src/main/res/values-vi/translations.xml | 47 + .../src/main/res/values-it/translations.xml | 26 +- .../src/main/res/values-ja/translations.xml | 18 + .../src/main/res/values-ru/translations.xml | 16 +- .../src/main/res/values-vi/translations.xml | 18 + .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-it/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 81 + .../src/main/res/values-vi/translations.xml | 60 + .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-ja/translations.xml | 8 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 20 + .../src/main/res/values-vi/translations.xml | 19 + .../src/main/res/values-ja/translations.xml | 82 + .../src/main/res/values-ru/translations.xml | 4 +- .../src/main/res/values-vi/translations.xml | 61 + .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-ja/translations.xml | 7 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-ja/translations.xml | 20 + .../src/main/res/values-vi/translations.xml | 17 + .../src/main/res/values-ja/translations.xml | 8 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 82 + .../src/main/res/values-vi/translations.xml | 58 + .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-ja/translations.xml | 5 + .../src/main/res/values-vi/translations.xml | 4 + .../src/main/res/values-it/translations.xml | 18 +- .../src/main/res/values-ja/translations.xml | 171 ++ .../src/main/res/values-vi/translations.xml | 107 + .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-ja/translations.xml | 7 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-ja/translations.xml | 5 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 22 + .../src/main/res/values-vi/translations.xml | 15 + .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-it/translations.xml | 27 +- .../src/main/res/values-ja/translations.xml | 70 + .../src/main/res/values-ru/translations.xml | 6 +- .../src/main/res/values-vi/translations.xml | 44 + .../src/main/res/values-zh/translations.xml | 16 +- .../src/main/res/values-it/translations.xml | 19 +- .../src/main/res/values-ja/translations.xml | 50 + .../src/main/res/values-vi/translations.xml | 11 + .../src/main/res/values-ja/translations.xml | 8 + .../src/main/res/values-vi/translations.xml | 8 + .../src/main/res/values-be/translations.xml | 1 + .../src/main/res/values-it/translations.xml | 10 + .../src/main/res/values-ja/translations.xml | 26 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 12 + .../src/main/res/values-vi/translations.xml | 6 + .../src/main/res/values-ja/translations.xml | 19 + .../src/main/res/values-vi/translations.xml | 16 + .../src/main/res/values-zh/translations.xml | 20 +- .../src/main/res/values-it/translations.xml | 10 +- .../src/main/res/values-ja/translations.xml | 54 + .../src/main/res/values-ru/translations.xml | 4 +- .../src/main/res/values-vi/translations.xml | 31 + .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-ja/translations.xml | 4 + .../src/main/res/values-vi/translations.xml | 4 + .../src/main/res/values-ja/translations.xml | 5 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 73 + .../src/main/res/values-vi/translations.xml | 64 + .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-ja/translations.xml | 9 + .../src/main/res/values-vi/translations.xml | 4 + .../matrixui/src/main/res/values/localazy.xml | 2 + .../src/main/res/values-ja/translations.xml | 21 + .../src/main/res/values-ja/translations.xml | 7 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-ja/translations.xml | 5 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-it/translations.xml | 7 + .../src/main/res/values-ja/translations.xml | 93 + .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 61 + .../src/main/res/values-zh/translations.xml | 5 +- .../src/main/res/values-ja/translations.xml | 11 + .../src/main/res/values-ja/translations.xml | 9 + .../src/main/res/values-ja/translations.xml | 33 + .../src/main/res/values-vi/translations.xml | 25 + .../src/main/res/values-ja/translations.xml | 12 + .../src/main/res/values-vi/translations.xml | 6 + .../src/main/res/values-be/translations.xml | 21 + .../src/main/res/values-it/translations.xml | 86 +- .../src/main/res/values-ja/translations.xml | 525 +++++ .../src/main/res/values-pl/translations.xml | 6 +- .../src/main/res/values-ru/translations.xml | 20 +- .../src/main/res/values-vi/translations.xml | 425 ++++ .../src/main/res/values-zh/translations.xml | 47 +- .../src/main/res/values/localazy.xml | 3 + plugins/src/main/kotlin/extension/locales.kt | 2 + ...me.impl.spaces_HomeSpacesView_Day_2_de.png | 4 +- ...me.impl.spaces_HomeSpacesView_Day_3_de.png | 3 - ...mEventRowWithReplyInformative_Day_0_de.png | 4 +- ...mEventRowWithReplyInformative_Day_1_de.png | 4 +- ...TimelineItemEventRowWithReply_Day_4_de.png | 4 +- ...TimelineItemEventRowWithReply_Day_8_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_0_de.png | 4 +- ...extComposerReplyNotEncrypted_Day_10_de.png | 4 +- ...extComposerReplyNotEncrypted_Day_11_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_1_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_2_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_3_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_4_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_5_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_6_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_7_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_8_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_9_de.png | 4 +- ...extcomposer_TextComposerReply_Day_0_de.png | 4 +- ...xtcomposer_TextComposerReply_Day_10_de.png | 4 +- ...xtcomposer_TextComposerReply_Day_11_de.png | 4 +- ...extcomposer_TextComposerReply_Day_1_de.png | 4 +- ...extcomposer_TextComposerReply_Day_2_de.png | 4 +- ...extcomposer_TextComposerReply_Day_3_de.png | 4 +- ...extcomposer_TextComposerReply_Day_4_de.png | 4 +- ...extcomposer_TextComposerReply_Day_5_de.png | 4 +- ...extcomposer_TextComposerReply_Day_6_de.png | 4 +- ...extcomposer_TextComposerReply_Day_7_de.png | 4 +- ...extcomposer_TextComposerReply_Day_8_de.png | 4 +- ...extcomposer_TextComposerReply_Day_9_de.png | 4 +- ...es.apperror.api_AppErrorView_Day_0_de.png} | 0 screenshots/html/data.js | 2031 ++++++++--------- 186 files changed, 4902 insertions(+), 1254 deletions(-) create mode 100644 appnav/src/main/res/values-ja/translations.xml create mode 100644 appnav/src/main/res/values-vi/translations.xml create mode 100644 features/analytics/api/src/main/res/values-ja/translations.xml create mode 100644 features/analytics/api/src/main/res/values-vi/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-ja/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-vi/translations.xml create mode 100644 features/announcement/impl/src/main/res/values-ja/translations.xml create mode 100644 features/call/impl/src/main/res/values-ja/translations.xml create mode 100644 features/call/impl/src/main/res/values-vi/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-ja/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-vi/translations.xml create mode 100644 features/deactivation/impl/src/main/res/values-ja/translations.xml create mode 100644 features/deactivation/impl/src/main/res/values-vi/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-ja/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-vi/translations.xml create mode 100644 features/home/impl/src/main/res/values-ja/translations.xml create mode 100644 features/home/impl/src/main/res/values-vi/translations.xml create mode 100644 features/invite/impl/src/main/res/values-ja/translations.xml create mode 100644 features/invite/impl/src/main/res/values-vi/translations.xml create mode 100644 features/invitepeople/impl/src/main/res/values-ja/translations.xml create mode 100644 features/invitepeople/impl/src/main/res/values-vi/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-ja/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-vi/translations.xml create mode 100644 features/knockrequests/impl/src/main/res/values-ja/translations.xml create mode 100644 features/knockrequests/impl/src/main/res/values-vi/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-ja/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-vi/translations.xml create mode 100644 features/linknewdevice/impl/src/main/res/values-ja/translations.xml create mode 100644 features/linknewdevice/impl/src/main/res/values-vi/translations.xml create mode 100644 features/location/impl/src/main/res/values-it/translations.xml create mode 100644 features/location/impl/src/main/res/values-ja/translations.xml create mode 100644 features/location/impl/src/main/res/values-ru/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-ja/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-vi/translations.xml create mode 100644 features/login/impl/src/main/res/values-ja/translations.xml create mode 100644 features/login/impl/src/main/res/values-vi/translations.xml create mode 100644 features/logout/impl/src/main/res/values-ja/translations.xml create mode 100644 features/logout/impl/src/main/res/values-vi/translations.xml create mode 100644 features/messages/impl/src/main/res/values-ja/translations.xml create mode 100644 features/messages/impl/src/main/res/values-vi/translations.xml create mode 100644 features/poll/api/src/main/res/values-ja/translations.xml create mode 100644 features/poll/api/src/main/res/values-vi/translations.xml create mode 100644 features/poll/impl/src/main/res/values-ja/translations.xml create mode 100644 features/poll/impl/src/main/res/values-vi/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-ja/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-vi/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-ja/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-vi/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-ja/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-vi/translations.xml create mode 100644 features/reportroom/impl/src/main/res/values-ja/translations.xml create mode 100644 features/reportroom/impl/src/main/res/values-vi/translations.xml create mode 100644 features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml create mode 100644 features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-ja/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-vi/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-ja/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-vi/translations.xml create mode 100644 features/roomdetailsedit/impl/src/main/res/values-ja/translations.xml create mode 100644 features/roomdetailsedit/impl/src/main/res/values-vi/translations.xml create mode 100644 features/roomdirectory/impl/src/main/res/values-ja/translations.xml create mode 100644 features/roomdirectory/impl/src/main/res/values-vi/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-ja/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-vi/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-ja/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-vi/translations.xml create mode 100644 features/securityandprivacy/impl/src/main/res/values-ja/translations.xml create mode 100644 features/securityandprivacy/impl/src/main/res/values-vi/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-ja/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-vi/translations.xml create mode 100644 features/space/impl/src/main/res/values-ja/translations.xml create mode 100644 features/space/impl/src/main/res/values-vi/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-ja/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-vi/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-ja/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-vi/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-ja/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-ja/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-vi/translations.xml create mode 100644 libraries/dateformatter/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/dateformatter/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-ja/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-vi/translations.xml create mode 100644 libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-ja/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-vi/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/pushproviders/firebase/src/main/res/values-ja/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-ja/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-ja/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-vi/translations.xml delete mode 100644 screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_3_de.png rename screenshots/de/{services.apperror.impl_AppErrorView_Day_0_de.png => services.apperror.api_AppErrorView_Day_0_de.png} (100%) diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index a171646bad..c95b3a5cc0 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -19,6 +19,7 @@ + @@ -35,6 +36,7 @@ + diff --git a/appnav/src/main/res/values-ja/translations.xml b/appnav/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..3405cc1d68 --- /dev/null +++ b/appnav/src/main/res/values-ja/translations.xml @@ -0,0 +1,6 @@ + + + "ログアウトしてアップグレード" + "%1$s は古いプロトコルに非対応になりました。アプリを引き続き使用するには、ログアウトしてから再度ログインしてください。" + "使用しているホームサーバーは古いプロトコルに非対応になりました。アプリケーションを引き続き使用するには、ログアウトしてから再度ログインしてください。" + diff --git a/appnav/src/main/res/values-vi/translations.xml b/appnav/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..8fa3a7ee30 --- /dev/null +++ b/appnav/src/main/res/values-vi/translations.xml @@ -0,0 +1,6 @@ + + + "Đăng xuất & Nâng cấp" + "%1$s không còn hỗ trợ giao thức cũ. Vui lòng đăng xuất và đăng nhập lại để tiếp tục sử dụng ứng dụng." + "Homeserver của bạn không còn hỗ trợ giao thức cũ. Vui lòng đăng xuất và đăng nhập lại để tiếp tục sử dụng ứng dụng." + diff --git a/features/analytics/api/src/main/res/values-ja/translations.xml b/features/analytics/api/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..5554ee162f --- /dev/null +++ b/features/analytics/api/src/main/res/values-ja/translations.xml @@ -0,0 +1,7 @@ + + + "問題発見のため、匿名の使用データの共有にご協力ください。" + "利用規約の全文を%1$sから確認することができます。" + "こちら" + "使用データを共有" + diff --git a/features/analytics/api/src/main/res/values-vi/translations.xml b/features/analytics/api/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..0dc02d79d6 --- /dev/null +++ b/features/analytics/api/src/main/res/values-vi/translations.xml @@ -0,0 +1,7 @@ + + + "Chia sẻ dữ liệu sử dụng ẩn danh để giúp chúng tôi xác định vấn đề." + "Bạn có thể xem tất cả điều khoản của chúng tôi tại %1$s" + "tại đây" + "Chia sẻ dữ liệu phân tích" + diff --git a/features/analytics/impl/src/main/res/values-ja/translations.xml b/features/analytics/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..2cee69962c --- /dev/null +++ b/features/analytics/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,10 @@ + + + "いかなる個人情報も記録, 分析されることはありません" + "問題発見のため、匿名の使用データの共有にご協力ください。" + "利用規約の全文を%1$sから確認することができます。" + "こちら" + "いつでも設定は変更できます" + "情報が第三者に共有されることはありません" + "%1$s の改善にご協力ください" + diff --git a/features/analytics/impl/src/main/res/values-vi/translations.xml b/features/analytics/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..205a52c296 --- /dev/null +++ b/features/analytics/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,10 @@ + + + "Chúng tôi sẽ không ghi lại hoặc lập hồ sơ bất kỳ dữ liệu cá nhân nào." + "Chia sẻ dữ liệu sử dụng ẩn danh để giúp chúng tôi xác định vấn đề." + "Bạn có thể xem tất cả điều khoản của chúng tôi tại %1$s" + "tại đây" + "Bạn có thể tắt tính năng này bất cứ lúc nào" + "Chúng tôi sẽ không chia sẻ dữ liệu của bạn với bên thứ ba." + "Giúp cải thiện %1$s" + diff --git a/features/announcement/impl/src/main/res/values-ja/translations.xml b/features/announcement/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..47273cc12d --- /dev/null +++ b/features/announcement/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,11 @@ + + + "作成または参加したスペースを表示できます" + "スペースへの招待を受諾または拒否できます" + "スペース内の参加可能なルームを検索できます" + "公開スペースに参加できます" + "参加したスペースを退出できます" + "スペースの作成や管理, フィルター検索は近日実装予定です。" + "ベータ版のスペースにようこそ。この最新のバージョンでは:" + "スペースの紹介" + diff --git a/features/announcement/impl/src/main/res/values-zh/translations.xml b/features/announcement/impl/src/main/res/values-zh/translations.xml index e01e63b2ae..70d86638ea 100644 --- a/features/announcement/impl/src/main/res/values-zh/translations.xml +++ b/features/announcement/impl/src/main/res/values-zh/translations.xml @@ -6,6 +6,6 @@ "加入公共空间" "离开你加入的所有空间" "筛选、创建及管理空间功能即将上线。" - "欢迎使用 Spaces 测试版!使用首个版本,您可以:" - "Spaces 简介" + "欢迎使用空间测试版!使用首个版本,您可以:" + "空间简介" diff --git a/features/call/impl/src/main/res/values-ja/translations.xml b/features/call/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..18ee195d0f --- /dev/null +++ b/features/call/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,8 @@ + + + "通話中" + "タップして通話に戻る" + "☎️ 通話中" + "Element CallはこのAndroidバージョンにおいて、Bluetoothオーディオデバイスの使用をサポートしていません。別のオーディオデバイスを選択してください。" + "Element Call の着信" + diff --git a/features/call/impl/src/main/res/values-vi/translations.xml b/features/call/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..c88cf651e6 --- /dev/null +++ b/features/call/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,8 @@ + + + "Cuộc gọi đang diễn ra" + "Nhấn để quay lại cuộc gọi." + "☎️ Cuộc gọi đang diễn ra" + "Ứng dụng Element Call không hỗ trợ sử dụng thiết bị âm thanh Bluetooth trên phiên bản Android này. Vui lòng chọn thiết bị âm thanh khác." + "Cuộc gọi Element đến" + diff --git a/features/createroom/impl/src/main/res/values-it/translations.xml b/features/createroom/impl/src/main/res/values-it/translations.xml index ce8bca20e0..7a936f41a8 100644 --- a/features/createroom/impl/src/main/res/values-it/translations.xml +++ b/features/createroom/impl/src/main/res/values-it/translations.xml @@ -3,14 +3,34 @@ "Nuova stanza" "Invita persone" "Si è verificato un errore durante la creazione della stanza" - "Solo le persone invitate possono accedere a questa stanza. Tutti i messaggi sono cifrati end-to-end." + "Non è stato possibile creare lo spazio a causa di un errore sconosciuto. Riprova più tardi." + "Aggiungi nome…" + "Nuova stanza" + "Nuovo spazio" + "Possono partecipare solo le persone invitate." + "Privato" "Chiunque può trovare questa stanza. Puoi modificarlo in qualsiasi momento nelle impostazioni della stanza." - "Chiunque può chiedere di entrare nella stanza, ma un amministratore o un moderatore dovrà accettare la richiesta" - "Chiedi di entrare" - "Chiunque può entrare in questa stanza" - "Affinché questa stanza sia visibile nell\'elenco delle stanze pubbliche, è necessario un indirizzo della stanza." - "Indirizzo della stanza" + "Chiunque può partecipare." + "Pubblico" + "Chiunque può chiedere di partecipare, ma un amministratore o un moderatore deve accettare la richiesta." + "Consenti di chiedere di partecipare" + "Chiunque sia membro di %1$s può partecipare, mentre tutti gli altri devono richiedere l\'accesso." + "Richiedi accesso" + "Possono partecipare solo le persone invitate." + "Privato" + "Chiunque può partecipare." + "Pubblico" + "Chiunque in %1$s può unirsi." + "Standard" + "Chi ha accesso" + "Avrai bisogno di un indirizzo per renderlo visibile nella directory pubblica." + "Indirizzo" "Visibilità della stanza" + "(nessuno spazio)" + "Non aggiungere a uno spazio" + "Nessuno spazio selezionato" + "Aggiungi allo spazio" "Argomento (facoltativo)" + "Aggiungi descrizione…" diff --git a/features/createroom/impl/src/main/res/values-ja/translations.xml b/features/createroom/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..f6f7c71390 --- /dev/null +++ b/features/createroom/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,36 @@ + + + "新しいルーム" + "ユーザーを招待" + "ルームの作成中に問題が発生しました" + "不明な問題のためスペースを作成できませんでした。再度お試しください。" + "名前を追加…" + "新しいルーム" + "新しいスペース" + "招待されたユーザーのみ参加できます。" + "非公開" + "ルームは全世界に公開されます。 +ルーム設定でいつでも変更できます。" + "誰でも参加できます。" + "公開" + "誰でも参加できますが、管理者またはモデレーターの承認が必要です。" + "参加の要求を許可" + "%1$s にいる全員が参加することができますが、事前に参加の要求をする必要があります。" + "参加を要求" + "招待されたユーザーのみが参加できます。" + "非公開" + "誰でも参加できます。" + "公開" + "%1$s にいる全員が参加することができます。" + "スタンダード" + "参加できるユーザー" + "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" + "アドレス" + "ルームの公開度" + "(スペースなし)" + "スペースに追加しない" + "スペースが選択されていません" + "スペースに追加" + "トピック (任意)" + "説明を追加…" + diff --git a/features/createroom/impl/src/main/res/values-vi/translations.xml b/features/createroom/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..b10d15e077 --- /dev/null +++ b/features/createroom/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,11 @@ + + + "Phòng mới" + "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." + "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." + "Chủ đề (tùy chọn)" + "Thêm mô tả…" + diff --git a/features/deactivation/impl/src/main/res/values-ja/translations.xml b/features/deactivation/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..873b1308ec --- /dev/null +++ b/features/deactivation/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,14 @@ + + + "アカウントを無効化することを再度確認します。この操作は元に戻せません。" + "メッセージをすべて削除" + "注意: 新しいユーザーには断片的な会話が表示されます" + "アカウントを無効化することは %1$s であり、次の変化が生じます:" + "不可逆" + "アカウントを %1$s (再度ログイン不可, 同一のIDを再利用不可)" + "恒久的に無効化する" + "すべてのチャットルームから退出します。" + "アカウント提供元サーバーからアカウント情報を削除します。" + "あなたの会話は、既存ユーザーには引き続き表示されますが、新規ユーザーには表示されなくなります。" + "アカウントを無効化" + diff --git a/features/deactivation/impl/src/main/res/values-vi/translations.xml b/features/deactivation/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..22bc0a6d6e --- /dev/null +++ b/features/deactivation/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,7 @@ + + + "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." + "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-it/translations.xml b/features/ftue/impl/src/main/res/values-it/translations.xml index 25ba544d00..8aa9132732 100644 --- a/features/ftue/impl/src/main/res/values-it/translations.xml +++ b/features/ftue/impl/src/main/res/values-it/translations.xml @@ -2,8 +2,8 @@ "Non puoi confermare?" "Crea una nuova chiave di recupero" - "Verifica questo dispositivo per segnare i tuoi messaggi come sicuri." - "Conferma la tua identità" + "Scegli come effettuare la verifica per configurare la messaggistica sicura." + "Conferma la tua identità digitale" "Usa un altro dispositivo" "Usa la chiave di recupero" "Ora puoi leggere o inviare messaggi in tutta sicurezza e anche chi chatta con te può fidarsi di questo dispositivo." diff --git a/features/ftue/impl/src/main/res/values-ja/translations.xml b/features/ftue/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..68b69079ef --- /dev/null +++ b/features/ftue/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,15 @@ + + + "認証できませんか?" + "回復鍵を新規作成します" + "安全なメッセージを設定するための検証方法を選択してください。" + "デジタルIDの認証" + "他の端末を使用" + "回復鍵を使用" + "メッセージのやり取りを安全に行えるようになりました。他のユーザーはこの端末を信頼できます。" + "検証済みの端末" + "他の端末を使用" + "一方の端末を待機中…" + "設定は後で変更することができます。" + "メッセージを見逃さないため通知を許可" + diff --git a/features/ftue/impl/src/main/res/values-ru/translations.xml b/features/ftue/impl/src/main/res/values-ru/translations.xml index b2f0925813..34ac77ae3f 100644 --- a/features/ftue/impl/src/main/res/values-ru/translations.xml +++ b/features/ftue/impl/src/main/res/values-ru/translations.xml @@ -2,7 +2,7 @@ "Не можете подтвердить?" "Создайте новый ключ восстановления" - "Подтвердите это устройство, чтобы настроить безопасный обмен сообщениями." + "Выберите способ подтверждения для настройки защищенного обмена сообщениями." "Подтвердите личность" "Использовать другое устройство" "Использовать ключ восстановления" diff --git a/features/ftue/impl/src/main/res/values-vi/translations.xml b/features/ftue/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..c70d9be0fb --- /dev/null +++ b/features/ftue/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,10 @@ + + + "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" + "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" + "Đ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/translations.xml b/features/ftue/impl/src/main/res/values-zh/translations.xml index 669a316243..68a48831e0 100644 --- a/features/ftue/impl/src/main/res/values-zh/translations.xml +++ b/features/ftue/impl/src/main/res/values-zh/translations.xml @@ -2,8 +2,8 @@ "无法确认?" "创建新的恢复密钥" - "验证此设备以开始安全地收发消息。" - "确认这是你" + "选择验证方式以设置安全的消息传输。" + "确认您的数字身份" "使用其他设备" "使用恢复密钥" "现在,您可以安全地阅读或发送消息,与您聊天的人也会信任此设备。" diff --git a/features/home/impl/src/main/res/values-it/translations.xml b/features/home/impl/src/main/res/values-it/translations.xml index 932545c7b0..2c5461bfa8 100644 --- a/features/home/impl/src/main/res/values-it/translations.xml +++ b/features/home/impl/src/main/res/values-it/translations.xml @@ -5,9 +5,9 @@ "Le notifiche non arrivano?" "Il ping delle notifiche è stato aggiornato: ora è più chiaro, più rapido e meno fastidioso." "Abbiamo rinnovato i tuoi suoni" - "Recupera la tua identità crittografica e la cronologia dei messaggi con una chiave di recupero se hai perso tutti i tuoi dispositivi." - "Configura il recupero" - "Configura il ripristino" + "Le tue conversazioni vengono automaticamente salvate con crittografia end-to-end. Per ripristinare questo backup e conservare la tua identità digitale quando perdi l\'accesso a tutti i tuoi dispositivi, avrai bisogno della tua chiave di recupero." + "Ottieni la chiave di recupero" + "Esegui il backup delle tue conversazioni" "Conferma la chiave di recupero per mantenere l\'accesso all\'archiviazione delle chiavi e alla cronologia dei messaggi." "Inserisci la tua chiave di recupero" "Hai dimenticato la chiave di recupero?" @@ -50,6 +50,7 @@ Non hai messaggi non letti!" "Segna come letto" "Segna come non letto" "Questa stanza è stata aggiornata" + "I tuoi spazi" "Sembra che tu stia usando un nuovo dispositivo. Verificati con un altro dispositivo per accedere ai tuoi messaggi cifrati." "Verifica che sei tu" diff --git a/features/home/impl/src/main/res/values-ja/translations.xml b/features/home/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..3e4b16b682 --- /dev/null +++ b/features/home/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,56 @@ + + + "すべての通知を確実に受信するために、このアプリのバッテリー最適化を無効にしてください。" + "最適化を無効にする" + "通知が届いていませんか?" + "通知音が更新され、より明確で速く、そして邪魔にならなくなりました。" + "サウンドを刷新しました" + "あなたのチャットはエンドツーエンド暗号化を使用して自動的にバックアップされています。すべての端末を使用できない状況で、このバックアップからデジタルIDを復元するには、回復鍵が必要となります。" + "回復鍵を作成" + "チャットをバックアップ" + "鍵の保管庫と過去のメッセージにアクセスするために、回復鍵を認証してください。" + "回復鍵を入力してください" + "回復鍵を忘れましたか?" + "鍵の保管庫を同期できません。" + "重要な電話を確実に受け取るため、端末がロックされている状態での全画面通知を、設定から許可してください。" + "通話品質を高める" + "チャット" + "スペース" + "%1$sへの招待を本当に破棄しますか?" + "招待を破棄" + "%1$sとのチャットを本当に拒否しますか?" + "チャットを拒否" + "招待はありません" + "%1$s (%2$s) があなたを招待しました" + "一度限りの工程です。お待ちください。" + "アカウントを設定しています。" + "新しい会話またはルームを作成" + "フィルターを解除" + "誰かにメッセージを送信しましょう。" + "まだチャットがありません。" + "お気に入り" + "チャットの設定からお気に入りに追加できます。 +現在は、フィルターの選択を解除することで他のチャットを表示できます。" + "お気に入りのチャットはまだありません" + "招待" + "承認待ちの招待はありません" + "低い優先度" + "低い優先度のチャットはまだありません" + "フィルターを解除して他のチャットを表示できます" + "この選択中にチャットがありません" + "人" + "まだダイレクトメッセージは届いていません" + "ルーム" + "まだルームに参加していません" + "未読" + "やった! +未読メッセージはありません。" + "参加リクエストを送信しました" + "チャット" + "既読にする" + "未読にする" + "このルームはアップグレードされました" + "あなたのスペース" + "新しいデバイスをご利用のようです。暗号化されたメッセージにアクセスするには、別のデバイスで検証してください。" + "本人確認" + diff --git a/features/home/impl/src/main/res/values-ru/translations.xml b/features/home/impl/src/main/res/values-ru/translations.xml index d06c9a3854..233e8749b4 100644 --- a/features/home/impl/src/main/res/values-ru/translations.xml +++ b/features/home/impl/src/main/res/values-ru/translations.xml @@ -5,7 +5,7 @@ "Уведомления не приходят?" "Ваши уведомления были обновлены — теперь они понятнее, быстрее и менее отвлекающие." "Мы обновили ваши звуки" - "Создайте новый ключ восстановления, который можно использовать для восстановления зашифрованной истории сообщений в случае потери доступа к своим устройствам." + "Ваши чаты автоматически резервируются с использованием сквозного шифрования. Для восстановления этой резервной копии и сохранения вашей цифровой личности в случае потери доступа ко всем вашим устройствам вам потребуется ключ восстановления." "Получить ключ восстановления" "Сделайте резервную копию своих чатов." "Подтвердите ключ восстановления, чтобы сохранить доступ к хранилищу ключей и истории сообщений." diff --git a/features/home/impl/src/main/res/values-vi/translations.xml b/features/home/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..bc62880fff --- /dev/null +++ b/features/home/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,48 @@ + + + "Tắt tính năng tối ưu hóa pin cho ứng dụng này để đảm bảo nhận được mọi thông báo." + "Tắt tối ưu hóa" + "Có nhận được thông báo không?" + "Thông báo của bạn đã được cập nhật — rõ ràng hơn, nhanh hơn và ít gây khó chịu hơn." + "Chúng tôi đã làm mới âm thanh của bạn." + "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." + "Lấy khóa khôi phục." + "Sao lưu tin nhắn của bạn" + "Xác nhận khóa khôi phục để không bị mất quyền truy cập vào tin nhắn." + "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ộ" + "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" + "Bạn có chắc muốn từ chối cuộc trò chuyện riêng với %1$s không?" + "Từ chối trò chuyện" + "Không có lời mời" + "%1$s(%2$s ) đã mời bạn" + "Quá trình này chỉ thực hiện một lần, cảm ơn bạn đã kiên nhẫn." + "Đang thiết lập tài khoản của bạn." + "Tạo một cuộc trò chuyện hoặc phòng mới" + "Bắt đầu bằng cách nhắn tin cho ai đó." + "Chưa có cuộc trò chuyện nào." + "Yêu thích" + "Bạn có thể thêm cuộc trò chuyện vào mục yêu thích trong cài đặt chat. +Hiện tại, bạn có thể bỏ chọn bộ lọc để xem các cuộc trò chuyện khác." + "Bạn chưa có cuộc trò chuyện yêu thích nào." + "Lời mời" + "Ưu tiên thấp" + "Bạn có thể bỏ chọn bộ lọc để xem các cuộc trò chuyện khác" + "Bạn không có cuộc trò chuyện nào cho lựa chọn này" + "Danh bạ" + "Bạn chưa có tin nhắn riêng nào cả" + "Phòng" + "Bạn chưa tham gia phòng nào" + "Chưa đọc" + "Chúc mừng! +Bạn không còn tin nhắn nào chưa đọc nữa!" + "Yêu cầu tham gia đã được gửi" + "Cuộc trò chuyện" + "Đánh dấu đã đọc" + "Đánh dấu chưa đọc" + "Có vẻ như bạn đang sử dụng thiết bị mới. Hãy xác minh bằng một thiết bị khác để truy cập tin nhắn được mã hóa của bạn." + "Xác thực danh tính của bạn" + 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 1705569a49..58e5b1eb91 100644 --- a/features/home/impl/src/main/res/values-zh/translations.xml +++ b/features/home/impl/src/main/res/values-zh/translations.xml @@ -6,7 +6,7 @@ "您的通知提示音已升级 - 更清晰、更快速、干扰更少。" "我们已更新您的声音" "生成新的恢复密钥,该密钥可用于在您无法访问设备时恢复加密的消息历史记录。" - "设置恢复" + "获取恢复密钥" "设置恢复" "确认恢复密钥,以保持对密钥存储和消息历史的访问。" "输入恢复密钥" diff --git a/features/invite/impl/src/main/res/values-be/translations.xml b/features/invite/impl/src/main/res/values-be/translations.xml index fca38b796a..3c17aa0cdb 100644 --- a/features/invite/impl/src/main/res/values-be/translations.xml +++ b/features/invite/impl/src/main/res/values-be/translations.xml @@ -1,10 +1,12 @@ "Заблакіраваць карыстальніка" + "Адхіліць і заблакіраваць" "Вы ўпэўненыя, што хочаце адхіліць запрашэнне ў %1$s?" "Адхіліць запрашэнне" "Вы ўпэўненыя, што хочаце адмовіцца ад прыватных зносін з %1$s?" "Адхіліць чат" "Няма запрашэнняў" "%1$s (%2$s) запрасіў(-ла) вас" + "Адхіліць і заблакіраваць" diff --git a/features/invite/impl/src/main/res/values-ja/translations.xml b/features/invite/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..5e1b527dd3 --- /dev/null +++ b/features/invite/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,18 @@ + + + "このユーザーからのメッセージと招待を非表示します" + "ユーザーをブロック" + "アカウント提供元にこのルームを報告" + "報告の理由を説明してください…" + "拒否してブロック" + "%1$sへの招待を本当に破棄しますか?" + "招待を破棄" + "%1$sとのチャットを本当に拒否しますか?" + "チャットを拒否" + "招待はありません" + "%1$s (%2$s) があなたを招待しました" + "拒否してブロックする" + "本当にこのルームへの参加の招待を拒否しますか?%1$s は、あなたと会話することやルームに招待することができなくなります。" + "招待を拒否してブロック" + "拒否してブロック" + diff --git a/features/invite/impl/src/main/res/values-vi/translations.xml b/features/invite/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..9b7784c25d --- /dev/null +++ b/features/invite/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,17 @@ + + + "Bạn sẽ không nhận được bất kỳ tin nhắn hoặc lời mời tham gia phòng nào từ người dùng này." + "Chặn người dùng" + "Báo cáo phòng này cho nhà cung cấp tài khoản của bạn." + "Từ chối và chặ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" + "Bạn có chắc muốn từ chối cuộc trò chuyện riêng với %1$s không?" + "Từ chối trò chuyện" + "Không có lời mời" + "%1$s(%2$s ) đã mời bạn" + "Có, từ chối & chặn" + "Bạn có chắc muốn từ chối lời mời tham gia phòng này không? Điều này cũng sẽ ngăn %1$s liên hệ với bạn hoặc mời bạn vào các phòng." + "Từ chối lời mời và chặn" + "Từ chối và chặn" + diff --git a/features/invite/impl/src/main/res/values-zh/translations.xml b/features/invite/impl/src/main/res/values-zh/translations.xml index e7cf39a9c3..8c27397225 100644 --- a/features/invite/impl/src/main/res/values-zh/translations.xml +++ b/features/invite/impl/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ - "您不会看到来自该用户的任何信息或房间邀请" - "封禁用户" + "您将不会看到来自该用户的任何信息或房间邀请" + "屏蔽用户" "向您的帐户提供商举报此房间。" "描述举报的原因…" "拒绝并屏蔽" @@ -12,7 +12,7 @@ "没有邀请" "%1$s (%2$s)邀请了你" "是的,拒绝并屏蔽" - "您确定要拒绝加入此房间的邀请吗?这也将阻止%1$s 与您联系或邀请您加入房间。" + "您确定要拒绝加入此房间的邀请吗?这也将阻止 %1$s 与您联系或邀请您加入房间。" "拒绝邀请并屏蔽" "拒绝并屏蔽" diff --git a/features/invitepeople/impl/src/main/res/values-ja/translations.xml b/features/invitepeople/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..6aa1fb0370 --- /dev/null +++ b/features/invitepeople/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,11 @@ + + + "既に参加しています" + "既に招待しています" + + "この連絡先とのチャットがありません。続行する前に、このルームに招待してください。" + + + "このルームに新しい連絡先を追加しますか?" + + diff --git a/features/invitepeople/impl/src/main/res/values-vi/translations.xml b/features/invitepeople/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..934cb7d24f --- /dev/null +++ b/features/invitepeople/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "Đã là thành viên" + "Đã được mời" + diff --git a/features/invitepeople/impl/src/main/res/values/localazy.xml b/features/invitepeople/impl/src/main/res/values/localazy.xml index d89ae92e75..0515121428 100644 --- a/features/invitepeople/impl/src/main/res/values/localazy.xml +++ b/features/invitepeople/impl/src/main/res/values/localazy.xml @@ -2,4 +2,12 @@ "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?" + diff --git a/features/joinroom/impl/src/main/res/values-be/translations.xml b/features/joinroom/impl/src/main/res/values-be/translations.xml index 1986a761b0..f166186a1b 100644 --- a/features/joinroom/impl/src/main/res/values-be/translations.xml +++ b/features/joinroom/impl/src/main/res/values-be/translations.xml @@ -1,5 +1,6 @@ + "Адхіліць і заблакіраваць" "Далучыцца" "Націсніце, каб далучыцца" "%1$s пакуль не падтрымлівае прасторы. Вы можаце атрымаць доступ да прастор праз вэб-старонку." diff --git a/features/joinroom/impl/src/main/res/values-ja/translations.xml b/features/joinroom/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..f5bb2e3b66 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,34 @@ + + + "%1$s があなたを追放しました。" + "追放されました" + "理由: %1$s" + "リクエストをキャンセル" + "キャンセルします" + "このルームへの参加のリクエストを本当にキャンセルしますか?" + "参加のリクエストをキャンセル" + "拒否してブロックする" + "本当にこのルームへの参加の招待を拒否しますか?%1$s は、あなたと会話することやルームに招待することができなくなります。" + "招待を拒否してブロック" + "拒否してブロック" + "参加に失敗" + "制限付きアクセスまたは招待制です。" + "忘れる" + "参加するには招待が必要です" + "以下のユーザーからの招待" + "参加" + "参加するには、招待またはスペースのメンバーである必要があります。" + "参加をリクエスト" + "文字数制限 %1$d/%2$d 字" + "メッセージ (任意)" + "リクエストが承認された場合はルームへの招待が届きます。" + "参加リクエストを送信しました" + "ルームのプレビューを表示できません。サーバーまたはネットワークの問題の可能性があります。" + "ルームのプレビューを表示できません" + "%1$s はスペースに対応していません。Webからアクセスすることができます。" + "まだスペースに対応していません" + "下のボタンを押すとルーム管理者に通知が届きます。承認の後、会話に参加することができます。" + "過去のメッセージを表示するには、このルームのメンバーである必要があります。" + "ルームに参加しますか?" + "プレビューは利用できません" + diff --git a/features/joinroom/impl/src/main/res/values-vi/translations.xml b/features/joinroom/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..cb9258b308 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,19 @@ + + + "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?" + "Hủy yêu cầu tham gia" + "Có, từ chối & chặn" + "Bạn có chắc muốn từ chối lời mời tham gia phòng này không? Điều này cũng sẽ ngăn %1$s liên hệ với bạn hoặc mời bạn vào các phòng." + "Từ chối lời mời và chặn" + "Từ chối và chặn" + "Được mời bởi" + "Tham gia" + "Số ký tự cho phép: %1$d / %2$d" + "Lời nhắn (tùy chọn)" + "Bạn sẽ nhận được lời mời tham gia phòng nếu yêu cầu của bạn được chấp nhận." + "Yêu cầu tham gia đã được gửi" + "Không thể hiển thị bản xem trước của phòng. Có thể do lỗi mạng hoặc máy chủ." + "Không thể hiển thị bản xem trước của phòng này" + diff --git a/features/joinroom/impl/src/main/res/values-zh/translations.xml b/features/joinroom/impl/src/main/res/values-zh/translations.xml index 7bea362c81..d38f9d3427 100644 --- a/features/joinroom/impl/src/main/res/values-zh/translations.xml +++ b/features/joinroom/impl/src/main/res/values-zh/translations.xml @@ -1,14 +1,14 @@ - "您已被禁止访问%1$s。" - "你已被禁止访问" + "您已被 %1$s 封禁。" + "你已被此房间封禁" "理由:%1$s。" "取消请求" "是的,取消" "您确定要取消加入此房间的请求吗?" "取消加入申请" "是的,拒绝并屏蔽" - "您确定要拒绝加入此房间的邀请吗?这也将阻止%1$s 与您联系或邀请您加入房间。" + "您确定要拒绝加入此房间的邀请吗?这也将阻止 %1$s 与您联系或邀请您加入房间。" "拒绝邀请并屏蔽" "拒绝并屏蔽" "加入失败" @@ -29,6 +29,6 @@ "空间尚不支持" "点击下面的按钮,系统将通知聊天室管理员。获得批准后将能够加入对话。" "只有聊天室成员才能查看消息历史记录。" - "想加入这个聊天室吗?" + "想加入此聊天室吗?" "预览不可用" diff --git a/features/knockrequests/impl/src/main/res/values-ja/translations.xml b/features/knockrequests/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..d08d4f3c20 --- /dev/null +++ b/features/knockrequests/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,35 @@ + + + "すべて承認" + "本当にすべての参加リクエストを承認しますか?" + "すべてのリクエストを承認" + "すべて承認" + "リクエストの一部を承認できませんでした。もう一度試しますか?" + "リクエストの承認に一部失敗" + "すべてのリクエストを承認中" + "リクエストを承認できませんでした。もう一度試しますか?" + "リクエストの承認に失敗" + "リクエストを承認中" + "拒否して追放する" + "本当に %1$s を拒否して追放しますか?このユーザーが再度リクエストを送信することはできなくなります。" + "拒否してアクセスから追放" + "拒否してアクセスから追放中" + "拒否する" + "本当に %1$s の参加リクエストを拒否しますか?" + "アクセスを拒否" + "拒否と追放" + "このリクエストを拒否できません。もう一度試しますか?" + "リクエストの拒否に失敗" + "参加リクエストを拒否中" + "ルームへの参加リクエストがある場合は、ここに表示されます。" + "参加リクエストがありません" + "参加リクエストを読み込み中" + "参加のリクエスト" + + "%1$s 他 %2$d 人がルーム参加を希望" + + "すべて表示" + "承諾" + "%1$s がこのルームの参加を要求しています" + "表示" + diff --git a/features/knockrequests/impl/src/main/res/values-vi/translations.xml b/features/knockrequests/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..a80aa6fbb8 --- /dev/null +++ b/features/knockrequests/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,29 @@ + + + "Có, chấp nhận tất cả" + "Bạn có chắc chắn muốn chấp nhận tất cả các yêu cầu tham gia không?" + "Chấp nhận tất cả các yêu cầu" + "Chấp nhận tất cả" + "Không thể chấp nhận tất cả yêu cầu. Bạn có muốn thử lại không?" + "Chấp nhận tất cả yêu cầu thất bại" + "Đang duyệt tất cả yêu cầu tham gia" + "Không thể chấp nhận yêu cầu này. Bạn có muốn thử lại không?" + "Chấp nhận yêu cầu thất bại" + "Đang duyệt yêu cầu tham gia" + "Có, từ chối và cấm" + "Bạn có chắc muốn từ chối và cấm %1$s không? Người dùng này sẽ không thể yêu cầu tham gia phòng này nữa" + "Từ chối và cấm truy cập" + "Đang từ chối và chặn truy cập" + "Có, từ chối" + "Bạn có chắc muốn từ chối yêu cầu tham gia phòng của %1$s không?" + "Từ chối truy cập" + "Từ chối và chặn" + "Không thể từ chối yêu cầu. Bạn có muốn thử lại không?" + "Từ chối yêu cầu thất bại" + "Đang từ chối yêu cầu tham gia" + "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…" + "Đồng ý" + "Xem" + diff --git a/features/knockrequests/impl/src/main/res/values-zh/translations.xml b/features/knockrequests/impl/src/main/res/values-zh/translations.xml index f568ee1120..08718dfc5a 100644 --- a/features/knockrequests/impl/src/main/res/values-zh/translations.xml +++ b/features/knockrequests/impl/src/main/res/values-zh/translations.xml @@ -30,6 +30,6 @@ "查看全部" "接受" - "%1$s想加入这个房间" + "%1$s 想加入此房间" "查看" diff --git a/features/leaveroom/api/src/main/res/values-ja/translations.xml b/features/leaveroom/api/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..73c1508bd2 --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-ja/translations.xml @@ -0,0 +1,10 @@ + + + "本当にこの会話を退出しますか?この会話は非公開で、再度参加するには招待が必要です。" + "本当にこのルームを退出しますか?あなたが最後の一人であり、このルームには誰も参加することができなくなります。" + "ルームから退出してもよいですか? このルームは非公開のため、参加しなおすには改めて招待される必要があります。" + "所有者を選択" + "あなたがこのルームの唯一の所有者です。退出する前に所有権を他のユーザーへ譲与する必要があります。" + "所有権の譲与" + "本当にこのルームを退出しますか?" + diff --git a/features/leaveroom/api/src/main/res/values-vi/translations.xml b/features/leaveroom/api/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..d25a7e34b2 --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-vi/translations.xml @@ -0,0 +1,7 @@ + + + "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." + "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-it/translations.xml b/features/linknewdevice/impl/src/main/res/values-it/translations.xml index 0cf548c19b..9a6476823a 100644 --- a/features/linknewdevice/impl/src/main/res/values-it/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-it/translations.xml @@ -1,16 +1,33 @@ "Scansiona il codice QR" + "Apri %1$s su un laptop o un computer desktop" "Scansiona il codice QR con questo dispositivo" "Pronto per la scansione" + "Apri %1$s su un computer desktop per ottenere il codice QR" + "I numeri non corrispondono" + "Inserisci il codice a 2 cifre" + "Questo verificherà che la connessione con l\'altro dispositivo sia sicura." + "Inserisci il numero visualizzato sull\'altro dispositivo" "Il tuo fornitore di account non supporta %1$s." "%1$s non supportato" + "Il tuo provider di account non supporta l\'accesso a un nuovo dispositivo tramite codice QR." "Codice QR non supportato" "L\'accesso è stato annullato sull\'altro dispositivo." "Richiesta di accesso annullata" "L\'accesso è scaduto. Riprova." "L\'accesso non è stato completato in tempo" + "Apri %1$s sull\'altro dispositivo" "Seleziona %1$s" + "“Accedi con codice QR”" + "Scansiona il codice QR qui riportato con l\'altro dispositivo" + "Apri %1$s sull\'altro dispositivo" + "Computer desktop" + "Caricamento codice QR in corso…" + "Dispositivo mobile" + "Che tipo di dispositivo desideri collegare?" + "Prova di nuovo e assicurati di aver inserito correttamente il codice a 2 cifre. Se i numeri continuano a non corrispondere, contatta il gestore del tuo account." + "I numeri non corrispondono" "Non è stato possibile stabilire una connessione sicura con il nuovo dispositivo. I tuoi dispositivi esistenti sono ancora al sicuro e non devi preoccuparti di loro." "E adesso?" "Prova ad accedere di nuovo con un codice QR nel caso si sia verificato un problema di rete." @@ -21,6 +38,8 @@ "Richiesta di accesso annullata" "L\'accesso è stato rifiutato sull\'altro dispositivo." "Accesso rifiutato" + "Non devi fare altro." + "L\'altro tuo dispositivo è già connesso" "L\'accesso è scaduto. Riprova." "L\'accesso non è stato completato in tempo" "L\'altro dispositivo non supporta l\'accesso a %s con un codice QR. diff --git a/features/linknewdevice/impl/src/main/res/values-ja/translations.xml b/features/linknewdevice/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..6cfd5baf84 --- /dev/null +++ b/features/linknewdevice/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,57 @@ + + + "QRコードを読み取り" + "%1$s をコンピュータで開いてください" + "この端末でQRコードを読み取る" + "読み取る" + "%1$s をコンピュータで開き、QRコードを表示してください" + "数字が一致しません" + "2桁の数字を入力してください" + "他の端末との接続が安全であることを確認します。" + "一方の端末で表示される数字を入力してください" + "アカウント提供元が %1$s に対応していません。" + "%1$s に非対応" + "あなたのアカウント提供元は、QRコードによる追加のサインインに対応していません。" + "QRコードに非対応" + "もう一方の端末がサインインをキャンセルしました" + "サインインのリクエストがキャンセルされました" + "サインインが無効です。もう一度試してください。" + "サインインが時間内に完了しませんでした" + "%1$s を他の端末で開いてください" + "%1$s を選択してください" + "\"QRコードでサインイン\"" + "表示されているQRコードを一方の端末で読み取ってください" + "%1$s を他の端末で開いてください" + "コンピュータ" + "QRコードを読み込み中…" + "モバイル端末" + "どのような端末を使用してサインインしますか?" + "入力した2桁の数字が正しいことを確認し、再度試してください。問題が継続する場合はアカウント提供元に問い合わせてください。" + "数字が一致しません" + "新しい端末で安全な通信を確立できませんでした。既存の端末は安全な状態を維持しています。" + "どうしますか?" + "ネットワークの問題の可能性があるため、再度QRコードでログインを試してください。" + "同様の問題が発生する場合は、異なるWi-Fiやモバイルデータ通信を試してください" + "問題が解決しない場合は、手動でサインインしてください" + "接続が安全ではありません" + "もう一方の端末がサインインをキャンセルしました" + "サインインのリクエストがキャンセルされました" + "もう一方の端末でサインインを拒否されました" + "サインインを拒否" + "他には何もする必要はありません。" + "他の端末で既にサインインしています" + "サインインが無効です。もう一度試してください。" + "サインインが時間内に完了しませんでした" + "QRコードを使用した %s へのサインインに他の端末が対応していません。 + +異なる端末でQRコードを読み取るか、手動でサインインしてください。" + "QRコードに非対応" + "アカウント提供元が %1$s に対応していません。" + "%1$s に非対応" + "もう一方の端末に表示されているQRコードを使用してください" + "もう一度やり直してください" + "QRコードが間違っています" + "続行するには、%1$s にカメラの使用を許可する必要があります。" + "QRコードを読み取るため、カメラへのアクセスを許可" + "予期せぬ問題が発生しました。もう一度試してください。" + diff --git a/features/linknewdevice/impl/src/main/res/values-vi/translations.xml b/features/linknewdevice/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..5e7709f814 --- /dev/null +++ b/features/linknewdevice/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,4 @@ + + + "Thử lại" + diff --git a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml index 843395fab7..10ae1ae7a7 100644 --- a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml @@ -23,7 +23,7 @@ "请用另一台设备扫描此处显示的二维码" "在另一台设备上打开 %1$s" "台式计算机" - "正在加载 QR 码…" + "正在加载二维码…" "移动设备" "您想连接哪种类型的设备?" "请重试,并确保您已正确输入两位验证码。如果验证码仍然不匹配,请联系您的账户提供商。" diff --git a/features/location/impl/src/main/res/values-it/translations.xml b/features/location/impl/src/main/res/values-it/translations.xml new file mode 100644 index 0000000000..235a9eba4a --- /dev/null +++ b/features/location/impl/src/main/res/values-it/translations.xml @@ -0,0 +1,5 @@ + + + "La cronologia delle tue posizioni in tempo reale verrà archiviata nella stanza e sarà visibile ai membri al termine della sessione." + "Scegli per quanto tempo condividere la tua posizione in tempo reale." + diff --git a/features/location/impl/src/main/res/values-ja/translations.xml b/features/location/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..971693ef11 --- /dev/null +++ b/features/location/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,5 @@ + + + "ライブ位置情報の履歴はルームに保管され、メンバーは後から確認することもできます。" + "ライブ位置情報を共有する期間を選択してください。" + diff --git a/features/location/impl/src/main/res/values-ru/translations.xml b/features/location/impl/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..3c496f1d39 --- /dev/null +++ b/features/location/impl/src/main/res/values-ru/translations.xml @@ -0,0 +1,5 @@ + + + "История вашего местоположения в режиме реального времени будет сохранена в комнате и станет доступна участникам после окончания сессии." + "Выберите, как долго вы будете делиться своим местоположением в режиме реального времени." + diff --git a/features/lockscreen/impl/src/main/res/values-it/translations.xml b/features/lockscreen/impl/src/main/res/values-it/translations.xml index 514d2461a2..5f9c82a34a 100644 --- a/features/lockscreen/impl/src/main/res/values-it/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-it/translations.xml @@ -23,7 +23,7 @@ Scegli un PIN facile da ricordare. Se lo dimentichi, verrai disconnesso dall’a "Inserisci lo stesso PIN due volte" "I PIN non corrispondono" "Dovrai effettuare nuovamente l\'accesso e creare un nuovo PIN per procedere" - "Stai per essere disconnesso" + "Questo dispositivo verrà rimosso" "Hai %1$d tentativo di sblocco" "Hai %1$d tentativi di sblocco" @@ -34,5 +34,5 @@ Scegli un PIN facile da ricordare. Se lo dimentichi, verrai disconnesso dall’a "Usa la biometria" "Usa il PIN" - "Disconnessione in corso…" + "Rimozione del dispositivo…" diff --git a/features/lockscreen/impl/src/main/res/values-ja/translations.xml b/features/lockscreen/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..982c4574c8 --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,36 @@ + + + "生体認証" + "生体認証で解除" + "生体認証を使用" + "生体認証を使用しますか?" + "PINをお忘れですか?" + "PINを変更" + "生体認証を使用" + "PINを削除" + "本当にPINを削除しますか?" + "PINを削除しますか?" + "%1$sを使用" + "PINを使用する" + "素早い認証のために %1$s を常に使用" + "PINを選択" + "PINの確認" + "チャットのセキュリティを強化するため、%1$s を保護しましょう。 + +覚えやすいPINを設定してください。PINを忘れると、アプリにログインできなくなります。" + "セキュリティ上の理由により、入力された内容をPINとして使用できません。" + "別のPINを使用してください" + "同一のPINを2回入力してください" + "PINが一致しません" + "再度ログインし、PINを再設定する必要があります" + "端末を削除しようとしています" + + "%1$d 回試すことができます" + + + "PINが間違っています。あと %1$d 回試すことができます。" + + "生体認証を使用" + "PINを使用" + "削除中…" + diff --git a/features/lockscreen/impl/src/main/res/values-vi/translations.xml b/features/lockscreen/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..2a177b843b --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,35 @@ + + + "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" + "Quên mã PIN rồi à?" + "Thay đổi mã PIN" + "Cho phép mở khóa bằng sinh trắc học" + "Xóa mã PIN" + "Bạn có chắc chắn muốn xóa mã PIN không?" + "Xóa mã PIN?" + "Cho phép %1$s" + "Tôi thích dùng mã PIN hơn." + "Dùng %1$s để mở khóa ứng dụng nhanh hơn." + "Chọn mã PIN" + "Xác nhận mã PIN" + "Khóa %1$s để tăng cường bảo mật cho các cuộc trò chuyện của bạn. + +Chọn một mã dễ nhớ. Nếu quên PIN này, bạn sẽ bị đăng xuất khỏi ứng dụng." + "Vì lý do bảo mật, bạn không thể chọn mã này làm mã PIN của mình." + "Chọn mã PIN khác" + "Vui lòng nhập cùng một mã PIN hai lần." + "Mã PIN không khớp" + "Đăng nhập lại và tạo PIN mới để tiếp tục." + "Thiết bị này đang được gỡ bỏ" + + "Bạn còn %1$d lần thử để mở khóa" + + + "PIN không đúng. Còn %1$d lần thử" + + "Sử dụng sinh trắc học" + "Sử dụng mã PIN" + "Đang gỡ thiết bị…" + 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 d3633e4af5..defe7a0e32 100644 --- a/features/lockscreen/impl/src/main/res/values-zh/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-zh/translations.xml @@ -32,5 +32,5 @@ "使用生物识别" "使用 PIN 码" - "正在登出…" + "正在删除设备……" 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 310aa22906..0de1cc0690 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -60,6 +60,8 @@ "Richiesta di accesso annullata" "L\'accesso è stato rifiutato sull\'altro dispositivo." "Accesso rifiutato" + "Non devi fare altro." + "L\'altro tuo dispositivo è già connesso" "L\'accesso è scaduto. Riprova." "L\'accesso non è stato completato in tempo" "L\'altro dispositivo non supporta l\'accesso a %s con un codice QR. diff --git a/features/login/impl/src/main/res/values-ja/translations.xml b/features/login/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..e2c89ba26e --- /dev/null +++ b/features/login/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,99 @@ + + + "アカウントの提供元を変更" + "ホームサーバーのアドレス" + "検索用のキーワードまたはドメインのアドレスを入力してください。" + "会社やコミュニティ, 個人のサーバーなどを検索します。" + "アカウントの提供元を検索" + "メールアプリのように、あなたの会話はここに保管されています。" + "%s にサインインを試みています" + "メールアプリのように、あなたの会話はここに保管されています。" + "%s にアカウントの作成を試みています" + "Matrix.org は Matrix.org Foundation が運営する、大規模で安全な分散型コミュニケーションを実現する無償のサーバーです。" + "その他" + "自身のサーバーや仕事用のアカウントにサインインするには、アカウント提供元のサーバーを指定してください。" + "アカウントの提供元を変更" + "Google Play" + "%1$s では Element Pro を使用する必要があります。アプリストアよりダウンロードしてください。" + "Element Pro が必要です" + "このホームサーバーに接続できませんでした。正しいURLを入力したことを確認し、問題が継続する場合は、ホームサーバーの管理者に問い合わせてください。" + ".well-knownファイルに問題があるためサーバーを使用できません: %1$s" + "このアカウント提供元は、スライド同期に対応していません。%1$s を使用するにはサーバーのアップグレードが必要です。" + "%2$s は %1$s からの接続を許可していません。" + "このアプリは次のサーバーを許可します: %1$s" + "アカウント提供元 %1$s は許可されていません。" + "ホームサーバーURL" + "ドメイン名を入力してください" + "サーバーのアドレスは何ですか?" + "サーバーを選択" + "アカウントを作成" + "このアカウントは無効化されています。" + "ユーザー名またはパスワードが違います" + "無効なユーザーIDです。正しい形式は \"@ユーザー:ホームサーバー\" です。" + "このサーバーはリフレッシュトークンを使用します。パスワードを使用したログインとは併用できません。" + "指定したホームサーバはパスワードまたはOIDCによるログインに対応していません。管理者に問い合わせるか、異なるホームサーバーを使用してください。" + "詳細を入力" + "Matrix は安全で分散型のオープンなネットワークです。" + "お待ちしておりました。" + "%1$s にサインイン" + "バージョン %1$s" + "手動で指定してサインイン" + "%1$s にサインイン" + "QRコードでサインイン" + "アカウントを作成" + "最速の %1$s にようこそ。機能性と利便性を極限まで追求しました。" + "機敏と利便を追求した %1$s へようこそ。" + "Be in your element" + "安全な通信を確立しています" + "新しい端末で安全な通信を確立できませんでした。既存の端末は安全な状態を維持しています。" + "どうしますか?" + "ネットワークの問題の可能性があるため、再度QRコードでログインを試してください。" + "同様の問題が発生する場合は、異なるWi-Fiやモバイルデータ通信を試してください" + "問題が解決しない場合は、手動でサインインしてください" + "接続が安全ではありません" + "この端末に表示される2つの数字の入力を要求されます" + "もう一方に表示される数字を入力してください" + "他の端末にサインインしてからもう一度試すか、既にサインインしてある端末を使用してください" + "他の端末でサインインしていません" + "もう一方の端末がサインインをキャンセルしました" + "サインインのリクエストがキャンセルされました" + "もう一方の端末でサインインを拒否されました" + "サインインを拒否" + "他には何もする必要はありません。" + "他の端末で既にサインインしています" + "サインインが無効です。もう一度試してください。" + "サインインが時間内に完了しませんでした" + "QRコードを使用した %s へのサインインに他の端末が対応していません。 + +異なる端末でQRコードを読み取るか、手動でサインインしてください。" + "QRコードに非対応" + "アカウント提供元が %1$s に対応していません。" + "%1$s に非対応" + "読み取る" + "コンピュータで %1$s を開く" + "アバターをタップしてください" + "%1$s を選択してください" + "\"新しい端末を追加\"" + "この端末でQRコードを読み取る" + "アカウント提供元が対応する場合にのみ使用できます。" + "他の端末の %1$s でQRコードを表示" + "もう一方の端末に表示されているQRコードを使用してください" + "もう一度やり直してください" + "QRコードが間違っています" + "カメラの設定を開く" + "続行するには、%1$s にカメラの使用を許可する必要があります。" + "QRコードを読み取るため、カメラへのアクセスを許可" + "QRコードを読み取り" + "やり直す" + "予期せぬ問題が発生しました。もう一度試してください。" + "一方の端末を待機しています" + "アカウント提供元が、サインインを検証するために以下の文字列を要求することがあります。" + "検証コード" + "アカウントの提供元を変更" + "Element 開発者用の非公開のサーバーです。" + "Matrix は安全で分散型のオープンなネットワークです。" + "メールアプリのように、あなたの会話はここに保管されています。" + "%1$s にサインインを試みています" + "アカウント提供元を選択" + "%1$s 上にアカウントの作成を試みています" + diff --git a/features/login/impl/src/main/res/values-vi/translations.xml b/features/login/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..b22ba5de7c --- /dev/null +++ b/features/login/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,47 @@ + + + "Thay đổi nhà cung cấp tài khoản" + "Địa chỉ Homeserver" + "Nhập từ khóa tìm kiếm hoặc địa chỉ tên miền." + "Tìm kiếm công ty, cộng đồng hoặc máy chủ riêng." + "Tìm nhà cung cấp tài khoản" + "Đây là nơi các cuộc trò chuyện của bạn sẽ được lưu — giống như bạn dùng nhà cung cấp email để giữ email của mình." + "Bạn sắp đăng nhập vào %s" + "Đây là nơi các cuộc trò chuyện của bạn sẽ được lưu — giống như bạn dùng nhà cung cấp email để giữ email của mình." + "Bạn sắp tạo tài khoản trên %s" + "Matrix.org là một máy chủ lớn, miễn phí trên mạng Matrix công cộng, cung cấp liên lạc an toàn và phi tập trung, được điều hành bởi Quỹ Matrix.org." + "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" + "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" + "URL homeserver" + "Địa chỉ máy chủ của bạn là gì?" + "Chọn máy chủ của bạn" + "Tạo tài khoản" + "Tài khoản này đã bị vô hiệu hóa." + "Tên người dùng và/hoặc mật khẩu không chính xác" + "Đây không phải là mã nhận dạng người dùng hợp lệ. Định dạng mong đợi: ‘@user:homeserver.org’" + "Máy chủ này được cấu hình sử dụng refresh token. Điều này không được hỗ trợ khi đăng nhập bằng mật khẩu." + "Homeserver đã chọn không hỗ trợ đăng nhập bằng mật khẩu hoặc OIDC. Vui lòng liên hệ với quản trị viên của cậu hoặc chọn một homeserver khác." + "Nhập thông tin chi tiết của bạn." + "Matrix là một mạng mở cho việc liên lạc an toàn và phi tập trung." + "Chào mừng bạn quay trở lại!" + "Đăng nhập vào %1$s" + "Đăng nhập thủ công" + "Đăng nhập vào %1$s" + "Đăng nhập bằng mã QR" + "Tạo tài khoản" + "Chào mừng đến với %1$s nhanh nhất từ trước đến nay. Tối ưu cho tốc độ và sự đơn giản." + "Chào mừng đến với %1$s. Tối ưu hóa cho tốc độ và sự đơn giản." + "Hãy ở trong thế mạnh (element) của mình" + "Thử lại" + "Bắt đầu lại" + "Thay đổi nhà cung cấp tài khoản" + "Máy chủ riêng dành cho nhân viên của Element." + "Matrix là một mạng mở cho việc liên lạc an toàn và phi tập trung." + "Đây là nơi các cuộc trò chuyện của bạn sẽ được lưu — giống như bạn dùng nhà cung cấp email để giữ email của mình." + "Bạn sắp đăng nhập vào %1$s" + "Bạn sắp tạo tài khoản trên %1$s" + diff --git a/features/logout/impl/src/main/res/values-it/translations.xml b/features/logout/impl/src/main/res/values-it/translations.xml index 47d6bcf519..eea93297c0 100644 --- a/features/logout/impl/src/main/res/values-it/translations.xml +++ b/features/logout/impl/src/main/res/values-it/translations.xml @@ -1,18 +1,18 @@ - "Sei sicuro di voler uscire?" - "Disconnetti" - "Disconnetti" - "Disconnessione in corso…" - "Stai per disconnettere la tua ultima sessione. Se esci ora, perderai l\'accesso ai tuoi messaggi cifrati." - "Hai disattivato il backup" - "Il backup delle chiavi era ancora in corso quando sei andato offline. Riconnettiti per eseguire il backup delle chiavi prima di uscire." + "Sei sicuro di voler rimuovere questo dispositivo?" + "Rimuovi questo dispositivo" + "Rimuovi questo dispositivo" + "Rimozione del dispositivo…" + "Questo è il tuo unico dispositivo. Se lo rimuovi, avrai bisogno di una chiave di recupero per confermare la tua identità digitale e ripristinare le tue conversazioni cifrate al prossimo accesso." + "Stai per perdere l\'accesso alle tue conversazioni cifrate" + "Il backup delle tue chiavi era ancora in corso quando ti sei disconnesso. Riconnettiti in modo che il backup delle tue chiavi possa essere completato prima di rimuovere questo dispositivo." "Il backup delle chiavi è ancora in corso" - "Attendi il completamento dell\'operazione prima di uscire." + "Attendi il completamento dell\'operazione prima di rimuovere questo dispositivo." "Il backup delle chiavi è ancora in corso" - "Disconnetti" - "Stai per disconnettere la tua ultima sessione. Se esci ora, perderai l\'accesso ai tuoi messaggi cifrati." - "Recupero non impostato" - "Stai per disconnettere la tua ultima sessione. Se esci ora, potresti perdere l\'accesso ai tuoi messaggi cifrati." - "Hai salvato la chiave di recupero?" + "Rimuovi questo dispositivo" + "Questo è il tuo unico dispositivo. Se lo rimuovi, avrai bisogno di una chiave di recupero per confermare la tua identità digitale e ripristinare le tue conversazioni cifrate al prossimo accesso." + "Stai per perdere l\'accesso alle tue conversazioni cifrate" + "Questo è il tuo unico dispositivo. Se lo rimuovi, avrai bisogno di una chiave di recupero per confermare la tua identità digitale e ripristinare le tue conversazioni cifrate al prossimo accesso." + "Assicurati di avere accesso alla tua chiave di recupero prima di rimuovere questo dispositivo" diff --git a/features/logout/impl/src/main/res/values-ja/translations.xml b/features/logout/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..2082bacf6e --- /dev/null +++ b/features/logout/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,18 @@ + + + "本当にこの端末を削除しますか?" + "この端末を削除" + "この端末を削除" + "削除中…" + "この端末が唯一の端末です。削除を続行すると次回のログインの際に、デジタルIDと暗号化された会話を復元するために、回復鍵を入力する必要があります。" + "暗号化された会話は見られなくなります" + "鍵のバックアップ中にオフライン状態になりました。この端末を削除する前に、オンラインに復旧してバックアップを完了させてください。" + "鍵のバックアップは継続しています" + "端末の削除の前に、処理の完了をお待ち下さい。" + "鍵のバックアップは継続しています" + "この端末を削除" + "この端末が唯一の端末です。削除を続行すると次回のログインの際に、デジタルIDと暗号化された会話を復元するために、回復鍵を入力する必要があります。" + "暗号化された会話は見られなくなります" + "この端末が唯一の端末です。削除を続行すると次回のログインの際に、デジタルIDと暗号化された会話を復元するために、回復鍵を入力する必要があります。" + "この端末を削除する前に、回復鍵が手元にあることを確認してください。" + diff --git a/features/logout/impl/src/main/res/values-ru/translations.xml b/features/logout/impl/src/main/res/values-ru/translations.xml index efb0d3d645..d96b8f24f2 100644 --- a/features/logout/impl/src/main/res/values-ru/translations.xml +++ b/features/logout/impl/src/main/res/values-ru/translations.xml @@ -1,18 +1,18 @@ - "Вы уверены, что вы хотите выйти?" + "Вы уверены, что хотите удалить это устройство?" "Удалить это устройство" "Удалить это устройство" "Удаление устройства…" - "Вы собираетесь выйти из последнего сеанса. Если вы выйдете из системы сейчас, вы потеряете доступ к зашифрованным сообщениям." - "Вы отключили резервное копирование" - "Когда вы перешли в автономный режим, резервное копирование ваших ключей продолжалось. Повторно подключитесь, чтобы перед выходом из системы можно было создать резервную копию ключей." + "Это ваше единственное устройство. Если вы его удалите, вам потребуется ключ восстановления, чтобы подтвердить свою цифровую личность и восстановить зашифрованные чаты при следующем входе в систему." + "Вы потеряете доступ к своим зашифрованным чатам" + "Когда вы отключились от сети, резервное копирование ваших ключей продолжалось. Подключитесь снова, чтобы резервная копия ваших ключей была создана, прежде чем вы отключите это устройство." "Резервное копирование ключей все еще продолжается" "Пожалуйста, дождитесь завершения процесса, прежде чем выходить из системы." "Резервное копирование ключей все еще продолжается" "Удалить это устройство" - "Вы собираетесь выйти из последнего сеанса. Если вы выйдете из системы сейчас, вы потеряете доступ к зашифрованным сообщениям." - "Восстановление не настроено" - "Вы собираетесь выйти из последнего сеанса. Если вы выйдете из системы сейчас, вы можете потерять доступ к зашифрованным сообщениям." - "Вы сохранили свой ключ восстановления?" + "Это ваше единственное устройство. Если вы его удалите, вам потребуется ключ восстановления, чтобы подтвердить свою цифровую личность и восстановить зашифрованные чаты при следующем входе в систему." + "Вы потеряете доступ к своим зашифрованным чатам" + "Это ваше единственное устройство. Если вы его удалите, вам потребуется ключ восстановления, чтобы подтвердить свою цифровую личность и восстановить зашифрованные чаты при следующем входе в систему." + "Перед тем как отключить это устройство, убедись, что у тебя есть доступ к ключу восстановления" diff --git a/features/logout/impl/src/main/res/values-vi/translations.xml b/features/logout/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..6c1a028948 --- /dev/null +++ b/features/logout/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,18 @@ + + + "Bạn có chắc muốn gỡ thiết bị này không?" + "Gỡ bỏ thiết bị này" + "Gỡ bỏ thiết bị này" + "Đang gỡ thiết bị…" + "Đây là thiết bị duy nhất của bạn. Nếu xóa nó, bạn sẽ cần khóa khôi phục để xác nhận danh tính kỹ thuật số và khôi phục các cuộc trò chuyện được mã hóa lần tiếp theo khi đăng nhập." + "Bạn sắp mất quyền truy cập vào các cuộc trò chuyện được mã hóa" + "Bạn đã ngoại tuyến khi các khóa đang được sao lưu. Kết nối lại để hoàn tất sao lưu trước khi gỡ thiết bị." + "Khóa của bạn vẫn đang được sao lưu." + "Đợi quá trình hoàn tất rồi hãy gỡ thiết bị." + "Khóa của bạn vẫn đang được sao lưu." + "Gỡ bỏ thiết bị này" + "Bạn sắp đăng xuất khỏi phiên làm việc cuối cùng. Nếu bạn đăng xuất ngay bây giờ, bạn sẽ mất quyền truy cập vào các tin nhắn đã mã hóa của mình." + "Bạn sắp mất quyền truy cập vào các cuộc trò chuyện được mã hóa" + "Đây là thiết bị duy nhất của bạn. Nếu xóa nó, bạn sẽ cần khóa khôi phục để xác nhận danh tính kỹ thuật số và khôi phục các cuộc trò chuyện được mã hóa khi đăng nhập lần tới." + "Đảm bảo bạn có khóa khôi phục trước khi gỡ thiết bị này." + diff --git a/features/logout/impl/src/main/res/values-zh/translations.xml b/features/logout/impl/src/main/res/values-zh/translations.xml index 0a8ec07e87..d438c64ff3 100644 --- a/features/logout/impl/src/main/res/values-zh/translations.xml +++ b/features/logout/impl/src/main/res/values-zh/translations.xml @@ -1,16 +1,16 @@ - "确定要登出吗?" - "登出" - "登出" - "正在登出…" + "您确定要删除此设备吗?" + "删除此设备" + "删除此设备" + "正在删除设备……" "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" "您已关闭备份" "当你离线时,密钥仍在备份中。重新连接以便在登出之前备份密钥。" "您的密钥仍在备份中" "请等待此操作完成后再登出。" "您的密钥仍在备份中" - "登出" + "删除此设备" "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" "未设置恢复" "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" diff --git a/features/messages/impl/src/main/res/values-it/translations.xml b/features/messages/impl/src/main/res/values-it/translations.xml index 0d750e7ed5..4eb3fd61bb 100644 --- a/features/messages/impl/src/main/res/values-it/translations.xml +++ b/features/messages/impl/src/main/res/values-it/translations.xml @@ -35,7 +35,7 @@ "Registra video" "Allegato" "Libreria di foto e video" - "Posizione" + "Condividi posizione" "Sondaggio" "Formattazione del testo" "La cronologia dei messaggi non è attualmente disponibile." diff --git a/features/messages/impl/src/main/res/values-ja/translations.xml b/features/messages/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..4fd18e8db5 --- /dev/null +++ b/features/messages/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,81 @@ + + + "イベントの送信者と、使用された端末の所有者が一致しません。" + "この暗号化されたメッセージの真正性を、この端末では保証できません。" + "以前に検証されたユーザーにより暗号化されています。" + "暗号化されていません。" + "削除されたまたは不明な端末により暗号化されています。" + "所有者に検証されていない端末により暗号化されています。" + "未検証のユーザーにより暗号化されています。" + "アクティビティ" + "旗" + "食べ物" + "動物・自然" + "物" + "顔・人" + "旅・場所" + "最近使用" + "記号" + "古いアプリケーションを使用しているユーザーはキャプションを見られない可能性があります。" + "動画のアップロード画質を変更するにはタップしてください" + "ファイルをアップロードに失敗しました。" + "ファイルの処理に失敗しました。再試行してください。" + "ファイルのアップロードに失敗しました。再試行してください。" + "許容されている最大サイズは %1$s です。" + "ファイルが大きすぎるためアップロードできません" + "個数 %1$d / %2$d" + "画像の品質を最適化" + "処理中…" + "ユーザーをブロック" + "このユーザーからのメッセージをすべて非表示にする場合はチェックしてください。" + "このメッセージはホームサーバーの管理者に報告されます。暗号化されたメッセージを確認することはできません。" + "このコンテンツを通報する理由" + "カメラ" + "写真を撮影" + "動画を撮影" + "添付ファイル" + "アルバムの写真・動画" + "場所を共有" + "投票" + "書式設定" + "過去のメッセージを現在表示できません。" + "このルームの過去のメッセージを表示できません。確認するには、この端末を検証してください。" + "招待し直しますか?" + "このチャットにはあなた一人だけです" + "ルーム全体に通知" + "全員" + "再送信する" + "メッセージの送信に失敗しました" + "リアクションを追加" + "%1$s の始まりです。" + "ここが会話の開始点です。" + "非対応の着信です。新しい Element X を使用できないか確認してください。" + "一部を表示" + "メッセージをコピーしました" + "このルームに発言する権限がありません" + + "%1$d 人の反応 %2$s" + + + "あなたと %1$d 人の反応 %2$s" + + "%1$s と反応" + "一部を表示" + "さらに表示" + "リアクションのまとめを表示" + "新着" + + "%1$d 個のルーム更新点" + + "新しいルームに移動" + "このルームは移行して非アクティブ状態です" + "古いメッセージを表示" + "このルームは他のルームからの移行先です" + + "%1$s, %2$s 他 %3$d 人" + + + "%1$s が入力中" + + "%1$s と %2$s" + diff --git a/features/messages/impl/src/main/res/values-vi/translations.xml b/features/messages/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..81ac0b7b8e --- /dev/null +++ b/features/messages/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,60 @@ + + + "Người gửi sự kiện không khớp với chủ sở hữu của thiết bị đã gửi nó." + "Tin nhắn mã hóa này không thể được xác thực trên thiết bị này." + "Được mã hóa bởi một người dùng đã từng được xác minh." + "Không được mã hóa" + "Được mã hóa bởi một thiết bị không xác định hoặc đã bị xóa." + "Được mã hóa bởi một thiết bị chưa được chủ sở hữu xác minh." + "Được mã hóa bởi một người dùng chưa được xác minh." + "Hoạt động" + "Cờ" + "Thực phẩm và đồ uống" + "Động vật và thiên nhiên" + "Đồ vật" + "Mặt cười & mọi người" + "Du lịch và địa danh" + "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." + "Chặn người dùng" + "Chọn tùy chọn này nếu bạn muốn ẩn tất cả tin nhắn hiện tại và tương lai từ người dùng này." + "Tin nhắn này sẽ được báo cáo cho quản trị viên máy chủ của bạn. Họ sẽ không thể đọc bất kỳ tin nhắn được mã hóa nào." + "Lý do báo cáo nội dung này" + "Máy ảnh" + "Chụp ảnh" + "Quay video" + "Tệp đính kèm" + "Thư viện ảnh và video" + "Chia sẻ vị trí" + "Bỏ phiếu" + "Định dạng văn bản" + "Lịch sử tin nhắn hiện không khả dụng." + "Lịch sử tin nhắn không khả dụng trong phòng này. Vui lòng xác minh thiết bị này để xem lịch sử tin nhắn của bạn." + "Bạn có muốn mời họ quay lại không?" + "Bạn đang một mình trong cuộc trò chuyện này" + "Thông báo cho cả phòng" + "Mọi người" + "Gửi lại" + "Gửi tin nhắn không thành công" + "Thêm biểu cảm" + "Đây là sự kiện khởi đầu của phòng %1$s ." + "Đây là khởi đầu của cuộc trò chuyện này." + "Cuộc gọi không được hỗ trợ. Hãy hỏi xem người gọi có thể sử dụng ứng dụng Element X mới hay không." + "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" + "Thu gọn" + "Xem thêm" + "Mới" + + "%1$d số lượng phòng thay đổi" + + + "%1$s,%2$s và %3$d người khác" + + + "%1$s đang gõ" + + "%1$s và %2$s" + diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index 5247193b84..2a6b9bf78d 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -26,7 +26,7 @@ "第%1$d/%2$d项" "优化图像质量" "处理中…" - "封禁用户" + "屏蔽用户" "请确认是否要隐藏该用户当前和未来的所有信息" "此消息将举报给您的服务器管理员。他们无法读取任何加密消息。" "举报此内容的原因" @@ -35,13 +35,13 @@ "录制视频" "附件" "照片和视频库" - "位置" + "共享位置" "投票" "文本格式化" "消息历史记录当前不可用。" "此聊天室无法查看消息历史记录。请验证此设备以查看之。" "您想邀请他们回来吗?" - "聊天中只有你一个人" + "此聊天室中只有您一个人" "通知整个聊天室" "所有人" "再次发送" diff --git a/features/poll/api/src/main/res/values-ja/translations.xml b/features/poll/api/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..c66e27d85d --- /dev/null +++ b/features/poll/api/src/main/res/values-ja/translations.xml @@ -0,0 +1,8 @@ + + + + "総投票数うち%1$d%" + + "前の項目を削除します" + "投票の勝者はこちらです" + diff --git a/features/poll/api/src/main/res/values-vi/translations.xml b/features/poll/api/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..21651828df --- /dev/null +++ b/features/poll/api/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "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-ja/translations.xml b/features/poll/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..a4cd3fbff3 --- /dev/null +++ b/features/poll/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,20 @@ + + + "選択肢を追加" + "結果を投票終了後に表示します" + "投票を非表示" + "選択肢 %1$d" + "変更は保存されていません。本当に戻りますか?" + "選択肢を削除 %1$s" + "質問またはトピック" + "何についての投票ですか?" + "投票を作成" + "本当にこの投票を削除しますか?" + "投票を削除" + "投票を編集" + "進行中の投票が見つかりません。" + "過去の投票が見つかりません。" + "進行中" + "過去" + "投票" + diff --git a/features/poll/impl/src/main/res/values-vi/translations.xml b/features/poll/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..dc29666c74 --- /dev/null +++ b/features/poll/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,19 @@ + + + "Thêm lựa chọn" + "Chỉ hiển thị kết quả sau khi cuộc thăm dò kết thúc" + "Ẩ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?" + "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" + "Bạn có chắc chắn muốn xóa cuộc thăm dò này không?" + "Xóa cuộc thăm dò" + "Sửa cuộc thăm dò" + "Không tìm thấy bất kỳ cuộc thăm dò nào đang diễn ra." + "Không tìm thấy bất kỳ cuộc thăm dò nào trước đây." + "Đang diễn ra" + "Quá khứ" + "Cuộc thăm dò ý kiến" + diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..9cd0dfea96 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,82 @@ + + + "重要な電話を確実に受け取るため、端末がロックされている状態での全画面通知を、設定から許可してください。" + "通話品質を高める" + "通知の受信方法を選択してください" + "開発者モード" + "開発者向けの機能を表示します。" + "任意の Element Call のベースURL" + "任意の Element Call のベースURLを入力してください。" + "無効なURLです。プロトコル (http/https) が明記されていることと、アドレスが正しいことを確認してください。" + "ルームへの招待リクエストにアバターを表示しない" + "タイムラインにメディアのプレビューを表示しない" + "ラボ" + "写真や動画を高速で送信してデータ使用量を減らす" + "メディアの品質を最適化" + "制限と安全" + "自動的に画像を最適化してアップロード時間とファイルサイズを削減します。" + "画像のアップロード画質を最適化" + "%1$s 変更するにはタップしてください。" + "高画質 (1080p)" + "低画質 (480p)" + "標準 (720p)" + "動画のアップロード品質" + "プッシュ通知プロバイダー" + "リッチテキスト編集機能を無効化し、Markdown記法を手入力できるようにします。" + "既読を通知" + "機能がオフの場合、メッセージを確認したことを誰にも通知しません。他のユーザーの既読は確認することができます。" + "在席を共有" + "機能がオフの場合、既読の情報と入力中の通知を使用できなくなります。" + "常に非表示" + "常に表示" + "非公開ルームのみ" + "非表示のメディアはタップして表示することができます。" + "タイムラインにメディアを表示" + "タイムラインでメッセージのソースを表示する機能を追加します。" + "ブロックしたユーザーはいません" + "ブロックを解除" + "すべてのメッセージが再表示されます。" + "ユーザーのブロックを解除" + "ブロック解除中…" + "表示名" + "あなたの表示名" + "不明な問題が発生したため、情報の更新に失敗しました。" + "プロフィールを更新できません" + "プロフィールを編集" + "プロフィールを更新中…" + "スレッドへの返信を有効化" + "変更を適用するためにアプリケーションは再起動します。" + "開発段階の最新機能を試します。未完成のため変更や不安定な挙動を生じる可能性があります。" + "探究したいですか?" + "ラボ" + "追加設定" + "音声・ビデオ通話" + "設定の不一致" + "通知設定を簡素化し、見つけやすくしました。以前のカスタム設定の一部はここに表示されませんが、引き続き有効です。 + +続行すると、一部の設定が変更される可能性があります。" + "ダイレクトチャット" + "チャットごとのカスタム設定" + "通知設定の更新中に問題が発生しました。" + "すべてのメッセージ" + "メンションとキーワードのみ" + "ダイレクトチャットで以下の通知を受け取る" + "グループチャットでは以下の通知を受け取る" + "この端末で通知を受け取る" + "設定が修正されていません。再試行してください。" + "グループチャット" + "招待" + "暗号化されたルームでは、この機能にホームサーバーが対応しないため、一部のルームから通知が届かない可能性があります。" + "メンション" + "すべて" + "メンション" + "以下を通知する" + @ルームで通知を受け取る + "通知を受け取るには、%1$s を変更してください。" + "システム設定" + "システムで通知がオフです" + "通知" + "プッシュ履歴" + "トラブルシューティング" + "通知のトラブルシューティング" + diff --git a/features/preferences/impl/src/main/res/values-ru/translations.xml b/features/preferences/impl/src/main/res/values-ru/translations.xml index bf9d268b45..77be6fd8db 100644 --- a/features/preferences/impl/src/main/res/values-ru/translations.xml +++ b/features/preferences/impl/src/main/res/values-ru/translations.xml @@ -25,7 +25,7 @@ "Отключить редактор форматированного текста и включить Markdown." "Уведомления о прочтении" "Если этот параметр выключен, другие пользователи не будут видеть, прочитали ли вы сообщения. Вы по-прежнему будете видеть статус прочтения других пользователей." - "Поделиться присутствием" + "Делиться присутствием" "Если выключено, вы не будете видеть, кто печатает и читает сообщения, а также другие пользователи не будут знать, когда вы печатаете или читаете сообщения." "Всегда скрывать" "Всегда показывать" @@ -44,7 +44,7 @@ "Невозможно обновить профиль" "Редактировать профиль" "Обновление профиля…" - "Включить ответы в ветке" + "Включить ответы в обсуждениях" "Приложение перезапустится, чтобы применить это изменение." "Попробуйте функции в разработке. Эти функции ещё не завершены, они нестабильны и могут измениться." "Хотите попробовать?" diff --git a/features/preferences/impl/src/main/res/values-vi/translations.xml b/features/preferences/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..db242130ed --- /dev/null +++ b/features/preferences/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,61 @@ + + + "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." + "Địa chỉ tùy chỉnh máy chủ cuộc gọi Element" + "Đặ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ắ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." + "Chia sẻ trạng thái" + "Nếu tắt, bạn sẽ không thể gửi hoặc nhận thông báo đã đọc và thông báo \"đang nhập…\"." + "Bật tùy chọn xem nguồn tin nhắn trong dòng thời gian." + "Bạn chưa chặn ai cả" + "Bỏ chặn" + "Bạn sẽ có thể xem lại tất cả tin nhắn từ họ." + "Bỏ chặn người dùng" + "Đang mở khóa…" + "Tên hiển thị" + "Tên hiển thị của bạn" + "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 hồ sơ" + "Chỉnh sửa hồ sơ" + "Đang cập nhật hồ sơ…" + "Cho phép trả lời theo chủ đề" + "Ứng dụng sẽ khởi động lại để áp dụng thay đổi này." + "Hãy thử các ý tưởng mới nhất đang được phát triển. Các tính năng này chưa hoàn thiện; có thể không ổn định và có thể thay đổi." + "Bạn muốn thử tính năng thử nghiệm?" + "Labs" + "Cài đặt bổ sung" + "Cuộc gọi âm thanh và video" + "Cấu hình không khớp" + "Chúng tôi đã đơn giản hóa Cài đặt Thông báo để các tùy chọn dễ tìm hơn. Một số cài đặt tùy chỉnh bạn đã chọn trước đây không hiển thị ở đây, nhưng vẫn đang hoạt động. + +Nếu bạn tiếp tục, một số cài đặt của bạn có thể thay đổi." + "Trò chuyện trực tiếp" + "Cài đặt tùy chỉnh cho từng cuộc trò chuyện" + "Đã xảy ra lỗi khi cập nhật cài đặt thông báo." + "Tất cả tin nhắn." + "Chỉ đề cập và từ khóa" + "Trong chat riêng, nhắc tôi khi" + "Trong chat nhóm, nhắc tôi khi" + "Bật thông báo trên thiết bị này" + "Cấu hình chưa đúng, hãy thử lại." + "Trò chuyện nhóm" + "Lời mời" + "Máy chủ không hỗ trợ tùy chọn này trong phòng mã hóa, một số phòng có thể không thông báo." + "Nhắc đến" + "Tất cả" + "Nhắc đến" + "Thông báo cho tôi khi" + "Thông báo cho tôi khi @room" + "Để nhận thông báo, vui lòng thay đổi %1$s của bạn." + "cài đặt hệ thống" + "Thông báo hệ thống đã tắt" + "Thông báo" + "Khắc phục sự cố" + "Khắc phục sự cố thông báo" + diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 0c576b58b6..0dac7ab6d8 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -6,7 +6,7 @@ "开发者模式" "允许开发人员访问特性和功能。" "自定义 Element Call URL" - "为 Element 通话设置根 URL。" + "为 Element 通话设置基本 URL。" "URL 无效,请确保包含协议(http/https)和正确的地址。" "在房间邀请请求中隐藏头像" "在时间轴中隐藏媒体预览" @@ -34,12 +34,12 @@ "在时间轴中显示媒体" "启用在时间轴中查看消息源码的选项。" "您没有屏蔽用户" - "解封" + "解除屏蔽" "可以重新接收他们的消息。" - "解封用户" + "解除屏蔽用户" "正在解除屏蔽……" "显示名称" - "你的显示名称" + "您的显示名称" "遇到未知错误,无法更改信息。" "无法更新个人资料" "编辑个人资料" diff --git a/features/rageshake/api/src/main/res/values-ja/translations.xml b/features/rageshake/api/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..7afb523cd1 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-ja/translations.xml @@ -0,0 +1,7 @@ + + + "%1$s は前回の利用時にクラッシュしました。クラッシュレポートを開発者に共有しますか?" + "怒り狂って端末を振っていますね。バグの報告をしますか?" + "怒り狂う" + "検出感度" + diff --git a/features/rageshake/api/src/main/res/values-vi/translations.xml b/features/rageshake/api/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..086619eed0 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-vi/translations.xml @@ -0,0 +1,7 @@ + + + "%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?" + "Có vẻ như bạn đang lắc điện thoại vì bực bội. Bạn có muốn mở màn hình báo cáo lỗi không?" + "Lắc điện thoại" + "Ngưỡng phát hiện" + diff --git a/features/rageshake/impl/src/main/res/values-ja/translations.xml b/features/rageshake/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..7c46d2beb5 --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,20 @@ + + + "スクリーンショットを添付" + "追加の質問がある場合は、ご連絡ください。" + "返信を受け取る" + "スクリーンショットを編集" + "問題を教えてください。行った操作、想定した挙動、実際の挙動などについて、可能な限り詳細に記述してください。" + "問題の説明…" + "可能であれば英語で記入してください。" + "説明が過度に短いです。問題についてより詳細にご記入ください。" + "クラッシュログを送信" + "ログの記録を許可" + "ログのサイズが大きく、報告に添付することができません。ログは別の方法で送信してください。" + "スクリーンを送信" + "メッセージには、正常に動作していることを確認するため、ログが含まれています。ログを含めたくない場合は、オフにしてください。" + "%1$s は前回の利用時にクラッシュしました。クラッシュレポートを開発者に共有しますか?" + "通知について問題がある場合は、プッシュ通知の設定を添付することで、原因究明の手がかりになります。この設定には、ユーザーネームや通知のキーワードなどの個人情報が含まれる場合があります。ご注意ください。" + "通知設定を送信" + "ログを表示" + diff --git a/features/rageshake/impl/src/main/res/values-vi/translations.xml b/features/rageshake/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..5a60edd206 --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,17 @@ + + + "Đính kèm ảnh chụp màn hình" + "Bạn có thể liên hệ với tôi nếu có bất kỳ câu hỏi nào khác." + "Liên hệ với tôi" + "Chỉnh sửa ảnh chụp màn hình" + "Hãy mô tả vấn đề. Bạn đã làm gì? Bạn mong đợi/dự đoán điều gì sẽ xảy ra? Điều gì thực sự đã xảy ra? Hãy trình bày càng chi tiết càng tốt." + "Hãy mô tả vấn đề…" + "Nếu có thể, vui lòng viết mô tả bằng tiếng Anh." + "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ý" + "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?" + "Xem nhật ký" + diff --git a/features/reportroom/impl/src/main/res/values-ja/translations.xml b/features/reportroom/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..9718ca432f --- /dev/null +++ b/features/reportroom/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,8 @@ + + + "報告は正常に送信されましたが、ルームの退出中に問題が発生しました。もう一度試してください。" + "ルームの退出に失敗" + "管理者にこのルームを報告します。メッセージが暗号化されている場合、管理者は内容を確認することができません。" + "報告の理由を説明してください…" + "ルームを通報" + diff --git a/features/reportroom/impl/src/main/res/values-vi/translations.xml b/features/reportroom/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..3037521f98 --- /dev/null +++ b/features/reportroom/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "Hãy báo cáo phòng chat này cho quản trị viên của bạn. Nếu tin nhắn được mã hóa, quản trị viên sẽ không thể đọc được chúng." + "Báo cáo phòng" + diff --git a/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..c9410e9e3c --- /dev/null +++ b/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,82 @@ + + + "管理者" + "ユーザーの追放" + "設定の変更" + "メッセージの削除" + "メンバー" + "ユーザーの招待" + "スペースの管理" + "ルームを管理" + "メンバーの管理" + "メッセージと内容" + "モデレーター" + "ユーザーの削除" + "アバターの変更" + "詳細を編集" + "名前の変更" + "トピックの変更" + "メッセージの送信" + "権限" + "管理者を編集" + "この操作は取り消せません。このユーザーをあなたと同じ権限まで昇格します。" + "管理者を追加しますか?" + "この操作は取り消せません。選択したユーザーに所有権を譲与します。あなたがルームを退出すると恒久的に変更が適用されます。" + "所有権を譲与しますか?" + "降格" + "自身を降格しようとしているため、後から取り消すことはできません。このルームに他に特権を持つユーザーが存在しない場合、それを回復することはできなくなります。" + "自身を降格しますか?" + "%1$s (承認待ち)" + "承認待ち" + "管理者はモデレータの特権を有します。" + "所有者は管理者の特権を有します。" + "モデレーターを編集" + "所有者を選択" + "管理者" + "モデレーター" + "メンバー" + "未保存の変更内容があります。" + "変更を保存しますか?" + "追放されたユーザーはいません。" + + "%1$d 人の追放" + + "スペルを確認するか、新たに検索し直してください" + "\"%1$s\" の検索結果はありません" + + "%1$d 人" + + "ユーザーを追放" + "メンバーのみを削除" + "追放を解除" + "招待を受け取ると再度参加できます。" + "ユーザーの追放を解除" + "追放済み" + "メンバー" + + "%1$d 件の招待" + + "待機中" + "管理者" + "モデレーター" + "所有者" + "ルームのメンバー" + "%1$s の追放を解除中" + "管理者" + "管理者と所有者" + "自身の役割を変更" + "権限を譲与" + "モデレーターに譲与" + "メンバーの編集" + "メッセージと内容" + "モデレーター" + "所有者" + "権限" + "権限をリセット" + "権限をリセットすると現在の設定はすべて失われます。" + "権限をリセットしますか?" + "役割" + "ルームの詳細" + "スペースの詳細" + "役割と権限" + diff --git a/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..5e6c736cbe --- /dev/null +++ b/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,58 @@ + + + "Quản trị viên" + "Cấm người dùng" + "Xóa tin nhắn" + "Thành viên" + "Mời mọi người" + "Quản lý phòng trò chuyện" + "Quản lý thành viên" + "Tin nhắn và nội dung." + "Người điều hành" + "Gỡ người dùng" + "Đổi ảnh đại diện" + "Chỉnh sửa thông tin" + "Đổi tên" + "Đổi chủ đề" + "Gửi tin nhắn." + "Chỉnh sửa Quản trị viên" + "Bạn sẽ không thể hoàn tác hành động này. Bạn đang thăng quyền cho người dùng lên cùng cấp quyền với bạn." + "Thêm quản trị viên?" + "Giáng cấp" + "Bạn sẽ không thể hoàn tác thay đổi này vì bạn đang tự giáng cấp bản thân, nếu bạn là người dùng cuối cùng có đặc quyền trong phòng, nó sẽ không thể lấy lại đặc quyền." + "Giáng cấp bản thân?" + "%1$s (Đang chờ xử lý)" + "Chỉnh sửa Người điều hành" + "Quản trị viên" + "Người điều hành" + "Thành viên" + "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 người" + + "Cấm người dùng" + "Chỉ xóa thành viên" + "Bỏ cấm" + "Họ có thể tham gia lại phòng này nếu được mời." + "Bị cấm" + "Thành viên" + "Quản trị viên" + "Người điều hành" + "Thành viên phòng" + "Đang gỡ cấm %1$s" + "Quản trị viên" + "Thay đổi vai trò của tôi" + "Hạ cấp xuống thành thành viên" + "Hạ cấp xuống làm người điều hành" + "Quản lý thành viên" + "Tin nhắn và nội dung." + "Người điều hành" + "Đặt lại quyền truy cập" + "Sau khi bạn đặt lại quyền truy cập, bạn sẽ mất các cài đặt hiện tại." + "Đặt lại quyền truy cập?" + "Vai trò" + "Chi tiết phòng" + "Vai trò và quyền hạn" + diff --git a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml index 768bed1a86..d3c4cada77 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml @@ -19,7 +19,7 @@ "发送消息" "权限" "编辑管理员" - "您将无法撤消此操作。您正在提升用户的权限,使其拥有与您平权。" + "您将无法撤消此操作。您正在提升用户的权限到与您相同的级别。" "添加管理员?" "此操作无法撤销。您正在将所有权转移给所选用户。一旦离开此界面,该操作将永久生效。" "转让所有权" @@ -50,7 +50,7 @@ "仅移除成员" "取消封禁" "如果受到邀请,他们可以重新加入聊天室。" - "从房间取消解封" + "解封用户" "已封禁用户" "成员" @@ -61,7 +61,7 @@ "协管员" "所有者" "聊天室成员" - "解除封禁 %1$s" + "正在解除封禁 %1$s" "管理员" "管理员和所有者" "更改我的角色" diff --git a/features/roomaliasresolver/impl/src/main/res/values-ja/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..4e3f765f88 --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,5 @@ + + + "ルームのプレビューを表示できません" + "ルームエイリアスを解決できません。" + diff --git a/features/roomaliasresolver/impl/src/main/res/values-vi/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..b08c97b72a --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,4 @@ + + + "Không thể hiển thị bản xem trước của phòng này" + diff --git a/features/roomdetails/impl/src/main/res/values-it/translations.xml b/features/roomdetails/impl/src/main/res/values-it/translations.xml index 053e269bc4..22ec99f2b5 100644 --- a/features/roomdetails/impl/src/main/res/values-it/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-it/translations.xml @@ -1,5 +1,8 @@ + "I nuovi membri non vedono la cronologia" + "I nuovi membri vedono la cronologia" + "Chiunque può vedere la cronologia" "Per renderlo visibile nell\'elenco pubblico, avrai bisogno di un indirizzo." "Modifica indirizzo" "Si è verificato un errore durante l\'aggiornamento delle impostazioni di notifica." @@ -63,6 +66,7 @@ "Profilo" "Richieste di accesso" "Ruoli e autorizzazioni" + "Nome" "Sicurezza e privacy" "Sicurezza" "Condividi stanza" @@ -128,8 +132,10 @@ "Dettagli della stanza" "Ruoli e autorizzazioni" "Aggiungi indirizzo" + "Chiunque si trovi in spazi autorizzati può partecipare, ma tutti gli altri devono richiedere l\'accesso." "Chiunque deve richiedere l\'accesso." "Chiedi di entrare" + "Chiunque all\'interno di %1$s può partecipare, mentre tutti gli altri devono richiedere l\'accesso." "Sì, attiva la crittografia" "Una volta attivata, la crittografia di una stanza non può essere disattivata, la cronologia dei messaggi sarà visibile solo ai membri della stanza da quando sono stati invitati o da quando sono entrati nella stanza. Nessuno, oltre ai membri della stanza, sarà in grado di leggere i messaggi. Ciò potrebbe impedire ai bot e ai bridge di funzionare correttamente. @@ -140,19 +146,25 @@ Non consigliamo di attivare la crittografia per le stanze che chiunque può trov "Attiva la crittografia end-to-end" "Chiunque può partecipare." "Chiunque" + "Scegli quali membri dello spazio possono accedere a questa stanza senza invito.%1$s" + "Gestisci gli spazi" "Solo le persone invitate possono entrare." "Solo su invito" "Accesso" + "Chiunque si trovi in ​​spazi autorizzati può partecipare." + "Chiunque in %1$s può partecipare." + "Membri dello spazio" "Gli spazi non sono attualmente supportati" "Per renderlo visibile nell\'elenco pubblico, avrai bisogno di un indirizzo." "Indirizzo" "Consenti la ricerca di questa stanza effettuando una ricerca nell\'elenco delle stanze pubbliche di %1$s" "Consenti di essere trovato effettuando una ricerca nell\'elenco pubblico." "Visibile nell\'elenco pubblico" - "Chiunque" + "Chiunque (la cronologia è pubblica)" + "Le modifiche non interesseranno i messaggi passati, ma solo quelli nuovi. %1$s" "Chi può leggere la cronologia messaggi" - "Solo membri da quando sono stati invitati" - "Solo membri da dopo aver selezionato questa opzione" + "Members invited" + "Members (cronologia completa)" "Gli indirizzi delle stanze sono modi per trovare e accedervi. In questo modo puoi anche condividere facilmente la tua stanze con altri. Puoi scegliere di pubblicare la tua stanza nell\'elenco delle stanza pubbliche dell\'homeserver." "Pubblicazione della stanza" diff --git a/features/roomdetails/impl/src/main/res/values-ja/translations.xml b/features/roomdetails/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..70b3255437 --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,171 @@ + + + "新しいメンバーは過去の内容を確認できない" + "新しいメンバーは過去の内容を確認できる" + "すべてのユーザーが過去の内容を確認できる" + "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" + "アドレスの編集" + "通知設定の更新中に問題が発生しました。" + "暗号化されたルームでは、この機能にホームサーバーが対応しないため、一部のルームから通知が届かない可能性があります。" + "投票" + "管理者" + "ユーザーの追放" + "メッセージの削除" + "メンバー" + "ユーザーの招待" + "メンバーの管理" + "メッセージと内容" + "モデレーター" + "ユーザーの削除" + "アバターの変更" + "詳細を編集" + "名前の変更" + "トピックの変更" + "メッセージの送信" + "管理者を編集" + "この操作は取り消せません。このユーザーをあなたと同じ権限まで昇格します。" + "管理者を追加しますか?" + "この操作は取り消せません。選択したユーザーに所有権を譲与します。あなたがルームを退出すると恒久的に変更が適用されます。" + "所有権を譲与しますか?" + "降格" + "自身を降格しようとしているため、後から取り消すことはできません。このルームに他に特権を持つユーザーが存在しない場合、それを回復することはできなくなります。" + "自身を降格しますか?" + "%1$s (承認待ち)" + "承認待ち" + "管理者はモデレータの特権を有します。" + "所有者は管理者の特権を有します。" + "モデレーターを編集" + "所有者を選択" + "管理者" + "モデレーター" + "メンバー" + "未保存の変更内容があります。" + "変更を保存しますか?" + "トピックを追加" + "暗号化済み" + "暗号化されていません" + "公開ルーム" + "詳細を編集" + "不明な問題が発生したため、情報の更新に失敗しました。" + "ルームを更新することができません" + "メッセージは、あなたと受信者のみが持つ鍵で暗号化されています。" + "メッセージの暗号化が有効です" + "通知設定の読み込み中に問題が発生しました。" + "ルームをミュートできませんでした。再試行してください。" + "ルームをミュート解除できませんでした。再試行してください。" + "終了するまでアプリを閉じないでください。" + "招待を準備中…" + "ユーザーを招待" + "会話を退出" + "ルームを退出" + "ファイルとメディア" + "カスタム" + "デフォルト" + "通知" + "ピン留めされたメッセージ" + "プロフィール" + "参加のリクエスト" + "役割と権限" + "名前" + "セキュリティとプライバシー" + "セキュリティ" + "ルームを共有" + "ルームの情報" + "トピック" + "詳細を更新中…" + "追放されたユーザーはいません。" + + "%1$d 人の追放" + + "スペルを確認するか、新たに検索し直してください" + "\"%1$s\" の検索結果はありません" + + "%1$d 人" + + "ユーザーを追放" + "メンバーのみを削除" + "追放を解除" + "招待を受け取ると再度参加できます。" + "ユーザーの追放を解除" + "追放済み" + "メンバー" + + "%1$d 件の招待" + + "待機中" + "管理者" + "モデレーター" + "所有者" + "ルームのメンバー" + "%1$s の追放を解除中" + "カスタム設定を許可" + "オンにするとデフォルト設定が上書きされます" + "このチャットで以下の通知を受け取る" + "%1$s から変更できます。" + "全体設定" + "デフォルト設定" + "カスタム設定を削除する" + "通知設定の読み込み中に問題が発生しました。" + "デフォルトの復元に失敗しました。再試行してください。" + "設定に失敗しました。再試行してください。" + "暗号化されたルームでは、この機能にホームサーバーが対応しないため、このルームからの通知を受信できません。" + "すべてのメッセージ" + "メンションとキーワードのみ" + "このルームでは以下の通知を受け取る" + "管理者" + "管理者と所有者" + "自身の役割を変更" + "権限を譲与" + "モデレーターに譲与" + "メンバーの編集" + "メッセージと内容" + "モデレーター" + "所有者" + "権限" + "権限をリセット" + "権限をリセットすると現在の設定はすべて失われます。" + "権限をリセットしますか?" + "役割" + "ルームの詳細" + "役割と権限" + "アドレスを追加" + "認証済みのスペースに所属するユーザーのみが参加できます。それ以外のユーザーは参加へのリクエストが必要です。" + "参加のリクエストが必須です。" + "参加をリクエスト" + "%1$s に所属するユーザーのみが参加できます。それ以外のユーザーは参加のリクエストが必要です。" + "暗号化を有効にする" + "暗号化が有効のルームを再び無効化することはできません。過去のメッセージの参照は、ユーザーが招待された、あるいは参加した以降に投稿された内容に限定されます。 +ルームのメンバー以外がメッセージを確認することはできないため、bot やブリッジのサービスが正常に動作しない可能性があります。 +公開スペースを暗号化することは一般に推奨されません。" + "暗号化を有効にしますか?" + "一度有効にすると元に戻すことはできません。" + "暗号化" + "エンドツーエンド暗号化を有効にする" + "誰でも参加できます" + "全員" + "招待無しで参加できるユーザーが所属するルームを選択してください。%1$s" + "スペースを管理" + "招待されたユーザーのみ参加できます。" + "招待制" + "アクセス" + "認証済みのスペースに所属するすべてのユーザーが参加できます。" + "%1$s に所属するすべてのユーザーが参加できます。" + "スペースのメンバー" + "スペースは現在対応していません。" + "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" + "アドレス" + "%1$s の公開ルームの検索結果に、このルームを表示します" + "公開ディレクトリの検索結果に表示" + "公開ディレクトリに表示" + "全員(履歴を公開)" + "過去のメッセージに変更は適用されません。新規のメッセージにのみ適用されます。%1$s" + "履歴を表示するユーザー" + "招待済みのユーザー" + "ユーザー (すべての履歴)" + "ルームアドレスはルームの検索やアクセスに役立ち、他のユーザーにルームを簡単に共有できます。 +ホームサーバーの公開ディレクトリにルームを表示するかを設定できます。" + "ルームの公開" + "ルームアドレスはルームの検索やアクセスに役立ち、他のユーザーにルームを簡単に共有できます。" + "視認性" + "セキュリティとプライバシー" + diff --git a/features/roomdetails/impl/src/main/res/values-vi/translations.xml b/features/roomdetails/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..a2ee35b563 --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,107 @@ + + + "Thành viên mới không thể xem lịch sử" + "Thành viên mới có thể xem lịch sử" + "Ai cũng có thể xem lịch sử" + "Bạn cần một địa chỉ để hiển thị trong danh bạ công khai." + "Chỉnh sửa địa chỉ" + "Đã xảy ra lỗi khi cập nhật cài đặt thông báo." + "Máy chủ không hỗ trợ tùy chọn này trong phòng mã hóa, một số phòng có thể không thông báo." + "Cuộc thăm dò ý kiến" + "Quản trị viên" + "Cấm người dùng" + "Xóa tin nhắn" + "Thành viên" + "Mời mọi người" + "Quản lý thành viên" + "Tin nhắn và nội dung." + "Người điều hành" + "Gỡ người dùng" + "Đổi ảnh đại diện" + "Chỉnh sửa thông tin" + "Đổi tên" + "Đổi chủ đề" + "Gửi tin nhắn." + "Chỉnh sửa Quản trị viên" + "Bạn sẽ không thể hoàn tác hành động này. Bạn đang thăng quyền cho người dùng lên cùng cấp quyền với bạn." + "Thêm quản trị viên?" + "Giáng cấp" + "Bạn sẽ không thể hoàn tác thay đổi này vì bạn đang tự giáng cấp bản thân, nếu bạn là người dùng cuối cùng có đặc quyền trong phòng, nó sẽ không thể lấy lại đặc quyền." + "Giáng cấp bản thân?" + "%1$s (Đang chờ xử lý)" + "Chỉnh sửa Người điều hành" + "Quản trị viên" + "Người điều hành" + "Thành viên" + "Bạn có thay đổi chưa được lưu." + "Lưu thay đổi?" + "Thêm chủ đề" + "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" + "Tin nhắn được bảo mật bằng khóa. Chỉ bạn và người nhận mới có chìa khóa riêng để mở khóa." + "Mã hóa tin nhắn đã được bật" + "Đã xảy ra lỗi khi tải cài đặt thông báo." + "Không thể tắt tiếng phòng này, vui lòng thử lại." + "Không thể bật tiếng cho phòng này. Vui lòng thử lại." + "Mời ai đó" + "Rời khỏi cuộc trò chuyện" + "Rời phòng" + "Tùy chỉnh" + "Mặc định" + "Thông báo" + "Tin nhắn được ghim" + "Vai trò và quyền hạn" + "Tên" + "Bảo mật" + "Chia sẻ phòng" + "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 người" + + "Cấm người dùng" + "Chỉ xóa thành viên" + "Bỏ cấm" + "Họ có thể tham gia lại phòng này nếu được mời." + "Bị cấm" + "Thành viên" + "Quản trị viên" + "Người điều hành" + "Thành viên phòng" + "Đang gỡ cấm %1$s" + "Cho phép tùy chỉnh cài đặt" + "Kích hoạt sẽ thay thế cài đặt mặc định" + "Thông báo cho tôi trong cuộc trò chuyện này khi" + "Bạn có thể thay đổi trong %1$s của mình." + "cài đặt chung" + "Cài đặt mặc định" + "Xóa cài đặt tùy chỉnh" + "Đã xảy ra lỗi khi tải cài đặt thông báo." + "Không thể khôi phục chế độ mặc định, vui lòng thử lại." + "Không thể thiết lập chế độ, hãy thử lại nhé." + "Máy chủ không hỗ trợ tùy chọn này trong phòng mã hóa, bạn sẽ không nhận thông báo ở đây." + "Tất cả tin nhắn." + "Chỉ đề cập và từ khóa" + "Trong phòng này, thông báo cho tôi khi" + "Quản trị viên" + "Thay đổi vai trò của tôi" + "Hạ cấp xuống thành thành viên" + "Hạ cấp xuống làm người điều hành" + "Quản lý thành viên" + "Tin nhắn và nội dung." + "Người điều hành" + "Đặt lại quyền truy cập" + "Sau khi bạn đặt lại quyền truy cập, bạn sẽ mất các cài đặt hiện tại." + "Đặt lại quyền truy cập?" + "Vai trò" + "Chi tiết phòng" + "Vai trò và quyền hạn" + "Sau khi được kích hoạt, mã hóa cho một phòng chat không thể tắt được. Lịch sử tin nhắn chỉ hiển thị cho các thành viên phòng chat kể từ khi họ được mời hoặc kể từ khi họ tham gia phòng chat. +Không ai ngoài các thành viên phòng chat có thể đọc tin nhắn. Điều này có thể ngăn chặn bot và các thiết bị kết nối hoạt động đúng cách. +Chúng tôi không khuyến khích bật mã hóa cho các phòng chat mà bất kỳ ai cũng có thể tìm thấy và tham gia." + "Mã hóa" + "Thành viên không gian" + "Bạn cần một địa chỉ để hiển thị trong danh bạ công khai." + diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index 4101f67260..d803f01fb7 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -23,7 +23,7 @@ "更改聊天室主题" "发送消息" "编辑管理员" - "您将无法撤消此操作。您正在提升用户的权限,使其拥有与您平权。" + "您将无法撤消此操作。您正在提升用户的权限到与您相同的级别。" "添加管理员?" "此操作无法撤销。您正在将所有权转移给所选用户。一旦离开此界面,该操作将永久生效。" "转让所有权" @@ -42,8 +42,8 @@ "您有未保存的更改。" "保存更改?" "添加主题" - "加密的" - "未加密的" + "已加密" + "未加密" "公共聊天室" "编辑详情" "出现未知错误,无法更改信息。" @@ -86,7 +86,7 @@ "仅移除成员" "取消封禁" "如果受到邀请,他们可以重新加入聊天室。" - "从房间取消解封" + "解封用户" "已封禁用户" "成员" @@ -97,7 +97,7 @@ "协管员" "所有者" "聊天室成员" - "解除封禁 %1$s" + "正在解除封禁 %1$s" "允许自定义设置" "开启此功能将覆盖您的默认设置" "在此聊天中通知我以下内容" diff --git a/features/roomdetailsedit/impl/src/main/res/values-ja/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..5dbdbe22e1 --- /dev/null +++ b/features/roomdetailsedit/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,7 @@ + + + "詳細を編集" + "不明な問題が発生したため、情報の更新に失敗しました。" + "ルームを更新することができません" + "詳細を更新中…" + diff --git a/features/roomdetailsedit/impl/src/main/res/values-vi/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..9a5d8948e4 --- /dev/null +++ b/features/roomdetailsedit/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,7 @@ + + + "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" + "Đang cập nhật thông tin…" + diff --git a/features/roomdirectory/impl/src/main/res/values-ja/translations.xml b/features/roomdirectory/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..f533dc8eab --- /dev/null +++ b/features/roomdirectory/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,5 @@ + + + "読み込みに失敗しました" + "ルーム階層" + diff --git a/features/roomdirectory/impl/src/main/res/values-vi/translations.xml b/features/roomdirectory/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..efbe223f79 --- /dev/null +++ b/features/roomdirectory/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "Không tải được" + "Danh sách phòng" + diff --git a/features/roommembermoderation/impl/src/main/res/values-ja/translations.xml b/features/roommembermoderation/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..5ca793fd5a --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,22 @@ + + + "ユーザーを追放" + "追放" + "招待されても再度参加することはできません。" + "このメンバーを本当に追放しますか?" + "招待されても再度参加することはできませんが、すべてのルームとスペースにおける権限を維持します。" + "%1$s を追放中" + "削除" + "招待を受け取ると再度参加できます。" + "このメンバーを本当に削除しますか?" + "すべてのルームとスペースにおける権限を維持し、招待によって再度参加することができます。" + "プロフィールを表示" + "ユーザーを削除" + "メンバーを削除し、今後の参加を禁止しますか?" + "%1$s を削除中…" + "ユーザーの追放を解除" + "追放を解除" + "招待によって再度参加することができます。" + "このメンバーの追放を本当に解除しますか?" + "%1$s の追放を解除中" + diff --git a/features/roommembermoderation/impl/src/main/res/values-vi/translations.xml b/features/roommembermoderation/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..07d712cd4c --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,15 @@ + + + "Cấm người dùng" + "Cấm" + "Họ sẽ không thể tham gia lại ngay cả khi được mời." + "Xác nhận cấm thành viên này?" + "Đang cấm %1$s" + "Họ có thể tham gia lại phòng này nếu được mời." + "Xem hồ sơ" + "Xóa người dùng" + "Xóa thành viên và cấm tham gia trong tương lai?" + "Đang xóa %1$s…" + "Bỏ cấm" + "Đang gỡ cấm %1$s" + diff --git a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml index aa8b2e3df8..2c18ee4216 100644 --- a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml @@ -5,7 +5,7 @@ "即使受到邀请,他们也无法再次加入聊天室。" "您确定要封禁该成员吗?" "即使再次受邀,他们也无法加入这个空间,但他们仍将保留其在任何房间或子空间的成员资格。" - "封禁 %1$s" + "正在封禁 %1$s" "移除" "如果受到邀请,他们可以重新加入聊天室。" "您确定要移除此成员吗?" @@ -14,9 +14,9 @@ "移除用户" "删除成员并禁止重新加入?" "正在移除 %1$s……" - "从房间取消解封" + "解封用户" "取消封禁" "如果再次收到邀请,他们可以重新加入该聊天室" "确定要解除该成员的封禁吗?" - "解除封禁 %1$s" + "正在解除封禁 %1$s" diff --git a/features/securebackup/impl/src/main/res/values-it/translations.xml b/features/securebackup/impl/src/main/res/values-it/translations.xml index fe7ba13c60..188de2c3df 100644 --- a/features/securebackup/impl/src/main/res/values-it/translations.xml +++ b/features/securebackup/impl/src/main/res/values-it/translations.xml @@ -2,16 +2,17 @@ "Disattiva il backup" "Attiva il backup" - "Archivia la tua identità crittografica e le chiavi dei messaggi in modo sicuro sul server. Ciò ti consentirà di visualizzare la cronologia dei messaggi su tutti i nuovi dispositivi. %1$s." + "Questo ti permetterà di visualizzare la cronologia delle conversazioni su qualsiasi nuovo dispositivo ed è necessario per il backup delle chat e dell\'identità digitale.%1$s ." "Archiviazione chiavi" - "L\'archiviazione delle chiavi deve essere attivata per configurare il ripristino." + "Per eseguire il backup delle tue conversazioni, devi attivare l\'archiviazione delle chiavi." "Carica le chiavi da questo dispositivo" "Consenti l\'archiviazione delle chiavi" "Cambia la chiave di recupero" - "Recupera la tua identità crittografica e la cronologia dei messaggi con una chiave di recupero se hai perso tutti i dispositivi esistenti." + "Le tue conversazioni vengono automaticamente salvate con crittografia end-to-end. Per ripristinare questo backup e conservare la tua identità digitale quando perdi l\'accesso a tutti i tuoi dispositivi, avrai bisogno della tua chiave di recupero." "Inserisci la chiave di recupero" "L\'archiviazione delle chiavi non è sincronizzata." - "Configura il recupero" + "Ottieni la chiave di recupero" + "Le tue conversazioni vengono automaticamente salvate con crittografia end-to-end. Per ripristinare questo backup e conservare la tua identità digitale quando perdi l\'accesso a tutti i tuoi dispositivi, avrai bisogno della tua chiave di recupero." "Apri %1$s in un dispositivo desktop" "Accedi nuovamente al tuo account" "Quando ti viene chiesto di verificare il tuo dispositivo, seleziona %1$s" @@ -23,12 +24,12 @@ "I dettagli del tuo account, i contatti, le preferenze e l\'elenco delle conversazioni verranno conservati" "Perderai la cronologia dei messaggi esistente" "Dovrai verificare nuovamente tutti i dispositivi e i contatti esistenti" - "Reimposta la tua identità solo se non hai accesso a un altro dispositivo su cui hai effettuato l\'accesso e hai perso la chiave di recupero." - "Reimposta la tua identità nel caso in cui non riesci a confermare in un altro modo" - "Disattiva" - "Perderai i tuoi messaggi cifrati se sei disconnesso da tutti i dispositivi." - "Vuoi davvero disattivare il backup?" - "La disattivazione del backup rimuoverà il backup dell\'attuale chiave crittografica e disattiverà altre funzioni di sicurezza. In questo caso:" + "Reimposta la tua identità digitale solo se non hai accesso a un altro dispositivo verificato e non disponi della tua chiave di recupero." + "Non riesci a confermare? Dovrai reimpostare la tua identità digitale." + "Elimina" + "Se rimuovi tutti i tuoi dispositivi, perderai la cronologia delle conversazioni cifrate e dovrai reimpostare la tua identità digitale." + "Sei sicuro di voler eliminare l\'archivio delle chiavi?" + "L\'eliminazione della memoria delle chiavi rimuoverà l\'identità digitale e le chiavi dei messaggi dal server e disattiverà le seguenti funzionalità di sicurezza:" "Non avrai la cronologia dei messaggi cifrati su nuovi dispositivi" "Perderai l\'accesso ai tuoi messaggi cifrati se ti sei disconnesso da %1$s ovunque" "Vuoi davvero disattivare il backup?" @@ -58,12 +59,12 @@ "Genera la tua chiave di recupero" "Non condividerla con nessuno!" "Configurazione del recupero completata" - "Configura il recupero" + "Ottieni la chiave di recupero" "Sì, reimposta ora" "Questo processo è irreversibile." - "Sei sicuro di voler reimpostare la crittografia?" + "Sei sicuro di voler reimpostare la tua identità digitale?" "Si è verificato un errore sconosciuto. Controlla che la password del tuo account sia corretta e riprova." "Inserisci…" - "Conferma di voler reimpostare la crittografia." + "Conferma che desideri reimpostare la tua identità digitale." "Inserisci la password del tuo account per continuare" diff --git a/features/securebackup/impl/src/main/res/values-ja/translations.xml b/features/securebackup/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..7a7dd041fe --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,70 @@ + + + "保存されている鍵を削除" + "バックアップを有効化" + "暗号化されたデジタルIDとメッセージの鍵をサーバーに保存します。これにより、新しい端末から過去のメッセージを確認することができます。%1$s" + "鍵の保管庫" + "チャットをバックアップするには、鍵の保管庫を使用する必要があります。" + "この端末上の鍵をアップロードします" + "鍵の保管庫を使用します" + "回復鍵を変更" + "あなたのチャットはエンドツーエンド暗号化を使用して自動的にバックアップされています。すべての端末を使用できない状況で、このバックアップからデジタルIDを復元するには、回復鍵が必要となります。" + "回復鍵を入力" + "鍵の保管庫を現在同期できません。" + "回復鍵を作成" + "あなたのチャットはエンドツーエンド暗号化を使用して自動的にバックアップされています。すべての端末を使用できない状況で、このバックアップからデジタルIDを復元するには、回復鍵が必要となります。" + "%1$s をコンピュータで開く" + "再度サインインしてください" + "端末の認証を要求されたら %1$s を選択してください" + "\"すべてリセット\"" + "指示に従って回復鍵を作成してください" + "生成された回復鍵をパスワードマネージャや暗号化に対応するメモアプリに保存してください。" + "他の端末を使用して暗号化をリセット" + "リセットを続行" + "アカウントの情報と連絡先や設定などは残ります" + "サーバー上にのみ存在する過去のメッセージは確認できなくなります" + "すべての端末と連絡先を再度検証する必要があります" + "デジタルIDのリセットは、他のサインイン済みの端末と、回復鍵の両方へのアクセスを失った場合にのみ行ってください。" + "認証できませんか?デジタルIDをリセットする必要があります。" + "削除" + "すべての端末を削除してしまうと、暗号化された会話が失われ、デジタルIDをリセットする必要があります。" + "本当に鍵の保管庫を削除しますか?" + "鍵の保管庫を消去することにより、デジタルIDとメッセージの鍵はサーバーから削除され、次のセキュリティ機能が無効化されます:" + "新しい端末で暗号化された過去のメッセージを確認できなくなります" + "すべての端末で %1$s からサインアウトすると、暗号化されたメッセージを確認することはできなくなります。" + "本当に鍵を保管庫から削除しますか?" + "既存の回復鍵を紛失した場合は、新しい回復鍵を生成してください。回復鍵を更新すると、それ以前の回復鍵は使用できなくなります。" + "新しい回復鍵を生成する" + "誰にも共有しないでください!" + "回復鍵を更新しました" + "回復鍵を変更しますか?" + "新しい回復鍵を生成" + "誰にもこの画面を見せないでください!" + "鍵の保管庫にアクセスするには、もう一度お試しください。" + "回復鍵が間違っています" + "代わりにセキュリティキーまたはセキュリティフレーズを入力することも可能です。" + "回復鍵を入力してください…" + "回復鍵を紛失しましたか?" + "回復鍵が承認されました" + "回復鍵を入力してください" + "回復鍵をコピーしました" + "生成中…" + "回復鍵を保存" + "この回復鍵をパスワードマネージャーや、暗号化に対応するメモアプリなどに記録するか、物理的な金庫などに書き留めて保管してください。" + "タップして回復鍵をコピー" + "回復鍵を安全な場所に保管してください" + "後からこの回復鍵を確認することはできません。" + "回復鍵を保存しましたか?" + "鍵の保管庫は回復鍵によって保護されています。新しい回復鍵が必要な場合は「回復鍵を変更」を選択して再生成できます。" + "新しい回復鍵を生成する" + "誰にも共有しないでください!" + "回復鍵の設定に成功しました" + "回復鍵を作成" + "はい、リセットします" + "この操作は元に戻せません。" + "本当にデジタルIDをリセットしますか?" + "不明な問題が発生しました。アカウントのパスワードが正しいことを確認してもう一度試してください。" + "回復鍵を入力してください…" + "デジタルIDをリセットしようとしています。" + "アカウントのパスワードを入力" + 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 bcc44c29ae..ec5237235e 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -24,12 +24,12 @@ "Данные вашего аккаунта, контакты, настройки и список чатов будут сохранены" "Вы потеряете историю тех сообщений, которые хранятся только на сервере" "Вам нужно будет заново подтвердить все существующие устройства и контакты." - "Сбрасывайте личность только в том случае, если у вас нет доступа к другим устройству, на которых выполнен вход, и вы потеряли ключ восстановления." - "Не можете подтвердить? Вам потребуется сбросить личность вашей учетной записи." + "Сбрасывайте ключ шифрования только в том случае, если у вас нет доступа к другому устройству, на котором выполнен вход, и вы потеряли ключ восстановления." + "Не можете подтвердить? Вам потребуется сбросить свою цифровую идентификацию." "Удалить" "Вы потеряете зашифрованные сообщения, если выйдете из всех устройств." "Вы уверены, что хотите удалить хранилище ключей?" - "Удаление хранилища ключей приведёт к удалению вашей криптографической личности и ключей сообщений с сервера, а также отключению следующих функций безопасности:" + "Удаление хранилища ключей приведет к удалению вашей цифровой идентификации и ключей сообщений с сервера, а также к отключению следующих функций безопасности:" "Нет зашифрованной истории сообщений на новых устройствах" "Вы потеряете доступ к зашифрованным сообщениям, если выйдете из %1$s везде" "Вы уверены, что хотите отключить хранение ключей и удалить их?" diff --git a/features/securebackup/impl/src/main/res/values-vi/translations.xml b/features/securebackup/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..70913a5e24 --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,44 @@ + + + "Xóa kho lưu trữ khóa" + "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" + "Thay đổi 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." + "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?" + "Xóa lưu trữ khóa sẽ loại bỏ danh tính kỹ thuật số và khóa tin nhắn của bạn khỏi máy chủ, đồng thời tắt các tính năng bảo mật sau:" + "Lịch sử tin nhắn mã hóa sẽ không có trên thiết bị mới." + "Bạn sẽ mất quyền truy cập vào các tin nhắn được mã hóa nếu đăng xuất khỏi %1$s trên tất cả thiết bị" + "Bạn có chắc muốn tắt lưu trữ khóa và xóa nó không?" + "Nếu mất khóa khôi phục hiện tại, hãy tạo khóa mới. Khóa cũ sẽ không còn dùng được sau khi thay đổi." + "Tạo khóa khôi phục mới." + "Đừng chia sẻ điều này với bất kỳ ai!" + "Khóa khôi phục đã thay đổi." + "Thay đổi khóa khôi phục?" + "Đảm bảo không ai có thể nhìn thấy màn hình này!" + "Thử lại để xác nhận quyền truy cập lưu trữ khóa." + "Khóa khôi phục không chính xác." + "Nếu bạn có khóa bảo mật hoặc mật khẩu, bạn cũng có thể dùng." + "Nhập…" + "Khóa khôi phục xác nhận thành công." + "Nhập khóa khôi phục của bạn." + "Đã sao chép khóa khôi phục." + "Đang tạo…" + "Lưu khóa khôi phục." + "Ghi khóa khôi phục vào nơi an toàn, như trình quản lý mật khẩu, ghi chú mã hóa hoặc két sắt." + "Chạm để sao chép khóa khôi phục." + "Hãy lưu khóa khôi phục ở nơi an toàn." + "Sau bước này, bạn sẽ không còn truy cập khóa khôi phục mới." + "Bạn đã lưu lại khóa khôi phục chưa?" + "Lưu trữ khóa của bạn được bảo vệ bằng một khóa khôi phục. Nếu cần một khóa khôi phục mới sau khi thiết lập, bạn có thể tạo lại bằng cách chọn \'Thay đổi khóa khôi phục\'." + "Tạo khóa khôi phục của bạn." + "Đừng chia sẻ điều này với bất kỳ ai!" + "Thiết lập khôi phục thành công" + "Lấy khóa khôi phục." + "Nhập…" + diff --git a/features/securebackup/impl/src/main/res/values-zh/translations.xml b/features/securebackup/impl/src/main/res/values-zh/translations.xml index 438a05f893..8d86e496cb 100644 --- a/features/securebackup/impl/src/main/res/values-zh/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh/translations.xml @@ -11,7 +11,7 @@ "如果您丢失了所有现有设备,使用恢复密钥恢复您的密码学身份和消息历史记录。" "输入恢复密钥" "您的密钥存储当前不同步。" - "设置恢复" + "获取恢复密钥" "在桌面设备中打开 %1$s" "再次登录您的账户" "当要求验证您的设备时,选择 %1$s" @@ -23,8 +23,8 @@ "您的账户信息、联系人、偏好设置和聊天列表将被保留" "您将丢失现有的消息历史记录" "您将需要再次验证所有您的现有设备和联系人" - "仅当您无法访问其他已登录设备并且丢失了恢复密钥时才重置您的身份。" - "如果您无法通过其他方式确认,请重置您的身份" + "仅当您无法访问其他已登录设备并且丢失了恢复密钥时才重置您的数字身份。" + "无法确认?那么你需要重置您的数字身份。" "关闭" "如果您登出所有设备,您的加密消息将丢失。" "您确定要关闭备份吗?" @@ -34,7 +34,7 @@ "您确定要关闭备份吗?" "如果您丢失了现有的恢复密钥,请获取新的恢复密钥。更改恢复密钥后,您的旧密钥将不再起作用。" "生成新的恢复密钥" - "不要告诉任何人!" + "请勿与任何人分享!" "恢复密钥已更改" "更改恢复密钥?" "创建新的恢复密钥" @@ -56,14 +56,14 @@ "您保存了恢复密钥吗?" "您的聊天备份受恢复密钥保护。如果您在安装后需要新的恢复密钥,则可以通过选择「更改恢复密钥」来重新创建。" "生成恢复密钥" - "不要告诉任何人!" + "请勿与任何人分享!" "恢复设置成功" - "设置恢复" + "获取恢复密钥" "是的,立即重置" "此过程不可逆。" - "您确定要重置加密吗?" + "您确定要重置您的数字身份吗?" "发生未知错误。请检查您的帐户密码是否正确,然后重试。" "输入……" - "确认您要重置加密。" + "确认您要重置您的数字身份。" "输入您的账户密码以继续" diff --git a/features/securityandprivacy/impl/src/main/res/values-it/translations.xml b/features/securityandprivacy/impl/src/main/res/values-it/translations.xml index 0cf3326022..41b0c1a047 100644 --- a/features/securityandprivacy/impl/src/main/res/values-it/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-it/translations.xml @@ -2,9 +2,16 @@ "Per renderlo visibile nell\'elenco pubblico, avrai bisogno di un indirizzo." "Modifica indirizzo" + "Spazi in cui i membri possono entrare nella stanza senza invito." + "Gestisci gli spazi" + "(Spazio sconosciuto)" + "Altri spazi di cui non sei membro" + "I tuoi spazi" "Aggiungi indirizzo" + "Chiunque si trovi in spazi autorizzati può partecipare, ma tutti gli altri devono richiedere l\'accesso." "Chiunque deve richiedere l\'accesso." "Chiedi di entrare" + "Chiunque all\'interno di %1$s può partecipare, mentre tutti gli altri devono richiedere l\'accesso." "Sì, attiva la crittografia" "Una volta attivata, la crittografia di una stanza non può essere disattivata, la cronologia dei messaggi sarà visibile solo ai membri della stanza da quando sono stati invitati o da quando sono entrati nella stanza. Nessuno, oltre ai membri della stanza, sarà in grado di leggere i messaggi. Ciò potrebbe impedire ai bot e ai bridge di funzionare correttamente. @@ -15,19 +22,25 @@ Non consigliamo di attivare la crittografia per le stanze che chiunque può trov "Attiva la crittografia end-to-end" "Chiunque può partecipare." "Chiunque" + "Scegli quali membri dello spazio possono accedere a questa stanza senza invito.%1$s" + "Gestisci gli spazi" "Solo le persone invitate possono entrare." "Solo su invito" "Accesso" + "Chiunque si trovi in ​​spazi autorizzati può partecipare." + "Chiunque in %1$s può partecipare." + "Membri dello spazio" "Gli spazi non sono attualmente supportati" "Per renderlo visibile nell\'elenco pubblico, avrai bisogno di un indirizzo." "Indirizzo" "Consenti la ricerca di questa stanza effettuando una ricerca nell\'elenco delle stanze pubbliche di %1$s" "Consenti di essere trovato effettuando una ricerca nell\'elenco pubblico." "Visibile nell\'elenco pubblico" - "Chiunque" + "Chiunque (la cronologia è pubblica)" + "Le modifiche non interesseranno i messaggi passati, ma solo quelli nuovi. %1$s" "Chi può leggere la cronologia messaggi" - "Solo membri da quando sono stati invitati" - "Solo membri da dopo aver selezionato questa opzione" + "Members invited" + "Members (cronologia completa)" "Gli indirizzi delle stanze sono modi per trovare e accedervi. In questo modo puoi anche condividere facilmente la tua stanze con altri. Puoi scegliere di pubblicare la tua stanza nell\'elenco delle stanza pubbliche dell\'homeserver." "Pubblicazione della stanza" diff --git a/features/securityandprivacy/impl/src/main/res/values-ja/translations.xml b/features/securityandprivacy/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..110d19a325 --- /dev/null +++ b/features/securityandprivacy/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,50 @@ + + + "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" + "アドレスの編集" + "招待なしでルームへの参加が可能なスペース" + "スペースを管理" + "(不明なスペース)" + "参加していない他のスペース" + "あなたのスペース" + "アドレスを追加" + "認証済みのスペースに所属するユーザーのみが参加できます。それ以外のユーザーは参加へのリクエストが必要です。" + "参加のリクエストが必須です。" + "参加をリクエスト" + "%1$s に所属するユーザーのみが参加できます。それ以外のユーザーは参加のリクエストが必要です。" + "暗号化を有効にする" + "暗号化が有効のルームを再び無効化することはできません。過去のメッセージの参照は、ユーザーが招待された、あるいは参加した以降に投稿された内容に限定されます。 +ルームのメンバー以外がメッセージを確認することはできないため、bot やブリッジのサービスが正常に動作しない可能性があります。 +公開スペースを暗号化することは一般に推奨されません。" + "暗号化を有効にしますか?" + "一度有効にすると元に戻すことはできません。" + "暗号化" + "エンドツーエンド暗号化を有効にする" + "誰でも参加できます" + "全員" + "招待無しで参加できるユーザーが所属するルームを選択してください。%1$s" + "スペースを管理" + "招待されたユーザーのみ参加できます。" + "招待制" + "アクセス" + "認証済みのスペースに所属するすべてのユーザーが参加できます。" + "%1$s に所属するすべてのユーザーが参加できます。" + "スペースのメンバー" + "スペースは現在対応していません。" + "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" + "アドレス" + "%1$s の公開ルームの検索結果に、このルームを表示します" + "公開ディレクトリの検索結果に表示" + "公開ディレクトリに表示" + "全員(履歴を公開)" + "過去のメッセージに変更は適用されません。新規のメッセージにのみ適用されます。%1$s" + "履歴を表示するユーザー" + "招待済みのユーザー" + "ユーザー (すべての履歴)" + "ルームアドレスはルームの検索やアクセスに役立ち、他のユーザーにルームを簡単に共有できます。 +ホームサーバーの公開ディレクトリにルームを表示するかを設定できます。" + "ルームの公開" + "ルームアドレスはルームの検索やアクセスに役立ち、他のユーザーにルームを簡単に共有できます。" + "視認性" + "セキュリティとプライバシー" + diff --git a/features/securityandprivacy/impl/src/main/res/values-vi/translations.xml b/features/securityandprivacy/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..c400036307 --- /dev/null +++ b/features/securityandprivacy/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,11 @@ + + + "Bạn cần một địa chỉ để hiển thị trong danh bạ công khai." + "Chỉnh sửa địa chỉ" + "Sau khi được kích hoạt, mã hóa cho một phòng chat không thể tắt được. Lịch sử tin nhắn chỉ hiển thị cho các thành viên phòng chat kể từ khi họ được mời hoặc kể từ khi họ tham gia phòng chat. +Không ai ngoài các thành viên phòng chat có thể đọc tin nhắn. Điều này có thể ngăn chặn bot và các thiết bị kết nối hoạt động đúng cách. +Chúng tôi không khuyến khích bật mã hóa cho các phòng chat mà bất kỳ ai cũng có thể tìm thấy và tham gia." + "Mã hóa" + "Thành viên không gian" + "Bạn cần một địa chỉ để hiển thị trong danh bạ công khai." + diff --git a/features/signedout/impl/src/main/res/values-ja/translations.xml b/features/signedout/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..27fc2a1d4b --- /dev/null +++ b/features/signedout/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,8 @@ + + + "他のセッションでパスワードを変更しました" + "このセッションは他のセッションより削除されました" + "サーバー管理者があなたのアクセスを無効にしました" + "以下のいずれかの理由によってサインアウトされました。%s を引き続き使用するには再度サインインしてください。" + "サインアウトしました" + diff --git a/features/signedout/impl/src/main/res/values-vi/translations.xml b/features/signedout/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..320f4a8731 --- /dev/null +++ b/features/signedout/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,8 @@ + + + "Bạn đã thay đổi mật khẩu trên phiên đăng nhập khác." + "Bạn đã xóa phiên đăng nhập này từ một phiên khác." + "Quản trị viên của máy chủ đã thu hồi quyền truy cập của bạn." + "Bạn có thể đã bị đăng xuất vì một trong những lý do được liệt kê bên dưới. Vui lòng đăng nhập lại để tiếp tục sử dụng %s ." + "Bạn đã đăng xuất." + diff --git a/features/space/impl/src/main/res/values-be/translations.xml b/features/space/impl/src/main/res/values-be/translations.xml index dbd39abf09..1a3adafd72 100644 --- a/features/space/impl/src/main/res/values-be/translations.xml +++ b/features/space/impl/src/main/res/values-be/translations.xml @@ -1,4 +1,5 @@ + "Пакінуць прастору" "Ролі і дазволы" diff --git a/features/space/impl/src/main/res/values-it/translations.xml b/features/space/impl/src/main/res/values-it/translations.xml index 62f4787002..20859ee70f 100644 --- a/features/space/impl/src/main/res/values-it/translations.xml +++ b/features/space/impl/src/main/res/values-it/translations.xml @@ -8,10 +8,20 @@ "Seleziona le stanze che desideri abbandonare e di cui non sei l\'unico amministratore:" "Prima di poter uscire, devi assegnare un altro amministratore a questo spazio." + "Sei l\'unico proprietario di %1$s. Devi trasferire la proprietà a qualcun altro prima di andartene." "Non verrai rimosso dalle seguenti stanze perché sei l\'unico amministratore:" "Uscire da %1$s?" "Sei l\'unico amministratore di %1$s" + "Trasferisci proprietà" + "Stanza" + "L\'aggiunta di una stanza non influirà sull\'accesso alla stessa. Per modificare l\'accesso, vai su Impostazioni stanza > Sicurezza & privacy." + "Aggiungi la tua prima stanza" "Visualizza membri" + "La rimozione di una stanza non influirà sull\'accesso alla stessa. Per modificare l\'accesso, vai su Informazioni sulla stanza > Sicurezza & privacy" + + "Rimuovi %1$d stanza da %2$s" + "Rimuovi %1$d stanze da %2$s" + "Esci dallo spazio" "Ruoli e autorizzazioni" "Sicurezza e privacy" diff --git a/features/space/impl/src/main/res/values-ja/translations.xml b/features/space/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..e00d045038 --- /dev/null +++ b/features/space/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,26 @@ + + + "所有者を選択" + "%1$s (管理者)" + + "%1$d 個のルームとスペースを退出" + + "あなたが唯一の管理者であるルーム以外を選択してください。" + "このスペースを退出する前に、新しく管理者を設定してください。" + "あなたは %1$s の唯一の所有者です。退出する前に所有権を譲与する必要があります。" + "あなたが唯一の管理者であるため、以下のルームからは退出しません。" + "%1$s を退出しますか?" + "あなたが唯一の %1$s の管理者です。" + "所有権の譲渡" + "ルーム" + "ルームの追加はルームへのアクセスに影響しません。アクセスの設定は、ルームの設定 > セキュリティーとプライバシー から変更できます。" + "最初のルームを追加しましょう" + "メンバーを表示" + "ルームの削除はルームへのアクセスに影響しません。アクセスの設定は、ルームの設定 > セキュリティーとプライバシー から変更できます。" + + "%2$s から%1$d 個のルームを削除" + + "スペースを退出" + "役割と権限" + "セキュリティとプライバシー" + diff --git a/features/space/impl/src/main/res/values-vi/translations.xml b/features/space/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..a19747d029 --- /dev/null +++ b/features/space/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "Rời space" + "Vai trò và quyền hạn" + diff --git a/features/startchat/impl/src/main/res/values-ja/translations.xml b/features/startchat/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..ed490becfc --- /dev/null +++ b/features/startchat/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,12 @@ + + + "新しいルーム" + "ルーム階層" + "新しい会話を開始する際に問題が発生しました。" + "アドレスからルームに参加" + "有効なアドレスではありません" + "入力してください…" + "ルームが見つかりました" + "ルームが見つかりません" + "例) #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-vi/translations.xml b/features/startchat/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..765b5bc302 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,6 @@ + + + "Phòng mới" + "Danh sách phòng" + "Đã xảy ra lỗi khi cố gắng bắt đầu cuộc trò chuyện" + diff --git a/features/userprofile/shared/src/main/res/values-ja/translations.xml b/features/userprofile/shared/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..33ba6b6a85 --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-ja/translations.xml @@ -0,0 +1,19 @@ + + + "ブロック" + "ブロックしたユーザーのメッセージは非表示になり、新しく送信することもできません。ブロックはいつでも解除することができます。" + "ユーザーをブロック" + "ブロックを解除" + "すべてのメッセージが再表示されます。" + "ユーザーのブロックを解除" + "ブロック" + "ブロックしたユーザーのメッセージは非表示になり、新しく送信することもできません。ブロックはいつでも解除することができます。" + "ユーザーをブロック" + "プロフィール" + "ブロックを解除" + "すべてのメッセージが再表示されます。" + "ユーザーのブロックを解除" + "このユーザーを検証するにはWeb版アプリを使用してください。" + "%1$s を検証" + "新しい会話を開始する際に問題が発生しました。" + diff --git a/features/userprofile/shared/src/main/res/values-vi/translations.xml b/features/userprofile/shared/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..122d8a2153 --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-vi/translations.xml @@ -0,0 +1,16 @@ + + + "Chặn" + "Người dùng bị chặn sẽ không thể gửi tin nhắn cho bạn và tất cả tin nhắn của họ sẽ bị ẩn. Bạn có thể bỏ chặn họ bất cứ lúc nào." + "Chặn người dùng" + "Bỏ chặn" + "Bạn sẽ có thể xem lại tất cả tin nhắn từ họ." + "Bỏ chặn người dùng" + "Chặn" + "Người dùng bị chặn sẽ không thể gửi tin nhắn cho bạn và tất cả tin nhắn của họ sẽ bị ẩn. Bạn có thể bỏ chặn họ bất cứ lúc nào." + "Chặn người dùng" + "Bỏ chặn" + "Bạn sẽ có thể xem lại tất cả tin nhắn từ họ." + "Bỏ chặn người dùng" + "Đã xảy ra lỗi khi cố gắng bắt đầu cuộc trò chuyện" + diff --git a/features/userprofile/shared/src/main/res/values-zh/translations.xml b/features/userprofile/shared/src/main/res/values-zh/translations.xml index b1b37bdbdc..38c4e3e8eb 100644 --- a/features/userprofile/shared/src/main/res/values-zh/translations.xml +++ b/features/userprofile/shared/src/main/res/values-zh/translations.xml @@ -1,18 +1,18 @@ - "封禁" - "被封禁的用户无法给你发消息,并且他们的消息会被隐藏。你可以随时解封。" - "封禁用户" - "解封" + "屏蔽" + "被屏蔽的用户无法给你发消息,并且他们的消息会被隐藏。你可以随时解除屏蔽。" + "屏蔽用户" + "解除屏蔽" "可以重新接收他们的消息。" - "解封用户" - "封禁" - "被封禁的用户无法给你发消息,并且他们的消息会被隐藏。你可以随时解封。" - "封禁用户" + "解除屏蔽用户" + "屏蔽" + "被屏蔽的用户无法给你发消息,并且他们的消息会被隐藏。你可以随时解除屏蔽。" + "屏蔽用户" "个人资料" - "解封" + "解除屏蔽" "可以重新接收他们的消息。" - "解封用户" + "解除屏蔽用户" "使用 Web 应用程序验证此用户。" "验证 %1$s" "在开始聊天时发生了错误" diff --git a/features/verifysession/impl/src/main/res/values-it/translations.xml b/features/verifysession/impl/src/main/res/values-it/translations.xml index 5b11c27cbe..2bb22e98f9 100644 --- a/features/verifysession/impl/src/main/res/values-it/translations.xml +++ b/features/verifysession/impl/src/main/res/values-it/translations.xml @@ -2,8 +2,8 @@ "Non puoi confermare?" "Crea una nuova chiave di recupero" - "Verifica questo dispositivo per segnare i tuoi messaggi come sicuri." - "Conferma la tua identità" + "Scegli come effettuare la verifica per configurare la messaggistica sicura." + "Conferma la tua identità digitale" "Usa un altro dispositivo" "Usa la chiave di recupero" "Ora puoi leggere o inviare messaggi in tutta sicurezza e anche chi chatta con te può fidarsi di questo dispositivo." @@ -17,7 +17,7 @@ "Conferma che i numeri seguenti corrispondano a quelli mostrati nell\'altra sessione." "Confronta i numeri" "Ora puoi leggere o inviare messaggi in modo sicuro sul tuo altro dispositivo." - "Ora puoi fidarti dell\'identità di questo utente quando invii o ricevi messaggi." + "Ora puoi fidarti dell\'identità digitale di questo utente quando invii o ricevi messaggi." "Dispositivo verificato" "Inserisci la chiave di recupero" "La richiesta è scaduta, è stata rifiutata o c\'è stata una mancata corrispondenza nella verifica." @@ -42,7 +42,7 @@ "Apri l\'app su un altro dispositivo verificato" "Per una maggiore sicurezza, verifica questo utente confrontando un set di emoji sui tuoi dispositivi. A tale scopo, utilizza un metodo di comunicazione affidabile." "Verificare questo utente?" - "Per una maggiore sicurezza, un altro utente desidera verificare la tua identità. Ti verrà mostrato un set di emoji da confrontare." + "Per maggiore sicurezza, un altro utente vuole verificare la tua identità digitale. Ti verrà mostrata una serie di emoji da confrontare." "Dovresti vedere un popup sull\'altro dispositivo. Inizia subito la verifica da lì." "Avvia la verifica sull\'altro dispositivo" "Avvia la verifica sull\'altro dispositivo" @@ -50,5 +50,5 @@ "Una volta accettata, potrai proseguire con la verifica." "Accetta la richiesta di avviare il processo di verifica nell\'altra sessione per continuare." "In attesa di accettare la richiesta" - "Disconnessione in corso…" + "Rimozione del dispositivo…" diff --git a/features/verifysession/impl/src/main/res/values-ja/translations.xml b/features/verifysession/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..72360fda21 --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,54 @@ + + + "認証できませんか?" + "回復鍵を新規作成します" + "安全なメッセージを設定するための検証方法を選択してください。" + "デジタルIDの認証" + "他の端末を使用" + "回復鍵を使用" + "メッセージのやり取りを安全に行えるようになりました。他のユーザーはこの端末を信頼できます。" + "検証済みの端末" + "他の端末を使用" + "一方の端末を待機中…" + "問題が発生しました。リクエストがタイムアウトまたは拒否されました。" + "以下の絵文字が、もう一方の端末の表示と一致することを確認してください。" + "絵文字の比較" + "一方のユーザーの端末上に表示される絵文字と一致することを確認してください。" + "もう一方のセッションと数字が一致することを確認してください。" + "数字を比較してください" + "もう一方の端末でも、安全なメッセージのやり取りが可能になりました。" + "メッセージのやり取りにおいて、このユーザーのデジタルIDを信頼できるようになりました。" + "検証済みの端末" + "回復鍵を入力" + "リクエストがタイムアウトしたか、リクエストの拒否あるいは検証に不一致がありました。" + "暗号化された過去のメッセージを確認するには本人検証が必要です。" + "既存のセッションを使用" + "検証を再試行" + "検証を実行" + "一致を待機中…" + "絵文字の組み合わせを比較してください。" + "絵文字が双方で一致して表示されていることを確認してください。" + "サインイン済み" + "リクエストがタイムアウトしたか、リクエストの拒否あるいは検証に不一致がありました。" + "検証に失敗しました" + "あなたが検証を開始した場合にのみ続行してください。" + "他の端末を検証して過去のメッセージの安全を保ってください。" + "もう一方の端末でも、安全なメッセージのやり取りが可能になりました。" + "検証済みの端末" + "検証をリクエスト済み" + "一致しません" + "一致します" + "検証を開始する前に、他の端末でアプリケーションを開いてください。" + "検証済みの他の端末でアプリケーションを開いてください" + "安全性を高めるために、絵文字の組み合わせを使用してこのユーザーを検証してください。これにより安全にやり取りを行うことができるようになります。" + "このユーザーを検証しますか?" + "安全性を高めるために、相手ユーザーがあなたのデジタルIDを検証することを要求しています。比較用の絵文字の組み合わせが表示されます。" + "一方の端末でポップアップが表示されます。そこから検証を開始してください。" + "一方の端末で検証を開始してください" + "一方の端末で検証を開始してください" + "一方の端末を待機中" + "検証を承認することで続行できます。" + "他の端末で検証リクエストを承認してください。" + "リクエストの承認を待機中" + "削除中…" + diff --git a/features/verifysession/impl/src/main/res/values-ru/translations.xml b/features/verifysession/impl/src/main/res/values-ru/translations.xml index 53d4196d9d..91974caa1f 100644 --- a/features/verifysession/impl/src/main/res/values-ru/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ru/translations.xml @@ -2,7 +2,7 @@ "Не можете подтвердить?" "Создайте новый ключ восстановления" - "Подтвердите это устройство, чтобы настроить безопасный обмен сообщениями." + "Выберите способ подтверждения для настройки защищенного обмена сообщениями." "Подтвердите личность" "Использовать другое устройство" "Использовать ключ восстановления" @@ -17,7 +17,7 @@ "Убедитесь, что приведенные ниже числа совпадают с цифрами, показанными в другом сеансе." "Сравните числа" "Теперь вы можете безопасно читать или отправлять сообщения на новом устройстве." - "Теперь вы можете доверять сообщениям этого пользователя." + "Теперь ты можешь доверять цифровой идентичности этого пользователя при отправке или получении сообщений." "Устройство проверено" "Введите ключ восстановления" "Время ожидания подтверждения истекло, запрос был отклонён, или произошла ошибка." diff --git a/features/verifysession/impl/src/main/res/values-vi/translations.xml b/features/verifysession/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..7cb5b916cf --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,31 @@ + + + "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" + "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" + "Đ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." + "So sánh các biểu tượng cảm xúc" + "Xác nhận rằng các số bên dưới khớp với số hiển thị trên thiết bị đăng nhập khác của bạn." + "So sánh số liệu" + "Giờ đây, bạn có thể đọc hoặc gửi tin nhắn một cách an toàn trên thiết bị khác của mình." + "Thiết bị được xác thực" + "Nhập mã khôi phục." + "Hãy chứng minh đó là bạn để truy cập vào lịch sử tin nhắn đã mã hóa của bạn." + "Mở một phiên hiện có" + "Thử xác minh lại" + "Tôi đã sẵn sàng" + "Đang chờ ghép đôi…" + "So sánh một bộ biểu tượng cảm xúc duy nhất." + "So sánh các biểu tượng cảm xúc riêng biệt, đảm bảo chúng xuất hiện theo cùng một thứ tự." + "Xác minh thất bại" + "Giờ đây, bạn có thể đọc hoặc gửi tin nhắn một cách an toàn trên thiết bị khác của mình." + "Thiết bị được xác thực" + "Chúng không khớp nhau" + "Chúng khớp với nhau" + "Hãy chấp nhận yêu cầu bắt đầu quá trình xác minh trong phiên làm việc khác của bạn để tiếp tục." + "Đang chờ chấp nhận yêu cầu" + "Đang gỡ thiết bị…" + diff --git a/features/verifysession/impl/src/main/res/values-zh/translations.xml b/features/verifysession/impl/src/main/res/values-zh/translations.xml index 54b6de5d68..b48bfe3f87 100644 --- a/features/verifysession/impl/src/main/res/values-zh/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh/translations.xml @@ -2,8 +2,8 @@ "无法确认?" "创建新的恢复密钥" - "验证此设备以开始安全地收发消息。" - "确认这是你" + "选择验证方式以设置安全的消息传输。" + "确认您的数字身份" "使用其他设备" "使用恢复密钥" "现在,您可以安全地阅读或发送消息,与您聊天的人也会信任此设备。" @@ -17,7 +17,7 @@ "确认以下数字与其他会话中显示的一致。" "比较数字" "现在您可以在其他设备上安全地阅读或发送消息。" - "现在您可以在发送或接收消息时信任该用户的身份。" + "现在您可以在发送或接收消息时信任该用户的数字身份。" "设备已验证" "输入恢复密钥" "要么请求超时,要么请求被拒绝,要么验证不匹配。" @@ -42,7 +42,7 @@ "在另一台验证的设备上打开应用" "为了提高安全性,请通过比较设备上的一组表情符号来验证此用户。通过使用安全方式来做到这一点,如面对面。" "验证此用户?" - "为了提高安全性,另一位用户想要验证您的身份。您将看到一组表情符号供您比较。" + "为了额外的安全性,另一位用户想要验证您的数字身份。您将看到一组表情符号供您比较。" "您应该会在另一台设备上看到一个弹出窗口。现在从那里开始验证。" "在另一台设备上开始验证" "在另一台设备上开始验证" @@ -50,5 +50,5 @@ "一旦被接受,您将能够继续进行验证。" "请在其他会话中接受验证请求。" "等待接受请求" - "正在登出…" + "正在删除设备……" diff --git a/libraries/androidutils/src/main/res/values-ja/translations.xml b/libraries/androidutils/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..c27f0f3ed2 --- /dev/null +++ b/libraries/androidutils/src/main/res/values-ja/translations.xml @@ -0,0 +1,4 @@ + + + "このアクションを処理できるアプリが見つかりません。" + diff --git a/libraries/androidutils/src/main/res/values-vi/translations.xml b/libraries/androidutils/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..bf30372f4a --- /dev/null +++ b/libraries/androidutils/src/main/res/values-vi/translations.xml @@ -0,0 +1,4 @@ + + + "Không tìm thấy ứng dụng tương thích nào để xử lý hành động này." + diff --git a/libraries/dateformatter/impl/src/main/res/values-ja/translations.xml b/libraries/dateformatter/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..d044992377 --- /dev/null +++ b/libraries/dateformatter/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,5 @@ + + + "%1$s %2$s" + "今月" + diff --git a/libraries/dateformatter/impl/src/main/res/values-vi/translations.xml b/libraries/dateformatter/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..b846434e9e --- /dev/null +++ b/libraries/dateformatter/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "%1$s lúc %2$s" + "Tháng này" + diff --git a/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml b/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..8613aae2df --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,73 @@ + + + "(アバターも変更)" + "%1$s がアバターを変更" + "あなたがアバターを変更" + "%1$s がメンバーに降格" + "%1$s がモデレーターに降格" + "%1$sが表示名を変更: %2$s > %3$s" + "あなたが表示名を変更: %1$s > %2$s" + "%1$sが表示名を削除 (%2$s)" + "表示名を削除 (%1$s)" + "%1$sが表示名を設定: %2$s" + "あなたが表示名を設定: %1$s" + "%1$s が管理者に昇格" + "%1$s がモデレーターに昇格" + "%1$sがルームアバターを変更" + "あなたがルームアバターを変更" + "%1$sがルームアバターを削除" + "あなたがルームアバターを削除" + "%1$s が %2$s を追放" + "あなたが %1$s を追放" + "あなたが %1$s を追放: %2$s" + "%1$s が %2$s を追放: %3$s" + "%1$s がルームを作成" + "あなたがルームを作成" + "%1$s が %2$s を招待" + "%1$s が招待を受諾" + "あなたが招待を受諾" + "あなたが %1$s を招待" + "%1$s があなたを招待" + "%1$s がルームに参加" + "あなたがルームに参加" + "%1$s が参加をリクエスト" + "%1$s が %2$s の参加を許可" + "あなたが %1$s の参加を許可" + "あなたが参加をリクエスト" + "%1$s が %2$s の参加リクエストを拒否" + "あなたが %1$s の参加リクエストを拒否" + "%1$s があなたの参加リクエストを拒否" + "%1$s が参加リクエストを取り消し" + "あなたが参加リクエストを取り消し" + "%1$s がルームを退出" + "あなたがルームを退出" + "%1$s がルーム名を変更: %2$s" + "あなたがルーム名を変更: %1$s" + "%1$s がルーム名を削除" + "あなたがルーム名を削除" + "%1$s による変更はありません" + "あなたによる変更はありません" + "%1$s はピン留めメッセージを変更しました" + "あなたがピン留めメッセージを変更しました" + "%1$s がメッセージをピン留め" + "あなたがメッセージをピン留め" + "%1$s がメッセージのピン留めを解除" + "あなたがメッセージのピン留めを解除" + "%1$s が招待を拒否" + "あなたが招待を拒否" + "%1$s が %2$s を削除" + "あなたが %1$s を削除" + "あなたが%1$s を削除: %2$s" + "%1$s が %2$s を削除: %3$s" + "%1$s が %2$s をルームに招待" + "あなたが %1$s をルームに招待" + "%1$s が %2$s へのルームの招待を取り消し" + "あなたが %1$s へのルームの招待を取り消し" + "%1$s がトピックを変更: %2$s" + "あなたがトピックを変更: %1$s" + "%1$s がルームのトピックを削除" + "あなたがルームのトピックを削除" + "%1$s が %2$s の追放を解除" + "あなたが %1$s の追放を解除" + "%1$s がメンバーシップに未知の変更を追加" + diff --git a/libraries/eventformatter/impl/src/main/res/values-vi/translations.xml b/libraries/eventformatter/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..7598ba0cb9 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,64 @@ + + + "(ảnh hồ sơ cũng được thay)" + "%1$s đổi ảnh hồ sơ" + "Bạn đổi ảnh hồ sơ" + "%1$s bị giáng cấp xuống thành thành viên" + "%1$s bị giáng chức xuống làm người điều hành" + "%1$s đổi tên hiển thị từ %2$s sang %3$s" + "Bạn đổi tên hiển thị từ %1$s sang %2$s" + "%1$s xoá tên hiển thị (trước kia là %2$s)" + "Bạn xoá tên hiển thị (trước kia là %1$s)" + "%1$s đặt tên hiển thị thành %2$s" + "Bạn đặt tên hiển thị thành %1$s" + "%1$s đã được thăng chức lên quản trị viên" + "%1$s đã được thăng chức lên làm người điều hành" + "%1$s đổi ảnh phòng" + "Bạn đổi ảnh phòng" + "%1$s đã xóa ảnh đại diện của phòng." + "Bạn đã xóa hình đại diện của phòng trò chuyện" + "%1$s cấm %2$s vào phòng" + "Bạn cấm %1$s vào phòng" + "%1$s tạo phòng này" + "Bạn tạo phòng này" + "%1$s mời %2$s" + "%1$s đã chấp nhận lời mời" + "Bạn đã chấp nhận lời mời" + "Bạn mời %1$s" + "%1$s mời bạn" + "%1$s vào phòng" + "Bạn vào phòng" + "%1$s đang yêu cầu tham gia" + "%1$s được cấp quyền truy cập vào %2$s" + "Bạn đã cho phép %1$s tham gia" + "Bạn đã yêu cầu tham gia" + "%1$s đã từ chối yêu cầu tham gia của %2$s" + "Bạn đã từ chối yêu cầu tham gia của %1$s" + "%1$s đã từ chối yêu cầu tham gia của bạn" + "%1$s không còn mong muốn tham gia" + "Bạn đã hủy yêu cầu tham gia" + "%1$s rời phòng" + "Bạn rời phòng" + "%1$s đổi tên phòng thành %2$s" + "Bạn đổi tên phòng thành %1$s" + "%1$s xóa tên phòng" + "Bạn xóa tên phòng" + "%1$s không có thay đổi nào" + "Bạn chưa thực hiện thay đổi nào" + "Bạn đã thay đổi tin nhắn được ghim" + "%1$s từ chối lời mời" + "Bạn từ chối lời mời" + "%1$s cho %2$s cút khỏi phòng" + "Bạn cho %1$s cút khỏi phòng" + "%1$s đã gửi lời mời đến %2$s để tham gia phòng trò chuyện" + "Bạn đã gửi lời mời đến %1$s để tham gia phòng trò chuyện" + "%1$s đã thu hồi lời mời tham gia phòng trò chuyện của %2$s " + "Bạn đã thu hồi lời mời tham gia phòng trò chuyện của %1$s " + "%1$s đổi chủ đề sang: %2$s" + "Bạn đổi chủ đề sang: %1$s" + "%1$s đã xóa chủ đề phòng" + "Bạn đã xóa chủ đề của phòng." + "%1$s hủy lệnh cấm với %2$s" + "Bạn hủy lệnh cấm với %1$s" + "%1$s đã thực hiện một thay đổi không xác định đối với tư cách thành viên của họ" + diff --git a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml index 9776510d6f..cd22ebed38 100644 --- a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml @@ -54,11 +54,11 @@ "%1$s 取消置顶了一条消息" "您取消置顶了一条消息" "%1$s 拒绝了邀请" - "你拒绝了邀请" - "%1$s 移除了 %2$s" - "你移除了 %1$s" - "您已删除%1$s :%2$s" - "%1$s已移除%2$s:%3$s" + "您拒绝了邀请" + "%1$s 已移除 %2$s" + "您移除了 %1$s" + "您移除了 %1$s:%2$s" + "%1$s 移除了 %2$s:%3$s" "%1$s 向 %2$s 发送了加入聊天室的邀请" "你邀请 %1$s 加入聊天室" "%1$s 撤销了 %2$s 加入聊天室的邀请" diff --git a/libraries/matrixui/src/main/res/values-ja/translations.xml b/libraries/matrixui/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..ce2b24041c --- /dev/null +++ b/libraries/matrixui/src/main/res/values-ja/translations.xml @@ -0,0 +1,9 @@ + + + "招待を送信" + "%1$s とチャットを始めますか?" + "招待を送信しますか?" + "この人物とのチャットがありません。続行する前に、まず招待してください。" + "この新しい連絡先と新規にチャットを開始しますか?" + "%1$s (%2$s) があなたを招待しました" + diff --git a/libraries/matrixui/src/main/res/values-vi/translations.xml b/libraries/matrixui/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..638996cb06 --- /dev/null +++ b/libraries/matrixui/src/main/res/values-vi/translations.xml @@ -0,0 +1,4 @@ + + + "%1$s(%2$s ) đã mời bạn" + diff --git a/libraries/matrixui/src/main/res/values/localazy.xml b/libraries/matrixui/src/main/res/values/localazy.xml index b27021ebd6..c4000519a5 100644 --- a/libraries/matrixui/src/main/res/values/localazy.xml +++ b/libraries/matrixui/src/main/res/values/localazy.xml @@ -3,5 +3,7 @@ "Send invite" "Would you like to start a chat with %1$s?" "Send invite?" + "You currently don’t have any chats with this person. Confirm inviting them before continuing." + "Start a chat with this new contact?" "%1$s (%2$s) invited you" diff --git a/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..cb4da33df8 --- /dev/null +++ b/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,21 @@ + + + "このファイルはルームから削除され、他のユーザーは確認することができなくなります。" + "ファイルを削除しますか?" + "インターネット接続を確認した上、再度お試しください。" + "このルームに投稿された文書ファイルや音声ファイル・メッセージはここに表示されます。" + "アップロードされたファイルはありません" + "ファイルを読み込み中…" + "メディアを読み込み中…" + "ファイル" + "メディア" + "このルームに投稿された画像と動画はここに表示されます。" + "アップロードされたメディアはありません" + "ファイルとメディア" + "ファイル形式" + "ファイル名" + "これ以上ファイルはありません" + "これ以上メディアはありません" + "アップロード元" + "アップロード先" + diff --git a/libraries/permissions/api/src/main/res/values-ja/translations.xml b/libraries/permissions/api/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..1749b855a3 --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-ja/translations.xml @@ -0,0 +1,7 @@ + + + "カメラを使用するには、本体の設定から権限を付与する必要があります。" + "本体の設定から権限を付与してください。" + "マイクを使用するには、本体の設定から権限を付与してください。" + "通知を表示するには、本体の設定から権限を付与してください。" + diff --git a/libraries/permissions/api/src/main/res/values-vi/translations.xml b/libraries/permissions/api/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..c575d3b3bb --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-vi/translations.xml @@ -0,0 +1,7 @@ + + + "Để ứng dụng sử dụng camera, vui lòng cấp quyền trong cài đặt hệ thống." + "Vui lòng cấp quyền trong cài đặt hệ thống." + "Để ứng dụng có thể sử dụng micro, vui lòng cấp quyền trong cài đặt hệ thống." + "Để ứng dụng hiển thị thông báo, vui lòng cấp quyền trong cài đặt hệ thống." + diff --git a/libraries/permissions/impl/src/main/res/values-ja/translations.xml b/libraries/permissions/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..c29d26fd69 --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,5 @@ + + + "アプリケーションが通知を表示できることを確認してください。" + "権限の確認" + diff --git a/libraries/permissions/impl/src/main/res/values-vi/translations.xml b/libraries/permissions/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..0f960c909e --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,5 @@ + + + "Kiểm tra xem ứng dụng có hiển thị thông báo hay không." + "Kiểm tra quyền truy cập" + diff --git a/libraries/push/impl/src/main/res/values-it/translations.xml b/libraries/push/impl/src/main/res/values-it/translations.xml index 9e44c2d7f9..6ed91c3b6b 100644 --- a/libraries/push/impl/src/main/res/values-it/translations.xml +++ b/libraries/push/impl/src/main/res/values-it/translations.xml @@ -15,6 +15,11 @@ "Non è stato possibile registrare il distributore di notifiche UnifiedPush, quindi non riceverai più notifiche. Controlla le impostazioni delle notifiche dell\'app e lo stato del distributore push." "Hai nuovi messaggi." + + "Hai %d nuovo messaggio." + "Hai %d nuovi messaggi." + + "📞 Chiamata in arrivo" "📹 Chiamata in arrivo" "** Invio fallito - si prega di aprire la stanza" "Entra" @@ -38,6 +43,8 @@ "%1$s ti ha invitato a unirti alla stanza" "Io" "%1$s ti ha menzionato o risposto" + "Ti abbiamo invitato a unirti allo spazio" + "%1$s ti ha invitato a unirti allo spazio" "Stai visualizzando la notifica! Cliccami!" "Discussione in %1$s" "%1$s: %2$s" diff --git a/libraries/push/impl/src/main/res/values-ja/translations.xml b/libraries/push/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..f115a54042 --- /dev/null +++ b/libraries/push/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,93 @@ + + + "通話" + "イベントを監視中" + "通常の通知" + "着信" + "サイレント通知" + + "%1$s: %2$d件のメッセージ" + + + "%d 件の通知" + + "Unified Push の通知配信サービス (notification distributor) を登録できないため、通知を受け取ることができません。通知の設定と通知ディストリビューター (push distributor) の状況を確認してください。" + "新着メッセージがあります。" + + "新着のメッセージが%d 件あります。" + + "📞 着信" + "📹 通話着信" + "** 送信失敗 - ルームを開いてください" + "参加" + "拒否" + + "%d 件の招待" + + "チャットにあなたを招待しました" + "%1$sがあなたをチャットに招待しました" + "%1$s があなたをメンションしました" + "新着メッセージ" + + "%d 件の新着メッセージ" + + "%1$sへのリアクション" + "既読にする" + "クイック返信" + "ルームに招待されました" + "%1$s があなたをルームに招待しました" + "自分" + "%1$s がメンションまたは返信しました" + "スペースに招待されました" + "%1$s があなたをスペースに招待しました" + "通知を表示しています。タップしてください。" + "%1$sのスレッド" + "%1$s: %2$s" + "%1$s: %2$s %3$s" + + "%d件の未読メッセージ" + + "%1$sと%2$s" + "%2$sに%1$s" + "%2$sに%1$sと%3$s" + + "%d 個のルーム" + + "バックグラウンド同期" + "Google サービス" + "有効なGoogle Play 開発者サービスがありません。通知が正しく機能しない可能性があります。" + "ブロックしたユーザーを確認中" + "ブロックしたユーザーを表示" + "ブロックしたユーザーはいません。" + + "%1$d 人のユーザーをブロックしました。以降の通知を受信しません。" + + "ブロックしたユーザー" + "現在のプロバイダーの名前を取得してください。" + "プッシュ通知プロバイダーが選択されていません。" + "現在のプッシュ通知プロバイダーは %1$s で、現在のプッシュ通知ディストリビューター は %2$s です。しかし、ディストリビューター %3$s は見つかりませんでした。アンインストールされている可能性があります。" + "現在のプッシュ通知プロバイダーは %1$s ですが、ディストリビューターが設定されていません。" + "現在のプッシュ通知プロバイダー: %1$s" + "現在のプッシュ通知プロバイダー: %1$s (%2$s)" + "現在のプッシュ通知プロバイダー" + "少なくとも一つ以上のプッシュ通知プロバイダーに、アプリケーションが対応していることを確認してください。" + "対応しているプッシュ通知プロバイダーが見つかりませんでした。" + + "%1$d 個の通知プロバイダーを発見: %2$s" + + "このアプリケーションは %1$s に対応しています。" + "プッシュ通知プロバイダーへの対応状況" + "アプリケーションが通知を表示できることを確認してください。" + "通知がタップされていません。" + "通知を表示できません。" + "通知がタップされました。" + "通知の表示" + "テストを続行するには、通知にタップしてください。" + "プッシュ通知をアプリケーションが受信していることを確認してください。" + "エラー: プッシュ通知プロバイダーがリクエストを拒否しました。" + "エラー: %1$s" + "エラー: プッシュ通知をテストできません。" + "エラー: 通知の待機がタイムアウトしました。" + "プッシュ通知のループバックに %1$d ms 要しました。" + "プッシュ通知のループバックをテスト" + diff --git a/libraries/push/impl/src/main/res/values-ru/translations.xml b/libraries/push/impl/src/main/res/values-ru/translations.xml index 24b1412500..c0b597588b 100644 --- a/libraries/push/impl/src/main/res/values-ru/translations.xml +++ b/libraries/push/impl/src/main/res/values-ru/translations.xml @@ -51,7 +51,7 @@ "Пригласил(а) вас в пространство" "%1$s пригласил(а) вас в пространство" "Вы просматриваете уведомление! Нажмите на меня!" - "Ветка в %1$s" + "Обсуждение в %1$s" "%1$s: %2$s" "%1$s: %2$s %3$s" diff --git a/libraries/push/impl/src/main/res/values-vi/translations.xml b/libraries/push/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..5592ff0e3a --- /dev/null +++ b/libraries/push/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,61 @@ + + + "Gọi" + "Đang lắng nghe sự kiện" + "Thông báo ồn ào" + "Cuộc gọi đang đổ chuông" + "Thông báo im lặng" + + "%1$s:%2$d tin nhắn" + + + "%d thông báo" + + "Bạn có tin nhắn mới." + "📹 Cuộc gọi đến" + "** Không gửi được - vui lòng mở phòng" + "Tham gia" + "Từ chối" + + "%d lời mời" + + "Đã mời bạn trò chuyện" + "Đã nhắc đến bạn: %1$s" + "Tin nhắn mới" + + "%dtin nhắn mới" + + "Đã thả %1$s vào tin nhắn" + "Đánh dấu đã đọc" + "Trả lời nhanh" + "Đã mời bạn tham gia phòng" + "Tôi" + "Bạn đang xem thông báo! Bấm vào đây!" + "%1$s:%2$s" + "%1$s: %2$s %3$s" + + "%dtin nhắn chưa đọc đã thông báo" + + "%1$s và %2$s" + "%1$s in %2$s" + "%1$s trong %2$s và %3$s" + + "%d phòng" + + "Đồ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." + "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." + + "Đã tìm thấy %1$d nhà cung cấp thông báo đẩy: %2$s" + + "Hỗ trợ nhà cung cấp thông báo đẩy" + "Kiểm tra xem ứng dụng có thể hiển thị thông báo hay không." + "Thông báo chưa được nhấp vào." + "Không thể hiển thị thông báo." + "Thông báo đã được nhấp!" + "Hiển thị thông báo" + "Hãy nhấp vào thông báo để tiếp tục thử nghiệm." + diff --git a/libraries/push/impl/src/main/res/values-zh/translations.xml b/libraries/push/impl/src/main/res/values-zh/translations.xml index 9a9057b07b..7e59c317c3 100644 --- a/libraries/push/impl/src/main/res/values-zh/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh/translations.xml @@ -16,6 +16,7 @@ "您有 %d 条新消息。" + "📞 来电" "📹 来电" "** 无法发送——请打开聊天室" "加入" @@ -57,7 +58,7 @@ "找不到有效的 Google Play 服务。通知可能无法正常工作。" "检查被阻止的用户" "查看被屏蔽的用户" - "没有用户被阻止。" + "未屏蔽任何用户。" "您已屏蔽 %1$d 位用户。您将不再收到这些用户的推送通知。" @@ -87,6 +88,6 @@ "错误:%1$s。" "错误,无法测试推送。" "错误,等待推送超时。" - "推送回路耗时%1$d 毫秒。" + "推送回路耗时 %1$d 毫秒。" "测试推送回路" diff --git a/libraries/pushproviders/firebase/src/main/res/values-ja/translations.xml b/libraries/pushproviders/firebase/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..5c07e2ad79 --- /dev/null +++ b/libraries/pushproviders/firebase/src/main/res/values-ja/translations.xml @@ -0,0 +1,11 @@ + + + "Firebase が利用可能であることを確認してください。" + "Firebase を利用できません。" + "Firebase は利用可能です。" + "Firebase の確認" + "Firebase トークンが利用可能であることを確認してください。" + "Firebase トークンが不明です。" + "Firebase トークン: %1$s" + "Firebase トークンの確認" + diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-ja/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..a081ba04ff --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-ja/translations.xml @@ -0,0 +1,9 @@ + + + "UnifiedPush のディストリビューターが利用可能であることを確認してください。" + "プッシュ通知ディストリビューターが見つかりませんでした。" + + "%1$d 個のディストリビューターを発見: %2$s" + + "UnifiedPush を確認" + diff --git a/libraries/textcomposer/impl/src/main/res/values-ja/translations.xml b/libraries/textcomposer/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..6dea90b306 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,33 @@ + + + "添付ファイルを追加" + "箇条リスト" + "書式設定を中止して閉じる" + "コードブロックを切替" + "キャプションを追加" + "暗号化されたメッセージ…" + "メッセージ…" + "暗号化されていないメッセージ…" + "リンクを作成" + "リンクを編集" + "%1$s の状態: %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 new file mode 100644 index 0000000000..42b78d23f3 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,25 @@ + + + "Thêm tệp đính kèm" + "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ã" + "Tin nhắn…" + "Tạo liên kết" + "Sửa liên kết" + "Áp dụng định dạng in đậm" + "Áp dụng định dạng in nghiêng" + "Á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" + "Thụt lề" + "Áp dụng định dạng mã trong dòng" + "Đặt liên kết" + "Chuyển đổi danh sách được đánh số" + "Mở tùy chọn soạn tin" + "Chuyển sang Trích dẫn" + "Xóa liên kết" + "Bỏ thụt lề" + "Liên kết" + "Nhấn giữ để ghi âm" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-ja/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..a7357d7aae --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,12 @@ + + + "プッシュ履歴" + "テストを実行" + "再度テスト" + "一部のテストで失敗しました。詳細を確認してください。" + "テストを実行することで、不安定な通知を生じさせる設定の問題を特定できます。" + "修正を試行" + "テストは問題なく完了しました。" + "通知のトラブルシューティング" + "一部のテストはあなたの操作が必要です。詳細を確認してください。" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-vi/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..977938afab --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,6 @@ + + + "Chạy thử nghiệm" + "Chạy các bài kiểm tra để phát hiện vấn đề trong cấu hình có thể khiến thông báo không hoạt động như mong đợi." + "Khắc phục sự cố thông báo" + diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 6e2374a5aa..4011474193 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -1,5 +1,6 @@ + "Дадаць рэакцыю: %1$s" "Адрас" "Аватар" "Выдаліць" @@ -8,15 +9,21 @@ "Уведзена %1$d лічбы" "Уведзена %1$d лічб" + "Змяніць аватар" + "Поўны адрас будзе %1$s" + "Дэталі шыфравання" "Схаваць пароль" "Далучыцца да выкліку" "Перайсці ўніз" "Толькі згадкі" "Гук адключаны" + "Новыя згадкі" + "Новыя паведамленні" "Старонка %1$d" "Паўза" "Поле PIN-кода" "Прайграць" + "Хуткасць прайгравання" "Апытанне" "Апытанне скончана" "QR-код" @@ -34,11 +41,14 @@ "Адправіць файлы" "Паказаць пароль" "Пазваніць" + "Аватар карыстальніка" "Меню карыстальніка" "Паглядзець падрабязнасці" "Запісаць галасавое паведамленне." "Спыніць запіс" + "Ваш аватар" "Прыняць" + "Дадаць подпіс" "Дадаць у хроніку" "Назад" "Званок" @@ -52,26 +62,36 @@ "Пацвердзіць пароль" "Працягнуць" "Капіраваць" + "Скапіяваць подпіс" "Скапіраваць спасылку" "Скапіраваць спасылку на паведамленне" + "Скапіяваць тэкст" "Стварыць" "Стварыце пакой" "Дэактываваць" "Дэактываваць уліковы запіс" "Адхіліць" + "Адхіліць і заблакіраваць" "Выдаліць апытанне" + "Зняць выбар з усіх" "Адключыць" "Адмяніць" "Aдхіліць" "Гатова" "Рэдагаваць" + "Рэдагаваць подпіс" "Рэдагаваць апытанне" "Уключыць" "Скончыць апытанне" "Увядзіце PIN-код" + "Даследаваць публічныя прасторы" + "Завяршыць" "Забылі пароль?" "Пераслаць" "Вярнуцца" + "Перайсці да роляў і дазволаў" + "Перайсці ў Налады" + "Ігнараваць" "Запрасіць" "Запрасіць карыстальнікаў" "Запрасіць карыстальнікаў у %1$s" @@ -82,6 +102,7 @@ "Пакінуць" "Пакінуць размову" "Пакінуць пакой" + "Пакінуць прастору" "Загрузіць больш" "Кіраванне ўліковым запісам" "Кіраванне прыладамі" 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 99c5db6077..0d73a8c121 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -1,6 +1,7 @@ "Aggiungi reazione: %1$s" + "Indirizzo" "Avatar" "Riduci al minimo il campo di testo del messaggio" "Elimina" @@ -26,9 +27,12 @@ "Pausa" "Messaggio vocale, durata: %1$s, posizione attuale: %2$s" "Campo del PIN" + "Posizione fissata" "Riproduci" + "Velocità di riproduzione" "Sondaggio" "Sondaggio terminato" + "Codice QR" "Reagisci con %1$s" "Reagisci con altri emoji" "Visualizzato da %1$s e %2$s" @@ -42,9 +46,12 @@ "Rimuovere la reazione con %1$s" "Avatar della stanza" "Invia file" + "Posizione del mittente" "Azione richiesta a tempo limitato, hai un minuto per la verifica" "Mostra password" "Avvia una chiamata" + "Avvia una videochiamata" + "Avvia una chiamata vocale" "Stanza obsoleta" "Avatar utente" "Menu utente" @@ -56,6 +63,7 @@ "Il tuo avatar" "Accetta" "Aggiungi didascalia" + "Aggiungi stanze esistenti" "Aggiungi alla conversazione" "Indietro" "Chiama" @@ -75,6 +83,7 @@ "Copia testo" "Crea" "Crea stanza" + "Crea spazio" "Disattiva" "Disattiva account" "Rifiuta" @@ -91,6 +100,7 @@ "Attiva" "Termina sondaggio" "Inserisci PIN" + "Esplora gli spazi pubblici" "Fine" "Password dimenticata?" "Inoltra" @@ -111,6 +121,7 @@ "Esci dallo spazio" "Carica altro" "Gestisci account" + "Gestisci account & dispositivi" "Gestisci dispositivi" "Gestisci le stanze" "Invia messaggio" @@ -150,18 +161,21 @@ "Invia messaggio vocale" "Condividi" "Condividi collegamento" + "Condividi la posizione in tempo reale" "Mostra" "Accedi di nuovo" - "Disconnetti" - "Disconnetti comunque" + "Rimuovi questo dispositivo" + "Rimuovi comunque questo dispositivo" "Salta" "Inizia" "Avvia conversazione" "Ricomincia" "Avvia la verifica" "Tocca per caricare la mappa" + "Ferma" "Scatta foto" "Tocca per le opzioni" + "Traduci" "Riprova" "Rimuovi dai fissati" "Visualizza" @@ -179,6 +193,7 @@ "Impostazioni avanzate" "un\'immagine" "Statistiche di utilizzo" + "Sincronizzazione delle notifiche…" "Hai lasciato la stanza" "Sei stato disconnesso dalla sessione" "Aspetto" @@ -191,6 +206,7 @@ "Copiato negli appunti" "Copyright" "Creazione stanza…" + "Creazione spazio…" "Richiesta annullata" "Hai lasciato la stanza" "Hai lasciato lo spazio" @@ -211,6 +227,7 @@ "File vuoto" "Crittografia" "Crittografia abilitata" + "Termina alle %1$s" "Inserisci il PIN" "Errore" "Si è verificato un errore, potresti non ricevere notifiche per nuovi messaggi. Risolvi i problemi relativi alle notifiche dalle impostazioni. @@ -236,6 +253,9 @@ Motivo:. %1$s" "Chiaro" "Riga copiata negli appunti" "Collegamento copiato negli appunti" + "Collega un nuovo dispositivo" + "Posizione in tempo reale" + "Posizione in tempo reale terminata" "Caricamento…" "Caricamento in corso…" @@ -248,10 +268,12 @@ Motivo:. %1$s" "Messaggio" "Azioni messaggio" + "Impossibile inviare il messaggio" "Impaginazione del messaggio" "Messaggio rimosso" "Moderno" "Silenzia" + "Nome" "%1$s (%2$s)" "Nessun risultato" "Nessun nome della stanza" @@ -260,6 +282,7 @@ Motivo:. %1$s" "Non in linea" "Licenze open source" "o" + "Altre opzioni" "Password" "Persone" "Collegamento permanente" @@ -277,8 +300,10 @@ Motivo:. %1$s" "Preparazione…" "Informativa sulla privacy" + "Privato" "Stanza privata" "Spazio privato" + "Pubblico" "Stanza pubblica" "Spazio pubblico" "Reazione" @@ -286,6 +311,7 @@ Motivo:. %1$s" "Motivo" "Chiave di recupero" "Aggiornamento…" + "Rimozione…" "%1$d risposta" "%1$d risposte" @@ -295,6 +321,7 @@ Motivo:. %1$s" "Segnala un problema" "Segnalazione inviata" "Editor di testo avanzato" + "Ruolo" "Stanza" "Nome stanza" "ad es. il nome del tuo progetto" @@ -310,6 +337,10 @@ Motivo:. %1$s" "Sicurezza" "Visto da" "Seleziona un account" + + "%1$d selezionato" + "%1$d selezionati" + "Invia a" "Invio in corso…" "Invio fallito" @@ -320,12 +351,16 @@ Motivo:. %1$s" "URL del server" "Impostazioni" "Condividi lo spazio" + "I nuovi membri vedono la cronologia" + "Posizione in tempo reale condivisa" "Posizione condivisa" "Spazio condiviso" - "Disconnessione" + "Rimozione del dispositivo" "Qualcosa è andato storto" "Abbiamo riscontrato un problema. Per favore riprova." "Spazio" + "Membri dello spazio" + "Di cosa tratta questo spazio?" "%1$d Spazio" "%1$d Spazi" @@ -333,18 +368,20 @@ Motivo:. %1$s" "Avvio della conversazione…" "Adesivo" "Operazione riuscita" + "Suggeriti" "Suggerimenti" "Sincronizzazione" "Sistema" "Testo" "Comunicazioni di terze parti" "Discussione" + "Discussioni" "Argomento" - "Di cosa parla questa stanza?" + "Di cosa riguarda questa stanza?" "Impossibile decrittografare" "Inviato da un dispositivo non sicuro" "Non hai accesso a questo messaggio" - "L\'identità verificata del mittente è stata reimpostata" + "L\'identità digitale verificata del mittente è stata reimpostata" "Non è stato possibile spedire inviti a uno o più utenti." "Impossibile inviare inviti" "Sblocca" @@ -369,13 +406,19 @@ Motivo:. %1$s" "Messaggio vocale" "In attesa…" "In attesa del messaggio" + "In attesa della posizione in tempo reale…" + "Chiunque può vedere la cronologia" "Tu" - "L\'identità di %1$s è stata reimpostata. %2$s" - "L\'identità %2$s di %1$s sembra essere cambiata. %3$s" + "%1$s (%2$s) ha condiviso questo messaggio poiché non eri nella stanza quando è stato inviato." + "%1$s ha condiviso questo messaggio poiché non eri nella stanza quando è stato inviato." + "Questa stanza è stata configurata in modo che i nuovi membri possano leggere la cronologia. %1$s" + "%1$sL\'identità digitale di %2$s" + "%1$sL\'identità digitale di %2$s è stata reimpostata. %3$s" "(%1$s)" - "L\'identità di %1$s è stata reimpostata." - "L\'identità %2$s di %1$s è stata reimpostata. %3$s" + "L\'identità digitale di %1$s è stata reimpostata." + "L\'identità digitale %2$s di %1$s è stata reimpostata. %3$s" "Ritira verifica" + "Consenti l\'accesso" "Il link %1$s ti porta ad un altro sito %2$s Sei sicuro di voler continuare?" @@ -405,6 +448,7 @@ Sei sicuro di voler continuare?" "%1$s non è riuscito ad accedere alla tua posizione. Riprova più tardi." "Invio del messaggio vocale fallito." "La stanza non esiste più o l\'invito non è più valido." + "Attiva il GPS per accedere alle funzioni basate sulla posizione." "Messaggio non trovato" "%1$s non ha l\'autorizzazione di accedere alla tua posizione. Puoi attivare l\'accesso nelle impostazioni." "%1$s non ha l\'autorizzazione per accedere alla tua posizione. Attiva l\'accesso di seguito." @@ -424,6 +468,14 @@ 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" @@ -431,11 +483,11 @@ Sei sicuro di voler continuare?" "%1$d Messaggi fissati" "Messaggi fissati" - "Stai per accedere al tuo account di %1$s per ripristinare la tua identità. Dopodiché verrai riportato all\'app." - "Non riesci a confermare? Vai al tuo account per ripristinare la tua identità." + "Stai per accedere al tuo account %1$s per reimpostare la tua identità digitale. Al termine, verrai reindirizzato all\'app." + "Non riesci a confermare? Vai al tuo account per reimpostare la tua identità digitale." "Ritira la verifica e invia" "Puoi ritirare la tua verifica e inviare comunque questo messaggio, oppure annullarlo per ora e riprovare più tardi dopo aver riverificato %1$s." - "Il tuo messaggio non è stato inviato perché l\'identità verificata di %1$s è stata reimpostata." + "Il tuo messaggio non è stato inviato perché l\'identità digitale verificata di %1$sè stata reimpostata" "Invia comunque il messaggio" "%1$s sta usando uno o più dispositivi non verificati. Puoi inviare il messaggio in ogni caso, oppure annullarlo e riprovare più tardi quando %2$s avrà verificato tutti i suoi dispositivi." "Il tuo messaggio non è stato inviato perché %1$s non ha verificato tutti i dispositivi." @@ -458,12 +510,16 @@ Sei sicuro di voler continuare?" "Apri in Apple Maps" "Apri in Google Maps" "Apri in OpenStreetMap" - "Condividi questa posizione" + "Condividi la posizione selezionata" + "Opzioni di condivisione" "Spazi che hai creato o a cui hai aderito." "%1$s • %2$s" + "Crea spazi per organizzare le stanze" "%1$s spazio" "Spazi" - "Messaggio non inviato perché l\'identità verificata di %1$s è stata reimpostata." + "Condivisa %1$s" + "Sulla mappa" + "Il messaggio non è stato inviato perché l\'identità digitale verificata di %1$sè stata reimpostata." "Messaggio non inviato perché %1$s non ha verificato tutti i dispositivi." "Messaggio non inviato perché non hai verificato uno o più dispositivi." "Posizione" @@ -473,5 +529,5 @@ Sei sicuro di voler continuare?" "È necessario verificare questo dispositivo per accedere alla cronologia messaggi" "Non hai accesso a questo messaggio" "Impossibile decifrare il messaggio" - "Questo messaggio è stato bloccato perché il dispositivo non è verificato o perché il mittente deve verificare la tua identità." + "Questo messaggio è stato bloccato perché non hai verificato il tuo dispositivo o perché il mittente deve verificare la tua identità digitale." diff --git a/libraries/ui-strings/src/main/res/values-ja/translations.xml b/libraries/ui-strings/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..f77a92966b --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -0,0 +1,525 @@ + + + "リアクションを追加: %1$s" + "アドレス" + "アバター" + "入力欄を縮小" + "削除" + + "%1$d 桁入力済" + + "アバターを編集" + "完全なアドレスは %1$s になります。" + "暗号化の詳細" + "入力欄を拡大" + "パスワードを非表示" + "通話に参加" + "一番下へ" + "現在地に移動" + "メンションのみ" + "ミュート有効" + "新規メンション" + "新着メッセージ" + "通話中" + "他のユーザーのアバター" + "%1$d ページ" + "一時停止" + "音声メッセージ 長さ: %1$s 再生位置: %2$s" + "PIN入力欄" + "ピン留めした位置情報" + "再生" + "再生速度" + "投票" + "投票終了" + "QRコード" + "リアクション: %1$s" + "他の絵文字でリアクション" + "既読: %1$s, %2$s" + + "既読: %1$s ほか %2$d 人" + + "%1$s 既読" + "タップしてすべて表示" + "%1$s リアクションを削除" + "%1$s リアクションを削除" + "ルームのアバター" + "ファイルを送信" + "送信者の位置情報" + "1分以内に検証を完了してください" + "パスワードを表示" + "通話を開始" + "ビデオ通話を開始" + "音声通話を開始" + "埋没したルーム" + "ユーザーのアバター" + "ユーザーメニュー" + "アバターを表示" + "詳細を表示" + "音声メッセージ 長さ: %1$s" + "音声メッセージを録音してください。" + "録音を停止" + "あなたのアバター" + "承諾" + "キャプションを追加" + "既存のルームを追加" + "タイムラインに追加" + "戻る" + "通話" + "キャンセル" + "今回のみキャンセル" + "写真を選択" + "クリア" + "閉じる" + "検証してください" + "確認" + "パスワードを確認" + "続行" + "コピー" + "キャプションをコピー" + "リンクをコピー" + "リンクをメッセージにコピー" + "テキストをコピー" + "作成" + "ルームを作成" + "スペースを作成" + "停止" + "アカウントを無効化" + "拒否" + "拒否してブロック" + "投票を削除" + "全ての選択を解除" + "無効化" + "破棄" + "無視" + "完了" + "編集" + "キャプションを編集" + "投票を編集" + "有効化" + "投票を終了" + "PINを入力" + "公開スペースを探す" + "完了" + "パスワードをお忘れですか?" + "転送" + "戻る" + "役割と権限に移動" + "設定に移動" + "無視" + "招待" + "ユーザーを招待" + "%1$s にユーザーを招待" + "%1$s にユーザーを招待" + "招待" + "参加" + "詳細" + "退出" + "会話を退出" + "ルームを退出" + "スペースを退出" + "さらに表示" + "アカウントを管理" + "アカウントと端末を管理" + "端末を管理" + "ルームを管理" + "メッセージ" + "最小化" + "次へ" + "いいえ" + "後で" + "OK" + "コンテキストメニューを開く" + "設定" + "他のアプリで開く" + "ピン留め" + "クイック返信" + "引用" + "リアクション" + "拒否" + "削除" + "キャプションを削除" + "メッセージを削除" + "返信" + "スレッドで返信" + "報告" + "バグを報告" + "コンテンツを報告" + "会話を通報" + "ルームを通報" + "リセット" + "IDをリセット" + "再試行" + "復号化を再試行" + "保存" + "検索" + "すべて選択" + "送信" + "編集したメッセージを送信" + "メッセージを送信" + "音声メッセージを送信" + "共有" + "リンクを共有" + "ライブ位置情報を共有" + "表示" + "再度サインイン" + "この端末を削除" + "強制的に削除" + "スキップ" + "開始" + "チャットを開始" + "やり直す" + "検証を開始" + "タップして地図を読み込む" + "停止" + "写真を撮影" + "タップしてオプションを表示" + "翻訳" + "もう一度やり直してください" + "ピン留めを解除" + "表示" + "タイムラインで表示" + "ソースコードを表示" + "はい" + "再試行する" + "使用しているサーバーがより高速な新しいプロトコルに対応しました。将来、古いプロトコルへの対応が打ち切られ、強制的にログアウトされる可能性があるため、今すぐにログアウトし、再度ログインし直すことを推奨します。" + "アップグレードがあります" + "アプリケーションについて" + "利用規定" + "アカウントを追加" + "別のアカウントを追加" + "キャプションを追加" + "高度な設定" + "画像" + "分析" + "通知を同期中…" + "あなたがルームを退出" + "セッションからログアウトされました" + "外観" + "音声" + "ベータ版" + "ブロックしたユーザー" + "ふきだし" + "通話を開始しました" + "チャットをバックアップ" + "クリップボードにコピーしました" + "著作権" + "ルームを作成中…" + "スペースを作成中…" + "リクエストはキャンセルされました" + "ルームを退出しました" + "スペースから退出しました" + "招待は却下されました" + "ダーク" + "復号化エラー" + "詳細" + "開発者向けオプション" + "端末ID" + "ダイレクトチャット" + "次回からは表示しない" + "ダウンロードに失敗しました" + "ダウンロード中" + "(編集済み)" + "編集中" + "キャプションを編集" + "* %1$s %2$s" + "空のファイル" + "暗号化" + "暗号化が有効です" + "%1$s に終了" + "PINを入力してください" + "エラー" + "問題が発生しました。新着のメッセージの通知を受け取れない可能性があります。設定から通知のトラブルシューティングを行ってください。 + +理由: %1$s" + "全員" + "失敗" + "お気に入り" + "お気に入り" + "ファイル" + "ファイルを削除しました" + "ファイルを保存しました" + "ファイルはダウンロードに保存されました" + "メッセージを転送" + "頻繁に使用" + "GIF" + "画像" + "%1$s に返信" + "APK をインストール" + "このMatrix IDは見つからないため、招待が届かない可能性があります。" + "ルームを退出しています" + "スペースを退出しています" + "ライト" + "行をクリップボードにコピーしました" + "リンクをクリップボードにコピーしました" + "新しい端末から接続" + "ライブ位置情報" + "ライブ位置情報が終了しました" + "読み込み中…" + "読み込み中…" + + "他 %d 人" + + + "%1$d 人のメンバー" + + "メッセージ" + "メッセージアクション" + "メッセージの送信に失敗" + "メッセージのレイアウト" + "メッセージは削除されました" + "モダン" + "ミュート" + "名前" + "%1$s (%2$s)" + "結果なし" + "ルーム名なし" + "スペース名なし" + "暗号化されていません" + "オフライン" + "オープンソースライセンス" + "または" + "他のオプション" + "パスワード" + "人" + "固定リンク" + "権限" + "ピン留め" + "インターネット接続を確認してください" + "お待ちください…" + "本当に投票を終了しますか?" + "投票: %1$s" + "総投票数:%1$s" + "結果は投票終了後に表示されます" + + "%d 票" + + "準備中…" + "プライバシーポリシー" + "非公開" + "非公開ルーム" + "非公開スペース" + "公開" + "公開ルーム" + "公開スペース" + "リアクション" + "リアクション" + "理由" + "回復鍵" + "更新中…" + "削除しています…" + + "%1$d 件の返信" + + "%1$s に返信" + "バグを報告" + "問題を報告" + "報告は送信されました" + "リッチテキストエディター" + "役割" + "ルーム" + "ルーム名" + "例: プロジェクトの名称" + + "%1$d 個のルーム" + + "保存された変更" + "保存中…" + "画面ロック" + "ユーザーを検索" + "検索結果" + "セキュリティ" + "既読" + "アカウントを選択" + + "%1$d 個を選択" + + "送る:" + "送信中…" + "送信失敗" + "送信済" + "。" + "このサーバーには対応していません" + "サーバーに接続できません" + "サーバー URL" + "設定" + "スペースを共有" + "新しいメンバーは履歴を閲覧できます" + "共有したライブ位置情報" + "共有された位置情報" + "共有されたスペース" + "端末を削除中" + "問題が発生しました" + "問題が発生しました。再度お試しください。" + "スペース" + "スペースのメンバー" + "このスペースは何についてのものですか?" + + "%1$d 個のスペース" + + "チャットを開始しています…" + "ステッカー" + "成功" + "推奨される" + "提案" + "同期中" + "システム" + "テキスト" + "第三者に関する通知" + "スレッド" + "スレッド" + "トピック" + "何についてのルームですか?" + "復号化できません" + "安全でないデバイスから送信されました" + "このメッセージにアクセスできません" + "送信者の検証済みのデジタルIDがリセットされました" + "1人以上のユーザーに招待を送信できませんでした。" + "招待を送信できません" + "ロック解除" + "ミュート解除" + "非対応の通話" + "非対応のイベント" + "ユーザー名" + "検証がキャンセルされました" + "検証完了" + "検証に失敗しました" + "検証済み" + "端末を検証" + "IDを検証" + "ユーザーの検証" + "動画" + "高画質" + "高画質・ファイルサイズ大" + "低画質" + "最速アップロード・ファイルサイズ小" + "標準画質" + "中程度の画質とアップロード速度" + "音声メッセージ" + "待機中…" + "メッセージを待機中" + "ライブ位置情報を待機中…" + "誰でも履歴を閲覧できます" + "あなた" + "あなたが参加する以前に送信されたメッセージを、%1$s (%2$s) が共有しました。" + "あなたが参加する以前に送信されたメッセージを、%1$s が共有しました。" + "このルームは新しいメンバーが過去の内容を確認できるように設定されています。%1$s" + "%1$s のデジタルIDはリセットされました。%2$s" + "%1$s の %2$s のデジタルIDはリセットされました。%3$s" + "(%1$s)" + "%1$s のデジタルIDはリセットされました。" + "%1$s %2$s のデジタルIDはリセットされました。%3$s" + "検証のリクエストを却下" + "アクセスを許可" + "リンク %1$s が別サイト %2$s に遷移しようとしています。 + +続行しますか?" + "リンクを再度確認してください" + "アップロードする動画のデフォルト画質を選択してください。" + "動画のアップロード品質" + "アップロードできる最大サイズは %1$s です。" + "アップロードの許容サイズを超えています。" + "ルームを通報しました" + "ルームを通報し退出" + "確認" + "エラー" + "成功" + "警告" + "未保存の変更内容があります。" + "変更は保存されていません。本当に戻りますか?" + "変更を保存しますか?" + "アップロードできる最大サイズは %1$s です。" + "アップロードする画質を選択してください。" + "動画のアップロード品質を選択" + "絵文字を検索" + "この端末では既に %1$s としてログインしています。" + "Matrix Authentication Service とアカウント作成に対応するため、このホームサーバーはアップグレードが必要です。" + "固定リンクの作成に失敗しました" + "%1$s でマップを読み込めません。時間を置いて再度お試しください。" + "メッセージの読み込みに失敗しました" + "%1$s は現在地にアクセスできませんでした。時間を置いて再度お試しください。" + "音声メッセージの送信に失敗しました。" + "このルームは存在しないか、招待が無効です。" + "位置情報に基づく機能を使用するには、GPSを有効化してください。" + "メッセージが見つかりません" + "現在地を取得する権限が %1$s にありません。設定で権限を追加できます。" + "現在地を取得する権限が %1$s にありません。以下から許可してください。" + "%1$s には、マイクの使用が許可されていません。音声メッセージのために、マイクの使用を許可してください。" + "ネットワークまたはサーバーの問題である可能性があります。" + "このルームアドレスは既に存在しています。ルームの名称を変更するか、アドレスを編集してください。" + "一部の文字は使用できません。使用できるのは、英字、数字と記号 ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _ です。" + "送信されていないメッセージがあります。" + "申し訳ありません。エラーが発生しました。" + "🔐️ %1$s に参加してください" + "%1$s で話しましょう: %2$s" + "%1$s Android" + "開発者にバグを報告するには端末を振ってください。" + "スクリーンショット" + "%1$s: %2$s" + "選択肢" + "%1$s を削除" + "設定" + "ファイルの選択に失敗しました。再試行してください。" + "Element Classic を開く" + "Element Classic をこの端末で開く" + "「設定- セキュリティとプライバシー」に移動します" + "暗号鍵の管理から、暗号化されたメッセージの回復を選択します" + "指示に従って、鍵の保管庫を有効化してください" + "%1$s に戻ってください" + "%1$s に続行する前に、鍵の保管庫を有効化してください" + "アカウントを確認中" + "おかえりなさい" + "メッセージを長押しし \"%1$s\" を選択してください" + "重要なメッセージをピン留めして容易に見つけられるようにします" + + "%1$d 個のピン留めされたメッセージ" + + "ピン留めされたメッセージ" + "デジタルIDをリセットするため %1$s のアカウントの設定に移動します。完了後、アプリに遷移します。" + "認証できませんか?アカウントに移動してデジタルIDをリセットできます。" + "検証の要求を取り下げて送信" + "検証の要求を取り下げてメッセージの送信を続行するか、送信をキャンセルして %1$s の検証が完了した後に再試行することができます。" + "%1$s の検証済みのデジタルIDがリセットされたため、メッセージは送信されませんでした。" + "メッセージを強制送信" + "%1$s は未検証の端末を使用しています。メッセージを強制的に送信するか、%2$s がすべての端末を検証した後に送信を再試行することができます。" + "%1$s に未検証の端末が存在するため、メッセージは送信されませんでした。" + "検証の完了していない端末があります。メッセージを強制的に送信するか、すべての端末を検証した後に送信を再試行することができます。" + "未検証の端末が存在するため、メッセージは送信されませんでした。" + "管理者または所有者を編集" + "ファイルの処理に失敗しました。再試行してください。" + "ユーザーの詳細を取得できませんでした" + "%1$s のメッセージ" + "展開" + "縮小" + "ライブ位置情報を共有中" + "すでにこのルームを表示しています" + "%2$s 個のうち %1$s" + "%1$s 個のピン留めされたメッセージ" + "メッセージを読み込み中…" + "すべて表示" + "チャット" + "場所を共有" + "現在地を共有する" + "Apple Maps で開く" + "Google Maps で開く" + "OpenStreetMapで開く" + "この位置情報を共有する" + "共有設定" + "作成または参加したスペースです。" + "%1$s・%2$s" + "スペースを作成してルームを整頓しましょう" + "%1$s スペース" + "スペース" + "%1$s 共有" + "マップ上" + "%1$s の検証済みのデジタルIDがリセットされたため、メッセージは送信されませんでした。" + "%1$s に未検証の端末が存在するため、メッセージは送信されませんでした。" + "未検証の端末が存在するため、メッセージは送信されませんでした。" + "位置情報" + "バージョン: %1$s (%2$s)" + "ja" + "この端末で過去のメッセージを表示できません" + "過去のメッセージを表示するには、この端末を検証する必要があります" + "このメッセージにアクセスできません" + "メッセージの復号化に失敗" + "この端末を検証していないか、送信者があなたのデジタルIDを検証していないため、このメッセージはブロックされました。" + diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index bd6eaab990..6812885c9c 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -1,6 +1,7 @@ "Dodaj reakcję: %1$s" + "Adres" "Awatar" "Zmniejsz pole tekstowe wiadomości" "Usuń" @@ -27,6 +28,7 @@ "Wstrzymaj" "Wiadomość głosowa, czas trwania: %1$s, aktualna pozycja: %2$s" "Pole PIN" + "Przypięta lokalizacja" "Odtwórz" "Ankieta" "Zakończona ankieta" @@ -148,8 +150,8 @@ "Wyślij edytowaną wiadomość" "Wyślij wiadomość" "Wyślij wiadomość głosową" - "Udostępnij" - "Udostępnij link" + "Wyślij" + "Wyślij link" "Pokaż" "Zaloguj się ponownie" "Wyloguj" 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 e03a51eeb3..5e4d7f9b67 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -52,6 +52,7 @@ "Требуется действие, на которое есть ограничение по времени, у вас есть одна минута для проверки" "Показать пароль" "Начать звонок" + "Начать видеозвонок" "Начать голосовой вызов" "Брошенная комната" "Аватар пользователя" @@ -143,7 +144,7 @@ "Удалить подпись" "Удалить сообщение" "Ответить" - "Ответить в ветке" + "Обсудить" "Пожаловаться" "Сообщить об ошибке" "Пожаловаться на содержание" @@ -382,7 +383,8 @@ "Системное" "Текст" "Уведомления о третьих лицах" - "Ветка" + "Обсуждение" + "Обсуждения" "Тема" "О чем эта комната?" "Невозможно расшифровать" @@ -475,6 +477,13 @@ "Удалить %1$s" "Настройки" "Не удалось выбрать медиа, попробуйте еще раз." + "Открыть Element Classic" + "Откройте Element Classic на своем устройстве." + "Перейдите в Настройки > Безопасность и конфиденциальность" + "В разделе «Управление криптографическими ключами» выбери «Восстановление зашифрованных сообщений»" + "Следуйте инструкциям, чтобы активировать хранилище ключей" + "Вернитесь к %1$s" + "Перед продолжением активируйте хранилище ключей %1$s" "С возвращением" "Нажмите на сообщение и выберите «%1$s», чтобы добавить его сюда." "Закрепите важные сообщения, чтобы их можно было легко найти" @@ -488,7 +497,7 @@ "Не можете подтвердить? Перейдите в свой аккаунт, чтобы сбросить свою личность." "Сбросить верификацию и отправить" "Вы можете либо сбросить подтверждение и всё равно отправить это сообщение, либо отменить его сейчас и повторить попытку после повторного подтверждения %1$s." - "Ваше сообщение не было отправлено, потому что подтвержденная личность %1$s была сброшена" + "Ваше сообщение не было отправлено, потому что подтвержденная идентификации %1$s была сброшена" "Все равно отправить сообщение" "У %1$s есть одно или несколько неподтвержденных устройств. Вы все равно можете отправить сообщение или отменить его пока и повторить попытку позже, когда %2$s подтвердить все свои устройства." "Ваше сообщение не было отправлено, потому что %1$s имеет неподтвержденные устройства" @@ -500,6 +509,7 @@ "Сообщение в %1$s" "Развернуть" "Уменьшить" + "Поделиться текущим местоположением…" "Эта комната уже просматривается!" "%1$s из %2$s" "%1$s закрепленные сообщения" @@ -520,7 +530,7 @@ "Пространства" "Поделился %1$s" "На карте" - "Сообщение не отправлено, потому что подтвержденная личность %1$s была сброшена." + "Сообщение не отправлено, так как подтвержденная цифровая идентичность %1$s была сброшена." "Сообщение не отправлено, потому что %1$s не подтвердил(а) все свои устройства." "Сообщение не отправлено, поскольку вы не подтвердили одно или несколько своих устройств." "Местоположение" @@ -530,5 +540,5 @@ "Вам необходимо подтвердить это устройство чтобы получить доступ к истории сообщений" "Вы не имеете доступа к этому сообщению" "Не удалось расшифровать сообщение" - "Это сообщение было заблокировано, так как вы не подтвердили свое устройство, либо отправителю необходимо подтвердить вашу личность." + "Это сообщение было заблокировано либо потому, что вы не подтвердили свое устройство, либо потому, что отправителю необходимо подтвердить вашу цифровую личность." diff --git a/libraries/ui-strings/src/main/res/values-vi/translations.xml b/libraries/ui-strings/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..1cc07bb8cf --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -0,0 +1,425 @@ + + + "Thêm biểu cảm: %1$s" + "Địa chỉ" + "Ảnh đại diện" + "Thu nhỏ ô nhập tin nhắn" + "Xóa" + + "Đã nhập %1$d chữ số" + + "Đổi ảnh đại diện" + "Đường dẫn đầy đủ của phòng là %1$s" + "Chi tiết mã hóa" + "Mở rộng ô nhập tin nhắn" + "Ẩn mật khẩu" + "Tham gia cuộc gọi" + "Xuống cuối" + "Di chuyển bản đồ đến vị trí của tôi" + "Chỉ khi được đề cập tới" + "Tắt thông báo" + "Đề cập mới" + "Tin nhắn mới" + "Cuộc gọi hiện thời" + "Ảnh đại diện của người dùng khác" + "Trang %1$d" + "Tạm dừng" + "Tin nhắn thoại, thời lượng: %1$s, vị trí hiện tại: %2$s" + "Trường mã PIN" + "Vị trí được ghim" + "Phát" + "Tốc độ phát" + "Bỏ phiếu" + "Đã kết thúc cuộc thăm dò" + "Mã QR" + "Phản ứng với %1$s" + "Phản ứng với các biểu tượng cảm xúc khác" + "Đọc bởi %1$s và %2$s" + + "%1$s và %2$d người khác đã đọc." + + "Đọc bởi %1$s" + "Nhấn để hiển thị tất cả" + "Xóa phản ứng: %1$s" + "Loại bỏ phản ứng với %1$s" + "Ảnh đại diện phòng" + "Gửi tệp" + "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 thoại" + "Phòng Tombstone" + "Ảnh đại diện của người dùng" + "Menu người dùng" + "Xem ảnh đại diện" + "Xem chi tiết" + "Tin nhắn thoại, thời lượng: %1$s" + "Ghi âm tin nhắn thoại" + "Dừng ghi" + "Ảnh đại diện của bạn" + "Đồng ý" + "Thêm chú thích" + "Thêm các phòng trò chuyện hiện có" + "Thêm vào dòng thời gian" + "Quay lại" + "Gọi" + "Hủy" + "Hủy ngay" + "Chọn ảnh" + "Xoá" + "Đóng" + "Xác minh hoàn tất" + "Xác nhận" + "Xác nhận mật khẩu" + "Tiếp tục" + "Chép" + "Sao chép chú thích" + "Chép liên kết" + "Sao chép liên kết đến tin nhắn" + "Chép văn bản" + "Tạo" + "Tạo phòng" + "Tạo không gian" + "Hủy kích hoạt" + "Vô hiệu hóa tài khoản" + "Từ chối" + "Từ chối và chặn" + "Xóa cuộc thăm dò" + "Bỏ chọn tất cả" + "Tắt" + "Hủy" + "Bỏ qua" + "Xong" + "Chỉnh sửa" + "Chỉnh sửa chú thích" + "Sửa cuộc thăm dò" + "Bật" + "Kết thúc cuộc thăm dò" + "Nhập mã PIN" + "Khám phá các không gian công cộng" + "Hoàn tất" + "Quên mật khẩu?" + "Chuyển tiếp" + "Quay lại" + "Đi tới vai trò và quyền" + "Vào cài đặt" + "Bỏ qua" + "Mời" + "Mời ai đó" + "Mời ai đó vào %1$s" + "Mời ai đó vào %1$s" + "Lời mời" + "Tham gia" + "Tìm hiểu thêm" + "Rời" + "Rời khỏi cuộc trò chuyện" + "Rời phòng" + "Rời space" + "Tải thêm" + "Quản lý tài khoản" + "Quản lý tài khoản và thiết bị" + "Quản lý thiết bị" + "Quản lý phòng trò chuyện" + "Tin nhắn" + "Thu nhỏ" + "Tiếp" + "Không" + "Không phải lúc này" + "OK" + "Mở context menu" + "Cài đặt" + "Mở bằng" + "Ghim" + "Trả lời nhanh" + "Trích dẫn" + "Phản ứng" + "Từ chối" + "Xoá" + "Xóa chú thích" + "Xóa tin nhắn" + "Trả lời" + "Trả lời trong thread" + "Báo cáo" + "Báo lỗi" + "Báo cáo nội dung" + "Báo cáo cuộc trò chuyện" + "Báo cáo phòng" + "Đặt lại" + "Đặt lại danh tính" + "Thử lại" + "Thử giải mã lại" + "Lưu" + "Tìm kiếm" + "Chọn tất cả" + "Gửi" + "Gửi tin nhắn đã chỉnh sửa" + "Gửi tin nhắn" + "Gửi tin nhắn thoại" + "Chia sẻ" + "Chia sẻ liên kết" + "Chia sẻ vị trí trong thời gian thực" + "Hiện" + "Đăng nhập lại" + "Gỡ bỏ thiết bị này" + "Vẫn gỡ bỏ thiết bị này" + "Bỏ qua" + "Bắt đầu" + "Bắt đầu trò truyện" + "Bắt đầu lại" + "Bắt đầu xác thực" + "Nhấn để tải bản đồ" + "Dừng" + "Chụp ảnh" + "Nhấn để hiện tùy chọn" + "Dịch" + "Thử lại" + "Bỏ ghim" + "Xem" + "Xem trong dòng thời gian" + "Xem mã nguồn" + "Có" + "Có, thử lại" + "Máy chủ của bạn hiện đã hỗ trợ một giao thức mới, nhanh hơn. Hãy đăng xuất và đăng nhập lại để nâng cấp ngay. Việc này sẽ giúp bạn tránh bị buộc đăng xuất khi giao thức cũ bị loại bỏ sau này." + "Có thể nâng cấp" + "Giới thiệu" + "Quy định sử dụng dịch vụ" + "Thêm tài khoản" + "Thêm tài khoản khác" + "Thêm chú thích" + "Cài đặt nâng cao" + "một hình ảnh" + "Phân tích" + "Đang đồng bộ thông báo…" + "Bạn rời phòng" + "Bạn đã bị đăng xuất" + "Giao diện" + "Âm thanh" + "Thử nghiệm" + "Người dùng bị chặn" + "Bong bóng" + "Cuộc gọi bắt đầu" + "Sao lưu cuộc trò chuyện" + "Đã sao chép" + "Bản quyền" + "Đang tạo phòng…" + "Tạo không gian…" + "Yêu cầu bị hủy bỏ" + "Đã rời khỏi phòng" + "Rời khỏi không gian" + "Lời mời bị từ chối" + "Tối" + "Lỗi khi giải mã" + "Mô tả" + "Tùy chọn nhà phát triển" + "ID thiết bị" + "Chat trực tiếp" + "Không hiển thị lại" + "Tải xuống thất bại" + "Đang tải xuống" + "(đã sửa)" + "Đang chỉnh sửa" + "Chỉnh sửa chú thích" + "*%1$s%2$s" + "Tệp trống." + "Mã hóa" + "Đã bật mã hoá" + "Kết thúc lúc %1$s" + "Nhập mã PIN của bạn" + "Lỗi" + "Đã xảy ra lỗi, bạn có thể không nhận được thông báo cho tin nhắn mới. Vui lòng khắc phục sự cố thông báo trong phần cài đặt. + +Lý do: %1$s ." + "Mọi người" + "Thất bại" + "Yêu thích" + "Được yêu thích" + "Tập tin" + "Tệp đã bị xóa" + "Tệp đã được lưu" + "Tệp đã được lưu vào thư mục Tải xuống" + "Chuyển tiếp tin nhắn" + "Thường được sử dụng" + "Ảnh động" + "Ảnh" + "Trả lời %1$s" + "Cài đặt APK" + "Không tìm thấy Matrix ID này, nên lời mời có thể chưa được nhận." + "Rời khỏi phòng" + "Rời khỏi không gian" + "Sáng" + "Đã sao chép dòng" + "Đã chép liên kết vào bộ nhớ tạm" + "Liên kết thiết bị mới" + "Vị trí trong thời gian thực" + "Chia sẻ vị trí trực tiếp đã kết thúc" + "Đang tải" + "Đang tải thêm…" + + "%d người khác" + + + "%1$d số thành viên" + + "Tin nhắn" + "Thao tác tin nhắn" + "Không gửi được tin nhắn" + "Bố cục tin nhắn" + "Tin nhắn bị xoá" + "Hiện đại" + "Tắt tiếng" + "Tên" + "Không có kết quả" + "Không được mã hóa" + "Ngoại tuyến" + "hoặc" + "Mật khẩu" + "Danh bạ" + "Liên kết cố định" + "Quyền truy cập" + "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" + "Kết quả sẽ hiển thị sau khi cuộc thăm dò kết thúc" + + "%d lượt bình chọn" + + "Chính sách bảo mật" + "Phòng riêng tư" + "Biểu cảm" + "Cảm xúc" + "Khóa khôi phục." + "Đang làm mớ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" + "Phòng" + "Tên phòng" + "ví dụ: tên dự án của bạn" + "Đã lưu thay đổi" + "Đang lưu" + "Khóa màn hình" + "Tìm kiếm ai đó" + "Kết quả tìm kiếm" + "Bảo mật" + "Được xem bởi" + "Đang gửi…" + "Không gửi được" + "Đã gửi" + "Máy chủ không được hỗ trợ" + "Không thể kết nối với máy chủ" + "URL máy chủ" + "Cài đặt" + "Chia sẻ không gian" + "Thành viên mới có thể xem lịch sử." + "Chia sẻ vị trí trực tiếp" + "Vị trí được chia sẻ" + "Không gian chung" + "Đang gỡ thiết bị" + "Đã xảy ra sự cố" + "Đã xảy ra lỗi. Vui lòng thử lại." + "Không gian" + "Thành viên không gian" + "Không gian này dùng để làm gì?" + "Đang bắt đầu cuộc trò chuyện…" + "Sticker" + "Thành công" + "Gợi ý" + "Gợi ý" + "Đang đồng bộ" + "Hệ thống" + "Văn bản" + "Thông báo từ bên thứ ba" + "Chủ đề" + "Chủ đề" + "Chủ đề" + "Phòng này dùng để làm gì?" + "Không thể giải mã" + "Bạn không thể xem tin nhắn này" + "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" + "Bật tiếng" + "Cuộc gọi không được hỗ trợ" + "Sự kiện không được hỗ trợ" + "Tên người dùng" + "Đã hủy xác thực" + "Xác minh hoàn tất" + "Xác minh thất bại" + "Đã xác minh" + "Xác minh thiết bị" + "Xác minh danh tính" + "Xác minh người dùng" + "Video" + "Chất lượng cao" + "Chất lượng tốt nhất nhưng dung lượng tệp lớn hơn" + "Chất lượng thấp" + "Tốc độ tải lên nhanh nhất và kích thước tệp nhỏ nhất" + "Chất lượng tiêu chuẩn" + "Cân bằng giữa chất lượng và tốc độ tải lên" + "Tin nhắn thoại" + "Đang chờ…" + "Đang chờ tin nhắn này" + "Đang chờ vị trí trực tiếp…" + "Ai cũng có thể xem lịch sử" + "Bạn" + "%1$s (%2$s) đã chia sẻ tin nhắn này vì bạn không có trong phòng khi nó được gửi." + "%1$s đã chia sẻ tin nhắn này vì bạn không có trong phòng khi nó được gửi." + "Phòng chat này đã được thiết lập để các thành viên mới có thể xem lịch sử trò chuyện. %1$s" + "Danh tính số của %1$s đã được đặt lại. %2$s" + "Danh tính số %2$s của %1$s đã được đặt lại. %3$s" + "(%1$s )" + "Danh tính số của %1$s đã được đặt lại." + "Danh tính số %2$s của %1$s đã được đặt lại. %3$s" + "Hủy xác minh" + "Cho phép truy cập" + "Liên kết %1$s sẽ đưa bạn đến một trang khác %2$s + +Bạn có chắc muốn tiếp tục không?" + "Kiểm tra lại liên kết này" + "Chọn chất lượng mặc định cho video bạn tải lên." + "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" + "Xác nhận" + "Lỗi" + "Thành công" + "Cảnh báo" + "Bạn có thay đổi chưa được lưu." + "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?" + "Lưu thay đổi?" + "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" + "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." + "%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." + "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" + "Xin chào, hãy trò chuyện với tôi trên %1$s bằng đường liên kết sau: %2$s" + "%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." + "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" + "%1$s Tin nhắn được ghim" + "Chia sẻ vị trí" + "Chia sẻ vị trí của tôi" + "Mở trong Apple Maps" + "Mở trong Google Maps" + "Mở trong OpenStreetMap" + "Chia sẻ vị trí đã chọn" + "Vị trí" + "Phiên bản: %1$s (%2$s )" + "en" + "Bạn không thể xem tin nhắn này" + 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 44f7c1c1e6..1ce3a75ced 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -9,7 +9,7 @@ "已输入 %1$d 个数字" "编辑头像" - "完整地址为%1$s" + "完整地址为 %1$s" "加密详情" "展开消息文本框" "隐藏密码" @@ -26,11 +26,12 @@ "暂停" "语音消息,时长:%1$s,当前位置:%2$s" "PIN 字段" + "已钉住的位置" "播放" "播放速度" "投票" "投票已结束" - "QR 码" + "二维码" "使用 %1$s 回应" "使用其他表情符号回应" "%1$s 和 %2$s 已读" @@ -43,10 +44,12 @@ "移除表情符号%1$s" "房间头像" "发送文件" + "发送方位置" "限时操作,您有一分钟的时间来验证" "显示密码" "开始通话" - "墓碑聊天室" + "发起语音通话" + "已封存的聊天室" "用户头像" "用户菜单" "查看头像" @@ -122,7 +125,7 @@ "下一步" "否" "以后再说" - "好" + "确定" "打开上下文菜单" "打开设置" "用其他方式打开" @@ -154,10 +157,11 @@ "发送语音消息" "分享" "分享链接" + "共享实时位置" "显示" "再次登录" - "登出" - "仍然登出" + "删除此设备" + "仍要删除此设备" "跳过" "开始" "开始聊天" @@ -185,7 +189,7 @@ "一张图片" "分析" "你离开了聊天室" - "您已被注销当前会话" + "您已退出会话" "外观" "音频" "测试版" @@ -267,6 +271,7 @@ "离线" "开源许可证" "或" + "其他选项" "密码" "用户" "固定链接" @@ -276,7 +281,7 @@ "请稍候……" "确定要结束这个投票吗?" "投票:%1$s" - "总票数: %1$s" + "总票数:%1$s" "结果将在投票结束后显示" "%d 票" @@ -358,7 +363,7 @@ "无法解密" "从不安全的设备发送" "无权访问此消息" - "发送者的已验证身份已重置" + "发送者的已验证数字身份已重置" "无法向部分用户发送邀请。" "无法发送邀请" "解锁" @@ -388,12 +393,13 @@ "%1$s (%2$s) 由于您当时不在聊天室内,系统已将消息共享给您。" "%1$s 由于您当时不在聊天室内,系统已将此消息共享给您。" "本聊天室已配置为允许新成员阅读历史记录。%1$s" - "%1$s的身份已重置。%2$s" - "%1$s %2$s 的身份已重置。%3$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 确定要继续吗?" @@ -423,6 +429,7 @@ "%1$s 无法访问您的位置,请稍后再试。" "无法上传语音消息。" "该房间已不存在或邀请已失效。" + "请开启 GPS 以使用基于位置的功能。" "找不到消息" "%1$s 没有权限访问您的位置。您可以在设置中启用位置权限。" "%1$s 没有权限访问您的位置。在下方启用位置权限。" @@ -442,17 +449,18 @@ "移除%1$s" "设置" "选择媒体失败,请重试。" + "欢迎回来" "按下消息并选择 “%1$s” 将其包含在此处。" "固定重要消息,以便轻松发现它们" "%1$d 置顶消息" "置顶消息" - "您将要转到您的%1$s帐户来重置您的身份信息。之后,您将被带回该应用。" - "无法确认?请前往您的帐户重置您的身份。" + "您将要转到您的%1$s帐户来重置您的数字身份。之后,您将被带回该应用。" + "无法确认?请前往您的帐户重置您的数字身份。" "撤回验证并发送" "您可以撤回验证并仍然发送此消息;也可以暂时取消验证,在重新验证 %1$s 后重试。" - "您的消息未发送,因为%1$s的已验证身份已被重置" + "您的消息未发送,因为%1$s的已验证数字身份已被重置" "仍然发送消息" "%1$s 正在使用一个或多个未经验证的设备。您还是可以继续发送信息;也可以暂时取消,等 %2$s 验证了所有设备后重试。" "您的消息未发送,因为%1$s尚未验证所有设备" @@ -475,13 +483,16 @@ "在 Apple Maps 中打开" "在 Google Maps 中打开" "在 OpenStreetMap 中打开" - "分享这个位置" + "分享选定的位置" + "共享选项" "您创建或加入的空间。" "%1$s • %2$s" "创建空间以组织聊天室" "%1$s空间" "空间" - "消息未发送,因为%1$s的已验证身份已被重置。" + "共享于%1$s" + "在地图上" + "消息未发送,因为%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 0c1be935ef..f91e3a85b0 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -50,6 +50,7 @@ "Time limited action required, you have one minute to verify" "Show password" "Start a call" + "Start a video call" "Start a voice call" "Tombstoned room" "User avatar" @@ -474,6 +475,7 @@ Are you sure you want to continue?" "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" @@ -498,6 +500,7 @@ Are you sure you want to continue?" "Message in %1$s" "Expand" "Reduce" + "Sharing live location" "Already viewing this room!" "%1$s of %2$s" "%1$s Pinned messages" diff --git a/plugins/src/main/kotlin/extension/locales.kt b/plugins/src/main/kotlin/extension/locales.kt index 1af7146681..650fbc4d72 100644 --- a/plugins/src/main/kotlin/extension/locales.kt +++ b/plugins/src/main/kotlin/extension/locales.kt @@ -22,6 +22,7 @@ val locales = setOf( "hu", "in", "it", + "ja", "ka", "ko", "lt", @@ -38,6 +39,7 @@ val locales = setOf( "uk", "ur", "uz", + "vi", "zh-rCN", "zh-rTW", ) diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png index 0d394678ce..f0e44135ec 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c50c374b59c957f4e007d9548c2e03ffb622fcba3de9bb0adb2e36336114263b -size 39053 +oid sha256:c7f97df762e010742fb2627a83e0939f4e190195200c53004412e01c6361cb43 +size 28480 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_3_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_3_de.png deleted file mode 100644 index f0e44135ec..0000000000 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c7f97df762e010742fb2627a83e0939f4e190195200c53004412e01c6361cb43 -size 28480 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png index 538acbb4fd..36358041e6 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:180a33d511c0bcea775972eb4c0f80856d40657d0683eaee67e3d9b58687ef3e -size 365444 +oid sha256:4f44887b6c1d8c3de4e1bc4ae42f3999b99db906062ba95df22c88a2951f10d1 +size 364996 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png index 7d0a21c3d6..dd1594478c 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2d3bbb762ad093c0e60d1bb1f838d078449a1f3d733771f35660c3bbe5b374b -size 370934 +oid sha256:335e62d5380a9f6eba40017ed5f8bcfde6bacc7aaf29995852bf2c9c38960a09 +size 370563 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png index de58d2b1bf..6f4a81b5bb 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29c9f1d6d7972e8fb27701407eeb6febae153e92e60ac21f60a5bcb01beeede8 -size 364778 +oid sha256:6b6a749b9aefbf37b9bb4d9edcbf91f857acc395344a58439079268c73eb173f +size 364271 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png index 40d6fe691b..bce9fe091c 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fb43a66477ee416f6e8bea4acdecea322fc9cac09c5cc4c8fe6644fdefe78df -size 366590 +oid sha256:caf04029d097a3fcd937ecee55381b15353ca70b180629f3cc6b35dcde671c45 +size 366135 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png index 9b074e7cae..77f972cdd8 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5aea70f07d78c618613628503eae01783fef2561e963e4249ab89813886ab8f4 -size 73530 +oid sha256:49de6907472a673c5b79ae0f20a9939f9f6786fc757b9e1ac96077be34557d06 +size 73249 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png index c5b0d39e9d..ac61252e96 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41a9554ef3d3c8a9cf0b2234335728528b212caf954086ac7f8767fe795ec0c0 -size 60076 +oid sha256:29a442ba2414d64a550f4bded4835e11daeff0bd55031689af7072fba0fadcfd +size 59788 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png index bcc10c35e7..e9b333dc05 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bf87c47d0cee012847b5f0a0264f6f4e4cb948f965ad28af58fa5dac6b7e3a6 -size 73133 +oid sha256:e5493a95039dae9babedde3214acbbff01c7b53a3b454251f234c6cdb09bbd35 +size 72797 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png index 7218918f91..03a3fc0a40 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abd564eae0efae348f0cafbb5749879b29f2d2b0a82eb645cd0db4e75ada4ff3 -size 81908 +oid sha256:e817846aa9983e8e38ba6c8ff29ec205636e7b9a72b461215c16eb06e22ceb0e +size 81614 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png index e3d9c74293..bef0dfd03d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aa1be60455968000254246a1b307c8336e2c8e36cee5122e159254adeacf78e -size 62919 +oid sha256:ddf5dbaf0ad4247513d38a34e89897d099daa8e3f6c0bf9495ac65dad0771f34 +size 62532 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png index af6d69fde2..9267d1cb6c 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bb0d795e03931704043807bedc666f129ca23aa60b2690957588b15c2a6b5ff -size 61770 +oid sha256:35b64678b72a2e2433d278f717d859dc6f53414db565ed325604e0911e8a7e4b +size 61375 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png index 33ff1188ae..a43cafd104 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a40c856d3959ea432fa4a5bc5624e10005d8f405c5b5c199acfa38c3107035c -size 67354 +oid sha256:59b8beb90fbe005555a4de1d67230362623ab9b715796abb3a223f028bf89d5a +size 66981 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png index b100db999d..1f186b58be 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:797c78b06b51daa6088b94f38e536d59b619340a270bf7a4f8cbbf08c6c44be8 -size 90472 +oid sha256:0ad07ef8db1754dadbca19207273bbbffc83a591b615c22a6d38fcb8322af072 +size 90155 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png index 2c0063362c..558f92c29b 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c431aa38578a656d8f1bf8f58d2fe8534772ed127c2ce102b377052b007306e -size 60994 +oid sha256:e130d13f832caaa3b4016c2a915610bde46f0d34e7b394d52ccfb96f367afa74 +size 60683 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png index 2141974bd3..0db525b4a1 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecddf9e9d5c75c2675235b5399d899cb8ae24383d32ea1bdf1899cb95fb8be54 -size 61138 +oid sha256:72db00abddd84b586596e1dc61fe89b27096fbc08ba82d23eaf703c5c83173fd +size 60746 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png index d0d960153f..b14578a682 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:beb5791aeff09f5e757c8f560cc9b705c208eb886462a840bfcab7d78e622c15 -size 69793 +oid sha256:926284ff1d11c483707b568100fbdc8382a1a61ba146a0ef23594089bb3038c8 +size 69406 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png index 22917ebb0f..340cea1e36 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3285a648f80647c159933a083458fefd4d7f59687b74baacfd4a8dc7296ff05 -size 60504 +oid sha256:2cf0dd833df3ace9700622b31f64513a3c76908d6651dbb0ffcc3b5a6a4dce9e +size 60201 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png index 632d13a773..ef613cf899 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f61101788599662175adfd0b8e3fffa7d0152db1019e8424b2a3011572d1a01 -size 73241 +oid sha256:164558c7d8cdd701a1d11e4f3df0448818a47eecb06024904e14c29651800f56 +size 72929 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png index 05dae33d65..a16f0aaf45 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7d5e0c9b9c13b2e3d1cdfb1cbd666ced079e0faf230febc2377b9e10fab58be -size 56519 +oid sha256:b801d74b3feee574ba81d9d2e270090c86e3c007daa9b96674c752e6428a5d9e +size 56175 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png index 2443e232c8..39c6f3f77f 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81030d66c1ddbdf113dd49ea1a566cff5e6591d4733d27925673a99ad2f413f8 -size 71646 +oid sha256:e088310a4666c06e55fa88ef9d209e24ff681f9caaf148b1f1cbf4e0a8954206 +size 71274 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png index 5b4f8dddd2..a906ed4d88 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c7ef69c814541c026cf01b4466cb10f8737db3f673e81dbb57d1e5e8902f972 -size 83116 +oid sha256:8ffff1b75987e4b692fbec95fdc6bac243fdfb741e24d56f2e0f3b05c1b9a9a2 +size 82793 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png index e6cd15541d..6ffea11e25 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:081a69d09ed70a4bbba08690df9dab86d4a10a980f1330b3b27943cb1c10dff5 -size 59746 +oid sha256:17b44b1796d438eb804fec2aa1935c9ef0fbac16b90c55ee57ae0393862391c8 +size 59342 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png index c8eec3eb85..0bcdff0b59 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:893e712436eafea1791ad4bde6ef16b6e8389ed6dfcf6f5cd206f4e5cb25b44a -size 58863 +oid sha256:467e422cef79f2be11df55814794472113b434822434301e52bdfd12c094deae +size 58453 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png index 23c18ff2f0..d28b54f3cc 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72906d598feb20fba5d764485aa54ec3b3eb49ba9574dea5f97fefe8a5519a45 -size 66137 +oid sha256:e15f573b4d081b17f91ad2e19cc4920063dad46755217145fb8b13288eb2ad3b +size 65754 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png index 29d057fff0..1e87d303a9 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb9602983bbbf519d40a602fd7670585cf376aeb9a72a95e6da4077aae2d340b -size 101576 +oid sha256:d80a1a50b289631c432e1247af2ec1a41a9cb233f4ef9c5f6c964784113ff401 +size 101387 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png index ba9ec7f709..7903b1ba42 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8e52bb1582b86c3ba756282de449d61c673d7750c35813a712061456f246e4a -size 57799 +oid sha256:157c70292051f5dd737f309b2bdadddbe6cbf7ec3b322a3c47b937edc4df72e0 +size 57461 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png index 6313c48a1e..a997076a87 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9da73f77e0e7aa91c0620b6714dcf81234939f42773ef2afeb6bd920af6d3593 -size 57852 +oid sha256:44df9e6774110798c72042f560bcc344a5b292f11cba5893190ad78513a8d07e +size 57468 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png index c115f5a9db..b198b87ff5 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ae4658c6ce320cf09ca92d8321736d5079e085d7d41791ff33a2811a48fe2da -size 68025 +oid sha256:8323ee0e5869c5408cc17476fb603af972fa570d1e6896bc063ce401f4d1582f +size 67617 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png index 0b321d53de..5515d78ee1 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ae8ddc2b5c7794bebb89110d9538c86f9ad90e1edc6df837b1710f19bd13aed -size 57175 +oid sha256:31e974364b144d6270b890bf7293ca84a8680105d3914d5d6d2c1fa766b463a1 +size 56853 diff --git a/screenshots/de/services.apperror.impl_AppErrorView_Day_0_de.png b/screenshots/de/services.apperror.api_AppErrorView_Day_0_de.png similarity index 100% rename from screenshots/de/services.apperror.impl_AppErrorView_Day_0_de.png rename to screenshots/de/services.apperror.api_AppErrorView_Day_0_de.png diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 326e4ae318..df612e28d9 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,87 +1,87 @@ // 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",20548,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20553,], ["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",20548,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20548,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20548,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20548,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20548,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20548,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20548,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20548,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20548,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20548,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20548,], +["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.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",20548,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20548,], +["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,], ["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",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20548,], +["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_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",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20548,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20548,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20548,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20548,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20548,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20548,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20548,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20548,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20548,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20548,], +["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,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20548,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20548,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20548,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20548,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20548,], +["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,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",20548,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20556,], ["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",20548,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20553,], ["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",20548,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20553,], ["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",20548,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20553,], ["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",20548,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20553,], ["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 +91,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","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20548,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20548,], +["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,], ["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",20548,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20553,], ["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 +133,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",20548,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20553,], ["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",20548,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20548,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20548,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20548,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20548,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20548,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20548,], +["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,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20548,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20548,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20548,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20548,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20548,], +["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_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -159,141 +159,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",20548,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20548,], +["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_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",20548,], +["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_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",20548,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20548,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20548,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20548,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20548,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20548,], +["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.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",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20548,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20548,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20548,], +["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.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",20548,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20548,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20548,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20548,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20548,], +["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,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20548,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20553,], ["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",20548,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20548,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20548,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20548,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20548,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20548,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20548,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20548,], +["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,], ["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",20548,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20548,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20548,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20548,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20548,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20548,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20548,], +["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.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","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20548,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20548,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20548,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20548,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20548,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20548,], +["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,], ["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",20548,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20548,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20548,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20548,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20548,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20548,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20548,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20548,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20548,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20548,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20548,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20548,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20548,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20548,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20548,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20548,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20548,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20548,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20548,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20548,], +["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,], ["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","",20548,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20548,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20548,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20548,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20548,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20548,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20548,], +["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,], ["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",20548,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20548,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20548,], +["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_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",20548,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20553,], ["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",20548,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20548,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20548,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20548,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20548,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20548,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20548,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20548,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20548,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20548,], +["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,], ["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 +308,19 @@ 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",20548,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20548,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20548,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20548,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20548,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20548,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20548,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20548,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20548,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20548,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20548,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20548,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20548,], +["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,], ["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 +328,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",20548,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20548,], +["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_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",20548,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20548,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20548,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20548,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20548,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20548,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20548,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20548,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20548,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20548,], +["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.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,48 +369,47 @@ 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",20548,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20548,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20548,], +["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.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",20548,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20548,], +["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,], ["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",20548,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20548,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20548,], -["features.home.impl.spaces_HomeSpacesView_Day_3_en","features.home.impl.spaces_HomeSpacesView_Night_3_en",20548,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20548,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20548,], +["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.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",20548,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20548,], +["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_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20548,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20548,], +["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_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",20548,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20548,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20548,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20548,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20548,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20548,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20548,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20548,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20548,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20548,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20548,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20548,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20548,], +["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,], ["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,], @@ -421,12 +420,12 @@ export const screenshots = [ ["libraries.designsystem.atomic.molecules_IconTitlePlaceholdersRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_IconTitlePlaceholdersRowMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_IconTitleSubtitleMolecule_Day_0_en","libraries.designsystem.atomic.molecules_IconTitleSubtitleMolecule_Night_0_en",0,], ["libraries.designsystem.theme.components_IconToggleButton_Toggles_en","",0,], -["appicon.element_Icon_en","",0,], ["appicon.enterprise_Icon_en","",0,], +["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",20548,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20548,], +["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,], ["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,], @@ -434,117 +433,117 @@ 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",20548,], +["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_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",20548,], +["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_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",20548,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20548,], +["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.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20548,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20548,], +["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,], ["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",20548,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20548,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20548,], +["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.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",20548,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20548,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20548,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20548,], +["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_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20548,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20548,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20548,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20548,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20548,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20548,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20548,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20548,], +["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.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",20548,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20548,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20548,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20548,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20548,], +["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,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20548,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20548,], +["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.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",20548,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20548,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20548,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20548,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20548,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20548,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20548,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20548,], +["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,], ["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",20548,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20548,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20548,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20548,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20548,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20548,], +["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.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",20548,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20553,], ["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,], @@ -599,43 +598,43 @@ 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",20548,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20553,], ["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",20548,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20548,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20548,], +["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,], ["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",20548,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20548,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20548,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20548,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20548,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20548,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20548,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20548,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20548,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20548,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20548,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20548,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20548,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20548,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20548,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20548,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20548,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20548,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20548,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20548,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20548,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20548,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20548,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20548,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20548,], +["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,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20548,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20548,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20548,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20548,], +["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,], ["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,], @@ -649,22 +648,22 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20548,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20548,], +["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.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",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20548,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20548,], +["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.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,], @@ -672,14 +671,14 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20548,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20548,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20553,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20553,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20548,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20553,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20548,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20553,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -693,7 +692,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",20548,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20553,], ["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,], @@ -702,7 +701,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",20548,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20553,], ["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,], @@ -711,23 +710,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20548,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20548,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20548,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20548,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20548,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20548,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20548,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20548,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20548,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20548,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20548,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20548,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20548,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20548,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20548,], +["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.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",20548,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20553,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -738,112 +737,112 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20548,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20548,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20548,], +["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.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",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20548,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20548,], +["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,], ["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",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20548,], +["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,], ["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",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20548,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20548,], +["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,], ["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",20548,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20548,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20548,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20548,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20548,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20548,], +["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,], ["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",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20548,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20548,], +["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.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",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20548,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20548,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20548,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20548,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20548,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20548,], +["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,], ["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",20548,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20548,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20548,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20548,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20548,], +["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_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",20548,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20548,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20548,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20548,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20548,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20548,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20548,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20548,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20548,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20548,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20548,], +["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_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,], @@ -857,215 +856,215 @@ 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","",20548,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20548,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20548,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20548,], +["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.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","",20548,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20548,], +["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_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",20548,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20548,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20548,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20548,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20548,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20548,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20548,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20548,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20548,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20548,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20548,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20548,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20548,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20548,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20548,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20548,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20548,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20548,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20548,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20548,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20548,], +["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.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",20548,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20548,], +["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.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",20548,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20548,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20548,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20548,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20548,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20548,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20548,], +["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,], ["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",20548,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20548,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20548,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20548,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20548,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20548,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20548,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20548,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20548,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20548,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20548,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20548,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20548,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20548,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20548,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20548,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20548,], +["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.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",20548,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20548,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20548,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20548,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20548,], +["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,], ["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",20548,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20548,], +["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.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20548,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20548,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20548,], -["features.roomdetails.impl_RoomDetails_0_en","",20548,], -["features.roomdetails.impl_RoomDetails_10_en","",20548,], -["features.roomdetails.impl_RoomDetails_11_en","",20548,], -["features.roomdetails.impl_RoomDetails_12_en","",20548,], -["features.roomdetails.impl_RoomDetails_13_en","",20548,], -["features.roomdetails.impl_RoomDetails_14_en","",20548,], -["features.roomdetails.impl_RoomDetails_15_en","",20548,], -["features.roomdetails.impl_RoomDetails_16_en","",20548,], -["features.roomdetails.impl_RoomDetails_17_en","",20548,], -["features.roomdetails.impl_RoomDetails_18_en","",20548,], -["features.roomdetails.impl_RoomDetails_19_en","",20548,], -["features.roomdetails.impl_RoomDetails_1_en","",20548,], -["features.roomdetails.impl_RoomDetails_20_en","",20548,], -["features.roomdetails.impl_RoomDetails_21_en","",20548,], -["features.roomdetails.impl_RoomDetails_22_en","",20548,], -["features.roomdetails.impl_RoomDetails_2_en","",20548,], -["features.roomdetails.impl_RoomDetails_3_en","",20548,], -["features.roomdetails.impl_RoomDetails_4_en","",20548,], -["features.roomdetails.impl_RoomDetails_5_en","",20548,], -["features.roomdetails.impl_RoomDetails_6_en","",20548,], -["features.roomdetails.impl_RoomDetails_7_en","",20548,], -["features.roomdetails.impl_RoomDetails_8_en","",20548,], -["features.roomdetails.impl_RoomDetails_9_en","",20548,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20548,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20548,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20548,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20548,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20548,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20548,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20548,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20548,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20548,], +["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.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",20548,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20548,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20548,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20548,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20548,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20548,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20548,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20548,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20548,], +["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.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",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20548,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20548,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20548,], +["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.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",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20548,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20548,], +["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,], ["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",20548,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20548,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20548,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20548,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20548,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20548,], +["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,], ["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,], @@ -1088,16 +1087,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20548,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20548,], +["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_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",20548,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20553,], ["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,], @@ -1105,118 +1104,118 @@ 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",20548,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20548,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20548,], -["appicon.enterprise_RoundIcon_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,], ["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",20548,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20548,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20548,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20548,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20548,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20548,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20548,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20548,], +["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,], ["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","",20548,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20553,], ["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","",20548,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20548,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20548,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20548,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20548,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20548,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20548,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20548,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20548,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20548,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20548,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20548,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20548,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20548,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20548,], +["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,], ["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,], @@ -1239,33 +1238,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",20548,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20548,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20548,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20548,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20548,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20548,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20548,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20548,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20548,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20548,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20548,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20548,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20548,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20548,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20548,], +["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.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",20548,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20548,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20548,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20548,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20548,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20548,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20548,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20548,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20548,], +["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,], ["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,], @@ -1275,107 +1274,107 @@ 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",20548,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20553,], ["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",20548,], +["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",20548,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20548,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20548,], +["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,], ["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",20548,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20553,], ["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",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20548,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20548,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20548,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20548,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20548,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20548,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20548,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20548,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20548,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20548,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20548,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20548,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20548,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20548,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20548,], +["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.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",20548,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20548,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20548,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20548,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20548,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20548,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20548,], +["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.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",20548,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20553,], ["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",20548,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20553,], ["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",20548,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20548,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20548,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20548,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20548,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20548,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20548,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20548,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20548,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20548,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20548,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20548,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20548,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20548,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20548,], +["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_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",20548,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20548,], +["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.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,], @@ -1387,16 +1386,16 @@ 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",20548,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20548,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20548,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20548,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20548,], +["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.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",20548,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20548,], +["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_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,], @@ -1406,18 +1405,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",20548,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20553,], ["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",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20548,], +["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_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,], @@ -1425,18 +1424,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",20548,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20548,], +["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_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",20548,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20548,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20548,], +["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_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",20548,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20548,], +["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_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,], @@ -1445,42 +1444,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",20548,], +["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_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",20548,], +["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_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",20548,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20553,], ["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","",20548,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20553,], ["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",20548,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20548,], +["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.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",20548,], +["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_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",20548,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20548,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20548,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20548,], +["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_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",20548,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20548,], +["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_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",20548,], +["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.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,], @@ -1489,8 +1488,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",20548,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20548,], +["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_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,], @@ -1505,8 +1504,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",20548,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20548,], +["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_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,], @@ -1529,85 +1528,85 @@ 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",20548,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20548,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20548,], +["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_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",20548,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20553,], ["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",20548,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20553,], ["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",20548,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20553,], ["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",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20548,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20548,], +["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,], ["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",20548,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20548,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20548,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20548,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20548,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20548,], +["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_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","",20548,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20553,], ["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",20548,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20548,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20548,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20548,], +["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.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",20548,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20553,], ["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",20548,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20553,], ["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",20548,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20548,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20548,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20548,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20548,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20548,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20548,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20548,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20548,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20548,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20548,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20548,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20548,], +["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.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",20548,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20548,], +["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.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",20548,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20553,], ["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,], From 6ffb047bacd9d8242094e4ded1b0944bbb086823 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 06:29:49 +0000 Subject: [PATCH 0109/1083] Update metro to v0.13.1 --- 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 2d438c844c..941d169f86 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.6.1" # DI -metro = "0.12.1" +metro = "0.13.1" # Auto service autoservice = "1.1.1" From 683b1fe9d576a4f8fe5ba6c9d8683d438d79f877 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 24 Feb 2026 16:37:03 +0100 Subject: [PATCH 0110/1083] Fix typo --- .../impl/screens/onboarding/classic/ElementClassicConnection.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt index f895dd781e..d0ebbb336f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt @@ -107,7 +107,7 @@ class DefaultElementClassicConnection( if (context.bindService(intentService, serviceConnection, BIND_AUTO_CREATE)) { Timber.tag(loggerTag.value).d("Binding returned true") } else { - // This happen when the app is not installed + // This happens when the app is not installed Timber.tag(loggerTag.value).d("Binding returned false") mutableStateFlow.emit(ElementClassicConnectionState.ElementClassicNotFound) } From 8c5caabed488e28ae725d515a185c1bce49d702b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Mar 2026 16:11:37 +0100 Subject: [PATCH 0111/1083] Sign in with Classic --- .../io/element/android/appnav/RootFlowNode.kt | 3 +- .../features/login/impl/LoginFlowNode.kt | 73 ++- .../login/impl/LoginFlowTransitionHandler.kt | 54 +++ .../impl/classic/ElementClassicConnection.kt | 382 ++++++++++++++++ .../features/login/impl/di/LoginModule.kt | 5 - .../features/login/impl/login/LoginHelper.kt | 11 +- .../ChooseAccountProviderPresenter.kt | 1 + .../impl/screens/classic/ClassicFlowNode.kt | 143 ++++++ .../screens/classic/ClassicFlowNodeHelper.kt | 78 ++++ .../impl/screens/classic/NavigationEvent.kt | 18 + .../LoginWithClassicEvent.kt | 7 +- .../LoginWithClassicNavigator.kt | 12 + .../loginwithclassic/LoginWithClassicNode.kt | 69 +++ .../LoginWithClassicPresenter.kt | 109 +++++ .../loginwithclassic/LoginWithClassicState.kt | 26 ++ .../LoginWithClassicStateProvider.kt | 41 ++ .../loginwithclassic/LoginWithClassicView.kt | 226 +++++++++ .../missingkeybackup/MissingKeyBackupEvent.kt | 12 + .../missingkeybackup/MissingKeyBackupNode.kt | 70 +++ .../MissingKeyBackupPresenter.kt | 45 ++ .../missingkeybackup/MissingKeyBackupState.kt | 13 + .../MissingKeyBackupStateProvider.kt | 26 ++ .../missingkeybackup/MissingKeyBackupView.kt | 92 ++++ .../impl/screens/classic/root/RootNode.kt | 30 ++ .../impl/screens/classic/root/RootView.kt | 41 ++ .../ConfirmAccountProviderPresenter.kt | 1 + .../loginpassword/LoginPasswordNode.kt | 11 +- .../loginpassword/LoginPasswordPresenter.kt | 20 +- .../impl/screens/onboarding/OnBoardingNode.kt | 2 + .../screens/onboarding/OnBoardingPresenter.kt | 7 +- .../screens/onboarding/OnBoardingState.kt | 3 +- .../onboarding/OnBoardingStateProvider.kt | 9 +- .../impl/screens/onboarding/OnBoardingView.kt | 89 ++-- .../classic/ElementClassicConnection.kt | 260 ----------- .../classic/LoginWithClassicPresenter.kt | 103 ----- .../classic/LoginWithClassicState.kt | 16 - .../classic/LoginWithClassicStateProvider.kt | 20 - .../res/drawable-xxhdpi/element_foss_logo.png | Bin 0 -> 13888 bytes .../res/drawable-xxhdpi/element_pro_logo.png | Bin 0 -> 26428 bytes .../impl/src/main/res/values/localazy.xml | 8 + .../login/impl/DefaultLoginEntryPointTest.kt | 2 + .../DefaultElementClassicConnectionTest.kt | 429 ++++++++++++++++++ .../classic/FakeElementClassicConnection.kt | 9 +- .../login/impl/classic/FakeServiceBinder.kt | 26 ++ .../features/login/impl/classic/Fixtures.kt | 39 ++ .../classic/ClassicFlowNodeHelperTest.kt | 278 ++++++++++++ .../FakeLoginWithClassicNavigator.kt | 18 + .../LoginWithClassicPresenterTest.kt | 293 ++++++++++++ .../MissingKeyBackupPresenterTest.kt | 55 +++ .../LoginPasswordPresenterTest.kt | 17 + .../onboarding/OnBoardingPresenterTest.kt | 31 +- .../classic/LoginWithClassicPresenterTest.kt | 214 --------- .../androidutils/service/ServiceBinder.kt | 33 ++ .../appyx/FaderOrSliderTransitionHandler.kt | 54 +++ .../components/avatar/BitmapAvatar.kt | 79 ++++ .../matrix/api/auth/ElementClassicSession.kt | 11 +- .../api/auth/MatrixAuthenticationService.kt | 15 + .../libraries/matrix/api/core/UserIdTest.kt | 20 + .../auth/RustMatrixAuthenticationService.kt | 72 ++- .../auth/FakeMatrixAuthenticationService.kt | 12 + tools/localazy/checkForbiddenTerms.py | 3 + tools/localazy/config.json | 2 + 62 files changed, 3120 insertions(+), 728 deletions(-) create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowTransitionHandler.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/NavigationEvent.kt rename features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/{onboarding/classic => classic/loginwithclassic}/LoginWithClassicEvent.kt (54%) create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNavigator.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicState.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicStateProvider.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupNode.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootNode.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootView.kt delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenter.kt delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicState.kt delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicStateProvider.kt create mode 100644 features/login/impl/src/main/res/drawable-xxhdpi/element_foss_logo.png create mode 100644 features/login/impl/src/main/res/drawable-xxhdpi/element_pro_logo.png create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt rename features/login/impl/src/test/kotlin/io/element/android/features/login/impl/{screens/onboarding => }/classic/FakeElementClassicConnection.kt (72%) create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeServiceBinder.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/Fixtures.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/FakeLoginWithClassicNavigator.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt delete mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenterTest.kt create mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/service/ServiceBinder.kt create mode 100644 libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/FaderOrSliderTransitionHandler.kt create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/BitmapAvatar.kt rename features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ConfirmingLoginWithElementClassic.kt => libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/ElementClassicSession.kt (56%) create mode 100644 libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/core/UserIdTest.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index 745ab390b2..0e458d3b9c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -252,7 +252,8 @@ class RootFlowNode( val transitionHandler = rememberDelegateTransitionHandler { navTarget -> when (navTarget) { is NavTarget.SplashScreen, - is NavTarget.LoggedInFlow -> backstackFader + is NavTarget.LoggedInFlow, + is NavTarget.NotLoggedInFlow -> backstackFader else -> backstackSlider } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt index 928d98c244..bc928a936f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt @@ -22,6 +22,7 @@ import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.operation.pop import com.bumble.appyx.navmodel.backstack.operation.push +import com.bumble.appyx.navmodel.backstack.operation.replace import com.bumble.appyx.navmodel.backstack.operation.singleTop import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Assisted @@ -30,9 +31,11 @@ import io.element.android.annotations.ContributesNode import io.element.android.compound.theme.ElementTheme import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.features.login.impl.classic.ElementClassicConnection import io.element.android.features.login.impl.qrcode.QrCodeLoginFlowNode import io.element.android.features.login.impl.screens.changeaccountprovider.ChangeAccountProviderNode import io.element.android.features.login.impl.screens.chooseaccountprovider.ChooseAccountProviderNode +import io.element.android.features.login.impl.screens.classic.ClassicFlowNode import io.element.android.features.login.impl.screens.confirmaccountprovider.ConfirmAccountProviderNode import io.element.android.features.login.impl.screens.createaccount.CreateAccountNode import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordNode @@ -63,9 +66,10 @@ class LoginFlowNode( private val oidcActionFlow: OidcActionFlow, @AppCoroutineScope private val appCoroutineScope: CoroutineScope, + private val elementClassicConnection: ElementClassicConnection, ) : BaseFlowNode( backstack = BackStack( - initialElement = NavTarget.OnBoarding, + initialElement = NavTarget.CheckClassicFlow, savedStateMap = buildContext.savedStateMap, ), buildContext = buildContext, @@ -103,7 +107,12 @@ class LoginFlowNode( sealed interface NavTarget : Parcelable { @Parcelize - data object OnBoarding : NavTarget + data object CheckClassicFlow : NavTarget + + @Parcelize + data class OnBoarding( + val showBackButton: Boolean, + ) : NavTarget @Parcelize data object QrCode : NavTarget @@ -123,7 +132,9 @@ class LoginFlowNode( data object SearchAccountProvider : NavTarget @Parcelize - data object LoginPassword : NavTarget + data class LoginPassword( + val initialLogin: String = "", + ) : NavTarget @Parcelize data class CreateAccount(val url: String) : NavTarget @@ -131,7 +142,31 @@ class LoginFlowNode( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.OnBoarding -> { + NavTarget.CheckClassicFlow -> { + val callback = object : ClassicFlowNode.Callback { + override fun navigateToOnBoarding(allowBackNavigation: Boolean) { + if (allowBackNavigation) { + backstack.push(NavTarget.OnBoarding(showBackButton = true)) + } else { + backstack.replace(NavTarget.OnBoarding(showBackButton = false)) + } + } + + override fun navigateToLoginPassword() { + backstack.push(NavTarget.LoginPassword()) + } + + override fun navigateToOidc(oidcDetails: OidcDetails) { + navigateToMas(oidcDetails) + } + + override fun navigateToCreateAccount(url: String) { + backstack.push(NavTarget.CreateAccount(url)) + } + } + createNode(buildContext, listOf(callback)) + } + is NavTarget.OnBoarding -> { val callback = object : OnBoardingNode.Callback { override fun navigateToSignUpFlow() { backstack.push( @@ -166,17 +201,22 @@ class LoginFlowNode( } override fun navigateToLoginPassword() { - backstack.push(NavTarget.LoginPassword) + backstack.push(NavTarget.LoginPassword()) } override fun onDone() { - callback.onDone() + if (navTarget.showBackButton) { + backstack.pop() + } else { + callback.onDone() + } } } val params = inputs() val inputs = OnBoardingNode.Params( accountProvider = params.accountProvider, loginHint = params.loginHint, + showBackButton = navTarget.showBackButton, ) createNode(buildContext, listOf(callback, inputs)) } @@ -191,7 +231,7 @@ class LoginFlowNode( } override fun navigateToLoginPassword() { - backstack.push(NavTarget.LoginPassword) + backstack.push(NavTarget.LoginPassword()) } } createNode(buildContext, listOf(callback)) @@ -218,7 +258,7 @@ class LoginFlowNode( } override fun navigateToLoginPassword() { - backstack.push(NavTarget.LoginPassword) + backstack.push(NavTarget.LoginPassword()) } override fun navigateToChangeAccountProvider() { @@ -257,8 +297,11 @@ class LoginFlowNode( createNode(buildContext, plugins = listOf(callback)) } - NavTarget.LoginPassword -> { - createNode(buildContext) + is NavTarget.LoginPassword -> { + val inputs = LoginPasswordNode.Inputs( + initialLogin = navTarget.initialLogin, + ) + createNode(buildContext, plugins = listOf(inputs)) } is NavTarget.CreateAccount -> { val inputs = CreateAccountNode.Inputs( @@ -280,6 +323,14 @@ class LoginFlowNode( override fun View(modifier: Modifier) { activity = requireNotNull(LocalActivity.current) darkTheme = !ElementTheme.isLightTheme + + DisposableEffect(Unit) { + elementClassicConnection.start() + onDispose { + elementClassicConnection.stop() + } + } + DisposableEffect(Unit) { onDispose { activity = null @@ -288,6 +339,6 @@ class LoginFlowNode( } } } - BackstackView() + BackstackView(transitionHandler = rememberLoginFlowTransitionHandler()) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowTransitionHandler.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowTransitionHandler.kt new file mode 100644 index 0000000000..5486619e5d --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowTransitionHandler.kt @@ -0,0 +1,54 @@ +/* + * 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.login.impl + +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.Transition +import androidx.compose.animation.core.spring +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.navigation.transition.ModifierTransitionHandler +import com.bumble.appyx.core.navigation.transition.TransitionDescriptor +import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.operation.Replace +import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackFader +import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackSlider +import io.element.android.libraries.architecture.appyx.rememberDelegateTransitionHandler + +/** + * A TransitionHandler that uses fade transition when OnBoarding is replacing the current screen, + * and slide transition for all other cases. + */ +private class LoginFlowTransitionHandler( + private val slider: ModifierTransitionHandler, + private val fader: ModifierTransitionHandler, +) : ModifierTransitionHandler() { + override fun createModifier( + modifier: Modifier, + transition: Transition, + descriptor: TransitionDescriptor + ): Modifier { + val useFader = descriptor.element is LoginFlowNode.NavTarget.OnBoarding && + descriptor.operation is Replace + val handler = if (useFader) fader else slider + return handler.createModifier(modifier, transition, descriptor) + } +} + +@Composable +fun rememberLoginFlowTransitionHandler(): ModifierTransitionHandler { + val slider = rememberBackstackSlider( + transitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) }, + ) + val fader = rememberBackstackFader( + transitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) }, + ) + return rememberDelegateTransitionHandler { + LoginFlowTransitionHandler(slider, fader) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt new file mode 100644 index 0000000000..5e838094d3 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -0,0 +1,382 @@ +/* + * 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.login.impl.classic + +import android.content.ComponentName +import android.content.Context.BIND_AUTO_CREATE +import android.content.Intent +import android.content.ServiceConnection +import android.graphics.Bitmap +import android.os.Bundle +import android.os.Handler +import android.os.IBinder +import android.os.Message +import android.os.Messenger +import android.os.RemoteException +import androidx.annotation.VisibleForTesting +import androidx.core.os.BundleCompat +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn +import io.element.android.features.login.impl.BuildConfig +import io.element.android.libraries.androidutils.service.ServiceBinder +import io.element.android.libraries.core.log.logger.LoggerTag +import io.element.android.libraries.core.uri.ensureProtocol +import io.element.android.libraries.di.annotations.AppCoroutineScope +import io.element.android.libraries.matrix.api.auth.ElementClassicSession +import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker +import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.api.core.UserId +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import timber.log.Timber + +interface ElementClassicConnection { + fun start() + fun stop() + fun requestSession() + fun requestAvatar(userId: UserId) + val stateFlow: StateFlow +} + +sealed interface ElementClassicConnectionState { + object Idle : ElementClassicConnectionState + object ElementClassicNotFound : ElementClassicConnectionState + object ElementClassicReadyNoSession : ElementClassicConnectionState + data class ElementClassicReady( + val elementClassicSession: ElementClassicSession, + val displayName: String?, + val avatar: Bitmap?, + ) : ElementClassicConnectionState + + data class Error(val error: String) : ElementClassicConnectionState +} + +private val loggerTag = LoggerTag("ECConnection") + +@ContributesBinding(AppScope::class) +@SingleIn(AppScope::class) +class DefaultElementClassicConnection( + private val serviceBinder: ServiceBinder, + @AppCoroutineScope + private val coroutineScope: CoroutineScope, + private val matrixAuthenticationService: MatrixAuthenticationService, + private val homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker, +) : ElementClassicConnection { + // Messenger for communicating with the service. + private var messenger: Messenger? = null + + // Target we publish for external service to send messages to IncomingHandler. + private val incomingMessenger: Messenger = Messenger(IncomingHandler()) + + // Flag indicating whether we have called bind on the service. + private var bound: Boolean = false + + /** + * Class for interacting with the main interface of the service. + */ + private val serviceConnection = object : ServiceConnection { + override fun onServiceConnected(className: ComponentName, service: IBinder) { + Timber.tag(loggerTag.value).d("onServiceConnected") + // This is called when the connection with the service has been + // established, giving us the object we can use to + // interact with the service. We are communicating with the + // service using a Messenger, so here we get a client-side + // representation of that from the raw IBinder object. + messenger = Messenger(service) + bound = true + // Request the data as soon as possible + requestSession() + } + + override fun onServiceDisconnected(className: ComponentName) { + Timber.tag(loggerTag.value).d("onServiceDisconnected") + // This is called when the connection with the service has been + // unexpectedly disconnected—that is, its process crashed. + messenger = null + bound = false + } + } + + override fun start() { + Timber.tag(loggerTag.value).w("start()") + coroutineScope.launch { + // Establish a connection with the service. We use an explicit + // class name because there is no reason to be able to let other + // applications replace our component. + try { + val intentService = Intent() + intentService.setComponent(getElementClassicComponent()) + if (serviceBinder.bindService(intentService, serviceConnection, BIND_AUTO_CREATE)) { + Timber.tag(loggerTag.value).d("Binding returned true") + } else { + // This happens when the app is not installed + Timber.tag(loggerTag.value).d("Binding returned false") + emitState(ElementClassicConnectionState.ElementClassicNotFound) + } + } catch (e: SecurityException) { + Timber.tag(loggerTag.value).e(e, "Can't bind to Service") + emitState(ElementClassicConnectionState.Error(e.localizedMessage.orEmpty())) + } + } + } + + override fun stop() { + Timber.tag(loggerTag.value).w("stop(): Unbinding (bound=$bound)") + if (bound) { + // Detach our existing connection. + serviceBinder.unbindService(serviceConnection) + bound = false + } + coroutineScope.launch { + emitState(ElementClassicConnectionState.Idle) + } + } + + override fun requestSession() { + Timber.tag(loggerTag.value).w("requestSession()") + coroutineScope.launch { + val finalMessenger = messenger + if (finalMessenger == null) { + Timber.tag(loggerTag.value).w("The messenger is null, can't request data") + // Do not emit error, else the regular on boarding flow will be displayed + // emitState(ElementClassicConnectionState.Error("The messenger is null, can't request data")) + } else { + try { + // Get the data + val msg = Message.obtain(null, MSG_GET_SESSION) + msg.replyTo = incomingMessenger + finalMessenger.send(msg) + } catch (e: RemoteException) { + // In this case the service has crashed before we could even + // do anything with it; we can count on soon being + // disconnected (and then reconnected if it can be restarted) + // so there is no need to do anything here. + Timber.tag(loggerTag.value).e(e, "RemoteException") + emitState(ElementClassicConnectionState.Error(e.localizedMessage.orEmpty())) + } + } + } + } + + override fun requestAvatar(userId: UserId) { + Timber.tag(loggerTag.value).w("requestAvatar()") + coroutineScope.launch { + val finalMessenger = messenger + if (finalMessenger == null) { + Timber.tag(loggerTag.value).w("The messenger is null, can't request extra data") + } else { + try { + // Get the data + val msg = Message.obtain(null, MSG_GET_AVATAR) + msg.data = Bundle().apply { + putString(KEY_USER_ID_STR, userId.value) + } + msg.replyTo = incomingMessenger + finalMessenger.send(msg) + } catch (e: RemoteException) { + // In this case the service has crashed before we could even + // do anything with it; we can count on soon being + // disconnected (and then reconnected if it can be restarted) + // so there is no need to do anything here. + Timber.tag(loggerTag.value).e(e, "RemoteException") + } + } + } + } + + private val mutableStateFlow = MutableStateFlow(ElementClassicConnectionState.Idle) + override val stateFlow = mutableStateFlow.asStateFlow() + + /** + * Handler of incoming messages from service. + */ + @Suppress("DEPRECATION") + inner class IncomingHandler : Handler() { + override fun handleMessage(msg: Message) { + Timber.tag(loggerTag.value).d("IncomingHandler handling message ${msg.what}") + when (msg.what) { + MSG_GET_SESSION -> onSessionReceived(msg.data) + MSG_GET_AVATAR -> onAvatarReceived(msg.data) + else -> { + Timber.tag(loggerTag.value).w("Received unknown message ${msg.what}") + super.handleMessage(msg) + } + } + } + } + + @VisibleForTesting + fun onSessionReceived(data: Bundle) { + // The data must be extracted from the bundle before we launch the coroutine, else the bundle will be emptied + val state = data.toElementClassicConnectionState() + coroutineScope.launch { + val updatedState = ensureHomeserverIsSupported(state) + emitState(updatedState) + } + } + + @VisibleForTesting + fun onAvatarReceived(data: Bundle) { + val currentState = stateFlow.value + if (currentState is ElementClassicConnectionState.ElementClassicReady) { + // Check that the userId is still the same + val userId = data.getString(KEY_USER_ID_STR) + if (userId != currentState.elementClassicSession.userId.value) { + Timber.tag(loggerTag.value).w( + "Received profile data for userId $userId but current" + + " userId is ${currentState.elementClassicSession.userId}, ignoring" + ) + } else { + val avatar = BundleCompat.getParcelable(data, KEY_USER_AVATAR_PARCELABLE, Bitmap::class.java) + val updatedState = currentState.copy( + avatar = avatar, + ) + coroutineScope.launch { + emitState(updatedState) + } + } + } else { + Timber.tag(loggerTag.value).w("Received profile data but current state is not ElementClassicReady: %s", currentState) + } + } + + private suspend fun ensureHomeserverIsSupported(state: ElementClassicConnectionState): ElementClassicConnectionState { + return if (state is ElementClassicConnectionState.ElementClassicReady) { + val elementXCanConnect = setOfNotNull( + // Try with the domain name first + state.elementClassicSession.userId.domainName?.ensureProtocol(), + // Then try with the resolved homeserver URL, if provided and distinct + state.elementClassicSession.homeserverUrl, + ).any { url -> + val isCompatible = homeServerLoginCompatibilityChecker.check(url) + .onFailure { + Timber.tag(loggerTag.value).w(it, "Failed to check compatibility with homeserver: $url") + } + .getOrNull() == true + if (isCompatible) { + Timber.tag(loggerTag.value).d("Found compatible homeserver URL: %s", url) + } else { + Timber.tag(loggerTag.value).w("Homeserver URL is not compatible: %s", url) + } + isCompatible + } + if (elementXCanConnect) { + state + } else { + Timber.tag(loggerTag.value).w("Cannot import session because the homeserver is not compatible with Element X") + ElementClassicConnectionState.Error("The homeserver is not compatible with Element X") + } + } else { + state + } + } + + private suspend fun emitState(state: ElementClassicConnectionState) { + when (state) { + is ElementClassicConnectionState.Error -> { + Timber.tag(loggerTag.value).w("Error: %s", state.error) + } + is ElementClassicConnectionState.ElementClassicReady -> { + Timber.tag(loggerTag.value).d("Ready state for user: %s", state.elementClassicSession.userId) + } + ElementClassicConnectionState.ElementClassicReadyNoSession -> { + Timber.tag(loggerTag.value).d("No session from Element Classic") + } + ElementClassicConnectionState.ElementClassicNotFound -> { + Timber.tag(loggerTag.value).d("Element Classic not found") + } + ElementClassicConnectionState.Idle -> { + Timber.tag(loggerTag.value).d("Idle") + } + } + // Also give the Element Classic session info to the MatrixAuthenticationService + matrixAuthenticationService.setElementClassicSession( + session = (state as? ElementClassicConnectionState.ElementClassicReady)?.elementClassicSession + ) + mutableStateFlow.emit(state) + } + + private fun getElementClassicComponent() = ComponentName( + BuildConfig.elementClassicPackage, + ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME, + ) + + private fun Bundle.toElementClassicConnectionState(): ElementClassicConnectionState { + val error = getString(KEY_ERROR_STR) + return if (error != null) { + ElementClassicConnectionState.Error(error) + } else { + val userId = getString(KEY_USER_ID_STR)?.takeIf { it.isNotEmpty() }?.let(::UserId) + if (userId == null) { + ElementClassicConnectionState.ElementClassicReadyNoSession + } else { + val secrets = getString(KEY_SECRETS_STR)?.takeIf { it.isNotEmpty() } + val roomKeysVersion = getString(KEY_ROOM_KEYS_VERSION_STR)?.takeIf { it.isNotEmpty() } + val homeserverUrl = getString(KEY_HOMESERVER_URL_STR)?.takeIf { it.isNotEmpty() } + val displayName = getString(KEY_USER_DISPLAY_NAME_STR)?.takeIf { it.isNotEmpty() } + val doesContainBackupKey = secrets != null && + roomKeysVersion != null && + matrixAuthenticationService.doSecretsContainBackupKey(userId, secrets, roomKeysVersion) + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = userId, + homeserverUrl = homeserverUrl, + secrets = secrets, + roomKeysVersion = roomKeysVersion, + doesContainBackupKey = doesContainBackupKey, + ), + displayName = displayName, + avatar = null, + ) + } + } + } + + // Everything in this companion object must match what is defined in Element Classic + companion object { + const val ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME = "im.vector.app.features.importer.ImporterService" + + // Command to the service to get the userId/displayName/secrets of a verified session. + const val MSG_GET_SESSION = 1 + + // Command to the service to get the avatar oor the session. + const val MSG_GET_AVATAR = 2 + + // Keys for the bundle returned from the service + const val KEY_ERROR_STR = "error" + const val KEY_USER_ID_STR = "userId" + const val KEY_HOMESERVER_URL_STR = "homeserverUrl" + const val KEY_USER_DISPLAY_NAME_STR = "displayName" + + /** + * Key to extract the secrets from the bundle, as a Json string. + * Json will have this format: + * { + * "cross_signing" : { + * "master_key" : "z8RUxnaAGu___REDACTED___k+BQL9o", + * "user_signing_key" : "baJHzA___REDACTED___xMLbSUAXw9QUzqms", + * "self_signing_key" : "DU0CvLtR2G/___REDACTED___dV/MONNq4nsQhM" + * }, + * "backup" : { + * "algorithm" : "m.megolm_backup.v1.curve25519-aes-sha2", + * "key" : "VzncmQ+UOV___REDACTED___patxDz7m0Nc", + * "backup_version" : "1" + * } + * } + */ + const val KEY_SECRETS_STR = "secrets" + const val KEY_ROOM_KEYS_VERSION_STR = "roomKeysVersion" + + // For the avatar + const val KEY_USER_AVATAR_PARCELABLE = "avatar" + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/di/LoginModule.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/di/LoginModule.kt index 12b9106b71..4523e6f45e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/di/LoginModule.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/di/LoginModule.kt @@ -14,8 +14,6 @@ import dev.zacsweers.metro.Binds import dev.zacsweers.metro.ContributesTo import io.element.android.features.login.impl.changeserver.ChangeServerPresenter import io.element.android.features.login.impl.changeserver.ChangeServerState -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicPresenter -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicState import io.element.android.libraries.architecture.Presenter @ContributesTo(AppScope::class) @@ -23,7 +21,4 @@ import io.element.android.libraries.architecture.Presenter interface LoginModule { @Binds fun bindChangeServerPresenter(presenter: ChangeServerPresenter): Presenter - - @Binds - fun bindLoginWithClassicPresenter(presenter: LoginWithClassicPresenter): Presenter } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt index a62919e705..78be770bfc 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt @@ -60,10 +60,19 @@ class LoginHelper( suspend fun submit( isAccountCreation: Boolean, homeserverUrl: String, + resolvedHomeserverUrl: String?, loginHint: String?, ) { suspend { - authenticationService.setHomeserver(homeserverUrl).map { matrixHomeServerDetails -> + authenticationService.setHomeserver(homeserverUrl).recoverCatching { + // No .well-known file? + // If the homeserver is not reachable, try using resolvedHomeserverUrl. + if (resolvedHomeserverUrl != null && resolvedHomeserverUrl != homeserverUrl) { + authenticationService.setHomeserver(resolvedHomeserverUrl).getOrThrow() + } else { + throw it + } + }.map { matrixHomeServerDetails -> if (matrixHomeServerDetails.supportsOidcLogin) { // Retrieve the details right now val oidcPrompt = if (isAccountCreation) OidcPrompt.Create else OidcPrompt.Login diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenter.kt index 87010a4a30..c6d6d76486 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenter.kt @@ -44,6 +44,7 @@ class ChooseAccountProviderPresenter( loginHelper.submit( isAccountCreation = false, homeserverUrl = it.url, + resolvedHomeserverUrl = null, loginHint = null, ) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt new file mode 100644 index 0000000000..8d79453318 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt @@ -0,0 +1,143 @@ +/* + * 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.login.impl.screens.classic + +import android.os.Parcelable +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.lifecycle.lifecycleScope +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.operation.newRoot +import com.bumble.appyx.navmodel.backstack.operation.pop +import com.bumble.appyx.navmodel.backstack.operation.push +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode +import io.element.android.features.login.impl.screens.classic.loginwithclassic.LoginWithClassicNode +import io.element.android.features.login.impl.screens.classic.missingkeybackup.MissingKeyBackupNode +import io.element.android.features.login.impl.screens.classic.root.RootNode +import io.element.android.libraries.architecture.BackstackView +import io.element.android.libraries.architecture.BaseFlowNode +import io.element.android.libraries.architecture.appyx.rememberFaderOrSliderTransitionHandler +import io.element.android.libraries.architecture.callback +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.core.UserId +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.parcelize.Parcelize + +@ContributesNode(AppScope::class) +@AssistedInject +class ClassicFlowNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val classicFlowNodeHelper: ClassicFlowNodeHelper, +) : BaseFlowNode( + backstack = BackStack( + initialElement = NavTarget.Root, + savedStateMap = buildContext.savedStateMap, + ), + buildContext = buildContext, + plugins = plugins, +) { + interface Callback : Plugin { + fun navigateToOnBoarding(allowBackNavigation: Boolean) + fun navigateToLoginPassword() + fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToCreateAccount(url: String) + } + + sealed interface NavTarget : Parcelable { + @Parcelize + data object Root : NavTarget + + @Parcelize + data class LoginWithClassic( + val userId: UserId, + ) : NavTarget + + @Parcelize + data object MissingKeyBackup : NavTarget + } + + private val callback: Callback = callback() + + override fun onBuilt() { + super.onBuilt() + observeElementClassicConnection() + } + + private fun observeElementClassicConnection() { + classicFlowNodeHelper.navigationEventFlow().onEach { navigationEvent -> + when (navigationEvent) { + is NavigationEvent.Idle -> Unit + is NavigationEvent.NavigateToOnBoarding -> callback.navigateToOnBoarding(allowBackNavigation = false) + is NavigationEvent.NavigateToLoginWithClassic -> backstack.newRoot(NavTarget.LoginWithClassic(navigationEvent.userId)) + } + }.launchIn(lifecycleScope) + } + + override fun resolve( + navTarget: NavTarget, + buildContext: BuildContext, + ): Node { + return when (navTarget) { + NavTarget.Root -> { + createNode(buildContext) + } + is NavTarget.LoginWithClassic -> { + val callback = object : LoginWithClassicNode.Callback { + override fun navigateToOtherOptions() { + callback.navigateToOnBoarding(allowBackNavigation = true) + } + + override fun navigateToLoginPassword() { + callback.navigateToLoginPassword() + } + + override fun navigateToOidc(oidcDetails: OidcDetails) { + callback.navigateToOidc(oidcDetails) + } + + override fun navigateToCreateAccount(url: String) { + callback.navigateToCreateAccount(url) + } + + override fun navigateToMissingKeyBackup() { + backstack.push(NavTarget.MissingKeyBackup) + } + } + val inputs = LoginWithClassicNode.Inputs( + userId = navTarget.userId, + ) + createNode(buildContext, plugins = listOf(inputs, callback)) + } + NavTarget.MissingKeyBackup -> { + val callback = object : MissingKeyBackupNode.Callback { + override fun navigateBack() { + backstack.pop() + } + } + createNode(buildContext, listOf(callback)) + } + } + } + + @Composable + override fun View(modifier: Modifier) { + BackstackView( + modifier = modifier, + transitionHandler = rememberFaderOrSliderTransitionHandler(), + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt new file mode 100644 index 0000000000..f719fe5083 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt @@ -0,0 +1,78 @@ +/* + * 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.login.impl.screens.classic + +import dev.zacsweers.metro.Inject +import io.element.android.features.login.impl.classic.ElementClassicConnection +import io.element.android.features.login.impl.classic.ElementClassicConnectionState +import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.sessionstorage.api.toUserListFlow +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.take + +@Inject +class ClassicFlowNodeHelper( + private val elementClassicConnection: ElementClassicConnection, + private val sessionStore: SessionStore, +) { + // Ensure user is not stuck on the loading screen. + // If Element Classic is taking too long to communicate (or crashes), unblock the user after a few seconds. + private val timeoutFLow = flow { + emit(false) + delay(5_000) + emit(true) + } + + fun navigationEventFlow(): Flow { + return combine( + timeoutFLow, + elementClassicConnection.stateFlow + .distinctUntilChangedBy { + // Ignore change on ElementClassicConnectionState.ElementClassicReady.avatar + if (it is ElementClassicConnectionState.ElementClassicReady) { + it.copy(avatar = null) + } else { + it + } + }, + sessionStore.sessionsFlow().toUserListFlow() + // Take only 1 emission of the sessions, else when the user actually logged in it will trigger a navigation to OnBoarding. + .take(1), + ) { timeout, elementClassicConnectionState, existingSessions -> + when (elementClassicConnectionState) { + ElementClassicConnectionState.Idle -> { + if (timeout) { + NavigationEvent.NavigateToOnBoarding + } else { + NavigationEvent.Idle + } + } + ElementClassicConnectionState.ElementClassicNotFound, + ElementClassicConnectionState.ElementClassicReadyNoSession, + is ElementClassicConnectionState.Error -> { + NavigationEvent.NavigateToOnBoarding + } + is ElementClassicConnectionState.ElementClassicReady -> { + if (elementClassicConnectionState.elementClassicSession.userId.value in existingSessions) { + NavigationEvent.NavigateToOnBoarding + } else { + // 2 cases when this can be run: + // First time this screen will be displayed + // Missing key backup screen was displayed, but the data has changed (user set up the key backup on Classic), + // and the app is resuming. + NavigationEvent.NavigateToLoginWithClassic(elementClassicConnectionState.elementClassicSession.userId) + } + } + } + } + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/NavigationEvent.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/NavigationEvent.kt new file mode 100644 index 0000000000..cddca0015b --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/NavigationEvent.kt @@ -0,0 +1,18 @@ +/* + * 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.login.impl.screens.classic + +import io.element.android.libraries.matrix.api.core.UserId + +sealed interface NavigationEvent { + data object Idle : NavigationEvent + data object NavigateToOnBoarding : NavigationEvent + data class NavigateToLoginWithClassic( + val userId: UserId, + ) : NavigationEvent +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicEvent.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt similarity index 54% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicEvent.kt rename to features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt index 75a9496a02..e3c6ed782d 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicEvent.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt @@ -5,11 +5,10 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.login.impl.screens.onboarding.classic +package io.element.android.features.login.impl.screens.classic.loginwithclassic sealed interface LoginWithClassicEvent { data object RefreshData : LoginWithClassicEvent - data object StartLoginWithClassic : LoginWithClassicEvent - data object DoLoginWithClassic : LoginWithClassicEvent - data object CloseDialog : LoginWithClassicEvent + data object Submit : LoginWithClassicEvent + data object ClearError : LoginWithClassicEvent } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNavigator.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNavigator.kt new file mode 100644 index 0000000000..55716c2cf7 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNavigator.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.classic.loginwithclassic + +interface LoginWithClassicNavigator { + fun navigateToMissingKeyBackup() +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt new file mode 100644 index 0000000000..c42248a3f8 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.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.login.impl.screens.classic.loginwithclassic + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode +import io.element.android.features.login.impl.util.openLearnMorePage +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.callback +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.core.UserId + +@ContributesNode(AppScope::class) +@AssistedInject +class LoginWithClassicNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + presenterFactory: LoginWithClassicPresenter.Factory, +) : Node(buildContext, plugins = plugins), + LoginWithClassicNavigator { + interface Callback : Plugin { + fun navigateToOtherOptions() + fun navigateToLoginPassword() + fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToCreateAccount(url: String) + fun navigateToMissingKeyBackup() + } + + data class Inputs( + val userId: UserId, + ) : NodeInputs + + private val inputs: Inputs = inputs() + val presenter = presenterFactory.create(inputs.userId, this) + private val callback: Callback = callback() + + override fun navigateToMissingKeyBackup() { + callback.navigateToMissingKeyBackup() + } + + @Composable + override fun View(modifier: Modifier) { + val context = LocalContext.current + val state = presenter.present() + LoginWithClassicView( + state = state, + modifier = modifier, + onOtherOptionsClick = callback::navigateToOtherOptions, + onOidcDetails = callback::navigateToOidc, + onNeedLoginPassword = callback::navigateToLoginPassword, + onLearnMoreClick = { openLearnMorePage(context) }, + onCreateAccountContinue = callback::navigateToCreateAccount, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt new file mode 100644 index 0000000000..6494ee741e --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt @@ -0,0 +1,109 @@ +/* + * 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.login.impl.screens.classic.loginwithclassic + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +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 dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.features.login.impl.classic.ElementClassicConnection +import io.element.android.features.login.impl.classic.ElementClassicConnectionState +import io.element.android.features.login.impl.login.LoginHelper +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.uri.ensureProtocol +import io.element.android.libraries.matrix.api.core.UserId +import kotlinx.coroutines.launch + +@AssistedInject +class LoginWithClassicPresenter( + @Assisted private val userId: UserId, + @Assisted private val navigator: LoginWithClassicNavigator, + private val loginHelper: LoginHelper, + private val elementClassicConnection: ElementClassicConnection, + private val accountProviderDataSource: AccountProviderDataSource, + private val buildMeta: BuildMeta, +) : Presenter { + @AssistedFactory + interface Factory { + fun create( + userId: UserId, + navigator: LoginWithClassicNavigator, + ): LoginWithClassicPresenter + } + + @Composable + override fun present(): LoginWithClassicState { + val coroutineScope = rememberCoroutineScope() + var loginWithClassicAction by remember { + mutableStateOf>(AsyncAction.Uninitialized) + } + val loginMode by loginHelper.collectLoginMode() + val elementClassicConnectionState by elementClassicConnection.stateFlow.collectAsState() + + fun handleEvent(event: LoginWithClassicEvent) { + when (event) { + LoginWithClassicEvent.RefreshData -> { + // Request the avatar if not known yet + val currentState = elementClassicConnection.stateFlow.value + if ((currentState as? ElementClassicConnectionState.ElementClassicReady)?.avatar == null) { + elementClassicConnection.requestAvatar(userId) + } + } + LoginWithClassicEvent.Submit -> { + val currentState = elementClassicConnection.stateFlow.value + if (currentState is ElementClassicConnectionState.ElementClassicReady) { + if (currentState.elementClassicSession.secrets != null && + !currentState.elementClassicSession.doesContainBackupKey) { + navigator.navigateToMissingKeyBackup() + } else { + coroutineScope.launch { + loginWithClassicAction = AsyncAction.Loading + // Ensure that the current account provider is set + val elementClassicUserId = currentState.elementClassicSession.userId + val accountProvider = elementClassicUserId.domainName.orEmpty().ensureProtocol() + accountProviderDataSource.setUrl(accountProvider) + loginHelper.submit( + isAccountCreation = false, + homeserverUrl = accountProvider, + resolvedHomeserverUrl = currentState.elementClassicSession.homeserverUrl, + loginHint = "mxid:" + elementClassicUserId.value, + ) + } + } + } else { + loginWithClassicAction = AsyncAction.Failure(IllegalStateException("Element Classic is not ready")) + } + } + LoginWithClassicEvent.ClearError -> { + loginWithClassicAction = AsyncAction.Uninitialized + loginHelper.clearError() + } + } + } + + val elementClassicReady = elementClassicConnectionState as? ElementClassicConnectionState.ElementClassicReady + return LoginWithClassicState( + isElementPro = buildMeta.isEnterpriseBuild, + userId = userId, + displayName = elementClassicReady?.displayName, + avatar = elementClassicReady?.avatar, + loginMode = loginMode, + loginWithClassicAction = loginWithClassicAction, + eventSink = ::handleEvent, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicState.kt new file mode 100644 index 0000000000..275a444768 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicState.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.classic.loginwithclassic + +import android.graphics.Bitmap +import androidx.compose.runtime.Stable +import io.element.android.features.login.impl.login.LoginMode +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.core.UserId + +@Stable +data class LoginWithClassicState( + val isElementPro: Boolean, + val userId: UserId, + val displayName: String?, + val avatar: Bitmap?, + val loginWithClassicAction: AsyncAction, + val loginMode: AsyncData, + val eventSink: (LoginWithClassicEvent) -> Unit, +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicStateProvider.kt new file mode 100644 index 0000000000..d8dcfeb072 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicStateProvider.kt @@ -0,0 +1,41 @@ +/* + * 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.login.impl.screens.classic.loginwithclassic + +import android.graphics.Bitmap +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.login.impl.login.LoginMode +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.core.UserId + +open class LoginWithClassicStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aLoginWithClassicState(), + aLoginWithClassicState(isElementPro = true, displayName = "Alice"), + ) +} + +fun aLoginWithClassicState( + isElementPro: Boolean = false, + userId: UserId = UserId("@alice:matrix.org"), + displayName: String? = null, + avatar: Bitmap? = null, + loginWithClassicAction: AsyncAction = AsyncAction.Uninitialized, + loginMode: AsyncData = AsyncData.Uninitialized, + eventSink: (LoginWithClassicEvent) -> Unit = {}, +) = LoginWithClassicState( + isElementPro = isElementPro, + userId = userId, + displayName = displayName, + avatar = avatar, + loginWithClassicAction = loginWithClassicAction, + loginMode = loginMode, + eventSink = eventSink, +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt new file mode 100644 index 0000000000..aeb61946ff --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt @@ -0,0 +1,226 @@ +/* + * 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.login.impl.screens.classic.loginwithclassic + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.res.painterResource +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 androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect +import io.element.android.compound.theme.ElementTheme +import io.element.android.features.login.impl.R +import io.element.android.features.login.impl.login.LoginModeView +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.background.OnboardingBackground +import io.element.android.libraries.designsystem.components.async.AsyncActionView +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.BitmapAvatar +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.OutlinedButton +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.testtags.testTag +import io.element.android.libraries.ui.strings.CommonStrings + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LoginWithClassicView( + state: LoginWithClassicState, + onOtherOptionsClick: () -> Unit, + onOidcDetails: (OidcDetails) -> Unit, + onNeedLoginPassword: () -> Unit, + onLearnMoreClick: () -> Unit, + onCreateAccountContinue: (url: String) -> Unit, + modifier: Modifier = Modifier, +) { + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + state.eventSink(LoginWithClassicEvent.RefreshData) + } + + val isLoading by remember(state.loginMode) { + derivedStateOf { + state.loginMode is AsyncData.Loading + } + } + + HeaderFooterPage( + modifier = modifier + .fillMaxSize() + .systemBarsPadding() + .imePadding(), + background = { OnboardingBackground() }, + isScrollable = true, + header = { + Column( + modifier = Modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Spacer(Modifier.height(40.dp)) + Box( + modifier = Modifier + .size(54.dp) + .shadow(elevation = 10.dp, shape = RoundedCornerShape(15.dp)) + .background(ElementTheme.colors.bgCanvasDefault, shape = RoundedCornerShape(15.dp)), + contentAlignment = Alignment.Center, + ) { + val resId = if (state.isElementPro) { + R.drawable.element_pro_logo + } else { + R.drawable.element_foss_logo + } + Image( + modifier = Modifier.size(37.5.dp), + painter = painterResource(id = resId), + contentDescription = null, + ) + } + Spacer(Modifier.height(8.dp)) + Text( + text = stringResource(id = R.string.screen_onboarding_welcome_title), + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontHeadingMdBold, + textAlign = TextAlign.Center, + ) + Spacer(Modifier.height(10.dp)) + } + }, + content = { + Column( + modifier = Modifier + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Spacer(Modifier.height(40.dp)) + BitmapAvatar( + avatarData = AvatarData( + id = state.userId.value, + name = state.displayName, + // Not used here + url = null, + size = AvatarSize.UserHeader, + ), + bitmap = state.avatar, + ) + Spacer(Modifier.height(24.dp)) + Text( + modifier = Modifier.padding(horizontal = 32.dp), + text = stringResource(R.string.screen_onboarding_welcome_back), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + // User display name + if (state.displayName != null) { + Text( + text = state.displayName, + style = ElementTheme.typography.fontHeadingLgBold, + color = ElementTheme.colors.textPrimary, + textAlign = TextAlign.Center, + ) + Spacer(Modifier.height(16.dp)) + } + // UserId + Text( + text = state.userId.value, + style = if (state.displayName == null) ElementTheme.typography.fontHeadingLgBold else ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textPrimary, + textAlign = TextAlign.Center, + ) + // Min spacing + Spacer(Modifier.height(45.dp)) + ButtonColumnMolecule { + Button( + text = stringResource(CommonStrings.action_continue), + showProgress = isLoading, + onClick = { + state.eventSink(LoginWithClassicEvent.Submit) + }, + modifier = Modifier + .fillMaxWidth() + .testTag(TestTags.loginContinue) + ) + OutlinedButton( + text = stringResource(CommonStrings.common_other_options), + onClick = onOtherOptionsClick, + enabled = !isLoading, + modifier = Modifier + .fillMaxWidth() + .testTag(TestTags.loginContinue) + ) + } + } + }, + footer = {}, + ) + + AsyncActionView( + async = state.loginWithClassicAction, + onErrorDismiss = { + state.eventSink(LoginWithClassicEvent.ClearError) + }, + onSuccess = { + // noop, the view will be closed + }, + progressDialog = { + // The button is showing the progress + } + ) + LoginModeView( + loginMode = state.loginMode, + onClearError = { + state.eventSink(LoginWithClassicEvent.ClearError) + }, + onLearnMoreClick = onLearnMoreClick, + onOidcDetails = onOidcDetails, + onNeedLoginPassword = onNeedLoginPassword, + onCreateAccountContinue = onCreateAccountContinue, + ) +} + +@PreviewsDayNight +@Composable +internal fun LoginWithClassicViewPreview(@PreviewParameter(LoginWithClassicStateProvider::class) state: LoginWithClassicState) = ElementPreview { + LoginWithClassicView( + state = state, + onOtherOptionsClick = {}, + onOidcDetails = {}, + onNeedLoginPassword = {}, + onLearnMoreClick = {}, + onCreateAccountContinue = {}, + ) +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt new file mode 100644 index 0000000000..a8b86ec1bf --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.classic.missingkeybackup + +sealed interface MissingKeyBackupEvent { + data object OnResume : MissingKeyBackupEvent +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupNode.kt new file mode 100644 index 0000000000..45c16e7cde --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupNode.kt @@ -0,0 +1,70 @@ +/* + * 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.login.impl.screens.classic.missingkeybackup + +import android.content.ActivityNotFoundException +import android.content.Context +import android.content.Intent +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode +import io.element.android.features.login.impl.BuildConfig +import io.element.android.libraries.architecture.callback +import timber.log.Timber + +@ContributesNode(AppScope::class) +@AssistedInject +class MissingKeyBackupNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: MissingKeyBackupPresenter, +) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun navigateBack() + } + + private val callback: Callback = callback() + + /** + * Open Element Classic application. + */ + private fun openClassic(context: Context) { + context.packageManager.getLaunchIntentForPackage( + BuildConfig.elementClassicPackage, + )?.let { intent -> + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + try { + context.startActivity(intent) + } catch (e: ActivityNotFoundException) { + // Should not happen, Element Classic must be installed for this screen to be displayed. + Timber.e(e, "Element Classic app not found, cannot open it.") + } + } + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + val context = LocalContext.current + MissingKeyBackupView( + state = state, + onBackClick = callback::navigateBack, + onOpenClassicClick = { + openClassic(context) + }, + modifier = modifier, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt new file mode 100644 index 0000000000..7b8ea7e633 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt @@ -0,0 +1,45 @@ +/* + * 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.login.impl.screens.classic.missingkeybackup + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import dev.zacsweers.metro.Inject +import io.element.android.features.login.impl.classic.ElementClassicConnection +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.meta.BuildMeta + +@Inject +class MissingKeyBackupPresenter( + private val buildMeta: BuildMeta, + private val elementClassicConnection: ElementClassicConnection, +) : Presenter { + @Composable + override fun present(): MissingKeyBackupState { + var resumeCounter by remember { mutableIntStateOf(0) } + fun handleEvent(event: MissingKeyBackupEvent) { + when (event) { + MissingKeyBackupEvent.OnResume -> { + resumeCounter++ + if (resumeCounter > 1) { + // The user has returned to this screen, we can assume they have gone to the backup flow and are now back here + elementClassicConnection.requestSession() + } + } + } + } + + return MissingKeyBackupState( + appName = buildMeta.applicationName, + eventSink = ::handleEvent, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt new file mode 100644 index 0000000000..78d3d81c72 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt @@ -0,0 +1,13 @@ +/* + * 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.login.impl.screens.classic.missingkeybackup + +data class MissingKeyBackupState( + val appName: String, + val eventSink: (MissingKeyBackupEvent) -> Unit +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt new file mode 100644 index 0000000000..85d1042985 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.classic.missingkeybackup + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +open class MissingKeyBackupStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aMissingKeyBackupState(), + // Add other state here + ) +} + +fun aMissingKeyBackupState( + appName: String = "AppName", + eventSink: (MissingKeyBackupEvent) -> Unit = {}, +) = MissingKeyBackupState( + appName = appName, + eventSink = eventSink +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt new file mode 100644 index 0000000000..67865ffcb8 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt @@ -0,0 +1,92 @@ +/* + * 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.login.impl.screens.classic.missingkeybackup + +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import androidx.lifecycle.Lifecycle +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.login.impl.R +import io.element.android.libraries.designsystem.atomic.organisms.NumberedListOrganism +import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage +import io.element.android.libraries.designsystem.components.BigIcon +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.utils.OnLifecycleEvent +import kotlinx.collections.immutable.persistentListOf + +@Composable +fun MissingKeyBackupView( + state: MissingKeyBackupState, + onBackClick: () -> Unit, + onOpenClassicClick: () -> Unit, + modifier: Modifier = Modifier, +) { + OnLifecycleEvent { _, event -> + if (event == Lifecycle.Event.ON_RESUME) { + state.eventSink.invoke(MissingKeyBackupEvent.OnResume) + } + } + FlowStepPage( + modifier = modifier, + onBackClick = onBackClick, + iconStyle = BigIcon.Style.Default(CompoundIcons.KeySolid()), + title = stringResource(id = R.string.screen_missing_key_backup_title, state.appName), + content = { Content(state) }, + buttons = { + Buttons( + onOpenClassicClick = onOpenClassicClick, + ) + } + ) +} + +@Composable +private fun Content( + state: MissingKeyBackupState, +) { + NumberedListOrganism( + modifier = Modifier.padding(top = 50.dp, start = 20.dp, end = 20.dp), + items = persistentListOf( + AnnotatedString(stringResource(R.string.screen_missing_key_backup_step_1)), + AnnotatedString(stringResource(R.string.screen_missing_key_backup_step_2_android)), + AnnotatedString(stringResource(R.string.screen_missing_key_backup_step_3_android)), + AnnotatedString(stringResource(R.string.screen_missing_key_backup_step_4)), + AnnotatedString(stringResource(R.string.screen_missing_key_backup_step_5, state.appName)), + ), + ) +} + +@Composable +private fun ColumnScope.Buttons( + onOpenClassicClick: () -> Unit, +) { + Button( + text = stringResource(id = R.string.screen_missing_key_backup_open_element_classic), + modifier = Modifier.fillMaxWidth(), + onClick = onOpenClassicClick, + ) +} + +@PreviewsDayNight +@Composable +internal fun MissingKeyBackupViewPreview(@PreviewParameter(MissingKeyBackupStateProvider::class) state: MissingKeyBackupState) = ElementPreview { + MissingKeyBackupView( + state = state, + onBackClick = {}, + onOpenClassicClick = {}, + ) +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootNode.kt new file mode 100644 index 0000000000..adb8c2d728 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootNode.kt @@ -0,0 +1,30 @@ +/* + * 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.login.impl.screens.classic.root + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode + +@ContributesNode(AppScope::class) +@AssistedInject +class RootNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : Node(buildContext, plugins = plugins) { + @Composable + override fun View(modifier: Modifier) { + RootView(modifier) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootView.kt new file mode 100644 index 0000000000..f1ca4b048a --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/root/RootView.kt @@ -0,0 +1,41 @@ +/* + * 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.login.impl.screens.classic.root + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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.utils.DelayedVisibility +import kotlin.time.Duration.Companion.milliseconds + +@Composable +fun RootView( + modifier: Modifier = Modifier, +) { + Box( + modifier = modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + DelayedVisibility( + duration = 100.milliseconds, + ) { + CircularProgressIndicator() + } + } +} + +@PreviewsDayNight +@Composable +internal fun RootViewPreview() = ElementPreview { + RootView() +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt index c38da7b11c..bf06613830 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt @@ -48,6 +48,7 @@ class ConfirmAccountProviderPresenter( loginHelper.submit( isAccountCreation = params.isAccountCreation, homeserverUrl = accountProvider.url, + resolvedHomeserverUrl = null, loginHint = null, ) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordNode.kt index c6ce16141d..853b8a7423 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordNode.kt @@ -17,14 +17,23 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs @ContributesNode(AppScope::class) @AssistedInject class LoginPasswordNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: LoginPasswordPresenter, + presenterFactory: LoginPasswordPresenter.Factory, ) : Node(buildContext, plugins = plugins) { + data class Inputs( + val initialLogin: String, + ) : NodeInputs + + private val inputs: Inputs = inputs() + private val presenter = presenterFactory.create(inputs.initialLogin) + @Composable override fun View(modifier: Modifier) { val state = presenter.present() diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenter.kt index b1ddc6e5b8..f26f342a42 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenter.kt @@ -16,7 +16,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable -import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter @@ -25,11 +27,18 @@ import io.element.android.libraries.matrix.api.core.SessionId import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -@Inject +@AssistedInject class LoginPasswordPresenter( + @Assisted + private val initialLogin: String, private val authenticationService: MatrixAuthenticationService, private val accountProviderDataSource: AccountProviderDataSource, ) : Presenter { + @AssistedFactory + interface Factory { + fun create(initialLogin: String): LoginPasswordPresenter + } + @Composable override fun present(): LoginPasswordState { val localCoroutineScope = rememberCoroutineScope() @@ -38,7 +47,12 @@ class LoginPasswordPresenter( } val formState = rememberSaveable { - mutableStateOf(LoginFormState.Default) + mutableStateOf( + LoginFormState( + login = initialLogin, + password = "", + ) + ) } val accountProvider by accountProviderDataSource.flow.collectAsState() diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt index 1ded677c13..030d65eae9 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt @@ -48,6 +48,7 @@ class OnBoardingNode( data class Params( val accountProvider: String?, val loginHint: String?, + val showBackButton: Boolean, ) : NodeInputs private val callback: Callback = callback() @@ -61,6 +62,7 @@ class OnBoardingNode( override fun View(modifier: Modifier) { val state = presenter.present() val context = LocalContext.current + OnBoardingView( state = state, modifier = modifier, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt index 741f65234e..60fa34f4d0 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt @@ -26,7 +26,6 @@ import io.element.android.features.enterprise.api.canConnectToAnyHomeserver import io.element.android.features.login.impl.accesscontrol.DefaultAccountProviderAccessControl import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.login.LoginHelper -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicState import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta @@ -45,7 +44,6 @@ class OnBoardingPresenter( private val onBoardingLogoResIdProvider: OnBoardingLogoResIdProvider, private val sessionStore: SessionStore, private val accountProviderDataSource: AccountProviderDataSource, - private val loginWithClassicPresenter: Presenter, ) : Presenter { @AssistedFactory interface Factory { @@ -101,8 +99,6 @@ class OnBoardingPresenter( val loginMode by loginHelper.collectLoginMode() - val loginWithClassicState = loginWithClassicPresenter.present() - fun handleEvent(event: OnBoardingEvents) { when (event) { is OnBoardingEvents.OnSignIn -> localCoroutineScope.launch { @@ -111,6 +107,7 @@ class OnBoardingPresenter( loginHelper.submit( isAccountCreation = false, homeserverUrl = event.defaultAccountProvider, + resolvedHomeserverUrl = null, loginHint = params.loginHint?.takeIf { forcedAccountProvider == null }, ) } @@ -127,6 +124,7 @@ class OnBoardingPresenter( return OnBoardingState( isAddingAccount = isAddingAccount, + showBackButton = params.showBackButton, productionApplicationName = buildMeta.productionApplicationName, defaultAccountProvider = defaultAccountProvider, mustChooseAccountProvider = mustChooseAccountProvider, @@ -136,7 +134,6 @@ class OnBoardingPresenter( loginMode = loginMode, version = buildMeta.versionName, onBoardingLogoResId = onBoardingLogoResId, - loginWithClassicState = loginWithClassicState, eventSink = ::handleEvent, ) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt index 703120b260..a1c49e0d45 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt @@ -10,11 +10,11 @@ package io.element.android.features.login.impl.screens.onboarding import androidx.annotation.DrawableRes import io.element.android.features.login.impl.login.LoginMode -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicState import io.element.android.libraries.architecture.AsyncData data class OnBoardingState( val isAddingAccount: Boolean, + val showBackButton: Boolean, val productionApplicationName: String, val defaultAccountProvider: String?, val mustChooseAccountProvider: Boolean, @@ -25,7 +25,6 @@ data class OnBoardingState( @DrawableRes val onBoardingLogoResId: Int?, val loginMode: AsyncData, - val loginWithClassicState: LoginWithClassicState, val eventSink: (OnBoardingEvents) -> Unit, ) { val submitEnabled: Boolean diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt index 76f8eb3513..ec76404686 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt @@ -11,8 +11,6 @@ package io.element.android.features.login.impl.screens.onboarding import androidx.annotation.DrawableRes import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.login.impl.login.LoginMode -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicState -import io.element.android.features.login.impl.screens.onboarding.classic.aLoginWithClassicState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.R @@ -31,11 +29,15 @@ open class OnBoardingStateProvider : PreviewParameterProvider { canLoginWithQrCode = true, canCreateAccount = true, ), + anOnBoardingState( + showBackButton = true, + ), ) } fun anOnBoardingState( isAddingAccount: Boolean = false, + showBackButton: Boolean = false, productionApplicationName: String = "Element", defaultAccountProvider: String? = null, mustChooseAccountProvider: Boolean = false, @@ -46,10 +48,10 @@ fun anOnBoardingState( @DrawableRes customLogoResId: Int? = null, loginMode: AsyncData = AsyncData.Uninitialized, - loginWithClassicState: LoginWithClassicState = aLoginWithClassicState(), eventSink: (OnBoardingEvents) -> Unit = {}, ) = OnBoardingState( isAddingAccount = isAddingAccount, + showBackButton = showBackButton, productionApplicationName = productionApplicationName, defaultAccountProvider = defaultAccountProvider, mustChooseAccountProvider = mustChooseAccountProvider, @@ -59,6 +61,5 @@ fun anOnBoardingState( version = version, loginMode = loginMode, onBoardingLogoResId = customLogoResId, - loginWithClassicState = loginWithClassicState, eventSink = eventSink, ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt index d590f1fec8..6549e21e41 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt @@ -31,15 +31,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.compose.LifecycleEventEffect import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.login.impl.R import io.element.android.features.login.impl.login.LoginModeView -import io.element.android.features.login.impl.screens.onboarding.classic.ConfirmingLoginWithElementClassic -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicEvent -import io.element.android.features.login.impl.screens.onboarding.classic.LoginWithClassicState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtom import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtomSize @@ -47,11 +42,11 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.async.AsyncActionView -import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton @@ -114,45 +109,9 @@ fun OnBoardingView( state = state, loginView = loginView, buttons = buttons, + onBackClick = onBackClick, ) } - - LoginWithElementClassicView( - state = state.loginWithClassicState, - ) -} - -@Composable -private fun LoginWithElementClassicView( - state: LoginWithClassicState, -) { - LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { - state.eventSink(LoginWithClassicEvent.RefreshData) - } - AsyncActionView( - async = state.loginWithClassicAction, - confirmationDialog = { confirming -> - when (confirming) { - is ConfirmingLoginWithElementClassic -> { - // TODO i18n - ConfirmationDialog( - title = "Sign in with Element Classic", - content = "You are signing in as ${confirming.userId} on Element Classic." + - " Your existing session on Element Classic will not be signed out. Do you want to continue?", - submitText = stringResource(CommonStrings.action_continue), - onSubmitClick = { state.eventSink(LoginWithClassicEvent.DoLoginWithClassic) }, - onDismiss = { state.eventSink(LoginWithClassicEvent.CloseDialog) }, - ) - } - } - }, - onErrorDismiss = { - state.eventSink(LoginWithClassicEvent.CloseDialog) - }, - onSuccess = { - // noop, the view will be closed - } - ) } @Composable @@ -160,18 +119,36 @@ private fun AddFirstAccountScaffold( state: OnBoardingState, loginView: @Composable () -> Unit, buttons: @Composable () -> Unit, + onBackClick: () -> Unit, modifier: Modifier = Modifier, ) { OnBoardingPage( modifier = modifier, renderBackground = state.onBoardingLogoResId == null, content = { - if (state.onBoardingLogoResId != null) { - OnBoardingLogo( - onBoardingLogoResId = state.onBoardingLogoResId, - ) - } else { - OnBoardingContent(state = state) + Box( + modifier = Modifier.fillMaxSize(), + ) { + if (state.onBoardingLogoResId != null) { + OnBoardingLogo( + onBoardingLogoResId = state.onBoardingLogoResId, + ) + } else { + OnBoardingContent(state = state) + } + if (state.showBackButton) { + // Add icon button to "navigate back" + IconButton( + onClick = onBackClick, + modifier = Modifier + .align(Alignment.TopEnd), + ) { + Icon( + imageVector = CompoundIcons.Close(), + contentDescription = stringResource(CommonStrings.action_cancel), + ) + } + } } loginView() }, @@ -283,18 +260,6 @@ private fun OnBoardingButtons( } else { CommonStrings.action_continue } - if (state.loginWithClassicState.canLoginWithClassic) { - Button( - text = "Sign in with Element Classic", - leadingIcon = IconSource.Vector(CompoundIcons.Mobile()), - onClick = { - state.loginWithClassicState.eventSink( - LoginWithClassicEvent.StartLoginWithClassic - ) - }, - modifier = Modifier.fillMaxWidth(), - ) - } if (state.canLoginWithQrCode) { Button( text = stringResource(id = R.string.screen_onboarding_sign_in_with_qr_code), diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt deleted file mode 100644 index d0ebbb336f..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ElementClassicConnection.kt +++ /dev/null @@ -1,260 +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.features.login.impl.screens.onboarding.classic - -import android.content.ComponentName -import android.content.Context -import android.content.Context.BIND_AUTO_CREATE -import android.content.Intent -import android.content.ServiceConnection -import android.os.Bundle -import android.os.Handler -import android.os.IBinder -import android.os.Message -import android.os.Messenger -import android.os.RemoteException -import dev.zacsweers.metro.AppScope -import dev.zacsweers.metro.ContributesBinding -import io.element.android.features.login.impl.BuildConfig -import io.element.android.libraries.core.log.logger.LoggerTag -import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.di.annotations.ApplicationContext -import io.element.android.libraries.matrix.api.core.UserId -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import timber.log.Timber - -interface ElementClassicConnection { - fun start() - fun stop() - fun requestData() - val stateFlow: StateFlow -} - -sealed interface ElementClassicConnectionState { - object Idle : ElementClassicConnectionState - object ElementClassicNotFound : ElementClassicConnectionState - object ElementClassicReadyNoSession : ElementClassicConnectionState - data class ElementClassicReady( - val userId: UserId, - val secrets: String, - ) : ElementClassicConnectionState - - data class Error(val error: String) : ElementClassicConnectionState -} - -private val loggerTag = LoggerTag("ECConnection") - -@ContributesBinding(AppScope::class) -class DefaultElementClassicConnection( - @ApplicationContext - private val context: Context, - @AppCoroutineScope - private val coroutineScope: CoroutineScope, -) : ElementClassicConnection { - // Messenger for communicating with the service. - private var messenger: Messenger? = null - - // Target we publish for external service to send messages to IncomingHandler. - private val incomingMessenger: Messenger = Messenger(IncomingHandler()) - - // Flag indicating whether we have called bind on the service. - private var bound: Boolean = false - - /** - * Class for interacting with the main interface of the service. - */ - private val serviceConnection = object : ServiceConnection { - override fun onServiceConnected(className: ComponentName, service: IBinder) { - Timber.tag(loggerTag.value).d("onServiceConnected") - // This is called when the connection with the service has been - // established, giving us the object we can use to - // interact with the service. We are communicating with the - // service using a Messenger, so here we get a client-side - // representation of that from the raw IBinder object. - messenger = Messenger(service) - bound = true - // Request the data as soon as possible - requestData() - } - - override fun onServiceDisconnected(className: ComponentName) { - Timber.tag(loggerTag.value).d("onServiceDisconnected") - // This is called when the connection with the service has been - // unexpectedly disconnected—that is, its process crashed. - messenger = null - bound = false - } - } - - override fun start() { - Timber.tag(loggerTag.value).w("start()") - coroutineScope.launch { - // Establish a connection with the service. We use an explicit - // class name because there is no reason to be able to let other - // applications replace our component. - try { - val intentService = Intent() - intentService.setComponent(getElementClassicComponent()) - if (context.bindService(intentService, serviceConnection, BIND_AUTO_CREATE)) { - Timber.tag(loggerTag.value).d("Binding returned true") - } else { - // This happens when the app is not installed - Timber.tag(loggerTag.value).d("Binding returned false") - mutableStateFlow.emit(ElementClassicConnectionState.ElementClassicNotFound) - } - } catch (e: SecurityException) { - Timber.tag(loggerTag.value).e(e, "Can't bind to Service") - mutableStateFlow.emit(ElementClassicConnectionState.Error(e.localizedMessage.orEmpty())) - } - } - } - - override fun stop() { - Timber.tag(loggerTag.value).w("stop(): Unbinding (bound=$bound)") - if (bound) { - // Detach our existing connection. - context.unbindService(serviceConnection) - bound = false - } - coroutineScope.launch { - mutableStateFlow.emit(ElementClassicConnectionState.Idle) - } - } - - override fun requestData() { - Timber.tag(loggerTag.value).w("requestData()") - coroutineScope.launch { - val finalMessenger = messenger - if (finalMessenger == null) { - Timber.tag(loggerTag.value).w("The messenger is null, can't request data") - mutableStateFlow.emit(ElementClassicConnectionState.Error("The messenger is null, can't request data")) - } else { - try { - // Get the data - val msg = Message.obtain(null, MSG_GET_DATA) - msg.replyTo = incomingMessenger - finalMessenger.send(msg) - } catch (e: RemoteException) { - // In this case the service has crashed before we could even - // do anything with it; we can count on soon being - // disconnected (and then reconnected if it can be restarted) - // so there is no need to do anything here. - Timber.tag(loggerTag.value).e(e, "RemoteException") - mutableStateFlow.emit(ElementClassicConnectionState.Error(e.localizedMessage.orEmpty())) - } - } - } - } - - private val mutableStateFlow = MutableStateFlow(ElementClassicConnectionState.Idle) - override val stateFlow = mutableStateFlow.asStateFlow() - - /** - * Handler of incoming messages from service. - */ - @Suppress("DEPRECATION") - inner class IncomingHandler : Handler() { - override fun handleMessage(msg: Message) { - Timber.tag(loggerTag.value).d("IncomingHandler handling message ${msg.what}") - when (msg.what) { - MSG_GET_DATA -> { - // The data must be extracted from the bundle before we launch the coroutine, else the bundle will be emptied - val state = msg.data.toElementClassicConnectionState() - emitElementClassicState(state) - } - else -> { - super.handleMessage(msg) - } - } - } - } - - private fun emitElementClassicState(state: ElementClassicConnectionState) = coroutineScope.launch { - when (state) { - is ElementClassicConnectionState.Error -> { - Timber.tag(loggerTag.value).w("Received error from Element Classic: %s", state.error) - mutableStateFlow.emit(state) - } - is ElementClassicConnectionState.ElementClassicReady -> { - Timber.tag(loggerTag.value).d("Received userId from Element Classic: %s", state.userId) - mutableStateFlow.emit(state) - } - ElementClassicConnectionState.ElementClassicReadyNoSession -> { - Timber.tag(loggerTag.value).d("Received no session from Element Classic") - mutableStateFlow.emit(state) - } - else -> { - // Should not happen - Timber.tag(loggerTag.value).w("Received unexpected state from Element Classic: %s", state) - mutableStateFlow.emit(ElementClassicConnectionState.Idle) - } - } - } - - private fun getElementClassicComponent() = ComponentName( - BuildConfig.elementClassicPackage, - ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME, - ) - - private fun Bundle?.toElementClassicConnectionState(): ElementClassicConnectionState { - return if (this == null) { - ElementClassicConnectionState.Error("No data received from Element Classic") - } else { - val error = getString(KEY_ERROR_STR) - if (error != null) { - ElementClassicConnectionState.Error(error) - } else { - val userId = getString(KEY_USER_ID_STR)?.takeIf { it.isNotEmpty() }?.let(::UserId) - if (userId != null) { - val secrets = getString(KEY_SECRETS_STR)?.takeIf { it.isNotEmpty() } - if (secrets == null) { - ElementClassicConnectionState.Error("No secrets received from Element Classic") - } else { - ElementClassicConnectionState.ElementClassicReady(userId, secrets) - } - } else { - ElementClassicConnectionState.ElementClassicReadyNoSession - } - } - } - } - - // Everything in this companion object must match what is defined in Element Classic - private companion object { - const val ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME = "im.vector.app.features.importer.ImporterService" - - // Command to the service to get the data. - const val MSG_GET_DATA = 1 - - // Keys for the bundle returned from the service - const val KEY_ERROR_STR = "error" - const val KEY_USER_ID_STR = "userId" - - /** - * Key to extract the secrets from the bundle, as a Json string. - * Json will have this format: - * { - * "cross_signing" : { - * "master_key" : "z8RUxnaAGu___REDACTED___k+BQL9o", - * "user_signing_key" : "baJHzA___REDACTED___xMLbSUAXw9QUzqms", - * "self_signing_key" : "DU0CvLtR2G/___REDACTED___dV/MONNq4nsQhM" - * }, - * "backup" : { - * "algorithm" : "m.megolm_backup.v1.curve25519-aes-sha2", - * "key" : "VzncmQ+UOV___REDACTED___patxDz7m0Nc", - * "backup_version" : "1" - * } - * } - */ - const val KEY_SECRETS_STR = "secrets" - } -} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenter.kt deleted file mode 100644 index ef352794cb..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenter.kt +++ /dev/null @@ -1,103 +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.features.login.impl.screens.onboarding.classic - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import dev.zacsweers.metro.Inject -import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.sessionstorage.api.SessionStore -import io.element.android.libraries.sessionstorage.api.toUserListFlow -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch - -@Inject -class LoginWithClassicPresenter( - private val elementClassicConnection: ElementClassicConnection, - private val sessionStore: SessionStore, - private val featureFlagService: FeatureFlagService, -) : Presenter { - @Composable - override fun present(): LoginWithClassicState { - val coroutineScope = rememberCoroutineScope() - - val isSignInWithClassicEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.SignInWithClassic) - }.collectAsState(initial = false) - - if (isSignInWithClassicEnabled) { - DisposableEffect(Unit) { - elementClassicConnection.start() - onDispose { - elementClassicConnection.stop() - } - } - } - - val state by elementClassicConnection.stateFlow.collectAsState() - val loginWithClassicAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } - - val existingSession by remember { - sessionStore.sessionsFlow().toUserListFlow() - }.collectAsState(emptyList()) - - val canLoginWithClassic by remember { - derivedStateOf { - when (val finalState = state) { - is ElementClassicConnectionState.ElementClassicReady -> { - // Ensure there is no existing session with the same Id. - finalState.userId.value !in existingSession && isSignInWithClassicEnabled - } - else -> false - } - } - } - - fun handleEvent(event: LoginWithClassicEvent) { - when (event) { - LoginWithClassicEvent.RefreshData -> { - elementClassicConnection.requestData() - } - LoginWithClassicEvent.StartLoginWithClassic -> { - val currentState = elementClassicConnection.stateFlow.value - if (currentState is ElementClassicConnectionState.ElementClassicReady) { - loginWithClassicAction.value = ConfirmingLoginWithElementClassic( - userId = currentState.userId, - ) - } else { - loginWithClassicAction.value = AsyncAction.Failure(IllegalStateException("Element Classic is not ready")) - } - } - LoginWithClassicEvent.DoLoginWithClassic -> coroutineScope.launch { - // TODO Implement real login logic here - loginWithClassicAction.value = AsyncAction.Loading - delay(1000) - loginWithClassicAction.value = AsyncAction.Success(Unit) - } - LoginWithClassicEvent.CloseDialog -> { - loginWithClassicAction.value = AsyncAction.Uninitialized - } - } - } - - return LoginWithClassicState( - canLoginWithClassic = canLoginWithClassic, - loginWithClassicAction = loginWithClassicAction.value, - eventSink = ::handleEvent, - ) - } -} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicState.kt deleted file mode 100644 index d2706fc24a..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicState.kt +++ /dev/null @@ -1,16 +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.features.login.impl.screens.onboarding.classic - -import io.element.android.libraries.architecture.AsyncAction - -data class LoginWithClassicState( - val canLoginWithClassic: Boolean, - val loginWithClassicAction: AsyncAction, - val eventSink: (LoginWithClassicEvent) -> Unit, -) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicStateProvider.kt deleted file mode 100644 index 73f68e5d61..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicStateProvider.kt +++ /dev/null @@ -1,20 +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.features.login.impl.screens.onboarding.classic - -import io.element.android.libraries.architecture.AsyncAction - -fun aLoginWithClassicState( - canLoginWithClassic: Boolean = false, - loginWithClassicAction: AsyncAction = AsyncAction.Uninitialized, - eventSink: (LoginWithClassicEvent) -> Unit = {}, -) = LoginWithClassicState( - canLoginWithClassic = canLoginWithClassic, - loginWithClassicAction = loginWithClassicAction, - eventSink = eventSink, -) diff --git a/features/login/impl/src/main/res/drawable-xxhdpi/element_foss_logo.png b/features/login/impl/src/main/res/drawable-xxhdpi/element_foss_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..67684ee9449ce2261c34af5ecd2bf8f91c61077d GIT binary patch literal 13888 zcmV-GHowVYQe$`JuJ~aXL);9qJv_3KsXdj8hh`+wr#H?(cowxtejl^$?d zuRyiC#IgU65hIeIO_X8`BWe?_FXirebnsSQAhL+IZtFaV8WGt@fzmn~R41iyjJ z!EZp@uyboyqcPG$)nb zlWC2Yg`?wG&`n-g1(x&)$=DoJT_wzRma7Iq&Z^d+M#nl_8_cR!q21MjKphJfgT+?d zPO{^T4J@u7Y3p2n$;;GIUsgi&f@^Q=UFooLF>!h+B>Ip92D=-hZloN8eZ_bX7@H3W z*Gqa$MhD?$hp7)XO1a0W5ytE3Lr0|zX4l$aZnYgcs%_Zjs!lp$3r1Mq0C&yXk9p;K zcp0^qg%EFg=E0rVYi)tBYBo$XWnoEvylbGR))~}vlkv((PXWY{tAqu$+0Zqs6WY9MX2tQtTmxmX=91%<48Tj&UJ@aGbK9m~8afD1UEI#b zFbs_kldBw!WTCuTx0oZ7WOnHedvExr2SrFuM$~>pq|tiipjdYESpLJ@S_d4_)(LZJ z?c5EYURMQtNrd^L3h}zFo4Q6j;7VfGN@6FLW$AV__Ti4Py-?(?&~Y3>%Rw@)$oGgU z#hjcXQa2I=N6nf8hu1oj(l}WC zuH%-hffup8XhQt*Q$N4l6>c>R*yX=(AKwel2H};>F$;{VGl%F{iEa{#QLd4@(Ww=K zt6=zU(}`C1W=7k5dNMZoVM;GdJi7fbSWumqN3lH>*+=y4|{>Qdx7^A$GBcRES@A{O-#M0<88qUP+d)ZESald+4hu z;wo*7ORfDrwG{its-tU(13pow{B8t(J-Q1@)VwZQ zi!eDb+|V;gRuBc_a(QbCXr~m9neUZ&|Ab>GRyT3{P|9g??-_t%0XvssGxbFX)-CQl z9A=TL^?FK`gVld};(2S}5VV6X#LtoY#0qSnk9De+;M1dfoChu{u_gx=cwmpm&(@Oc z9WKd7EgGkxDH~Vs$t-o^=aw{0I>02f(%(_D4uhlVPo~>PxZtu6EPm|(9K?1|g?Q!G zTYIUzbshCOf1Hr#qr*F}L6wy}wn;pS=rhHY36R1t++nl%ac|9Kmtav7(*ux{0i0-o zT8^S#39KCdR46Xj4~H@`K=9f@A%l_*Z0FgXa_}z|GahMDk6Ke z|Gc9yf=?0p^d0+pOC_0_RowJlofYQsNJNmVL-MwGos>!0iegOVGt!TPyq4M|M6}n& z6s95q(3C{ROfGfGG$aRKf%H;KdEim&i5>Hyo$^akf}Jp4T=cP1m%U&?zF;B#<0BhZ z5#_6WS3d81W^7L^aWz|-i>yyc05%bW=AIbuY#alKT8}n<83DCo@nmre%(*Dt=JCYR zGq|Ic>72kd6Gv?rhzJNHjSD;G`FgDP?z@T-FZskN%lhC2v==1AzxM(}TUk1Zqq|RWSFBp#Kyd$XeEU4tMddsCzOyXGFIs)-n-AC`4_Jtw zeB_6hyV70dKR+|(t1o-CBK!q#ys#U@L(y4(qIE#8;8ONht=oA8mP zDenZ-TR7L0o^alfk8j6x&_uV3V>wZt<2&Xe3DWanCjr2V{^0-xc|bz^_%FY|94eLX zcoC5Gxo4?_78KFApv*nRNkObb8VfK9!^E_~EYt(EN+~9DlhNIQ3Qxjoer>D(@wNGN zSvX*q%H9Jrozk=?i=XPEU7Bn2-2GP)B+RGP5&AYzwpEw?)8b_Vu%B(eh4|N7ZmE~m z>L!{<*Y+{4e`ZLW^N8_>OEcclid2<3E z-E7mf$(=_y22Dtp(;6@+pef!~>2UY#1xV|a{`5fStbI#XFTP~Ib`aF|=i)22Ue`4` z0vlXWbnT%9+ijzJ!X%@1N@TLJr#Xpc;!75m-2sDgZO#WL0W`)t>#rb=>7+bH@Uk@H z#@H1{;N!6vj!CeXU6s>rl|A1ez<0!wTxN0_Hznl}zGxA@WcvIzlYxChZc%3!&T`f6 z=f^tN(%DO3KiYm-;^kXzSxbysIYttDjPgM8<9Q^?+0~+%I3izV<}SAqb8XJEjW&YpV=95ZV!?4h;Dy~Q|q1$%VgbMWx+bM(Fwo*I1~GV6~qTKW=U$CM-k zE?Eqhdl{fOU3`Wn;3A3>w~I8*$N1rB|9+u)amNCvhI`zH|Lv7;y$WX7W-P=%`^Ak^ z%yw4>%^BY58pxHt7AWH*89#^0Fb~t(V;nULo zG=Z-E-A}>yw?7R1&p(yLCcB21mGk%laj9A`f@q!2TC$m2X5=oKx_u6$?`gfwW_3@%H13 z-x!2>^Y;IAUwq=;(65Xy-a(`khK#lk8jck^<-Wd1!bJody2JcSai{$5;u>Ws6&-r_ z=bs+k3mqM8Sj9@W+Y77cq7P3ur)e$m()+K!9LvU4elO?aBfDW-HZRF^k~Fa?ZZ)S9 zChmk|5%yUZn;<@?5=nJ4s7`<1S@JGQnCHR^Z3NEX3na*!p8b^&D{m8Os3|PO%M6Y| z%M&bJjDNN~sDo-U1z=OE=)7iE+F&6S%tL?9E&Iw@m-N9DZAwdg_onOW7QtDm?Bo^OolT-1N3V1Y_<*jO9{p$Z2kvWtsOUTT>tfdQ9?xl(O_z~}kse!${DdA@8gB1Kz!kmq4 z&*j@4_>8z9u)8Yg<=lD4xi6gYHaM8gE5`dCyb+!pc^;<;hH?qD@9$ji5U54P;x zo-D~_^GpSLXx`^&!@O&nLr%L+RCT> zb=X5zI9xQiW0%sRG!fOt=ue^rifpp;(FcL%?+}5UZV$Beg6O^>{=Wi((YbELC6vwjuFLEE#n&h+qp{I@l0p0kdh@YIe14KEcb&>FAnPG`F zdx@wG{<8-&4Yk6oVe8xDIvf)z&}+iAvdV5jsIEPtQkLg&8lTL#)@_;9dhOzbj`?{0 zyyM-96V8EGl2G@j?QV?1#rv{Z!&8t-=(436x=Z#=yPE|`D3`-5X%3GY1SG?+>AF8a%7 zE{EUS^feObn9kLiG%7sAV`83b60*yJOUadS?`;fIjQle2E4*~L2gX7Ls=d-Se|KZ| z6#%^WZrcP?y5Nqr^;(q@dumT;N|CNk>v1hQK;u98b49AZ2C5^Z@Cb35&8TKVfHck; zviMDYXQ?24yI->f*g>ns z0pq>p9`90l3ncEUwc+BvC6{H^SZyYH;h!zPk_u`)-ko@;TLv2lLh(JiLL65a4$-^g z^QAz4|5qlvbAGEnhWN;NpZ~8A1Qzb+YePReMk#%Oyvz8&$3x@^<1g%(>lV(M>rU!i z5MtR-F^a>*xC{OJaT2Y14?M8v8MuYwDBTOEbWUHgJCTGvG(G}9+qI2pv$O}`9Ns0r z4?E3WdKccMc_Tap7v~DRKh~#ke%_-rN@u0br)cesvGVCBzIel(mc~p2dN!=> zsr^~UkC)T^4@BS4mj1K6+(`2bEJ&g9k-RX6Mdl~r{`f&$6UJnSfVeb+)b zBfOs&nA@uT%fOxRuLE~5e89}5h@=?)fS{KD^6ibJa8} zwpzNqNa)EOZ|raZ0}+*^-48UFaVGba^VtM)e!_rd2Mzt_;r zfz%m@uR{K-`UUV;i(fZwpSKM?4i|6wCNyJk(7wV5c^JS1c6e-;cFfs^8H|T!y2B^` zr1P<}=5TsORh$Q2`=@<+T?T9jg|6`T>}-tEI#*l^o3MchCbU#zVueSWTDW*`c)C{u z2tr(kLpwoqZ&+|5)i+-UZy<|1koK|qYvIe=9zbtF$x0I4qCA1lf7p6EtsZpX2Nu3+ zN{jTgTrmHHAWTq!l$fubHnq5d6Votgx&KE>kHU|%YT^tMZjhEgPobi-TJv--r9*vs ze?>o>w&8R2qAYu<%mX8h@qiA!&-O)Z{!E<}B_H>#^u`mi2>&H~E-@a7_k?f$-je;h zeD-~_21d&I-}snL z)Fok*kXd9DFk-aMf(Hvkpa?cuB>MB=v3u?p#WHabRqJnl^}F0Z|JFrhK^<@~+GA8E zy!F`uCpN4NlhnYReCmE*}oqrHVo-ZBYPa z^b+o~13x1qIx=P7m!5Ez%$4UA1%+Xy#`N#U6$Y^&n4io)=BNjA;*PaX{f>HFaHk>% zIzBeu2=gh6q8F?XDQfnRc%65ng)wc_Trq1Fgx5k0K3v?9xC3MMDnKO$#5Dv<4d+OJ zbB~5w&i`XrG0)!|(+w_F{?o+>nzgT?Ulr;SQ z(Wk;^2kw^Ylh*TNS&mU=93Z4pQba5DIUj_$=nY(F<^|W7ZlDU-kQYwVWj;3grK(1W zy>xhe5F#O-9^dz9aHVCQ8psP(r!~DuPW0Mp!%cr(J)pRzjQ9CnMg5P0dksy$h;;lU-3)0Y@9r1rQ&}l3zkM9l8-$HLP!fP z(8Ypvm~@4QEMjpPM3ro%MrNQ|1c|^B}Aw8+A{PZvej#6O<#EmqM84E=9{O~aNF)1dJ5is*Ee8r?~t{fi~`U2Qkj>E z1?jqIAtuoeH>&#+hL`!)$oqCaHD%)Ol`-G}srl-LWglMu_VlIh&tGwVxW-%bR|hx4 zr?zYqXO@-PvOPB#xBS~H;?rd*EYSZA=h1J~e`X<$j8?m=m6A6CBTDr_mrK-_b7g|f zKGq;G)+I|>6U?jfQch!HFRh;gmv)~6GijfF_%8ft|M#-(J5h7pgoiz&#;FSkp~+h4 zgi4bh7m1fKmW4C-lLAfE=97RtzoW2xJB+v8ypIy(+ z5ObA`B}ahhE}7?G=#RCtFpp3u59NI5s$aLdt5R`Ay_DoWx~W*%C&wsiN86$7iQ8v^ zv9}A_**#}^H~OguHqc+67!pQA#6O@|ro0)VZxO&yCTsQd7EX55v19O(#i-74VMW75 zMuWd+CPMV3J>Xjd!!A6k8>hPdZO5Mm8=rnu5e-CG@6fKZL>wUy2_QOIfnu^hwn55P zp>t!E@tzu;JjVl?B51NkPZUh!f;-H@ulQFec_*5VF0cAZm{+h<;&W09WDpt3%y0328?GZ{lU%@UQ=IT-Y@OAv&qR zXg)TtI%~=}>V@tKCeq{?GDqD^3~CDUn4QuT87*NhtkZ_u=&idJtPg-IDKSS8+mnDF znBt7~%Z@3OJrrpNe&`jIy`GXw7f-*{esIqaeDvoxvAdB~EJ;*#i;fem;ejk@WATAX zoC!%6P57)#3gVaX7^XtpdqICcd3q~cc+BES>FwX~WL)X@cXZ8~J>?vw0;q^psF%Gb zVq`Hn2NOKOZlYFt!+vuD)fEC(Wmkn_O5Im#%93M85UTgL;-5qI9}2#~cgMKM$JL+n zWF+pmSlOo&m!9-0n67>Fo||xJY?%8iq>x@{1<2NIHNMGy11@k&^+@QC@tkS2WwszE zF2#Y!$}gvLf>=UivLE+Tn}0MZy`OpLc6I=z$b;_pU}vgEAPALiUhm=97raN9BWe{a z_H8O&5=0>_B+&J~ObP{bRVclf?>iSz6D!*RHfu*(UMesa#xsEy8kA$;4({f{qZdyb z3%~rxy>R2;FB~&ON?``nD6_*sz6RoI0GGDdr3S@GK*2B~9FH~KGTo;Ia92oS+JBeA z^iQ7J3V*oaD`a&$BdtTU+VRn!-30&k;B8KoM|pAfg5#!~=g`P7FU1KD1D!$7vZXRc z(W0;le8RlUijgY0SA?Q$)N3Sw1;L?;>B=iY45i}5WZ5?$IJ3*%#p@-Kq9*--WQ9}4 z3Ew{R;7=K8>IPGY&bV;t#d69i25#$n*|rjZWw$J z>Cc^g`0?TNeLJ5_j$ES)y>}nBfZXZSmbm%3Cs_ahkfxEc({yD>JW~iz+AA?#lN^u3 zf}e9Om}GO338sTIlmu0=h&1~qB2ph09@{#mX#2^wM`82!C$#b*W5$Ra;<0uUM1TZB2xhCSyKH|8bp;NUl|L4yo zkCXk=u||bpRaEEXEG;@2BM^JN1IQnaS9+aR$w1ZG#p?~{oK98x0P{I3s?h&$U-U|t zstxXW&bw34K9~-Kv}?o8HEvhRB`ieiHf+B?ploodqvqorx{0?y%1)dxP~D|U+G&?6 zN^cz%nPm5zsRiiU#wQ-}f!W!Ih1GkiD?}ZEJ+%|$$^?Yj_|g}bl+tc-p*&<2r7Bza zTronh%8vFKU!{W?4yxVEdO_bT2<)DFgnL`}8B@;lCr>^KF;ytV>V-C$U$ksndgB1; z*z1%kc!<72GEE361|d}dt6yfTo#ZT`I^eA5ifF^DhZAE~qd+|S@Z+X*F`KtP34^B>JsftAkGOtvLxa0_Dt+Qo6C#CRKLq83}` zbCe%RP@R%uFvnKOy*_xx8(_M2!`26avZC6NSy4%w;e{5>CydglyXTsF%Cky2QloPN z*uXj^9WFW~m8V*0s=~6>>V88pNi;8ve$btB#PL&3Z1DN#KubuhhzJYXXTvw&a#;|f zZGZXG>*3$-yVdExeE~+8PU9yd+av%7@`#{#5I;SwIN92(vQ+~~ay6JpF9-|XLM@m8LMl?QoSe|FbtSf7>!V6t?}M1^`)A`A@s-J> zVt#EFFcril0ZJGYj&LOey4t5sem6h+gbGl+GUC6y?qb(0K;QoL^%sZhi5XzrZ5Rk+ z*-SK4G`j?|bP>D-#)THXgssBhMHj^>Ru+U6XvBz~obiv}Xq_}ZZ45JVOiaw`rA;AZrG_i+JcLT z+dINPl$9mM%5e3??3uad=pY8?An(E5JD@&qa#yo+M9OTkIzE3!mMaCNG?u0t;+OK2 z(a;`&tK6(8SXWB~=n}dP&vA3I9rI(STeAs`9(K6<;XD3f%DHL#yE|^tLWcFGMzq*Yb>P z&WSQ7aDpJS$`M2$GmixL&JWH=fY&~F7Yyv$A;OPZmn$FWF-+AaO*EpLF?mmd0O;2} zJwwWI7^;-x<1i%FMh=XY3cq4#SZxPvBgXUhrx z<%Vy=(7s_;7G>PpxOL}tn66Ro>71$MdRlbbyu|NR{|%atQkyJeypFY9`(2CUroQU( zcm?Mic>?_K4?i>`0eU61q6m@9EO)U6>d_M+!)VPdwKk1TXMS&$F& zZ;W>I*NVpI#%iq%k+T2rF9!toq5t@SR81AJseK1@BpH(?uQoyEwLkYiZ~hAOJ@zoJ zIOF_a4uiXP!l&=~u}7LwLs_qoEOFno%sJ=ig{0lvV@*}Je@HqZt{Kx~Wm#1zRhiIw z7C8rLIWZlU>p$_j--S=U{;e?6_P>AhEf^fyE^#{63!J><<2y-f0kZ0lYg!)F7_Q36 zKlJ1VVD(i)HCVlF2v)yu7ai?_vI6`w9C0ZhQ;7)EKqc=3jEut=goSBkB<$MzZij0( z-wrB#@pUd@1#ue#Lp!K6wGX;FIwxh0w}$H<+QbzahW~M4niFsd{<^(QP?(F$lVY(B zZTU`VmJ(yk_i^cor?@Y^^*vCZKfU#7`}?2XjMx8ib5tBNfRq)rK;bmK;3NY1p*6h^ zqZ5UgqdU!y3f_`J$HI@?)`a(c^tv3!$(CzTjlm?K5UY6#YU18XEt8Z|&EVhCauKoW z?w-K#sOB2*(`p3b=4XEGmM%JVQU)zu^a?f_gakf>>kb5nR8UkqtH?0D6)^$b*kw_x z#QFIhv+?rtE^-&2dXDp!zd!Ao`|g0%Ke>^IjHPOhae{#3B6ZA>RbqafF;-2*bw-9o zedJyn-UWxWWpflFb-0m^EDwWJO1({XbEq~6ZQ9~0xw=_U?RREaW2Ow-L1z`{#z>xj z>l^qLOfAGyJ&MJl(R~0aC(f@RI(vCu8f~s0PB_0|GYFlm-F44Df~uT?W`hvp= zv>fSryHAC4j#)Tu>d>lfe)`w&-W#t0FvUH#0Ie}I6~anUCS9$O9HT5_#FA7f-ln$% zehZeUK(){J%$tYD%l_~yS6(}6{1`uit#Fl~F-Z4)#M2O^0#Sg`&jF+&IvVLAZ#qcz z*l_K}!C%32?ef=L1Z(G9f7qoY}PcD6%^L-r5cFpEH;3Gfy zhNMi<`gqrXrYDg$$!M4d1~I4CaFtn}vzQ~?INk{IY5e2bK7X1YsQIULeMGf~d<{PQy{|>uk@wl6?D>H*{8QtyN2!6#7f{+n;WT$E<*}Or0kblnpua-iy?ny* zP2>6rLL|hqk*pAXJuYbj=QLXLL(BA1wF-5Ajorf%p3PIHf;?%Z*Ql16>t#%U^}o1x zS_ZD_eLKalBNzlr?iBiMl$b8GObJAN4F3;Z}6dq|mE z$mxW4kuDaFJo_m;Y?L6%XEuY0S1#GQ!5gxl&sZaP%d*n8exeY|S?j5rT|nka0*wi@ zFgP&9g&%FnEhrNzyE1m2sQ?gnzv)xLt}NrmrfAjS+5-C?{bgX%bnUu7`g6Zh;<6%k zbmK~g0ATt!G`tsHXd9s1@3L=y5ia`Dzrf&*?f&_}q=cmi31w{EeaF9hU<)XwI3hc~ z8Lc`<-bAdi&>e-mP|zs2C{a*q@lWdpl&opuSjiCS3KdRSr{G!nJ#z(er zXPm-B(CUP_z70J0Y#6imq|;$0&Bwf}@7#bN|Nb`}{ec&r)+#ulVPvut5duVriU$9p0{4Z?vb-NiG6_jq?MG{WW_@H>SOEZ7=xsW`!ESH{xsNxoXGvfJ9pCPU2b+e z|1c}((dG(FADB$tsgUwPtq7!t1?6B~@{(#^yeckrQCmy`y!VR#J7on&+f}!HA3k!! zS2>XYn^i$fyY<_ObKeN7e)|$vKRhYO0M%{1yY&{gdD|fLJ@OFrZ+pxXA|Nf%Skp*k z=Pk}klMQ)q;t7K7OVuH*xF}n~S#O1n!pna>eD0gsznd{Jv3>tLR?*Sb;n$x!+oNpK zfDSUBY05iVig#u?0nK%3$6YKsIm>92{Krpf<{GeAgsCG@B;!E`EOHupr;j@QNlq`A@X%T~sem&TzcTKA3!esJ%AtG~V8 z&V9lU^ud|GwVAqkKV3cB3sRrEm)NKAP23eEt_N2j!9dOnz>z{ubUjXEgDf~ha(@5< zT|-xQ4L%G@Pd**$haUygH6J6FpK&f()E?OU#DG{orWmOj&Do=it~Oo6wTBe9SRpY1 zBwiOl4HpdZSZaa?yq(JKt+d_RrM}SM3Z8!`SMrm9iYq|Ji98vj{G`$F{S3g>*L|RQ z?h}RB|Ii35In{4fyC6IYU8`zmGD+En%#(AG>0J0qMI{9@T*GiCW~4MAeC9X?k-0oS zWy=McJqM<1U9&r3`I+a!it{dXyU0Cm{`COMO#~XjlgcG3rYewL2MV%u zjv{~YG-Y&qP6hAOtl2NA&`{^%F!DjnTCqbQ-P!TPw4;LI@Q8Ea={)xlxc8w6|FWBF z$&HoE>#kaC4WBz^Aylg_a|U4DtBDKFL^;G(Jtr4xeDnl2CkOPHx5OWR@RRg@H0)3F zV5aZkU%<6@Z-h-GP`}(2y_-06-3f+G!z;ZS_xX!CulMt;P&r_ZXJI+r2gw^7UN*sk zG#(}QZfrbE2fujZ;uh1KM2Nnv{JnMbx&o?{N)pJiK^9~Z&_rzBvlierLZxGIlIDAU zt07GoTtDJy*zloM`z=V@`kxpece@V;cJS}G`S`i+u0G27p3w&saRU8Tj_iwKoK)J( zvQnIYtdS@vLTpm($T!1?i71cS-VyZ#m%+N5*R`706hd6y<;tfnoDRS$dtQer z#B&G81oEWJ+)`wgoS(w)Qyh&a|3wo%_mJpe|54GJ~md) zI(arRwl`D?{OX3 z`ptL4(o@fXW9Lo(n7~Y1?)8Y1KXcUtS>b{a`-odvw}u(VgfZOR|avgE}M%0 zD7l6!F&bMz02WuV!Zs8_q`<2)@DaH0;Yt6M)5(SC33=7Rei*O3+xfiFk4COl(H#UT zxFlq44kdZjgjkU(nxs~R8c~@+i9BHi0;tGAHP{X9-GiUM_4|Q=y{DcD2d^RA(0^B= zo8LtMXi&M%A0w(1x;1d>kMr@lQtGMNZz^g7$d)#pr}V+DXLyY64L>Ha4!-&yYo?;S zGUdG1^$k%km-%1OfPEuWP;N*qkcr`?lajS2{E7vyIEPhgeTXxxe9$$8Y%&OUr}RHPg{vopyE) zJUZacIH`vyKF#@ZT(v4LAgG+69W?KoIx?$2Vi1XFH zG~Z6?3#L59U*ngYhDX`^AbcFY{)6vLN4tZWwB@~Bt_qu|+d8z>eA=Pt%B2!p=uT3R zh3Le|2*`!`j){A+RTLL+dF%E z$#wiVAhFr)h`tDr(hTX%rNA9wX<`IV&`LDjgH5zF5r)lQ8M2#e(>Pc^@)%fp+Sx&< zJ&R7B)*032GLAN%0_!hbGN%El?>MxoU8qkWBb@pAU|Vdj%SV z(k+AaeFHFqHgh5Rw)_pN>4sIokx<$Z70?!jtK(wpMCT0c>O)MlPkS12~J!Hq%!}> z)|5UVPE4(o7e1XB9t8;~m%;j5*TD?i{t40FaPjLmP>fg#HCl7*>|o#KlwcPri#{{G z8P+g^QT88$7Ja1;bxCr_2$#9U+u}8UOZ{j43X}5W%*jr#O~yOnOnpwI&+WoDr!m5lyCLv zlL(Nm-imFrUqx|n+J6YTxgD4geS7P9Jv7q|L|7NpY7iEYBdUYUtw65xVcJ>jYx&uJ zN(|EQ>R?jiZFxkoNiwI@N0JB~tR%o>dci2I*e^yUNpsD;3g)25fH%Pj`$odvnE+(4 zvJAd==Kvf)J8&WT_9hafLl)$$DmcI50qROyrWp`t?2Mbu{0lSz2tAm)HWiCpl7%J& z19HIDWVs`V7MS8}q)xqn9u|H#(~FofF|*9cjz>BBoBbj$=a2(fsayG zbhbk_8GH^gqB%7jh`W&h zCJIjgESGB<*~tIQ1dH6 z!(&oBhklyWCD8Z61sLf$Xsx%WPU^OS7}rhdhr@O%(Y47x42R9iIx)^nXg22y-&-M? z2gJ5E$Q3xFtJ%};AU0PXm(8S{pEQ~oY1m(=F9>6;F`6b1ZrZ+koVm}NSQ&} z;sa!3m^EvYE85Tb7`*!8w;C2Dk5_>;(D%SHj&|mKs~?_g`*|N z|E{T$s(#HdIi1b}DL|fTpfM#`*t%09C zvJPH?_R$ml5t{fL!M!@Vz!@U*?OLbR=?zLKc9+<%H_#9N}@fnKE} zx*epk{ zgs6?Ivx22Zv%LVEnnZqk4%bM6zCP=LQAHt!ONA0yV>04I18rI(V1=O#L6!~Ko){sH z|5WLtD>l;KRV2KFR&6;L?d2y#+jPJLWF@o_UZX z2|6pN8;}%M5aLr=VgGDXAv_4p@44+Km+pV1Vm%3N0A8l;QEZUz5qA$~<+Z`%M2{ALKORr@bFT!y_W&gD}8 O0000=#AzpVeZ=gT?9w6Ow0XpeBxT=%N^C5Ix@OM-$bi8w&5UR1aJnb2y z@T)X!a`3AJD{fjlFsp72S6vtkRdqsSqv1%J!F*FWP7+?C8+0%KqVJBr_&@}X|AgXu zfXZPB`MQJAc&$@~Y8|w~==OGZbj6cT8-ri+^h?Q{i5X{%w-&orI05RgIC96J@E|c^ z;;+fcE_CZjsB0fTHRaMY#wQ~Nxc01o|#oz5#8`|yk z*NVT}`5rN7X6A|*Ik+%dRc^!ww{D`p9{FWt)?XUtyx^N_ha-zDssjvH;D&>NLLV7y za$*v8O-w|FoW#HGWM;IK(kG)KGg7`ID2aIlNa;F1$6`JR#8Soadn+<=Uw?mQ+!_5d zpuevVX3UsTfHh?wiIZSWe}6UdmZzQeOQ8xpq?vQY*S<1bwW>2+a7*LQfh=m{mk^Pz z8yRr>&K)oj8FJUeF5!ek5HHL~*IbFH%$PQ1QC&GiJ!VQShrdgKM$9)7@~(rKkwItB z-^`gabKcxGNa*T1G3Pa1S6#B=>8EwzA(|d?%(-Ii+5y+!Jv)lX#TCF18Y&?(|XZ<#E71xZri>UcJAB>-!Z>ylAyZ`-;Rwr<^mgB+L* zjB#R^BeMXxb?BG9L&yrkNTeK4?PWnQoo;}Y?|t?QSHXiQJ!qKooUdFx97p(~NbI51?D1VYVawQ96yXz;!|G>- zyC|^%!(8FW><-ZI?Z`Jorb?K^NnS-%D3~(IS`@1md7~AdMRc;j%as z!|8W&fNvh#1UsYU&8TMV68U0RWb&W~L{(-DMkdSDm8;6~pjlP}9+U7k>Ow_gyi{#j zhjoROAE-Ut764;(6(}9peI%1fn3taibl^AZ#4-Wq95yE+>4J=;r2npRebvfCoks|UKX{n?R_=cIM)#9Z69Y=Q0Dw&oR^JP1C38OwrcfEX$`>r@n(2~)i3&@gJO zrERTm%XyZI02=psQUugkr#!2PEpyR>bNjhHXrW6RL#ee+o2+_5DXm7$Iqa~AqzkxD zo!GWZ-hcXwE`~!i9g@uX+Amx=9Ea($*u25?J2B*^5{;@y_bZ7C&$Z6-?wGRKlsNO&9c zeo9GYNa#5)iu&2n6@}i7(1~A8`_S*cv;&7&I;5C0q2-Rgoy#L=oRb<>cWc;q?>*Ty z!~iGK7L<`Vh=S2He;3Z<2UKGeObVC}5!iAMCuI@<05=6)9T{OxmN%J;a=BruiU5|8 zxjq)ziNTzI{aHgJA5>Gr@pU^ZBaMMg${{r-=UP+QlND_0iN0 z_S-|zb>p5=re$fvLIgXL36;xYwV^+*Gz}bnI9c_f<9%3p#gb*K-~mn#D042p`m%vJ z5Zyx%mL?)?i~h=O(LIDZA#)XvdLR%Y<^ZFU8PQw0Ml?`<%sAW)>gBvi4WMh*uc+(o z*aUAyCBda5hN;;wllB=TXC}efQ#?D>xlYfdd(LRfw%x(Hnm`$qs#F89`8)s{SxvWE zx|ej(IrEb)dRV@Y#QZ0gEL#Z=V0yrq^Cee*a4`7R+DN{^q-$;2xDm#;Z7J}XnDkjFP3`(g3putd9AIv_=V4|NIh|Eac zP&a@k8H?q>Xx_B`+2|A3R0HPedqULO>!eO;&cOVri#{xwkEscx&b60(a>=p|JOJqd zVa`AJ^aqEdPw?v4`GIIb8js3SV9Xv;_BJTDxsKx_P;&Zsv5(KoFMp?VvH zSy>$r=C%5&QzI~t0*>@SouSp=2MZql@Q9{;>1U^E`O`kRPkdN~}NGYhaK<#G(;%7Wg<7OlcUXiK5oRW!DsTMU`O;@Zr_x49t5!d5f*Y_i~+WaE#p*K z_NhL_zCIRr1w+t?TOVSDdKHKcW=(EaJSNu>yo?^#Ob!asUaU+plYtfewn{d7O7$fW zgYoK>2782(lTEt>!I?JBxU~REx0j&|5mXsH{>@piAY1g=xO48@YhLpDgXXk9Xv}%~ zl@~3qJgi9D5;os^FYJttbrGS|ltKjAYoOvA#L$2##snKAwg{A3#$aLB6gSM-)f7_? z{YpQ0y*ufc-mFSFgfrk~8GgXu1aZ#vO(cThtzsboKqipqcG5pQ`LsSK(gbY1w*OA) zQZhZrq_#fPG$vV6fT|UVL1)jOhb?n%#b;l7_DVPi>7X#@b3XnL%c}q@5|eEI#YWh* zZJVrUXkxvt6u%`5f7)VuW~EC z{IWkk;0$`ene%t9c=z(?fL@W9XvuzWw!LKj2Uk>F!8EQZ7opV9SWHV@&~TO;RC2Uv z!2Q8bj(#frw0vDv2_S^@1&wSUOWIi}qj{(F8z>Yo)e?WVTr1bXhNd?FQ9cLIAN`l28>$RycZX&>3&HmNn}sE#_PgSc`rtQbIrfn!2FBElnAb`F90Q)B~POC0!f!2aQWet(bAxTsSN;D7mp#+_3B~4+w)E z5avATBP*9jJ!nPh(Y8D9hB}FIn7(pf7$bDuj^Z>TxG2K`Sfw6wGNPcfTjM?%*^KD2 zKoh2EAXUxUC^C*^$cElpJmv~X0T%7`@hq0vT~&gkwo{vECM=Xqwus-tPF69a;LVS1n%+`#J4*<~;F3=barpd2#B-j%fT$Y~5~{#ZU(? z7~<={`Fa|x1aFx;eIZ1#;g$TB;SvO@6g{D-281b$WEn+AK^^kY(BH}thACxEt7kO& zXPHRuu~Adht<|`KE>JLTE;fK5q9bF5^Kt(y5U5+uLFs}51I-|PFQiD!G&34W=`X7W zp?%u7UbkWd_G8+w%z5Jb-!T;B@=d9+<6~Q3*VtxdO!`-6a1hieR&W3cHfmatOgzvSe(&Uo_ZvK9N~T&FhdhctBAih*4_b|7P> zQ#Cej%-4DOk99qEo78~fDJ2|4^4-x=A%j!;^f9-hM457YC(rCaV#?{Dgunp}=02t1 z6`8$W#yXv1uw@LBO%RDg^knBJb}FAJV&^_He43Ql&p?s-Y|VR_j6T#P)~PtD6f%MZ zGkFEsrOz~p?A!?o651y)-?2?~?n97+BtV{pVhq@A~FngflbR0ilQ!)-k|U=#l(c#y^I#7I}bmJFSP}Y_)8sJ210} zCHi7yz*%$Pm5a`RKR)&OFmKjum@fTfpgwNSMQN=x0SEtMGyDGRhdYanIyr`X0!H1fU(fRXkIlp?%VGx}l9 zBaWcFaM~^BUOWQ(koJi=hc0?;)HB<+r`GP;xCthueu32WCEOAWe#~wrf3k^xTU(u$O6{bk2#|t&M;VlhIwYYs=PrjlE>7 z=cIPyR$eAV@gcgQLrw-pJC@{tR|rjYHHV4Ct|I^vj}DJ1s5#7ypwgR--OlK#UGHUZ zJ=MLpjG0nG+2v85RSx!GJ+TIFtY-yFra@9+$#jCc zG1)jq)N_nyKy@f17>Vd&QiIvHL0pb?*F++uV;$8qohYstlcJ5v|B#H~_N;zr&6qLJ zb(5FDKIor&t#dy9-LF|5JH5D`?845w?=AEeR5cS8p-zZ8BmQ~Oe?auHlvkB?)~CFp zAp|4JRA-|HsP0;xcZ{~A=SsWsK-k{_N(VW>i+=lA@$cENzfwZs=N^9&{GVKAfP1!V zgsnTb!4&<_=+&$vvOXQW(ne?&f_MfJ%Bk*+^poGg(63QGj}egm8$wwRGda_fb=5px zc05QoWqYAJJ`Sxp>0mK8c=+!;W%Dn-`k&u|y-0h-oX1@F+QDc=Uy~ZN{bzUOb--Y( zRkSvpA%rUJ;$%iD7z4?JieojLgh;|rV9F%Ro{zpJg!INx3Z^d048YHV8VD)9>5M;w zqaSf3?C&%$>afGV^_0x0b0fNLxc5#N+rCxmS9(xC$e>}y<-THfX)n_nn^I zOMAtf^PYX|O|jB}@r`59-LaFH!XtVSLa}w}X{Lh^$qREJF??a=GE(GqXJ0d(D#5%m z9HT8x2KF)T27y3{4+hDD1Sn&^SDbPN9QkXHfCH80&pr%Je%$eJ`Uy{mEjzZs%^QBG z?Fwq$Lr{81xL^M5jh6$x3ndzcOb?mZUi*v8SWf{7Pve2*swijaWzjtd$}%u8ek!7; zd};elE~CGi>0Nhd({<}tLyxIv=KPHdU$H#Sw8g&Lh4H&L$_x|&7$#ED1qIqU{tcQ( zSq-L{xd7yt1WRb3SFGl!!;7E(9Qfi* zUx&>*w$dFZOo+6g$&=C2gKWJ3?Uz+e#DK)87BYN-=_6+i#TY2fDZdYCMv!1kh)Acv^B;I>s&cPKg8H`n56C$FG|NI^Zbyt`~86#5$ z3K2|%MRAaB*Chd1tO}xPd4ePmib26@Y8?n5H-9lH6di&=RNbJa49lYONsm1mp7I+{ zgoBk5lfLG6eh)TB5&xe*`fs64ISG{}C{3&`N{D9k!Au)saI3?E>IHPINpsEzQkDaY z=!(v)YX(p?$9@4 zh}b~=RFNG7y&9s*t0BUQwnaqgTz0Y4<#l0h52ZmvOL$(1EQrd6l~MA!P2L+6KrV+} zaUtO)&o~_pc6!#6o(7LS{1NbtTSsAhVqBO&#W84qeK3>XEG7tTO~7=%!BPuKS_ai6 zRkb1!5B7c_X=fO>P(R8^fvN&Z$a-P|TK)aW7dEqM_0Jqzd&?d>=l7U7AN|*hmqzij z!gnWO@)ujc=jAyssAR>b20wTcS+2-h5C)V0ff$_iN1G3g2G(WO@@6+mA-+KkD?!E_&zcKQ{moCCEJQVtBus}pLr{8t5-sjFpsDIMDXFOre*00@q z=bq4GkC}7cqGPU(9T=F{7#VZtID~?EJX(zfA&ofpN*qBvvLxA3O(n(SY}%<}vVQaU=j6I$m^m!=P9(mLzS$$>XESmy1c? zyA&VM*G|#%$85Xd2YX~3?GbZ6@*OW&8XLXTrL zX5S1rSSc~+OP_fLd}aNOaL?E;z`D#z#H96hE9O}@t-bgrExiDgPQlR5lNwR6C%}xK zAYx#;67u>IAgpIVCKFw&$D?s{*o<_2aPIK2>$cr+Yv=yx;9w8Z5pR3$?QzX@aB}0; zsB7*5`h85-Odlp+PO2!ydZs(wN68C?hlO!-Xp7;*W`JJCHhM#z94vA1_o!!aY9q9Mwd)+ z4-(c#Yfd@vpPviL&^$oCIE)K3ixdD} zLM>we?C->!XFO#Qyll}6;rPg``zs{|ea72f3O~N*XQWB7L2-P z-lT>tNLx)qA%06A7iQBXFbV%^tVRHdCXI&-Vx>ZXWF)Rwl=x8A56DhQoZ)jS#zgNT z(St(F*20W-e`L~QU|&;GC!YV* zVfeRyzdqKnnJFZGOt7>~;C^(^sc4f4*X0Wq~gIYv1 zNC7${1s&vV5#>t(?7MxOh<7euw@C1BzF%xxFo$&oZUE@!vSt~wF3*UWK1|1gDWC6W zG(F-`@QxR~4*qC(G3;wfqW$TA@drXD4N6wYWMRvqX|WYq=uq}g4k#0(E$P6WYewQ@ zSwU3g69bGOKO*z2D<9Ovg+m)eZ^qiL1keUx|Ka zbw_8)BmIhX#r)ySwg;~Pvx)+Y8s%17J}`hAtVkQo@h%{+!3I=N#k%Nw9uU$2MNc!3 z)7%F9?pMA8-tdC6U|-U6{`%$cweS50)vY=u*U1QGC57&ja?)>ajH0G)&qV^12+WGry4TIX1g8;E z*bDU_P+d;yOHA%%hC~Sg3nH@3pEDPZKkAA3bK%1uliM>8zo#cVcmEWw{q~pPj`(SH zFSjJWTSi^G@5yEvo4L@kjj@eC97d1cQ56Uo*Y$+K<7XfApP7qku-4426|e;$Fk+x-TjI zY?aaX*3*#!jrH^uSB@<}akwt0CgqEJ!ESbpDH=u95pzS2>SLBx z(7p_IcA?(5UD%3es2DFnTgY%OV%{*KX(2HdAx#M7mR)+?p7l4DB0|4&IgG%vugDBc zv6Yul;MC)O8_qoGx$uhL`GdViuawsR=)d79Z}?r@J`oyywHkmOL^FD6B3$>btM-~f zpZ)e1!^n5PS&Cl(l}eye2-U4hkWW=Jr3*Wj3S*|B5}|Y|RT`_d=_i)WDh6L}?kjVL z&yI4vl{UpKssHKw*EIV$Ept|{eEjVx%n3G)gWoY(Z2Srk3QG(Jhq`R`k{ggK2%=~z z><&;cGU>L|aqhei&8-G>77+w-^x_N$LIK_Xk_?e^7QYJK82|Q#A)9ICKmP-q|A~u= zYXy2!TX2wCsB#3=p%a7t*ZaS`S8ZB%^EcsHZ+(%WD^-}t<#m!<`a1(Ns_QfDO4V!H z{^-SNBqaZa0wFQvuOeL^TOgYmXGeQ{-i-8nr2EkyoYw5)ROVdzxS`7Vo3bdsdxvqz zQkq8G7PH2R=Tt!&oThkoxX(uv=B)qG>?B=?da31lHFR_h0;X*Xi_^hJJ{Fe$(VOAS zlTY8TOv!01>U|IUy~j(RS;Z+;7HVt5NMMv-bo|M%_V51%_9i{+t$zR`qu-!khUOqF zn19P&`4D8gZ~$X0GK%JvxzeC4R57Raf-{n<$R+HM)TkD)A3G3$IjTGV8`TPU_$*X6 zpk4s0I)!MT;!0{AH}Arjb0~>)7-zQ#$e-f|_&~M_ci6F&gn5dS3MfAlFPBA@rYA$l z=HaY?>n71;0EwA1)veFr=fLcFaN!^SC0zOT55drH9t$)356rrFD)-tOzX*42yt}C1 z3IZNDabYo%Qr-=B{usuh%jxtJp9Q_9!ACp>R)6V}LZgJrPQDx2MB{=Da*DK^mkSI5 zrfxlM^d*o#Q}(+obZ?h4=CR0Jbe%?`&ZhjS%6x+pHa z6DCP+C8#~E&QNEv+3fT_F`WIA{M2Yi*J z`|KsJfgfG*o&0$)()>6PLd~mM)OMaQ>95A%hpOh_m)Kv?U6RcZ*BlMaQ z>MlC|89Ipp$QA&c1VZ~Tg{FDj@_o>_+?oPDXx#I-@M-hWX!PG zFq)-Zj5f;mGBYY6az|)Txctzi4#wy5vpx_(lC|mby>zWI`OzCPJoIGiW9`ct4lNc4-O#>V7_p*1rF(T*|=rx_QI&e8JGIWP>12M2853g&FresN~w@h<8LL`*OtXnWli^^dB#uXJ`i3B)ZI_@q zBa#dh2>J&a`XFd$QrbR=~$mq>XE-04iNr+X~itHg6x-vui%*agZDgyyo z=F+bqsws{S$T%`@1RCRt0K*yS5Jb2I!>+qZ^TcZ)L9Y@ei=02) zF6$Yt zL3%#<2d}^M8W?&2wo#x_Ihu?kDS@Y*6`B z_U9vmZtkf)!%rsBZfKqAbasq_QzWgGsl>uhZOP*RLT^W9xSG+Obw)zXT9KJmg2Y3P zRX>s_Rqe@605K4O?2$nH;Ib+S1F-lp!`v@fTaT;aXC}R)N)XE-`anx_?BA-9>cJ_x zv6EFo$Y{c$Z!!)7`}dreS(r;sgTj7HNhoe|eLeukO2(e$a+2s<_^8Li_3ytH1|xDF z$kh4y2Ki&J%laSO0;9Lx0_**Ug<)enxmaZYqd^w=;l0C*(CLreW;HyoaT7hv<| zO>oIoAB5$vdK>hTlJ0r!4WBc9U=SCU_|-kOgGT}Xuc`jXJkc-dSY31F4gxTXE7(@_ zNuz_B`pA(`pe{#@o-)#peWO8Fuk!!9@Hp{4Uk^Aauuva&0?ndce~xp~ir&5;0=xEJ9Sp zckY0ScE|b(&m{`eq7KQS2w+xx0E!ikTu&t2;IGHE=nq83eAND7%*2o*kr6Mw@&AG627Rlrf`f%Pn2W=+rL*i1q?((``wliOkB zJ70(4r#=(*Gz~xHnWA6jW-unO1cH39A-1vh(u2GR?9e{o@zOlhLygJ?u;avvvP0S7 z1jLXzJqN#dmM*}E0}=AXsaMX zMsseE9Set^0S+$%5tAIKLZ7ts$1@g5;tGi%<%Ym4faO)7j%{M*WN`JuoF_c~xV+y! zh0^hGNPGeWK}i=#qA?(3#zabIgAJ^@p-O-g$!wGr$5OT2$0g8049>L8Lz|wdz0}PU zAgdFT`JBfA7=Gj+jNIADyb-StXHh-rb=8H$6uTfqpClzWi-0b=h*0TvgaUZai;IO_ z4eU;$fglT#jVX?>X2*Trrs{DuWBH%F9fqE89PDel3@t6-Aj7mr8cIu!~0gh}h2{?i8=j7`ld<)flyiuet8C&}&NSPA-ew zTH;CI@u_{Geq^cO4MH}IS&69k-i#BiaC!8fa{tA(7|1|mSCzM?;|1|-@E8Z;vE1zm zq*tr29!~9PQ=?AEvu0Nb0;gippT49Y`v%eimrWSac*${y8@4 zSpNd@(>Ya91VPzoaE%Ch*2AFI`hn{wT`-r2gS-Cw>!H_l!sCvE(fFK%78|jfw{o}? zI6WWEe%b3_(TUHD6aIJ@m^(kK5UbaG99CcZaS~@$X3*^7s#F4|f2yFiMn+K~r|nM= ziG+g07+LJ}rQBKE)8Hr3p82rrvS`oD*$QsZCrF(@b3cPSalVbWWLqHj*KVue%1HD( zP+e2Q$0)*G8qG?!mw{tl4Ba6f1|Pi;&f7=EyyS`xAX0AK3hd+4pkwk#2y?2A?Z}Yx zLB*0p9}xrRevqE!Arzu6_cdK-JyXQH4vZK@U}7ki-W5{9N)M>U$ zGEI`PMbe2adtq;<##u6=eMpf^ZZJQV{;4M>hq8!EI%i%90FdP=Ry}VjvQ!BANxnDNf%c^oblChoI&nOdSL_k`SL`kxB>NPa=oBFKk^&% z+I((H{2TrL&AoIN#kviI$>V`yckq!%!u22f{C(=}>0ZjSVD@3yp5SEJm4irF{Rphe z)LzvTS&qdx3=RrPWqD6l2)WugUcyPAkNOk@jCph#u{uLB!ofUwbLo%u3Yy7-S^Z_?P7&G4+3pAMI- zdY?G;bKAv19;6-8PFaEkT>1+^+RPh1B|1mi4YYP#m$3ps(!&R%j~fK-QuGh$WO-sr z-$8Ws&0Bgq3^*_0cD>Lw)EYf>-k-iBPV~p#Zy71i8(;o6qdinr)$WD_rQ zGT?CBMWUhD9TW)_EUm!ly)N#O)Faf!tB zvOEC%@qm_TOz^4Gru_9l(R0X^;I&xMh1e@(=NB6m%JD3Dh{ z!~kHC>si>?8BUDM1PsosKXcnb`p+vciB_`i%&6I=P_=-Pf&(xDqcIJb^XLK^>ybIx z*a;-*oS<-k;isLl$K{;0^1R@LlOFp5DKD5$fpDLbn)-2HCm;U}A z?X@^R_nmKn_5V%cQ1qNi43u1V@UqhrNFQVWAd7x{!4vf~Agfpy6rykK4P>n{6S5CA8w#Ku=9*G1=e=R?P;=!ae*>3)<_c^pNz+`u z*LGBa9OG=sCKTkuy~Hm`6NtJSK>d=%93>W)pH7$igjTs)cC-gs`b&4S7bJkLK(Qm7 z9pH)xdzJ#KDCqDH--o0bN3Y2Pout5F|ReQTP-%LKbWY5!DfzNQ;p;6^=$8 z&Wcu#G9cA8=pLLXQeO0O7<|k^=ryg1Ou6!+zabJa;c!U~StHxdgpf6ueG0J+#!;PG zT;E|DqPNy`>#?d4$g-7``SoyAB zn9G=`dFhjMqhNw&L6r2YGj&mk4U7`0#xCtFM1@uqX4KWN;2@SUhL?c}Cg$j#<>&kr z^qM+9xdYCB?*&Crc%{w>lz5Utth3Q2M>!V_I19>3;jlKZt`N>Ujh0WoO$0G<0Fn=rZWtFVviXL{Nuv>-!T`l1dd!F)% z%M;e6q%Ik$j+R+||lpyrR>bz|6qe=mHjB#!KK4F~se}ZDb>ft>QdzE{fGLSoz++*&`aP z{?z3#@{JMMF2e0d?d}yh(}c*Ay335Cbj|KIsEns0sJoCnGjg&t@dO(>;(FsPA`B*7 zwDPmNiD?}z_qNMo9YwNd0?CR(MMjc!7B|kl3}!U~g$W&V465q^ub+^EpCCUJ+htLt z_nJm-TnDQ^c{ya^;8h&~s+ILwZ&rpfl9JXZC#wM(N)$39j&^#4%5`Rq8AxOW-O8LL z38@Tqkcgc^RU$P;A_p9*2K+h~N8yJYJaNf~FUbbV*{^=XZfUUomi2J%d2a@@*g~Qe z4UNGg7eX(o^W!^^v7AxW3|+zNvE4#z(&14!A#JnqsHP)?P+BsXVm?SzS1xZdezr4@ z4OWO2A$O!Qh{@~3c?pX|I&X|}#+~3&aH%+4QKaztsh9P1uje_6`-VD1$T~2002ZJA zLg+QU@{O+|ban-T;fyEI5)}DaMPYv~JB=Or^uVYdL0m{)btuy(S2IEcSw{x`B=sN= ztvstR1kdSS*2BrK8^{O>tO`)siAHbwt2e8noiO8gm5e0a{)a0*-yzjBA)&h zRD}tM`io9F6?#cyo5w&MzitDov* zRTrq-r1U4t47ejV z4obdOZbPrgnUI))MhupKQpgjCu{$UaaUfK5<+{5y6bs}f1PzvtD(-`LD+b#zQ5*9g zeNz&hoeQG)P6~=(^DA%zgyQ&Y&J!DsyZ11c6UPes28%Z5XU_cH7eKG+k`G@>?iWyF z2P*PoYONStLj3@$o_QC7KFhix^A=n16{!a#y7Ik>qyXqTyo&uGu9d9LF!SVwk`d|Y z;8zlnY+Z9eNlKYN6B?zHG00)PIilLSuZ>V1rxTBu1H|8o0Xu__T?j)@8iHO@=Z=nq z3FZKhJpQC-lLw|EmlXihgA693E7L*TSgGr@hbp&_;$DT7$+Abi6`yYl=cbDYJveC` z>rlv4uJMw142~cMpy?xgD*Bp<=}hIea0MeHX#hc$)YzU0xS<0hH(ZZ(5W(a)Y#`(V zAU~UVwTXb527qLm5Rx+52XT#nPJlr9@-?*DLt;|U$SO~IIgrkX+83cA@L+M-iXefS zXV3Rc5kR>|*`V3-Jh zzwmiyLa%A$h7ojW)-*ZkO(|%``Jx|8Cs$MdDi!T{iMT=+Vb0&xeqz9}V@(ivE0F58 zF7Xn2|MO=>@r0mbk~?2H)h}tQ5KHFZbdK=q2sSt9eFJ53QXH!RG5-n2p8&n4)mN@Y z0#;5Ml-ZCL3|PlY_p4Az`?%eF3LOo-^jk$YujT|9Ag&|#p#p^oEeL0Rg@Xb~Qn2-3 zInd(*LB8{L7ci*9OM|FO2bnawUBc7}RIUe6@f>mJQAZvHi_hroJo=HZk6>GY`cR=w zp4;G%Pnc#*Oh*9ZsLj%$%1pvw#Cx_6DhkQ0^g3}W_dl;Q<`6n#=2xujYc=>+@lHxd z8`_vYhCzrz6>oSmoa`ZhPBw(})ZwAydK2l%njF1lJr0;va;To*v_FCR=a@*XO7$UP zm>`2neRK{bfH1x*>JMbl1fqp9JcwJ#*}Q+7&y@3mc2FEf6!CKt?K0E?cvD5Fzi=yf-KO~kvjk=iHB1ZAHjQTwwm(tPH~|Hfnv zl|5gcCTj?)TXJ5*$fXMB%HOFzI?fy-Gs_uEPMKIvS2owqd+T3AuW8Na)*v0JZ_-Yt z3Dd#QM*yc$zc4cE^-QyLpT@{eWMpEXzExxG$c$srVjN&d70bMV7F@A2NEI55Z4wyB zwZcrp#*b^1oh-^;(&){j1!9XhPARq}xmzy!+kb#F&o~nX=Ihx|$%tC@iOb>qzds+d z@}zNi9CdMOGZQ(e6FpG*d=P4Wo}#>&CYO(n$s@?m`mnhtPWupaA}|P48Z|HU zrS`Eq>#RRKt7knv(dQ#ds z%yezV+s=cd77oI)KYOKdg#>xco<#?4GZ?f@_bR?;CIlY_!8BqTROSF&K}ce{$_%g= zl2#I!x(hV5OltBmn$Dj$AI^Kr-l1kiWfqgw_R9pi1T(qqfw;l6FXuB7jwN2vZreY{ zeb4^XFqZWJ)_t6tc7`}t>OsNeMg6SOXVR?TnVdcidNSd;>;(%R2EC@+qaUtFj2yAd z-7%(3XT9_lu>7s(Nk65(^v7*yqy$hx7n8!EcBWsjMwPayU^u2@LI*=fF0Uwq`)0-sLP*8-^6UlNrwB3zmQ|z4+oX>2RC3ZY{(a57?Q}GTqZbIs3J5 zg!uytv~Br|G5{E+k$&5LnR~!YNZ-NGj*}xRmj{P`7l;bwBq;LOdJThEwIHR1QAJ7< zuh+EZ^Vi1JwoWN}ttf9?bJPwtj%DIa!yC3g^3noA;b3(0jM(XWTEwYZors)%bD)_o z;@B`+F=I*Gc_yT3c(9_2^(21A5?EXjc&*o^wUpAbow}?*27NdhKYN;zE_&wkURWT6 zOh#iQIYSdLdLJ~UiBngRHM;beo-oA_1B)omscHc_A#%B_X1J*;k!AEGg|5H$I@p_Z z$%if#9Af^k>&5St z%}0%_40D5RC@3m4-)Y0=AoZH8sNnijI^jvZ`AY|*e(Jbg)&g~<7@l^LaXvPfEK@Zm z4m6)@B<_pfoq;*c7zk>bJRg1ENA_y6k3{#;$c;DT@0BsOit%sMXVnSUxE2geB#O0ONQ!IxC<2mg)iH54Ea+GYp!GV{vQ5phfi+QO8{V z7rk5ODP8`_E3)G~$J)Bm*eg&PptLdQvobv5sEo>t2^iksR2i{ubyYN^@OKx&SXIO1 zXlA6oc4>`4L$5G}hbDncXFaI?>5cItI-40J>N#BU;eUiZO;>#KpNqPMQDb>qw)D1J zabXmJ!S;#KE|>@{BDPL69S~7VXz*Go4;bTy2g+$VY{?b@+eDYjShwrDEl~C$0J7zrm`j zt|%r7Ti9t*^t#VG8AZIdYxN~HPVyb02~{Y}$L}$BYKLbUxCYYX{W2lQUQMfuR>mSH z%>W$jUe(w98G6TSHMQlU3;rIKzhxg7^WA?F-Ey}Rcp!?S>Q#vZ;J%}}*2>pgl`gqf z^qnV+H3Tg!QqTcTa9zZJ#xsuJ23Wb#Tz2}W)oypJZYl4Wditv6b2L{Evf|g3?qTO zBOGW?5nW4>-AAAJM0mxE{|H`q`t#waBL`vr{P}r3eDziT94*RqRF>+8JiwlOw3~a> zIg@3ZR#Wof0l7&|%jM!_J8aMa0%rm_urKzx$_6+9qh*l2H2IfE&s-vI;j24HVfKCUN%ffziM9&E<#NcEyFZN;yXcBKC+E5T%PCPof2 z_S|E~k|>~E!jnE*=R|kcBDE%jjGUP{t9C2>ILoJ5)UBm5W+Y)S%jV9wlN^A)7ZHHB zN>~Jt29ohWd-!CqIq&6HeLVkxAr9(!mCUx3)fy5N;JwlB^>*-8N@>eOngH4^JC*I) zv3_^dcD@d#pUkA(wt{tuW=`sHs+I%}5LQ*noGSvSoO}wbc=KPuqLcUhSef0W^WXhW z*zl7dOFhb#PM1_gmvq#mrtzqg)Ouo+CkTNZQv>9;x)hCPAnVnvySG)WPkKL^p7Okp z*MaCERyU9s$VzuPYJh}xzOXn&rvTAC>~Vq4Ffl-B&5MXII1`u41WWVlTzX)sp^-KGQ zG5_Ij;nI)%qmC=^cqtNkanTv0Pm)fwl&Xe`#(m(PR7P)Rx~g==`=YawP8#ay-UNAJ zLFCkwAoxjW2(0FoR3fCGyF?L)A^F&2UqF#7~MZN_W z$8oG(Ch+3%@acG*&j0132hF`@-pJ+(3m#pHN2{&Uzq)c~v%lP#716HUrMT zh4DySRE<>^PIatIA2Pt2LnDCHl$c|AG4L4tj4eT5`2%x3!}A`W!0f~6x} z4-NXIgCvHZ@k}`Ww~miUc}h?1-_x}ImYd;K=e|xauy{5=Q7SZ0OhQqks;ZbwVEPh_ zhzFw{Fr7etJ0ooX%V?v48yROEw?SU@;#%!>aXJsBpyRxY3)EUKW< z{UV-0L(2dP$F&R;Gz|nO9OAr0${mt*S~`>@D^$t+#_SfVR1$R3J3*N41!@=k$k9Apfb~HkMMRx8Hv_!4lIthuFgiy z&dCD0Wk#6}H7oG6v?*w4^s=h)3~_K(@Z`{eEw{XR=<8 z{_Q8h=B-;wHH9o$MwmjcGVO#0k~$+f67zlaGoO#1fdkKk)1}Kl^>KL9d2h{qgHXmk zG}WwPJ)BP=;k@aesscUB-z;wel)>54l+SdOI8ki`e#~lPB{SMjp8VcDY7nJV*D#U` zNa$qt&MY;|agJ|=W_s$=DN&8fvJOOEk#;gJt4V_y1^55ONsQ9i~iXVuj06~d6b z#!Y>0(ei3ac^pUru(K*6wfHOr=Sea)9X2fd~@zWPry z>NX8CAR^ijusrFi(lE4b<@UXI#k(Fb#{BaYZ_9r|V*>=v&{(7$^%dP*%D8spS`o%) z#?cw+#*-8P3Y&yi$?UVDO0>{hQMLL;Y#)jUhxpLC{Mp}@0-T*G&K1lcGsOHkJ5Uxa zsVv?@R2WtkO|jJlLx%HqzpFjz4LW~{Qbvk%kwGRUwrgXZ|S(!-E1H6{Q@ z8}az2&xFR-aW4SZ--pL4Rj|%Br(n*$I$VPgTS9YTq&PPP9Ww#=*gL1z8Yk8{nt=l? zaxn-KRMk|Kp;BLKHO&NIB1+^>ytZZgHn{xLpMYLd673o3oGSdb&xx4a=H@+nEe-C_ zvHSi~uU=DP$frK%nXvx*w_qPA!pb$Il^st;HftP-8V4Z0*d~*qe(rMxV8_(Z-5eu_?cu z#tA}0H1YHNJ3X`RTi=L2&#yzTY0=Z43GZEgVc9lk)Chy}(hg%NGM%<0>-Yetq`JIm z#oOV;=Pk;8wP={qbdrXD=ZS12lHG*HwD!hWayB1*a^zAS8ryrUVa)skDj{<{%=CR6 z*XmX``{$b6ef)0-l)ohvJBG^D)djTgo>%AjBXQ-1oI&T-1? zuA$tr%Fj;Os!QqAlb!+BeX93&NT&3vKmRjW{pqyE@5(w%RJxL7YF`KD&xap=V|_;B z{hg9tdHJWWgiAmA!R#VJnxuAAq|5VLQ8evtoGgage#j&&`i6PSd?3$H8Sngr#ptq* zR&u=0>dQ2Z_<7X$t#@|p^DStmjXUn_d&Jz~_-!zs#1>Q+$%Bz95YdLh!ZldD^qT>7 z2;{J)ay^!OnGME7BShVamVmj8s?xIU;;H!Ia1e(h5-!{eNB61mxi7D~4(__=F4I5T zZ~CM*8|^$ddgu5!%$hkXBk}%92_66V&;JzOeEwhN@8i41jlYoV2WbP-UunqW5#&_7 zswxA9`IUeUg073xk~C$&8l34bz_h+^Y>76&RopHrDuHHSJ}YR|uJ7Nqy4l~U$Qe`L z6AwQpgzBPvZsqu-yrTz?sH2r_8Wav!1JhPy7d|*Z;{XF6HtK*}E{w!VP5yn;+nhAr41Kk@R@4vOnk7fy=3C%pIy`J|McTLI55yZyYKe++(6hiL5$SID6HD{$tiyo zt_IOn33}Bn!(swd9MOM#FVMSsT9rl(F#~cJkj?EtD3#NS*L#-#ZMMYsCM5=W)tmk_ zGl(!EF$13lipYuW@OizzC5V$A`s;Jv3g^A)?e|+(dMn8K@7c}= z0OfH`w!!Sa^i*f!`*$BT9X)mnLhUCWak2Aoc9`r!I{jD(B9wBfQv_r%JM*ORL1Qp$ zvj)zG^9v&Lvy~A^GCLI!(J;45XegrCr#9Vgzkzx4;5%RX#y+iMpa0$q;ew0)4oWS` z6~DR70SvK7{4JO_kb_L-&7B8~bScjrKi&|TazhT3PRJ-clOtw8&qcLp2$-o5wKiBK zXxsxxc}^y_B~A$hMjbP(!Kaur>LrFmi3p9OW+1D9p3Z6I=y%5jSd^U^Cvem`+g0n_ zDAF&Uj^?{(&Z7?>c5PUj3imrEq)*BaO#h&>F_-8HGc)irA*Cxv7i^egIZAOcG;2dn9D96@ zVA{NOGet4!J*$ISiQ#4MegLbtI%`-tk_LiyrZ3J;d?*kRbwQBd=|^S9#iFEKw=|RH zfE-B#=us)2A$m(21cgC#P;(m#<TCMjir<2$<0nL&k|1C$UfO!cljVq6!bXMh}6C z5Zb82Gd{KJ`p9YGMK)2<0i<*t5O`lqi8(13$emIPG@tr)jBLE8DfSp!+vy_+Eb?gG`FJ(@XUkBII zWDph3h!%^J&F68VXbmXIFv|QpU%qj_#Ze}g&g!eKfXhE~C0=l*9r?E_^)fL+4DV!~ zF`^QT=wwbbXcuVWGDGm>oX)SD?%^@@W|`6EW$-q@pyhG~AciN8fGgM5>`$X|beQHF@hVmcf0b`(@6Ap5W`XSve=S60<`y7#DW;J(%crgCZ74nQ-7# zH`S5Tj#rc~08Ba8$LhUYzYxvnT??ao>AHxZ`!mot88tVgoubikpH3y2&gUo2{6PD| zjr6ho%2L34r4P}oSyr(!7fL^)UEuXW4NeAyOg}KRF?42CZOWOUAr$T5x=X(%m^PS1 z{q?ijdD*iCeN&w7&2+!anNr^q7Oag-IULeEizbbw9D+c3MTF*;H}mXcOHEx2X}K%9 zTa2|Qd!-2#tjnRI4RK6J713pIbNO5_x)qomf?h;gib%iiGhaMlk?3i=NZQZT`6;@G zHbrYZZ$XZ2N$#P1bWXt(Y}vXgOvgaL#)bkz5MUDq7nO$4&`waBtoQ~VD;&8xcnba~ zcU6W^ig2cHP0N*bJB=MD)B@w!^jG8aS?;`Q z#BW`|&hblhRMeNtkggz{G8aB42ZY(Y)Iw|Birxfn%6IG1;MFLLCbD2a1DAq<45(8U^RPo2UQkLj1)q`k)z2R*w91|Ii$>)Wk!du_e)1`U-#)R?A6hM`y-_z z#Gm#1r(^u7p($`Xphs`&zFf!F-&BcoJ?RMw*dWN4^<qV)ow*#*4Moc zjWM&nO==3AX%Og*toRJb)*R4M!5&zc>7H~=dfiTcU$qkUFtzqHBW#@LxCQ-3#Q`14 z@p_ZQJkm0C0a=0oG-osDTZ$`v&gk7l4E$R0yLXJOqXUTd8F6JDo<)xgaEUac*HNKK z2mHuCe>B&-Klh36X*%ZUCuEmYS}l@QrhwwsHD5wTbX7e+Oj~B5V_K`5%Q9$;G-Z!U zWv)A!?EJV&JX1~v3?Vg(KzS&{)u2}1Bji_3{=Y5Pz#gVOXUpCnx_;av6t8#uZQGVW52+{Sgt75)_prWQ@!RRi zIUBlB*@c#weMaA-9`Q_9{Y5B&iZbb-$bfhw@D?jW9}#2D9&v)@u%a$pNlX`@;hZ+3 z$VVKq&YKZEKDYjR>*3ljeKyBq4jtS3YY+D}rSP}QKXnBf5&4b6II+=CtVMiFw^?jE z?lOyA16-!x1rwWREP|>n5Gb!JCO=OY9xH1U731!dnOn2knNj2a=lYEkqtHXzW1W+e zzis=)E``)5-KH-gQ(fpU&bg8RL322uoxzD5|D9Zr^Y_EPLat;g#pUW{=Jd-5*KaUK-quZATZAr#)JN zUS9R|+-{nnDu#m^I}8Aft|YB0T3*fH0gq;6I$|9)Sa%gBa;g`S$cS_+{`-*Hv5x3E z+PVsQOg%GaN_DrrEH-AW>aXb79aRW3!|`S}+p#H3!VJyC_U3>vVje4Y9r{r9y_^9W zut+OHVahcCLr9)HS!r_w5Y7xd2!pTsy5gU%8Am&fJF-+bB=VA=ID2vGP*dBXBI1e8v|TRY@=%+3*Fs9yMK+5=EH+IeiHZhZYN zGA1MrTRFZ5KF#TpgMCP?-<-8J_GUOt*691pJpj>T^yratIgOc-S3CG};V3rwn}n7y zGE<*0dyaMq@(y;^kF2p3B%&Kc*R143VUI-su=+K(7dr-pqD}$C&gkfcj-QuI&B;VGG*~Cdd8?@V zqHQ4u$}+trFd3x1FdIV{+b*u3|IdzPu$O6{m=lf}7_26C-V}=&fL*cSlU@xJ(=n+m z6C)V@48pjU!G!1{XN46-H?w1qKZF@I7mI%JA#JxOKb(dzto)IU%8E|Kbp;tJC+e zvleALNbePm^7ml;p{nEon|RE?EY5W>jP8_G2Xj<(W@6?E@$sLuDbvkrSOqtY$RadQ&34}UzW%Oe+-%Khe zEuIk_viRrT5rdhyODxXxOeSbBv;2=g8!ad!u`{Ag4VN9-P z-_v0G;z-o9a}Rd8yt?C9tOz-HC{;wF$Z6p{7C+K33J=doHAfa<>~_M_&=~nl+42PA zr~}>r=0kJAfMz||fN8Fe+%vMJ!~;0vH?)&ShE1m?Kbz_vn71Iis8Y}e27Uk(T%X5S zRT6zU0sx3E$rFRAqqJpfyBUsXmnnnLUeUOzqcU=HUvs&D$AYUkcQPvZ-!wn_vFvuc zTG_pAd*s4vFJCLXHjp}Zm7z^IxjER0w`-aX?rkjVbpVG zYAMr_bq=(=(P+1-QD*UjsTIuLst{Cd;QkOCI06j-MPb9$pj&RzbI81z;|a~X+0U_B5-pJ9tpbxHdka$dU!5MrCb z5Eqbb2pJD75*caP+))-MQ3O0VL76U<;R8io8TXWBASml~(gS5&W(Lk!F)BLtaG-kP z01DkuNC6CXduC4&|%EIqM1k0b?QT#+9)w*yg|pRJaavh z+8|2cLCj*tm50+>NE5N9mmRIi7pkiOdT4MD82yxjg7XY;G9h#_VO<^!8dLsYbUUEF z6pS4d3zZfPeUG{lOnZf;1u029i^^c>Z0Vzu*`jfQ#TG@=zkRW9eYxyTnALaMzUrAa z?VX=o$Q!qKtwUg5~_qG9fWn zr2`A(12qDU+F>_wF`^MOG0gK0PP;Zuemq`9N&i>Em^c|7p;2xFi|qiS>NuGMtSORS zZqyq{t22%mi?2CFEg`JgTEX;D`gxTs)ZW60F4Ll%1TqR#o}=qdvtpfjjI$;>w!axO zrTr$>C5`z`^=qv=V)GXR+B#}UJ05jnfKs4i7LvzK@>-D(A_fsyZMm!=x#G=X_Ej=! zaFOVCPU_>qF7;D$&OLh)Kn1vE5@+{G@k8`RHs0fnh#3&Y0Bo3KNr5~WoG`geEMp)^ zJ1a-)2Gl0n1zU<}G-_O-ZYX`RE@OOw@vpim4aEEH$iRJMBtrdkxUG9D?B}%qnKP!a z$&b2$I3!gy>~esq641W(MNdJijP>WTu4jFZ{G4SRJT_0?8=1eG$b7lSWy)Ccgm5~@ z`T3S!7bF9*(x43}kO6#U;VhJ;vy2>E5mQy)hDy+<_aw^J?uT#{;f?{&nwg9@i zM9#}S&^*Dk(dk69E~-lU?UZKR*0gM${FyGl&}x~#z57Kt0O^1*XG&qrkMu3*OT#&w zP7})j<8kQud`87OW+*4?>r8z6CS4|O^Swq6%CIlN1;bdF%i+IH8By#IDlN03 zD1WZED2IM?d#o(rzOp2!#QEbSBFheXlQujdd7`k-(Y^q;a<;!Xv0cy!F7z;MV@9kD z^GaXS0l9+oP9&HzW(!*V*!Ol-Et~kC@l|ku(g9=6lEW(tEAc5s*xnPGU(Ju*v6+eg0{t#Vr{L|lvF z&P=RaE;Ez4rxVIi8PpfU3`!TI0ZtliPqR;zoutkcE;DA-K>ajSCsb9m=Na8{=3GvP zh*`~OFQ2mOmkILlbKf}jnODkPfmSGv+O+{5{Hz<1Nx!8`^XNYPQ8FTw8 zIKb(EGiOSZkwN<&)*l(PJzUYt-knzhGV16cSltasC&cR&p$;PepBsuOX5RNsXO>IZ zq7RzM5LEQD_+_!lB9=TelwXlq^g?j5yjOuTwxT_d7)Az{N!JjU(l(lWJb_rGW4m=t zh(iZ~CvMvI(lSbgneZ)M60J&Uqx7f>Jy~gwdT%Q(N%r-(b3fazy==#Ay~k$mO>%G$ z)10FR&WZiIC=sMPS%Xje;Mp(dtOL1xPDK>CJOUWwN8LoaJj^fG(%)K6SuWNd%#ki- znOvXja0K2u;l${W?I~PdQD5obEOs^)z2sj`f3r~&cpYC+Gk?-~sZw@9Gb~Hn1_gcX zk|nn>C52pptzP?Uek$hMlIeA_fx5oD7xZN#r(E4~WxqhD zWjno94PThnan7GMwwH04dz%hAbEY(K%p(UOOs`yRAXe|Fg%aPpaTwK1URno&C@{$?NA~K0XPtWo*!oV=yes8)?c{BzR8Lc=S zn%e-%WTK-^M@**-CrAs1SwpZHi?fo7Q=>>D6fiYfdw!vaH6ux0HUt6 zXSShDFG-8iX>~n5=bW*|D_9Ozdcc^I)5DK>_=-rJ<(Y_Gk4zdGK@~J&-W=N}agRLs zP6-W0#BmBnL>Kugb2=~$c)G{Od%9%3JoH?ooIRf}qF}T66 z)K~4ZTwdWOlE{B8yPD=SIcJ&|f%`OK$R=s@A1V~}(HCPBt2AD35(NnfCuHL)z?IH{{_S164Y!%%^^%{BGJY5F2F z)9N#r(@@cg>R=}ayVO{KTg$y~7NR90b6DNKwf~&X10=?q>5ySgPLDqJ(dPtLEswMs z@ZB2fEb1rA1NTj{)qh9mXhc8ji;j$_j4UZizf~#ng4Gv2M)~mD*$h*rw$9AO$2g#EDDvyk8TVT=`v@BmZXI6Mi0RSSyu zIDv9t2vdn@P}yRALdo`wK4`Z&ki=aR^DOI(9vWzA(;>;6oF0ALkxS$1#`5@eFd@=p z6!VEmgRyE^jPf3DJ*tliaf&>44E6aS`W-YZY!&ZD;gz~TCIjoG>b~LZjeMb52fLLF zQbNhV`Z`4@t$u(~qU+2Qy_c9zCSc#perWf#d3$dsUP??k0*7ciq?t3N!J)yyXzQ$q z%aLbgq>F=9M{z$HMZJ3Oot(QaR;Y7@8>Yc#B{SxKXh3D_azF>PeSv^&nA5qy+089w zVy@4)Z^SSIm|}Tnbfn3|{js1f{#sU19Q#xoeRSM~xXKeoR?v;!YAy(-_r;=?+boQ4W2J&h&PFAO1#0U)2wND{mdW zwF3`=^q^r*PDc+NJsexTJPyV%FL8D!Co`JXT|KrtCEji<{6}IoyB0Ack3AU9sFrlnUAwYQ>dl!;s)5-xa3h8r;?SNYFPY80 z-@->}5(i>HLw7BdNC2aD0PfZ`UI;E*>koyVDKi0_X*-3_wGbs!^ia-L=jrjFWJ*pC zTIS?*%u|m^NV+t-XU-CV8pm(f_^ybkUCboz7d3v06GJQ+3L^%0Fa~o#nZ6yu8OAZH zLC~em;vCUX9t0a2PI&vBUxX@wDq$Lf4lB;g*w@#W<1I;z8H?C@O{iL{Z~M-zBk&+j z4|?Y0bj(S|3_>)VqF%Zv_G*yVYLdwBMv>o5FIs4bZ%)A+b|sAF8lC`vQg1AhE0EM$ z?f7ApR75*{{Y)tQkyE`2(D=}WXCCpg0szPs#nMY!IYx)lBTQxc|`j9}$>C!`*Ic-Xe z8pZx_M4U4tlMY8D8(?vZR(}_K*XLKrB)zg5KfzBY!Z9hjmPw+@&HbioP^by<|16@D zE}FJMv{K}Gi(WN|`-D;ydTir0aSp9(&4Ftk$_#1KFAZ}xQ)JfRIQB!4LCys4hJp(N z3Wmfyk&`o%0-ZZgK2_b;q1zk4SpQr`-p3UGYq#1^Y)Yep4=UMZYLF8gF=J~aUR@Wz zkBt7u=mQ=h^gyIvTIOt~6Hh#GXwpp%w%UEebv=1P-d??gYU$8Mx&SZj`(wQCd?f9*0;XZfnTLxG3WiI#I&Im1|nt- zMs6DHYxgbecDn;E9aa{TYsF6w1FWxdWKv2Yo$iZzWGC$@uYG+-ET"Matrix is an open network for secure, decentralised communication." "Welcome back!" "Sign in to %1$s" + "Open Element Classic" + "Open Element Classic on your device" + "Go to Settings > Security & Privacy" + "In Cryptography keys management, select Encrypted message 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" "Sign in manually" "Sign in to %1$s" "Sign in with QR code" "Create account" + "Welcome back" "Welcome to the fastest %1$s ever. Supercharged for speed and simplicity." "Welcome to %1$s. Supercharged, for speed and simplicity." "Be in your element" diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt index 953693b40d..1d24d775be 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt @@ -15,6 +15,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.features.login.impl.classic.FakeElementClassicConnection import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode @@ -39,6 +40,7 @@ class DefaultLoginEntryPointTest { accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), oidcActionFlow = FakeOidcActionFlow(), appCoroutineScope = backgroundScope, + elementClassicConnection = FakeElementClassicConnection(), ) } val callback = object : LoginEntryPoint.Callback { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt new file mode 100644 index 0000000000..1c76a93650 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt @@ -0,0 +1,429 @@ +/* + * 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.login.impl.classic + +import android.graphics.Bitmap +import android.os.Bundle +import androidx.core.graphics.createBitmap +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.androidutils.service.ServiceBinder +import io.element.android.libraries.matrix.api.auth.ElementClassicSession +import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker +import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.test.A_FAILURE_REASON +import io.element.android.libraries.matrix.test.A_HOMESERVER_URL +import io.element.android.libraries.matrix.test.A_SECRET +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.auth.FakeHomeServerLoginCompatibilityChecker +import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class DefaultElementClassicConnectionTest { + @Test + fun `connection can be started Element Classic service can be bound`() = runTest { + val connection = createDefaultElementClassicConnection( + serviceBinder = FakeServiceBinder( + bindServiceResult = { + // Element Classic is found + true + }, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + connection.start() + runCurrent() + expectNoEvents() + } + } + + @Test + fun `connection can be started Element Classic service cannot be bound`() = runTest { + val setElementClassicSessionResult = lambdaRecorder { } + val connection = createDefaultElementClassicConnection( + serviceBinder = FakeServiceBinder( + bindServiceResult = { + // Element Classic not found + false + }, + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = setElementClassicSessionResult, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + connection.start() + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.ElementClassicNotFound) + setElementClassicSessionResult.assertions().isCalledOnce().with(value(null)) + } + } + + @Test + fun `connection cannot be started in case of security error`() = runTest { + val setElementClassicSessionResult = lambdaRecorder { } + val connection = createDefaultElementClassicConnection( + serviceBinder = FakeServiceBinder( + bindServiceResult = { throw SecurityException(A_FAILURE_REASON) }, + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = setElementClassicSessionResult, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + connection.start() + assertThat(awaitItem()).isInstanceOf(ElementClassicConnectionState.Error::class.java) + setElementClassicSessionResult.assertions().isCalledOnce().with(value(null)) + } + } + + @Test + fun `requestSession when messenger is not ready has no effect`() = runTest { + val connection = createDefaultElementClassicConnection() + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + connection.requestSession() + runCurrent() + expectNoEvents() + } + } + + @Test + fun `when an error is received, an error is emitted`() = runTest { + val connection = createDefaultElementClassicConnection( + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_ERROR_STR, A_FAILURE_REASON) + } + ) + assertThat(awaitItem()).isInstanceOf(ElementClassicConnectionState.Error::class.java) + } + } + + @Test + fun `when there is no Element Classic session, ElementClassicReadyNoSession is emitted`() = runTest { + val connection = createDefaultElementClassicConnection( + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving no session from Element Classic + connection.onSessionReceived(Bundle()) + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.ElementClassicReadyNoSession) + } + } + + @Test + fun `when there is Element Classic session with empty userId, ElementClassicReadyNoSession is emitted`() = runTest { + val connection = createDefaultElementClassicConnection( + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving empty userId from Element Classic + connection.onSessionReceived(Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, "") + }) + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.ElementClassicReadyNoSession) + } + } + + @Test + fun `when session is received, but homeserver is not supported, an error is emitted`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(false) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + } + ) + assertThat(awaitItem()).isInstanceOf(ElementClassicConnectionState.Error::class.java) + } + } + + @Test + fun `when session is received without secrets, and homeserver is supported, ElementClassicReady is emitted`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = null, + secrets = null, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = null, + avatar = null, + ) + ) + } + } + + @Test + fun `when session is received with all data including key backup, and homeserver is supported, ElementClassicReady is emitted`() { + `when session is received with all data, and homeserver is supported, ElementClassicReady is emitted`( + withKeyBackup = true, + ) + } + + @Test + fun `when session is received with all data without key backup, and homeserver is supported, ElementClassicReady is emitted - backup key is missing`() { + `when session is received with all data, and homeserver is supported, ElementClassicReady is emitted`( + withKeyBackup = false, + ) + } + + private fun `when session is received with all data, and homeserver is supported, ElementClassicReady is emitted`( + withKeyBackup: Boolean, + ) = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + doSecretsContainBackupKeyResult = { _, _, _ -> withKeyBackup }, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + putString(DefaultElementClassicConnection.KEY_HOMESERVER_URL_STR, A_HOMESERVER_URL) + putString(DefaultElementClassicConnection.KEY_SECRETS_STR, A_SECRET) + putString(DefaultElementClassicConnection.KEY_ROOM_KEYS_VERSION_STR, ROOM_KEYS_VERSION) + putString(DefaultElementClassicConnection.KEY_USER_DISPLAY_NAME_STR, A_USER_NAME) + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = A_HOMESERVER_URL, + secrets = A_SECRET, + roomKeysVersion = ROOM_KEYS_VERSION, + doesContainBackupKey = withKeyBackup, + ), + displayName = A_USER_NAME, + avatar = null, + ) + ) + } + } + + @Test + fun `when session is received with empty data, and homeserver is supported, ElementClassicReady is emitted`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + putString(DefaultElementClassicConnection.KEY_HOMESERVER_URL_STR, "") + putString(DefaultElementClassicConnection.KEY_SECRETS_STR, "") + putString(DefaultElementClassicConnection.KEY_USER_DISPLAY_NAME_STR, "") + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = null, + secrets = null, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = null, + avatar = null, + ) + ) + } + } + + @Test + fun `when avatar is received when the state is not ElementClassicReady, nothing happen`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving an avatar from Element Classic + connection.onAvatarReceived(Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + putParcelable(DefaultElementClassicConnection.KEY_USER_AVATAR_PARCELABLE, createBitmap(1, 1, Bitmap.Config.ARGB_8888)) + }) + runCurrent() + expectNoEvents() + } + } + + @Test + fun `when avatar is received when the state is ElementClassicReady with a different user, nothing happen`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = null, + secrets = null, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = null, + avatar = null, + ) + ) + // Simulate receiving an avatar for another user from Element Classic + connection.onAvatarReceived(Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID_2.value) + putParcelable(DefaultElementClassicConnection.KEY_USER_AVATAR_PARCELABLE, createBitmap(1, 1, Bitmap.Config.ARGB_8888)) + }) + runCurrent() + expectNoEvents() + } + } + + @Test + fun `when avatar is received, the state is updated`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = null, + secrets = null, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = null, + avatar = null, + ) + ) + // Simulate receiving an avatar from Element Classic + connection.onAvatarReceived(Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + putParcelable(DefaultElementClassicConnection.KEY_USER_AVATAR_PARCELABLE, createBitmap(1, 1, Bitmap.Config.ARGB_8888)) + }) + assertThat((awaitItem() as? ElementClassicConnectionState.ElementClassicReady)?.avatar).isNotNull() + } + } + + private fun TestScope.createDefaultElementClassicConnection( + serviceBinder: ServiceBinder = FakeServiceBinder( + bindServiceResult = { true }, + unbindServiceResult = { }, + ), + coroutineScope: CoroutineScope = backgroundScope, + matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), + homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + ) = DefaultElementClassicConnection( + serviceBinder = serviceBinder, + coroutineScope = coroutineScope, + matrixAuthenticationService = matrixAuthenticationService, + homeServerLoginCompatibilityChecker = homeServerLoginCompatibilityChecker, + ) +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/FakeElementClassicConnection.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt similarity index 72% rename from features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/FakeElementClassicConnection.kt rename to features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt index 2c41d2ed0f..6b601543ce 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/FakeElementClassicConnection.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt @@ -5,8 +5,9 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.login.impl.screens.onboarding.classic +package io.element.android.features.login.impl.classic +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -15,12 +16,14 @@ import kotlinx.coroutines.flow.asStateFlow class FakeElementClassicConnection( private val startResult: () -> Unit = { lambdaError() }, private val stopResult: () -> Unit = { lambdaError() }, - private val requestDataResult: () -> Unit = { lambdaError() }, + private val requestSessionResult: () -> Unit = { lambdaError() }, + private val requestAvatarResult: (UserId) -> Unit = { lambdaError() }, initialState: ElementClassicConnectionState = ElementClassicConnectionState.Idle ) : ElementClassicConnection { override fun start() = startResult() override fun stop() = stopResult() - override fun requestData() = requestDataResult() + override fun requestSession() = requestSessionResult() + override fun requestAvatar(userId: UserId) = requestAvatarResult(userId) private val mutableStateFlow = MutableStateFlow(initialState) override val stateFlow: StateFlow = mutableStateFlow.asStateFlow() suspend fun emitState(state: ElementClassicConnectionState) { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeServiceBinder.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeServiceBinder.kt new file mode 100644 index 0000000000..0a24f13fa7 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeServiceBinder.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl.classic + +import android.content.Intent +import android.content.ServiceConnection +import io.element.android.libraries.androidutils.service.ServiceBinder +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeServiceBinder( + private val bindServiceResult: () -> Boolean = { lambdaError() }, + private val unbindServiceResult: () -> Unit = { lambdaError() }, +) : ServiceBinder { + override fun bindService(service: Intent, conn: ServiceConnection, flags: Int): Boolean { + return bindServiceResult() + } + + override fun unbindService(conn: ServiceConnection) { + unbindServiceResult() + } +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/Fixtures.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/Fixtures.kt new file mode 100644 index 0000000000..9039743fd5 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/Fixtures.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl.classic + +import android.graphics.Bitmap +import io.element.android.libraries.matrix.api.auth.ElementClassicSession +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.A_USER_ID + +internal const val ROOM_KEYS_VERSION = "roomKeysVersion as Json data" + +fun anElementClassicReady( + elementClassicSession: ElementClassicSession = anElementClassicSession(), + displayName: String? = null, + avatar: Bitmap? = null, +) = ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = elementClassicSession, + displayName = displayName, + avatar = avatar, +) + +fun anElementClassicSession( + userId: UserId = A_USER_ID, + homeserverUrl: String? = null, + secrets: String? = null, + roomKeysVersion: String? = null, + doesContainBackupKey: Boolean = false, +) = ElementClassicSession( + userId = userId, + homeserverUrl = homeserverUrl, + secrets = secrets, + roomKeysVersion = roomKeysVersion, + doesContainBackupKey = doesContainBackupKey, +) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt new file mode 100644 index 0000000000..1184bb91af --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt @@ -0,0 +1,278 @@ +/* + * 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.login.impl.screens.classic + +import androidx.core.graphics.createBitmap +import androidx.test.ext.junit.runners.AndroidJUnit4 +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.features.login.impl.classic.ElementClassicConnection +import io.element.android.features.login.impl.classic.ElementClassicConnectionState +import io.element.android.features.login.impl.classic.FakeElementClassicConnection +import io.element.android.features.login.impl.classic.anElementClassicReady +import io.element.android.features.login.impl.classic.anElementClassicSession +import io.element.android.libraries.matrix.test.A_FAILURE_REASON +import io.element.android.libraries.matrix.test.A_SECRET +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.sessionstorage.api.SessionStore +import io.element.android.libraries.sessionstorage.test.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.tests.testutils.WarmUpRule +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +// Use AndroidJUnit4 for the test with the Bitmap. +@RunWith(AndroidJUnit4::class) +class ClassicFlowNodeHelperTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `initial state`() = runTest { + createHelper() + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + } + } + + @Test + fun `after a few seconds in Idle, NavigateToOnBoarding is emitted`() = runTest { + createHelper() + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + } + } + + @Test + fun `navigate to onboarding if a session with the same account already exists`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData( + sessionId = A_USER_ID.value, + ) + ) + ), + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + anElementClassicReady() + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + } + } + + @Test + fun `navigate to onboarding if Element Classic is not found`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + ElementClassicConnectionState.ElementClassicNotFound + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + } + } + + @Test + fun `navigate to onboarding if Element Classic has no session`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + ElementClassicConnectionState.ElementClassicReadyNoSession + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + } + } + + @Test + fun `navigate to onboarding if there has been an error`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + ElementClassicConnectionState.Error(A_FAILURE_REASON) + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + } + } + + @Test + fun `navigate to login with classic when the session can be retrieved`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + anElementClassicReady() + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + } + } + + @Test + fun `navigate to login with classic when the session can be retrieved - ignore avatar update`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + anElementClassicReady() + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + // When the avatar is retrieved, no new event is emitted + elementClassicConnection.emitState( + anElementClassicReady( + avatar = createBitmap(1, 1) + ) + ) + expectNoEvents() + } + } + + @Test + fun `navigate to login with classic when the session can be retrieved and navigate again once the session is verified`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + secrets = A_SECRET, + ) + ) + ) + val readyState = awaitItem() + assertThat(readyState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + // When the secret with the key backup is retrieved, NavigateToLoginWithClassic is emitted again + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + secrets = A_SECRET + A_SECRET, + ) + ) + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + } + } + + @Test + fun `navigate to login with classic if a session with another account already exists`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + createHelper( + elementClassicConnection = elementClassicConnection, + sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData( + sessionId = A_USER_ID_2.value, + ) + ) + ), + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + anElementClassicReady() + ) + val finalState = awaitItem() + assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + } + } + + @Test + fun `navigate to login with classic but do not navigate to OnBoarding once the user is logged in`() = runTest { + val elementClassicConnection = FakeElementClassicConnection() + val sessionStore = InMemorySessionStore( + initialList = listOf() + ) + createHelper( + elementClassicConnection = elementClassicConnection, + sessionStore = sessionStore, + ) + .navigationEventFlow() + .test { + val initialState = awaitItem() + assertThat(initialState).isEqualTo(NavigationEvent.Idle) + elementClassicConnection.emitState( + anElementClassicReady() + ) + val navigateToLoginWithClassicState = awaitItem() + assertThat(navigateToLoginWithClassicState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + // User actually logs in + sessionStore.addSession( + aSessionData( + sessionId = A_USER_ID.value, + ) + ) + expectNoEvents() + } + } +} + +private fun createHelper( + elementClassicConnection: ElementClassicConnection = FakeElementClassicConnection(), + sessionStore: SessionStore = InMemorySessionStore(), +) = ClassicFlowNodeHelper( + elementClassicConnection = elementClassicConnection, + sessionStore = sessionStore, +) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/FakeLoginWithClassicNavigator.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/FakeLoginWithClassicNavigator.kt new file mode 100644 index 0000000000..e5ff91aa91 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/FakeLoginWithClassicNavigator.kt @@ -0,0 +1,18 @@ +/* + * 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.login.impl.screens.classic.loginwithclassic + +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeLoginWithClassicNavigator( + private val navigateToMissingKeyBackupResult: () -> Unit = { lambdaError() }, +) : LoginWithClassicNavigator { + override fun navigateToMissingKeyBackup() { + navigateToMissingKeyBackupResult() + } +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt new file mode 100644 index 0000000000..3bd2dd0cf8 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt @@ -0,0 +1,293 @@ +/* + * 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.login.impl.screens.classic.loginwithclassic + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.features.login.impl.classic.ElementClassicConnection +import io.element.android.features.login.impl.classic.ElementClassicConnectionState +import io.element.android.features.login.impl.classic.FakeElementClassicConnection +import io.element.android.features.login.impl.classic.ROOM_KEYS_VERSION +import io.element.android.features.login.impl.classic.anElementClassicReady +import io.element.android.features.login.impl.classic.anElementClassicSession +import io.element.android.features.login.impl.login.LoginHelper +import io.element.android.features.login.impl.screens.onboarding.createLoginHelper +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.libraries.matrix.test.A_FAILURE_REASON +import io.element.android.libraries.matrix.test.A_SECRET +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_NAME +import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class LoginWithClassicPresenterTest { + @Test + fun `present - initial state`() = runTest { + val presenter = createPresenter() + presenter.test { + val initialState = awaitItem() + assertThat(initialState.isElementPro).isFalse() + assertThat(initialState.userId).isEqualTo(A_USER_ID) + assertThat(initialState.displayName).isNull() + assertThat(initialState.avatar).isNull() + assertThat(initialState.loginWithClassicAction.isUninitialized()).isTrue() + assertThat(initialState.loginMode.isUninitialized()).isTrue() + } + } + + @Test + fun `present - initial state - element Pro`() = runTest { + val presenter = createPresenter( + isEnterpriseBuild = true, + ) + presenter.test { + val initialState = awaitItem() + assertThat(initialState.isElementPro).isTrue() + } + } + + @Test + fun `present - refresh data invokes the expected methods`() = runTest { + val requestAvatarResult = lambdaRecorder { } + val elementClassicConnection = FakeElementClassicConnection( + startResult = {}, + requestAvatarResult = requestAvatarResult, + ) + val presenter = createPresenter( + elementClassicConnection = elementClassicConnection, + ) + presenter.test { + skipItems(1) + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + userId = A_USER_ID, + secrets = A_SECRET, + roomKeysVersion = ROOM_KEYS_VERSION, + ), + displayName = A_USER_NAME, + ) + ) + val readyState = awaitItem() + assertThat(readyState.userId).isEqualTo(A_USER_ID) + assertThat(readyState.displayName).isEqualTo(A_USER_NAME) + readyState.eventSink(LoginWithClassicEvent.RefreshData) + requestAvatarResult.assertions().isCalledOnce() + } + } + + @Test + fun `present - start login with correct state - user can login`() = runTest { + val authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { + Result.failure(AN_EXCEPTION) + }, + ) + val elementClassicConnection = FakeElementClassicConnection( + startResult = {}, + ) + val presenter = createPresenter( + elementClassicConnection = elementClassicConnection, + loginHelper = createLoginHelper( + authenticationService = authenticationService, + ), + ) + presenter.test { + skipItems(1) + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + userId = A_USER_ID, + secrets = A_SECRET, + roomKeysVersion = ROOM_KEYS_VERSION, + doesContainBackupKey = true, + ), + displayName = A_USER_NAME, + ) + ) + val readyState = awaitItem() + assertThat(readyState.userId).isEqualTo(A_USER_ID) + assertThat(readyState.displayName).isEqualTo(A_USER_NAME) + readyState.eventSink(LoginWithClassicEvent.Submit) + val loadingState = awaitItem() + assertThat(loadingState.loginWithClassicAction.isLoading()).isTrue() + skipItems(1) + } + } + + @Test + fun `present - start login with no secrets - user can login and will have to verify manually`() = runTest { + val authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { + Result.failure(AN_EXCEPTION) + }, + ) + val elementClassicConnection = FakeElementClassicConnection( + startResult = {}, + ) + val presenter = createPresenter( + elementClassicConnection = elementClassicConnection, + loginHelper = createLoginHelper( + authenticationService = authenticationService, + ), + ) + presenter.test { + skipItems(1) + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + userId = A_USER_ID, + secrets = null, + roomKeysVersion = null, + ), + displayName = A_USER_NAME, + ) + ) + val readyState = awaitItem() + assertThat(readyState.userId).isEqualTo(A_USER_ID) + assertThat(readyState.displayName).isEqualTo(A_USER_NAME) + readyState.eventSink(LoginWithClassicEvent.Submit) + val loadingState = awaitItem() + assertThat(loadingState.loginWithClassicAction.isLoading()).isTrue() + skipItems(1) + } + } + + @Test + fun `present - start login with secrets and without key backup - user will see the screen to enable key backup`() = runTest { + val authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { + Result.failure(AN_EXCEPTION) + }, + ) + val elementClassicConnection = FakeElementClassicConnection( + startResult = {}, + ) + val navigateToMissingKeyBackupResult = lambdaRecorder { } + val presenter = createPresenter( + elementClassicConnection = elementClassicConnection, + loginHelper = createLoginHelper( + authenticationService = authenticationService, + ), + navigator = FakeLoginWithClassicNavigator( + navigateToMissingKeyBackupResult = navigateToMissingKeyBackupResult, + ), + ) + presenter.test { + skipItems(1) + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + userId = A_USER_ID, + secrets = A_SECRET, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = A_USER_NAME, + ) + ) + val readyState = awaitItem() + assertThat(readyState.userId).isEqualTo(A_USER_ID) + assertThat(readyState.displayName).isEqualTo(A_USER_NAME) + readyState.eventSink(LoginWithClassicEvent.Submit) + navigateToMissingKeyBackupResult.assertions().isCalledOnce() + } + } + + @Test + fun `present - start login with secrets and with invalid key backup - user will see the screen to enable key backup`() = runTest { + val authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { + Result.failure(AN_EXCEPTION) + }, + ) + val elementClassicConnection = FakeElementClassicConnection( + startResult = {}, + ) + val navigateToMissingKeyBackupResult = lambdaRecorder { } + val presenter = createPresenter( + elementClassicConnection = elementClassicConnection, + loginHelper = createLoginHelper( + authenticationService = authenticationService, + ), + navigator = FakeLoginWithClassicNavigator( + navigateToMissingKeyBackupResult = navigateToMissingKeyBackupResult, + ), + ) + presenter.test { + skipItems(1) + elementClassicConnection.emitState( + anElementClassicReady( + elementClassicSession = anElementClassicSession( + userId = A_USER_ID, + secrets = A_SECRET, + roomKeysVersion = ROOM_KEYS_VERSION, + // false here + doesContainBackupKey = false, + ), + displayName = A_USER_NAME, + ) + ) + val readyState = awaitItem() + assertThat(readyState.userId).isEqualTo(A_USER_ID) + assertThat(readyState.displayName).isEqualTo(A_USER_NAME) + readyState.eventSink(LoginWithClassicEvent.Submit) + navigateToMissingKeyBackupResult.assertions().isCalledOnce() + } + } + + @Test + fun `present - submit in wrong state and clear error`() = runTest { + val elementClassicConnection = FakeElementClassicConnection( + startResult = {}, + ) + val presenter = createPresenter( + elementClassicConnection = elementClassicConnection, + ) + presenter.test { + skipItems(1) + elementClassicConnection.emitState( + ElementClassicConnectionState.Error( + error = A_FAILURE_REASON, + ) + ) + val initialState = awaitItem() + assertThat(initialState.loginWithClassicAction.isUninitialized()).isTrue() + initialState.eventSink(LoginWithClassicEvent.Submit) + val errorState = awaitItem() + assertThat(errorState.loginWithClassicAction.isFailure()).isTrue() + errorState.eventSink(LoginWithClassicEvent.ClearError) + val clearedState = awaitItem() + assertThat(clearedState.loginWithClassicAction.isUninitialized()).isTrue() + } + } +} + +private fun createPresenter( + userId: UserId = A_USER_ID, + navigator: LoginWithClassicNavigator = FakeLoginWithClassicNavigator(), + loginHelper: LoginHelper = createLoginHelper(), + elementClassicConnection: ElementClassicConnection = FakeElementClassicConnection(), + accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), + isEnterpriseBuild: Boolean = false, +) = LoginWithClassicPresenter( + userId = userId, + navigator = navigator, + loginHelper = loginHelper, + elementClassicConnection = elementClassicConnection, + accountProviderDataSource = accountProviderDataSource, + buildMeta = aBuildMeta( + isEnterpriseBuild = isEnterpriseBuild, + ), +) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt new file mode 100644 index 0000000000..2a4af8bf5a --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt @@ -0,0 +1,55 @@ +/* + * 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.login.impl.screens.classic.missingkeybackup + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.login.impl.classic.ElementClassicConnection +import io.element.android.features.login.impl.classic.FakeElementClassicConnection +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.matrix.test.AN_APPLICATION_NAME +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class MissingKeyBackupPresenterTest { + @Test + fun `present - initial state`() = runTest { + val presenter = createPresenter() + presenter.test { + val initialState = awaitItem() + assertThat(initialState.appName).isEqualTo(AN_APPLICATION_NAME) + } + } + + @Test + fun `present - when the screen is resumed twice, the start over method is called`() = runTest { + val requestSessionResult = lambdaRecorder { } + val presenter = createPresenter( + elementClassicConnection = FakeElementClassicConnection( + requestSessionResult = requestSessionResult, + ), + ) + presenter.test { + val initialState = awaitItem() + initialState.eventSink(MissingKeyBackupEvent.OnResume) + expectNoEvents() + initialState.eventSink(MissingKeyBackupEvent.OnResume) + requestSessionResult.assertions().isCalledOnce() + } + } +} + +private fun createPresenter( + buildMeta: BuildMeta = aBuildMeta(applicationName = AN_APPLICATION_NAME), + elementClassicConnection: ElementClassicConnection = FakeElementClassicConnection(), +) = MissingKeyBackupPresenter( + buildMeta = buildMeta, + elementClassicConnection = elementClassicConnection, +) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt index 92099180ec..31a835cb8c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_PASSWORD import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_NAME +import io.element.android.libraries.matrix.test.A_USER_NAME_2 import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.aMatrixHomeServerDetails import io.element.android.tests.testutils.WarmUpRule @@ -41,6 +42,20 @@ class LoginPasswordPresenterTest { } } + @Test + fun `present - initial login is in the first state and can be modified`() = runTest { + createLoginPasswordPresenter( + initialLogin = A_USER_NAME, + ).test { + val initialState = awaitItem() + assertThat(initialState.formState.login).isEqualTo(A_USER_NAME) + // Login can be changed + initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME_2)) + val loginChangedState = awaitItem() + assertThat(loginChangedState.formState.login).isEqualTo(A_USER_NAME_2) + } + } + @Test fun `present - enter login and password`() = runTest { val authenticationService = FakeMatrixAuthenticationService( @@ -140,9 +155,11 @@ class LoginPasswordPresenterTest { } private fun createLoginPasswordPresenter( + initialLogin: String = "", authenticationService: FakeMatrixAuthenticationService = FakeMatrixAuthenticationService(), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), ): LoginPasswordPresenter = LoginPasswordPresenter( + initialLogin = initialLogin, authenticationService = authenticationService, accountProviderDataSource = accountProviderDataSource, ) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt index 1e971ef265..1fdfb7e070 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt @@ -16,7 +16,6 @@ import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.accesscontrol.DefaultAccountProviderAccessControl import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.login.LoginHelper -import io.element.android.features.login.impl.screens.onboarding.classic.aLoginWithClassicState import io.element.android.features.login.impl.web.FakeWebClientUrlForAuthenticationRetriever import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever import io.element.android.features.wellknown.test.FakeWellknownRetriever @@ -83,16 +82,31 @@ class OnBoardingPresenterTest { ) presenter.test { val initialState = awaitItem() + assertThat(initialState.showBackButton).isFalse() assertThat(initialState.defaultAccountProvider).isNull() assertThat(initialState.canLoginWithQrCode).isFalse() assertThat(initialState.productionApplicationName).isEqualTo("B") assertThat(initialState.canCreateAccount).isEqualTo(OnBoardingConfig.CAN_CREATE_ACCOUNT) assertThat(initialState.canReportBug).isFalse() assertThat(initialState.isAddingAccount).isFalse() - assertThat(initialState.loginWithClassicState.canLoginWithClassic).isFalse() val finalState = awaitItem() assertThat(finalState.canLoginWithQrCode).isTrue() - assertThat(finalState.loginWithClassicState.canLoginWithClassic).isFalse() + } + } + + @Test + fun `present - initial state with back button`() = runTest { + val presenter = createPresenter( + params = OnBoardingNode.Params( + accountProvider = null, + loginHint = null, + showBackButton = true, + ), + ) + presenter.test { + val initialState = awaitItem() + assertThat(initialState.showBackButton).isTrue() + skipItems(1) } } @@ -162,6 +176,7 @@ class OnBoardingPresenterTest { params = OnBoardingNode.Params( accountProvider = ACCOUNT_PROVIDER_FROM_LINK, loginHint = null, + showBackButton = false, ), enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG, EnterpriseService.ANY_ACCOUNT_PROVIDER) }, @@ -184,6 +199,7 @@ class OnBoardingPresenterTest { params = OnBoardingNode.Params( accountProvider = ACCOUNT_PROVIDER_FROM_LINK, loginHint = null, + showBackButton = false, ), enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG, ACCOUNT_PROVIDER_FROM_CONFIG_2) }, @@ -206,6 +222,7 @@ class OnBoardingPresenterTest { params = OnBoardingNode.Params( accountProvider = ACCOUNT_PROVIDER_FROM_LINK, loginHint = null, + showBackButton = false, ), enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG) }, @@ -233,6 +250,7 @@ class OnBoardingPresenterTest { params = OnBoardingNode.Params( accountProvider = A_HOMESERVER_URL, loginHint = A_LOGIN_HINT, + showBackButton = false, ), enterpriseService = FakeEnterpriseService( isAllowedToConnectToHomeserverResult = { true }, @@ -265,7 +283,11 @@ class OnBoardingPresenterTest { } private fun createPresenter( - params: OnBoardingNode.Params = OnBoardingNode.Params(null, null), + params: OnBoardingNode.Params = OnBoardingNode.Params( + accountProvider = null, + loginHint = null, + showBackButton = false, + ), buildMeta: BuildMeta = aBuildMeta(), enterpriseService: EnterpriseService = FakeEnterpriseService(), wellknownRetriever: WellknownRetriever = FakeWellknownRetriever(), @@ -287,7 +309,6 @@ private fun createPresenter( onBoardingLogoResIdProvider = onBoardingLogoResIdProvider, sessionStore = sessionStore, accountProviderDataSource = accountProviderDataSource, - loginWithClassicPresenter = { aLoginWithClassicState() }, ) fun createLoginHelper( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenterTest.kt deleted file mode 100644 index 437e65f21d..0000000000 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/LoginWithClassicPresenterTest.kt +++ /dev/null @@ -1,214 +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. - */ - -@file:OptIn(ExperimentalCoroutinesApi::class) - -package io.element.android.features.login.impl.screens.onboarding.classic - -import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService -import io.element.android.libraries.matrix.test.A_SECRET -import io.element.android.libraries.matrix.test.A_USER_ID -import io.element.android.libraries.sessionstorage.api.SessionStore -import io.element.android.libraries.sessionstorage.test.InMemorySessionStore -import io.element.android.libraries.sessionstorage.test.aSessionData -import io.element.android.tests.testutils.WarmUpRule -import io.element.android.tests.testutils.lambda.lambdaRecorder -import io.element.android.tests.testutils.test -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runTest -import org.junit.Rule -import org.junit.Test - -class LoginWithClassicPresenterTest { - @get:Rule - val warmUpRule = WarmUpRule() - - @Test - fun `present - initial state - feature disabled - start is not invoked`() = runTest { - val presenter = createPresenter( - elementClassicConnection = FakeElementClassicConnection( - startResult = { - error("start should not be invoked when feature is disabled") - }, - ) - ) - presenter.test { - val initialState = awaitItem() - assertThat(initialState.canLoginWithClassic).isFalse() - assertThat(initialState.loginWithClassicAction.isUninitialized()).isTrue() - } - } - - @Test - fun `present - feature enabled - start is invoked`() = runTest { - val startResult = lambdaRecorder {} - val presenter = createPresenter( - elementClassicConnection = FakeElementClassicConnection( - startResult = startResult, - ), - isFeatureEnabled = true, - ) - presenter.test { - val initialState = awaitItem() - assertThat(initialState.canLoginWithClassic).isFalse() - assertThat(initialState.loginWithClassicAction.isUninitialized()).isTrue() - val finalState = awaitItem() - assertThat(finalState.canLoginWithClassic).isFalse() - } - startResult.assertions().isCalledOnce() - } - - @Test - fun `present - emit request data invokes the expected method`() = runTest { - val requestDataResult = lambdaRecorder {} - val presenter = createPresenter( - elementClassicConnection = FakeElementClassicConnection( - startResult = {}, - requestDataResult = requestDataResult, - ), - isFeatureEnabled = true, - ) - presenter.test { - val initialState = awaitItem() - assertThat(initialState.canLoginWithClassic).isFalse() - assertThat(initialState.loginWithClassicAction.isUninitialized()).isTrue() - val nextState = awaitItem() - assertThat(nextState.canLoginWithClassic).isFalse() - nextState.eventSink(LoginWithClassicEvent.RefreshData) - } - requestDataResult.assertions().isCalledOnce() - } - - @Test - fun `present - start login with wrong state emits an error`() = runTest { - val presenter = createPresenter( - elementClassicConnection = FakeElementClassicConnection( - startResult = {}, - ), - isFeatureEnabled = true, - ) - presenter.test { - skipItems(1) - val state = awaitItem() - state.eventSink(LoginWithClassicEvent.StartLoginWithClassic) - val errorState = awaitItem() - assertThat(errorState.loginWithClassicAction.isFailure()).isTrue() - } - } - - @Test - fun `present - start login with correct state - user cancel`() = runTest { - val elementClassicConnection = FakeElementClassicConnection( - startResult = {}, - ) - val presenter = createPresenter( - elementClassicConnection = elementClassicConnection, - isFeatureEnabled = true, - ) - presenter.test { - skipItems(2) - elementClassicConnection.emitState( - ElementClassicConnectionState.ElementClassicReady(userId = A_USER_ID, secrets = A_SECRET) - ) - val readyState = awaitItem() - assertThat(readyState.canLoginWithClassic).isTrue() - readyState.eventSink(LoginWithClassicEvent.StartLoginWithClassic) - val confirmingState = awaitItem() - assertThat(confirmingState.loginWithClassicAction.isConfirming()).isTrue() - assertThat((confirmingState.loginWithClassicAction as ConfirmingLoginWithElementClassic).userId).isEqualTo(A_USER_ID) - confirmingState.eventSink(LoginWithClassicEvent.CloseDialog) - val finalState = awaitItem() - assertThat(finalState.loginWithClassicAction.isUninitialized()).isTrue() - } - } - - @Test - fun `present - start login with correct state - user confirms`() = runTest { - val elementClassicConnection = FakeElementClassicConnection( - startResult = {}, - ) - val presenter = createPresenter( - elementClassicConnection = elementClassicConnection, - isFeatureEnabled = true, - ) - presenter.test { - skipItems(2) - elementClassicConnection.emitState( - ElementClassicConnectionState.ElementClassicReady(userId = A_USER_ID, secrets = A_SECRET) - ) - val readyState = awaitItem() - assertThat(readyState.canLoginWithClassic).isTrue() - readyState.eventSink(LoginWithClassicEvent.StartLoginWithClassic) - val confirmingState = awaitItem() - assertThat(confirmingState.loginWithClassicAction.isConfirming()).isTrue() - assertThat((confirmingState.loginWithClassicAction as ConfirmingLoginWithElementClassic).userId).isEqualTo(A_USER_ID) - confirmingState.eventSink(LoginWithClassicEvent.DoLoginWithClassic) - val loadingState = awaitItem() - assertThat(loadingState.loginWithClassicAction.isLoading()).isTrue() - val finalState = awaitItem() - assertThat(finalState.loginWithClassicAction.isSuccess()).isTrue() - } - } - - @Test - fun `present - cannot sign in if a session with the same account already exists`() = runTest { - val elementClassicConnection = FakeElementClassicConnection( - startResult = {}, - ) - val presenter = createPresenter( - elementClassicConnection = elementClassicConnection, - isFeatureEnabled = true, - sessionStore = InMemorySessionStore( - initialList = listOf( - aSessionData( - sessionId = A_USER_ID.value, - ) - ) - ), - ) - presenter.test { - skipItems(2) - elementClassicConnection.emitState( - ElementClassicConnectionState.ElementClassicReady(userId = A_USER_ID, secrets = A_SECRET) - ) - // No new item, because canLoginWithClassic is still false - } - } - - @Test - fun `present - cannot sign in if the feature is disabled`() = runTest { - val elementClassicConnection = FakeElementClassicConnection() - val presenter = createPresenter( - elementClassicConnection = elementClassicConnection, - isFeatureEnabled = false, - ) - presenter.test { - skipItems(1) - // Note: it should not happen IRL - elementClassicConnection.emitState( - ElementClassicConnectionState.ElementClassicReady(userId = A_USER_ID, secrets = A_SECRET) - ) - // No new item, because canLoginWithClassic is still false - } - } -} - -private fun createPresenter( - elementClassicConnection: ElementClassicConnection = FakeElementClassicConnection(), - sessionStore: SessionStore = InMemorySessionStore(), - isFeatureEnabled: Boolean = false, - featureFlagService: FeatureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.SignInWithClassic.key to isFeatureEnabled) - ), -) = LoginWithClassicPresenter( - elementClassicConnection = elementClassicConnection, - sessionStore = sessionStore, - featureFlagService = featureFlagService, -) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/service/ServiceBinder.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/service/ServiceBinder.kt new file mode 100644 index 0000000000..ba71ca131f --- /dev/null +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/service/ServiceBinder.kt @@ -0,0 +1,33 @@ +/* + * 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.androidutils.service + +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.di.annotations.ApplicationContext + +interface ServiceBinder { + fun bindService(service: Intent, conn: ServiceConnection, flags: Int): Boolean + fun unbindService(conn: ServiceConnection) +} + +@ContributesBinding(AppScope::class) +class DefaultServiceBinder( + @ApplicationContext private val context: Context, +) : ServiceBinder { + override fun bindService(service: Intent, conn: ServiceConnection, flags: Int): Boolean { + return context.bindService(service, conn, flags) + } + + override fun unbindService(conn: ServiceConnection) { + context.unbindService(conn) + } +} diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/FaderOrSliderTransitionHandler.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/FaderOrSliderTransitionHandler.kt new file mode 100644 index 0000000000..c8da7439a5 --- /dev/null +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/FaderOrSliderTransitionHandler.kt @@ -0,0 +1,54 @@ +/* + * 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.architecture.appyx + +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.Transition +import androidx.compose.animation.core.spring +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.navigation.transition.ModifierTransitionHandler +import com.bumble.appyx.core.navigation.transition.TransitionDescriptor +import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.operation.NewRoot +import com.bumble.appyx.navmodel.backstack.operation.Replace +import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackFader +import com.bumble.appyx.navmodel.backstack.transitionhandler.rememberBackstackSlider + +/** + * A TransitionHandler that uses fade transition when the operation is Replace or NewRoot, + * and slide transition for all other cases. + */ +private class FaderOrSliderTransitionHandler( + private val slider: ModifierTransitionHandler, + private val fader: ModifierTransitionHandler, +) : ModifierTransitionHandler() { + override fun createModifier( + modifier: Modifier, + transition: Transition, + descriptor: TransitionDescriptor + ): Modifier { + val operation = descriptor.operation + val useFader = operation is Replace || operation is NewRoot + val handler = if (useFader) fader else slider + return handler.createModifier(modifier, transition, descriptor) + } +} + +@Composable +fun rememberFaderOrSliderTransitionHandler(): ModifierTransitionHandler { + val slider = rememberBackstackSlider( + transitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) }, + ) + val fader = rememberBackstackFader( + transitionSpec = { spring(stiffness = Spring.StiffnessMediumLow) }, + ) + return rememberDelegateTransitionHandler { + FaderOrSliderTransitionHandler(slider, fader) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/BitmapAvatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/BitmapAvatar.kt new file mode 100644 index 0000000000..f25174b7b0 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/BitmapAvatar.kt @@ -0,0 +1,79 @@ +/* + * 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.designsystem.components.avatar + +import android.graphics.Bitmap +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import coil3.compose.AsyncImagePainter +import coil3.compose.SubcomposeAsyncImage +import coil3.compose.SubcomposeAsyncImageContent +import io.element.android.libraries.designsystem.components.avatar.internal.InitialLetterAvatar +import timber.log.Timber + +// For user avatar only. +@Composable +fun BitmapAvatar( + avatarData: AvatarData, + bitmap: Bitmap?, + modifier: Modifier = Modifier, + contentDescription: String? = null, +) { + val avatarShape = AvatarType.User.avatarShape() + when { + bitmap == null -> InitialLetterAvatar( + avatarData = avatarData, + avatarShape = avatarShape, + forcedAvatarSize = null, + modifier = modifier, + contentDescription = contentDescription, + ) + else -> { + val size = avatarData.size.dp + SubcomposeAsyncImage( + model = bitmap, + contentDescription = contentDescription, + contentScale = ContentScale.Crop, + modifier = modifier + .size(size) + .clip(avatarShape) + ) { + val collectedState by painter.state.collectAsState() + when (val state = collectedState) { + is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent() + is AsyncImagePainter.State.Error -> { + SideEffect { + Timber.e( + state.result.throwable, + "Error loading avatar $state\n${state.result}" + ) + } + InitialLetterAvatar( + avatarData = avatarData, + avatarShape = avatarShape, + forcedAvatarSize = null, + contentDescription = contentDescription, + ) + } + else -> InitialLetterAvatar( + avatarData = avatarData, + avatarShape = avatarShape, + forcedAvatarSize = null, + contentDescription = contentDescription, + ) + } + } + } + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ConfirmingLoginWithElementClassic.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/ElementClassicSession.kt similarity index 56% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ConfirmingLoginWithElementClassic.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/ElementClassicSession.kt index 5fae0afdd5..d094019db2 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/classic/ConfirmingLoginWithElementClassic.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/ElementClassicSession.kt @@ -5,11 +5,14 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.login.impl.screens.onboarding.classic +package io.element.android.libraries.matrix.api.auth -import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.UserId -class ConfirmingLoginWithElementClassic( +data class ElementClassicSession( val userId: UserId, -) : AsyncAction.Confirming + val homeserverUrl: String?, + val secrets: String?, + val roomKeysVersion: String?, + val doesContainBackupKey: Boolean, +) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt index 1c574ad467..7c82668242 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.UserId interface MatrixAuthenticationService { /** @@ -52,6 +53,20 @@ interface MatrixAuthenticationService { */ suspend fun cancelOidcLogin(): Result + /** + * Set the existing data about Element Classic session, if any. + */ + fun setElementClassicSession(session: ElementClassicSession?) + + /** + * Check if the provided secrets from Element Classic session contain a key backup. + */ + fun doSecretsContainBackupKey( + userId: UserId, + secrets: String, + backupInfo: String, + ): Boolean + /** * Attempt to login using the [callbackUrl] provided by the Oidc page. */ diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/core/UserIdTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/core/UserIdTest.kt new file mode 100644 index 0000000000..eb97ce0d8c --- /dev/null +++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/core/UserIdTest.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.libraries.matrix.api.core + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +class UserIdTest { + @Test + fun `valid user id`() { + val userId = UserId("@alice:example.org") + assertThat(userId.extractedDisplayName).isEqualTo("alice") + assertThat(userId.domainName).isEqualTo("example.org") + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 7cd9fbedf5..9fe7c7cd1f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.auth.AuthenticationException +import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.OidcDetails @@ -25,6 +26,7 @@ import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.impl.ClientBuilderSlidingSync import io.element.android.libraries.matrix.impl.RustMatrixClientFactory @@ -50,6 +52,7 @@ import org.matrix.rustcomponents.sdk.QrCodeData import org.matrix.rustcomponents.sdk.QrCodeDecodeException import org.matrix.rustcomponents.sdk.QrLoginProgress import org.matrix.rustcomponents.sdk.QrLoginProgressListener +import org.matrix.rustcomponents.sdk.SecretsBundleWithUserId import timber.log.Timber import uniffi.matrix_sdk.OAuthAuthorizationData import kotlin.time.Duration.Companion.seconds @@ -64,6 +67,9 @@ class RustMatrixAuthenticationService( private val passphraseGenerator: PassphraseGenerator, private val oidcConfigurationProvider: OidcConfigurationProvider, ) : MatrixAuthenticationService { + // Any existing Element Classic session that we want to try to import secrets from during login. + private var elementClassicSession: ElementClassicSession? = null + // Passphrase which will be used for new sessions. Existing sessions will use the passphrase // stored in the SessionData. private val pendingPassphrase = getDatabasePassphrase() @@ -138,9 +144,15 @@ class RustMatrixAuthenticationService( runCatchingExceptions { val client = currentClient ?: error("You need to call `setHomeserver()` first") val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first") - client.login(username, password, "Element X Android", null) + client.login( + username = username, + password = password, + initialDeviceName = "Element X Android", + deviceId = null, + ) // Ensure that the user is not already logged in with the same account ensureNotAlreadyLoggedIn(client) + tryToImportSecretForElementClassicSession(client) val sessionData = client.session() .toSessionData( isTokenValid = true, @@ -162,6 +174,53 @@ class RustMatrixAuthenticationService( } } + private suspend fun tryToImportSecretForElementClassicSession(client: Client) { + elementClassicSession + ?.takeIf { + // Note: the SDK will also do this check + it.userId.value == client.userId() + } + ?.let { + val secrets = it.secrets + val roomKeysVersion = it.roomKeysVersion + if (secrets == null || roomKeysVersion == null) { + Timber.d("No secrets or roomKeysVersion found for Element Classic session ${it.userId}, skipping import") + } else { + Timber.d("Trying to import secrets for Element Classic session ${it.userId}") + runCatchingExceptions { + SecretsBundleWithUserId.fromStr( + userId = it.userId.value, + bundle = secrets, + backupInfo = roomKeysVersion, + ).use { secretsBundle -> + client.encryption().importSecretsBundle(secretsBundle) + } + }.onFailure { failure -> + Timber.e(failure, "Failed to import secrets for Element Classic session ${it.userId}") + } + } + } + } + + override fun doSecretsContainBackupKey( + userId: UserId, + secrets: String, + backupInfo: String, + ): Boolean { + return try { + SecretsBundleWithUserId.fromStr( + userId = userId.value, + bundle = secrets, + backupInfo = backupInfo, + ).use { secretsBundle -> + secretsBundle.containsBackupKey() + } + } catch (failure: Exception) { + Timber.e(failure, "Failed to parse secrets for Element Classic session $userId") + false + } + } + override suspend fun importCreatedSession(externalSession: ExternalSession): Result = withContext(coroutineDispatchers.io) { runCatchingExceptions { @@ -233,6 +292,10 @@ class RustMatrixAuthenticationService( } } + override fun setElementClassicSession(session: ElementClassicSession?) { + elementClassicSession = session + } + /** * callbackUrl should be the uriRedirect from OidcClientMetadata (with all the parameters). */ @@ -241,14 +304,15 @@ class RustMatrixAuthenticationService( runCatchingExceptions { val client = currentClient ?: error("You need to call `setHomeserver()` first") val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first") - client.loginWithOidcCallback(callbackUrl) - + client.loginWithOidcCallback( + callbackUrl = callbackUrl, + ) // Free the pending data since we won't use it to abort the flow anymore pendingOAuthAuthorizationData?.close() pendingOAuthAuthorizationData = null - // Ensure that the user is not already logged in with the same account ensureNotAlreadyLoggedIn(client) + tryToImportSecretForElementClassicSession(client) val sessionData = client.session().toSessionData( isTokenValid = true, loginType = LoginType.OIDC, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt index c4acccb55c..238ad2663d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.test.auth import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.OidcDetails @@ -17,6 +18,7 @@ import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.FakeMatrixClient @@ -32,6 +34,8 @@ class FakeMatrixAuthenticationService( lambdaRecorder Unit, Result> { _, _ -> Result.success(A_SESSION_ID) }, private val importCreatedSessionLambda: (ExternalSession) -> Result = { lambdaError() }, private val setHomeserverResult: (String) -> Result = { lambdaError() }, + private val setElementClassicSessionResult: (ElementClassicSession?) -> Unit = { lambdaError() }, + private val doSecretsContainBackupKeyResult: (UserId, String, String) -> Boolean = { _, _, _ -> lambdaError() }, ) : MatrixAuthenticationService { private var oidcError: Throwable? = null private var oidcCancelError: Throwable? = null @@ -108,4 +112,12 @@ class FakeMatrixAuthenticationService( fun givenMatrixClient(matrixClient: MatrixClient) { this.matrixClient = matrixClient } + + override fun setElementClassicSession(session: ElementClassicSession?) { + setElementClassicSessionResult(session) + } + + override fun doSecretsContainBackupKey(userId: UserId, secrets: String, backupInfo: String): Boolean { + return doSecretsContainBackupKeyResult(userId, secrets, backupInfo) + } } diff --git a/tools/localazy/checkForbiddenTerms.py b/tools/localazy/checkForbiddenTerms.py index e190fcea68..123246ffd0 100755 --- a/tools/localazy/checkForbiddenTerms.py +++ b/tools/localazy/checkForbiddenTerms.py @@ -31,6 +31,9 @@ forbiddenTerms = { # We explicitly want to mention Element Pro in these 2: "screen_change_server_error_element_pro_required_title", "screen_change_server_error_element_pro_required_message", + # Contains "Element Classic" + "screen_missing_key_backup_open_element_classic", + "screen_missing_key_backup_step_1", ] } diff --git a/tools/localazy/config.json b/tools/localazy/config.json index d3e44b7c08..b38268e5f7 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -170,6 +170,8 @@ "name" : ":features:login:impl", "includeRegex" : [ "screen_onboarding_.*", + "screen\\.onboarding\\..*", + "screen\\.missing_key_backup\\..*", "screen_login_.*", "screen_server_confirmation_.*", "screen_change_server_.*", From 62f2251adbf003471045214c80a8eaee3439b808 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 9 Apr 2026 13:15:51 +0000 Subject: [PATCH 0112/1083] Update screenshots --- ....classic.loginwithclassic_LoginWithClassicView_Day_0_en.png | 3 +++ ....classic.loginwithclassic_LoginWithClassicView_Day_1_en.png | 3 +++ ...lassic.loginwithclassic_LoginWithClassicView_Night_0_en.png | 3 +++ ...lassic.loginwithclassic_LoginWithClassicView_Night_1_en.png | 3 +++ ....classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png | 3 +++ ...lassic.missingkeybackup_MissingKeyBackupView_Night_0_en.png | 3 +++ ...tures.login.impl.screens.classic.root_RootView_Day_0_en.png | 3 +++ ...res.login.impl.screens.classic.root_RootView_Night_0_en.png | 3 +++ ...s.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png | 3 +++ ...login.impl.screens.onboarding_OnBoardingView_Night_8_en.png | 3 +++ 10 files changed, 30 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en.png new file mode 100644 index 0000000000..adbcd16ec1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d861dd7397c0e15091e022d956c1955d86529fa0cc39e08c3c645d91e5023e0e +size 77677 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en.png new file mode 100644 index 0000000000..df7c95510d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0acaebca757642346f3381601f044a55d02749575150364e232f772ba0167e1 +size 73811 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en.png new file mode 100644 index 0000000000..7bed006a97 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54c841ffefb3d053bb74e6f88a9aa7cff5d39b4854c92de3b507552a9a4226bc +size 68693 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en.png new file mode 100644 index 0000000000..94a1749517 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eba1f4395b4c32e7edead84b1e22957cc8f973121207d7000419a8f4c314f5b8 +size 65936 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 new file mode 100644 index 0000000000..4a5a13a36a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ef35fd3f5346870f11120a37c9db969453b7594bf9a0ccc71fe43e7fdade488 +size 62532 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 new file mode 100644 index 0000000000..1b69f8f6a1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1501c2591f7df68404285770b1dad67360dddce074d4ce1c71223ea0baa0d1e4 +size 60873 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Day_0_en.png new file mode 100644 index 0000000000..e3e5480add --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72e73b036458ee32e207f711cf6656fe7646b23d3d9e096e62932c828dd53189 +size 5244 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Night_0_en.png new file mode 100644 index 0000000000..6582264383 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.root_RootView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:518818c549548b6304d2960242ce7251bb609fa439928539a7556c33223ca8ba +size 5251 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png new file mode 100644 index 0000000000..b5f0eb7fcf --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5015f504040a0141d40bc14bf8a3a3be43c9c95a3702a6dc53bb253746e5a3aa +size 311553 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png new file mode 100644 index 0000000000..4669c0b972 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8972af96ba5624f92c826ef0e20595b6193a44b6b0a0ea03cb133c516a93a90e +size 391678 From 73e1a092d22d348af8091f851c5744a34ab8b7c5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 13 Apr 2026 11:15:42 +0200 Subject: [PATCH 0113/1083] Ignore secrets when the bundle does not contain the room keys version. --- .../impl/classic/ElementClassicConnection.kt | 12 ++- .../DefaultElementClassicConnectionTest.kt | 76 +++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index 5e838094d3..e360aff376 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -319,8 +319,16 @@ class DefaultElementClassicConnection( if (userId == null) { ElementClassicConnectionState.ElementClassicReadyNoSession } else { - val secrets = getString(KEY_SECRETS_STR)?.takeIf { it.isNotEmpty() } - val roomKeysVersion = getString(KEY_ROOM_KEYS_VERSION_STR)?.takeIf { it.isNotEmpty() } + var secrets = getString(KEY_SECRETS_STR)?.takeIf { it.isNotEmpty() } + val roomKeysVersion = getString(KEY_ROOM_KEYS_VERSION_STR) + .also { + if (secrets != null && it == null) { + Timber.tag(loggerTag.value).w("Room keys version is null, outdated version of Element Classic, ignore secrets") + // In this case, just ignore the secrets, the SDK will not accept them anyway + secrets = null + } + } + ?.takeIf { it.isNotEmpty() } val homeserverUrl = getString(KEY_HOMESERVER_URL_STR)?.takeIf { it.isNotEmpty() } val displayName = getString(KEY_USER_DISPLAY_NAME_STR)?.takeIf { it.isNotEmpty() } val doesContainBackupKey = secrets != null && diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt index 1c76a93650..8ea1b2e3d3 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt @@ -270,6 +270,82 @@ class DefaultElementClassicConnectionTest { } } + @Test + fun `when session is received with secret but without room keys version Element Classic is outdated and the secret is ignored`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + putString(DefaultElementClassicConnection.KEY_HOMESERVER_URL_STR, A_HOMESERVER_URL) + putString(DefaultElementClassicConnection.KEY_SECRETS_STR, A_SECRET) + putString(DefaultElementClassicConnection.KEY_ROOM_KEYS_VERSION_STR, null) + putString(DefaultElementClassicConnection.KEY_USER_DISPLAY_NAME_STR, A_USER_NAME) + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = A_HOMESERVER_URL, + secrets = null, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = A_USER_NAME, + avatar = null, + ) + ) + } + } + + @Test + fun `when session is received with secret but with empty room keys version, doesContainBackupKey is false`() = runTest { + val connection = createDefaultElementClassicConnection( + homeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( + checkResult = { Result.success(true) } + ), + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + // Simulate receiving a session from Element Classic + connection.onSessionReceived( + Bundle().apply { + putString(DefaultElementClassicConnection.KEY_USER_ID_STR, A_USER_ID.value) + putString(DefaultElementClassicConnection.KEY_HOMESERVER_URL_STR, A_HOMESERVER_URL) + putString(DefaultElementClassicConnection.KEY_SECRETS_STR, A_SECRET) + putString(DefaultElementClassicConnection.KEY_ROOM_KEYS_VERSION_STR, "") + putString(DefaultElementClassicConnection.KEY_USER_DISPLAY_NAME_STR, A_USER_NAME) + } + ) + assertThat(awaitItem()).isEqualTo( + ElementClassicConnectionState.ElementClassicReady( + elementClassicSession = ElementClassicSession( + userId = A_USER_ID, + homeserverUrl = A_HOMESERVER_URL, + secrets = A_SECRET, + roomKeysVersion = null, + doesContainBackupKey = false, + ), + displayName = A_USER_NAME, + avatar = null, + ) + ) + } + } + @Test fun `when session is received with empty data, and homeserver is supported, ElementClassicReady is emitted`() = runTest { val connection = createDefaultElementClassicConnection( From 580e85d232de5287cf6acd9643ad1cfb9fdb0e62 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 13 Apr 2026 11:51:48 +0200 Subject: [PATCH 0114/1083] 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 f5e1cbef38df6c151acabbc7096a17990b6a25ce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 13 Apr 2026 15:25:37 +0200 Subject: [PATCH 0115/1083] Fix navigation issue. Ensure that the timeout has effect only in Idle state. --- .../screens/classic/ClassicFlowNodeHelper.kt | 87 +++++++++---------- .../classic/ClassicFlowNodeHelperTest.kt | 29 ++++--- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt index f719fe5083..cae4f834d0 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt @@ -12,67 +12,60 @@ import io.element.android.features.login.impl.classic.ElementClassicConnection import io.element.android.features.login.impl.classic.ElementClassicConnectionState import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.toUserListFlow +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.take +import kotlinx.coroutines.flow.flowOf @Inject class ClassicFlowNodeHelper( private val elementClassicConnection: ElementClassicConnection, private val sessionStore: SessionStore, ) { - // Ensure user is not stuck on the loading screen. - // If Element Classic is taking too long to communicate (or crashes), unblock the user after a few seconds. - private val timeoutFLow = flow { - emit(false) - delay(5_000) - emit(true) - } - + @OptIn(ExperimentalCoroutinesApi::class) fun navigationEventFlow(): Flow { - return combine( - timeoutFLow, - elementClassicConnection.stateFlow - .distinctUntilChangedBy { - // Ignore change on ElementClassicConnectionState.ElementClassicReady.avatar - if (it is ElementClassicConnectionState.ElementClassicReady) { - it.copy(avatar = null) - } else { - it - } - }, - sessionStore.sessionsFlow().toUserListFlow() - // Take only 1 emission of the sessions, else when the user actually logged in it will trigger a navigation to OnBoarding. - .take(1), - ) { timeout, elementClassicConnectionState, existingSessions -> - when (elementClassicConnectionState) { - ElementClassicConnectionState.Idle -> { - if (timeout) { - NavigationEvent.NavigateToOnBoarding - } else { - NavigationEvent.Idle - } + return elementClassicConnection.stateFlow + .distinctUntilChangedBy { + // Ignore change on ElementClassicConnectionState.ElementClassicReady.avatar + if (it is ElementClassicConnectionState.ElementClassicReady) { + it.copy(avatar = null) + } else { + it } - ElementClassicConnectionState.ElementClassicNotFound, - ElementClassicConnectionState.ElementClassicReadyNoSession, - is ElementClassicConnectionState.Error -> { - NavigationEvent.NavigateToOnBoarding - } - is ElementClassicConnectionState.ElementClassicReady -> { - if (elementClassicConnectionState.elementClassicSession.userId.value in existingSessions) { - NavigationEvent.NavigateToOnBoarding - } else { - // 2 cases when this can be run: - // First time this screen will be displayed - // Missing key backup screen was displayed, but the data has changed (user set up the key backup on Classic), - // and the app is resuming. - NavigationEvent.NavigateToLoginWithClassic(elementClassicConnectionState.elementClassicSession.userId) + } + .flatMapLatest { elementClassicConnectionState -> + when (elementClassicConnectionState) { + ElementClassicConnectionState.Idle -> { + // Ensure user is not stuck on the loading screen. + // If Element Classic is taking too long to communicate (or crashes), unblock the user after a few seconds. + flow { + emit(NavigationEvent.Idle) + delay(5_000) + emit(NavigationEvent.NavigateToOnBoarding) + } + } + ElementClassicConnectionState.ElementClassicNotFound, + ElementClassicConnectionState.ElementClassicReadyNoSession, + is ElementClassicConnectionState.Error -> { + flowOf(NavigationEvent.NavigateToOnBoarding) + } + is ElementClassicConnectionState.ElementClassicReady -> { + val existingSessions = sessionStore.sessionsFlow().toUserListFlow().first() + if (elementClassicConnectionState.elementClassicSession.userId.value in existingSessions) { + flowOf(NavigationEvent.NavigateToOnBoarding) + } else { + // 2 cases when this can be run: + // First time this screen will be displayed + // Missing key backup screen was displayed, but the data has changed (user set up the key backup on Classic), + // and the app is resuming. + flowOf(NavigationEvent.NavigateToLoginWithClassic(elementClassicConnectionState.elementClassicSession.userId)) + } } } } - } } } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt index 1184bb91af..017fd1b633 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelperTest.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -38,16 +39,6 @@ class ClassicFlowNodeHelperTest { @get:Rule val warmUpRule = WarmUpRule() - @Test - fun `initial state`() = runTest { - createHelper() - .navigationEventFlow() - .test { - val initialState = awaitItem() - assertThat(initialState).isEqualTo(NavigationEvent.Idle) - } - } - @Test fun `after a few seconds in Idle, NavigateToOnBoarding is emitted`() = runTest { createHelper() @@ -57,6 +48,8 @@ class ClassicFlowNodeHelperTest { assertThat(initialState).isEqualTo(NavigationEvent.Idle) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -82,6 +75,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -100,6 +95,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -118,6 +115,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -136,6 +135,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToOnBoarding) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -154,6 +155,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -178,6 +181,7 @@ class ClassicFlowNodeHelperTest { avatar = createBitmap(1, 1) ) ) + advanceTimeBy(10_000) expectNoEvents() } } @@ -211,6 +215,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -236,6 +242,8 @@ class ClassicFlowNodeHelperTest { ) val finalState = awaitItem() assertThat(finalState).isEqualTo(NavigationEvent.NavigateToLoginWithClassic(A_USER_ID)) + advanceTimeBy(10_000) + expectNoEvents() } } @@ -264,6 +272,7 @@ class ClassicFlowNodeHelperTest { sessionId = A_USER_ID.value, ) ) + advanceTimeBy(10_000) expectNoEvents() } } From 84e35079589e10e2de99b6d3c572fc37f993cc84 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:33:43 +0000 Subject: [PATCH 0116/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.04.13 --- 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 941d169f86..7902ee0cfa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.8" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.13" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 9a4da33340cf0b95928623bb16ed0b9d2b8b0291 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 13 Apr 2026 20:37:15 +0200 Subject: [PATCH 0117/1083] Fix breaking change, will implement in a separate PR --- .../matrix/impl/room/JoinedRustRoom.kt | 10 +-------- .../room/location/LiveLocationShareMapper.kt | 21 ------------------- 2 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationShareMapper.kt 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..73e76f73a8 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,6 @@ 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.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.timeline.RustTimeline @@ -68,7 +67,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 +502,7 @@ class JoinedRustRoom( } override fun subscribeToLiveLocationShares(): Flow> { - return mxCallbackFlow { - innerRoom.subscribeToLiveLocationShares(object : LiveLocationShareListener { - override fun call(liveLocationShares: List) { - trySend(liveLocationShares.map { it.map() }) - } - }) - } + TODO("Not implemented yet") } 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, - ) -} From d39e1e90034f0817172000cbde4425389b781d53 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:56:36 +0000 Subject: [PATCH 0118/1083] Update metro to v0.13.2 --- 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 7902ee0cfa..80334fd02a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.6.1" # DI -metro = "0.13.1" +metro = "0.13.2" # Auto service autoservice = "1.1.1" From d259eb663468422dc7aa8850d0ab4b5e4699d8a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 09:05:30 +0200 Subject: [PATCH 0119/1083] Update wysiwyg to v2.41.3 (#6572) 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 7902ee0cfa..7ab0cc6ee3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -46,7 +46,7 @@ showkase = "1.0.5" # When upgrading this version, check state restoration still works fine. appyx = "1.7.1" sqldelight = "2.3.2" -wysiwyg = "2.41.1" +wysiwyg = "2.41.3" telephoto = "0.19.0" haze = "1.7.2" From 1962b965fde31fa629e3ebdb9303a9cd0c29a175 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 10:12:03 +0200 Subject: [PATCH 0120/1083] Improve log and reduce severity. --- .../impl/classic/ElementClassicConnection.kt | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index e360aff376..393762fed2 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -107,7 +107,7 @@ class DefaultElementClassicConnection( } override fun start() { - Timber.tag(loggerTag.value).w("start()") + Timber.tag(loggerTag.value).d("start()") coroutineScope.launch { // Establish a connection with the service. We use an explicit // class name because there is no reason to be able to let other @@ -130,7 +130,7 @@ class DefaultElementClassicConnection( } override fun stop() { - Timber.tag(loggerTag.value).w("stop(): Unbinding (bound=$bound)") + Timber.tag(loggerTag.value).d("stop(): Unbinding (bound=$bound)") if (bound) { // Detach our existing connection. serviceBinder.unbindService(serviceConnection) @@ -142,13 +142,12 @@ class DefaultElementClassicConnection( } override fun requestSession() { - Timber.tag(loggerTag.value).w("requestSession()") + Timber.tag(loggerTag.value).d("requestSession()") coroutineScope.launch { val finalMessenger = messenger if (finalMessenger == null) { - Timber.tag(loggerTag.value).w("The messenger is null, can't request data") + Timber.tag(loggerTag.value).d("The messenger is null, can't request data") // Do not emit error, else the regular on boarding flow will be displayed - // emitState(ElementClassicConnectionState.Error("The messenger is null, can't request data")) } else { try { // Get the data @@ -168,7 +167,7 @@ class DefaultElementClassicConnection( } override fun requestAvatar(userId: UserId) { - Timber.tag(loggerTag.value).w("requestAvatar()") + Timber.tag(loggerTag.value).d("requestAvatar()") coroutineScope.launch { val finalMessenger = messenger if (finalMessenger == null) { @@ -265,7 +264,7 @@ class DefaultElementClassicConnection( if (isCompatible) { Timber.tag(loggerTag.value).d("Found compatible homeserver URL: %s", url) } else { - Timber.tag(loggerTag.value).w("Homeserver URL is not compatible: %s", url) + Timber.tag(loggerTag.value).d("Homeserver URL is not compatible: %s", url) } isCompatible } @@ -334,6 +333,16 @@ class DefaultElementClassicConnection( val doesContainBackupKey = secrets != null && roomKeysVersion != null && matrixAuthenticationService.doSecretsContainBackupKey(userId, secrets, roomKeysVersion) + Timber.tag(loggerTag.value).d( + buildString { + append("Receiving session $userId ($displayName) from Element Classic, with secrets: ") + append(secrets != null) + append(", with roomKeysVersion: ") + append(roomKeysVersion != null) + append(", with valid backup key: ") + append(doesContainBackupKey) + } + ) ElementClassicConnectionState.ElementClassicReady( elementClassicSession = ElementClassicSession( userId = userId, From 53c20f3f25a870d4d63fdad6b5c69702788dbc7b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 10:22:13 +0200 Subject: [PATCH 0121/1083] Make elementClassicComponent a val. --- .../features/login/impl/classic/ElementClassicConnection.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index 393762fed2..55bc5e1fd6 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -114,7 +114,7 @@ class DefaultElementClassicConnection( // applications replace our component. try { val intentService = Intent() - intentService.setComponent(getElementClassicComponent()) + intentService.setComponent(elementClassicComponent) if (serviceBinder.bindService(intentService, serviceConnection, BIND_AUTO_CREATE)) { Timber.tag(loggerTag.value).d("Binding returned true") } else { @@ -304,7 +304,7 @@ class DefaultElementClassicConnection( mutableStateFlow.emit(state) } - private fun getElementClassicComponent() = ComponentName( + private val elementClassicComponent = ComponentName( BuildConfig.elementClassicPackage, ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME, ) From e1d175c1ac2a2393034fc5c7597e39d28cf5e572 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 11:38:52 +0200 Subject: [PATCH 0122/1083] Let Announcement.Fullscreen be an enum. --- .../android/features/announcement/api/Announcement.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt b/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt index 1d6f357ca8..d743ae4cd6 100644 --- a/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt +++ b/features/announcement/api/src/main/kotlin/io/element/android/features/announcement/api/Announcement.kt @@ -12,9 +12,8 @@ import androidx.compose.runtime.Immutable @Immutable sealed interface Announcement { - @Immutable - sealed interface Fullscreen : Announcement { - data object Space : Fullscreen + enum class Fullscreen : Announcement { + Space, } data object NewNotificationSound : Announcement From 5ec4518409d6b79c9b5b0c1624241878e729ea1a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 11:40:53 +0200 Subject: [PATCH 0123/1083] Restore previous key. --- .../announcement/impl/store/DefaultAnnouncementStore.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt index d24e9ed26e..5a6c135247 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFac import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +private val spaceAnnouncementKey = intPreferencesKey("spaceAnnouncement") private val newNotificationSoundKey = intPreferencesKey("newNotificationSound") @ContributesBinding(AppScope::class) @@ -52,6 +53,6 @@ class DefaultAnnouncementStore( } private fun Announcement.toKey() = when (this) { - is Announcement.Fullscreen -> intPreferencesKey("fullscreen_" + this::class.simpleName) + Announcement.Fullscreen.Space -> spaceAnnouncementKey Announcement.NewNotificationSound -> newNotificationSoundKey } From d7e3c2df93957ddcf7a82ab01018342999628afb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 12:16:09 +0200 Subject: [PATCH 0124/1083] Add missing test for `AnnouncementEvent.Continue` --- .../impl/AnnouncementPresenterTest.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt index bcfd80942d..c37f49fad8 100644 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt +++ b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/AnnouncementPresenterTest.kt @@ -14,6 +14,7 @@ import io.element.android.features.announcement.impl.store.AnnouncementStatus import io.element.android.features.announcement.impl.store.AnnouncementStore import io.element.android.features.announcement.impl.store.InMemoryAnnouncementStore import io.element.android.tests.testutils.test +import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.Test @@ -44,6 +45,28 @@ class AnnouncementPresenterTest { assertThat(finalState.announcement).isNull() } } + + @Test + fun `present - continue event will mark the announcement as Shown`() = runTest { + val store = InMemoryAnnouncementStore() + val presenter = createAnnouncementPresenter( + announcementStore = store, + ) + presenter.test { + val state = awaitItem() + assertThat(state.announcement).isNull() + store.setAnnouncementStatus(Announcement.Fullscreen.Space, AnnouncementStatus.Show) + val statusShow = store.announcementStatusFlow(Announcement.Fullscreen.Space).first() + assertThat(statusShow).isEqualTo(AnnouncementStatus.Show) + val updatedState = awaitItem() + assertThat(updatedState.announcement).isEqualTo(Announcement.Fullscreen.Space) + updatedState.eventSink(AnnouncementEvent.Continue(Announcement.Fullscreen.Space)) + val statusShown = store.announcementStatusFlow(Announcement.Fullscreen.Space).first() + assertThat(statusShown).isEqualTo(AnnouncementStatus.Shown) + val finalState = awaitItem() + assertThat(finalState.announcement).isNull() + } + } } private fun createAnnouncementPresenter( From 76de9db94e14cc76ab53d2c42b85e0023e60b712 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 12:21:44 +0200 Subject: [PATCH 0125/1083] Move `val`s at the top of the class. --- .../impl/classic/ElementClassicConnection.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index 55bc5e1fd6..3c4dd4de3c 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -80,6 +80,14 @@ class DefaultElementClassicConnection( // Flag indicating whether we have called bind on the service. private var bound: Boolean = false + private val mutableStateFlow = MutableStateFlow(ElementClassicConnectionState.Idle) + override val stateFlow = mutableStateFlow.asStateFlow() + + private val elementClassicComponent = ComponentName( + BuildConfig.elementClassicPackage, + ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME, + ) + /** * Class for interacting with the main interface of the service. */ @@ -192,9 +200,6 @@ class DefaultElementClassicConnection( } } - private val mutableStateFlow = MutableStateFlow(ElementClassicConnectionState.Idle) - override val stateFlow = mutableStateFlow.asStateFlow() - /** * Handler of incoming messages from service. */ @@ -304,11 +309,6 @@ class DefaultElementClassicConnection( mutableStateFlow.emit(state) } - private val elementClassicComponent = ComponentName( - BuildConfig.elementClassicPackage, - ELEMENT_CLASSIC_SERVICE_FULL_CLASS_NAME, - ) - private fun Bundle.toElementClassicConnectionState(): ElementClassicConnectionState { val error = getString(KEY_ERROR_STR) return if (error != null) { From 83c4fa827855425c9b1a22bb2d0e8fba5caa141c Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 14 Apr 2026 14:45:35 +0200 Subject: [PATCH 0126/1083] feat: Default to camera muted when joining ongoing voice call --- .../home/impl/components/RoomSummaryRow.kt | 5 +- .../datasource/RoomListRoomSummaryFactory.kt | 6 ++ .../home/impl/model/RoomListRoomSummary.kt | 2 + .../impl/model/RoomListRoomSummaryProvider.kt | 11 +++ .../roomcall/impl/RoomCallStatePresenter.kt | 14 ++- .../impl/RoomCallStatePresenterTest.kt | 96 +++++++++++++++++++ 6 files changed, 131 insertions(+), 3 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index e2598a9e1c..f541417104 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -60,6 +60,7 @@ import io.element.android.libraries.designsystem.theme.roomListRoomMessage import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate import io.element.android.libraries.designsystem.theme.roomListRoomName import io.element.android.libraries.designsystem.theme.unreadIndicator +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.ui.components.InviteSenderView import io.element.android.libraries.matrix.ui.model.InviteSender @@ -349,6 +350,7 @@ private fun MessagePreviewAndIndicatorRow( if (room.hasRoomCall) { OnGoingCallIcon( color = tint, + isAudio = room.activeCallIntent == CallIntent.AUDIO ) } if (room.userDefinedNotificationMode == RoomNotificationMode.MUTE) { @@ -398,10 +400,11 @@ private fun InviteNameAndIndicatorRow( @Composable private fun OnGoingCallIcon( color: Color, + isAudio: Boolean ) { Icon( modifier = Modifier.size(16.dp), - imageVector = CompoundIcons.VideoCallSolid(), + imageVector = if (isAudio) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), contentDescription = stringResource(CommonStrings.a11y_notifications_ongoing_call), tint = color, ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt index d723d1a424..26054d7e56 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.api.DateFormatterMode import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter +import io.element.android.libraries.matrix.api.room.CallIntentConsensus import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.roomlist.LatestEventValue @@ -50,6 +51,11 @@ class RoomListRoomSummaryFactory( avatarData = avatarData, userDefinedNotificationMode = roomInfo.userDefinedNotificationMode, hasRoomCall = roomInfo.hasRoomCall, + activeCallIntent = when (val consensus = roomInfo.activeCallIntentConsensus) { + is CallIntentConsensus.Full -> consensus.callIntent + is CallIntentConsensus.Partial -> consensus.callIntent + CallIntentConsensus.None -> null + }, isDirect = roomInfo.isDirect, isFavorite = roomInfo.isFavorite, inviteSender = roomInfo.inviter?.toInviteSender(), diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt index a59e444455..628d0d0a9b 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt @@ -13,6 +13,7 @@ import io.element.android.features.invite.api.InviteData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.ui.model.InviteSender import kotlinx.collections.immutable.ImmutableList @@ -33,6 +34,7 @@ data class RoomListRoomSummary( val avatarData: AvatarData, val userDefinedNotificationMode: RoomNotificationMode?, val hasRoomCall: Boolean, + val activeCallIntent: CallIntent?, val isDirect: Boolean, val isDm: Boolean, val isFavorite: Boolean, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt index 400decff6f..eefb2d6484 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.ui.model.InviteSender import kotlinx.collections.immutable.toImmutableList @@ -132,6 +133,14 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider RoomCallState.StandBy( canStartCall = canJoinCall, @@ -70,3 +71,12 @@ class RoomCallStatePresenter( return callState } } + +fun CallIntentConsensus.isAudio(): Boolean { + val intent = when (this) { + is CallIntentConsensus.Full -> callIntent + is CallIntentConsensus.Partial -> callIntent + is CallIntentConsensus.None -> return false + } + return intent == CallIntent.AUDIO +} diff --git a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt index 0a561ad59a..4c6fcf8e59 100644 --- a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt +++ b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt @@ -14,6 +14,8 @@ import io.element.android.features.call.api.CurrentCallService import io.element.android.features.call.test.FakeCurrentCallService import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.roomcall.api.RoomCallState +import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.api.room.CallIntentConsensus import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.test.room.FakeBaseRoom @@ -188,6 +190,100 @@ class RoomCallStatePresenterTest { } } + @Test + fun `present - active call with audio Intent`() = runTest { + val room = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(true), + ).apply { + givenRoomInfo( + aRoomInfo( + hasRoomCall = true, + activeCallIntentConsensus = CallIntentConsensus.Full(CallIntent.AUDIO), + activeRoomCallParticipants = emptyList(), + ) + ) + } + ) + val presenter = createRoomCallStatePresenter( + joinedRoom = room, + currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))), + ) + presenter.test { + skipItems(1) + assertThat(awaitItem()).isEqualTo( + RoomCallState.OnGoing( + canJoinCall = true, + isAudioCall = true, + isUserInTheCall = false, + isUserLocallyInTheCall = true, + ) + ) + } + } + + @Test + fun `present - active call with partial audio Intent`() = runTest { + val room = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(true), + ).apply { + givenRoomInfo( + aRoomInfo( + hasRoomCall = true, + activeCallIntentConsensus = CallIntentConsensus.Partial(CallIntent.AUDIO, 1, 4), + ) + ) + } + ) + val presenter = createRoomCallStatePresenter( + joinedRoom = room, + currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))), + ) + presenter.test { + skipItems(1) + assertThat(awaitItem()).isEqualTo( + RoomCallState.OnGoing( + canJoinCall = true, + isAudioCall = true, + isUserInTheCall = false, + isUserLocallyInTheCall = true, + ) + ) + } + } + + @Test + fun `present - active call with no intent defaults to Audio`() = runTest { + val room = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(true), + ).apply { + givenRoomInfo( + aRoomInfo( + hasRoomCall = true, + activeCallIntentConsensus = CallIntentConsensus.None, + ) + ) + } + ) + val presenter = createRoomCallStatePresenter( + joinedRoom = room, + currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))), + ) + presenter.test { + skipItems(1) + assertThat(awaitItem()).isEqualTo( + RoomCallState.OnGoing( + canJoinCall = true, + isAudioCall = false, + isUserInTheCall = false, + isUserLocallyInTheCall = true, + ) + ) + } + } + @Test fun `present - user leaves the call`() = runTest { val room = FakeJoinedRoom( From 107524b01dec1a7c3d7612b815792587514c3b36 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 14 Apr 2026 13:18:21 +0000 Subject: [PATCH 0127/1083] Update screenshots --- .../features.home.impl.components_RoomSummaryRow_Day_38_en.png | 3 +++ ...eatures.home.impl.components_RoomSummaryRow_Night_38_en.png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_38_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_38_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_38_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_38_en.png new file mode 100644 index 0000000000..473fd3f275 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_38_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26071a6b16f4446526f6abf28274580eb0f385bd0e74f4f2b0479da5f5d4f6f2 +size 12914 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_38_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_38_en.png new file mode 100644 index 0000000000..14c08f0b62 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_38_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ddef7c50d6a791c6a32bae8506a999b198bc601b70b6ffb5e5e7a8d5a2f1543 +size 12869 From b033f2e1291b03f8b7a1c7d1d638bda0c608c771 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 14 Apr 2026 15:20:56 +0200 Subject: [PATCH 0128/1083] fixup: test compilation pb --- .../features/home/impl/model/RoomListBaseRoomSummaryTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt index 28e7051a55..63f1ecebd7 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt @@ -101,6 +101,7 @@ internal fun createRoomListRoomSummary( displayType = displayType, userDefinedNotificationMode = userDefinedNotificationMode, hasRoomCall = false, + activeCallIntent = null, isDirect = false, isFavorite = isFavorite, canonicalAlias = null, From 7a7a5a68b9f5d193e7095f77da50aa9ec948525e Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 14 Apr 2026 15:52:41 +0200 Subject: [PATCH 0129/1083] Fix `isInAirGappedEnvironment` check for older APIs (#6573) * Fix `isInAirGappedEnvironment` check for older APIs: use `networkCapabilities.hasCapability` instead of `networkCapabilities.capabilities.contains`, which only works on Android 12 and newer versions * Check for air-gapped env in the FOSS app too: this unifies the notification behaviour on EXA and Element Pro --- .../networkmonitor/impl/DefaultNetworkMonitor.kt | 12 +----------- .../SyncPendingNotificationsRequestBuilder.kt | 1 - ...aultSyncPendingNotificationsRequestBuilderTest.kt | 6 ++++++ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/features/networkmonitor/impl/src/main/kotlin/io/element/android/features/networkmonitor/impl/DefaultNetworkMonitor.kt b/features/networkmonitor/impl/src/main/kotlin/io/element/android/features/networkmonitor/impl/DefaultNetworkMonitor.kt index 7cffa057bc..6981d2c6af 100644 --- a/features/networkmonitor/impl/src/main/kotlin/io/element/android/features/networkmonitor/impl/DefaultNetworkMonitor.kt +++ b/features/networkmonitor/impl/src/main/kotlin/io/element/android/features/networkmonitor/impl/DefaultNetworkMonitor.kt @@ -15,13 +15,11 @@ import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest -import android.os.Build import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus -import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.di.annotations.ApplicationContext import kotlinx.coroutines.CoroutineScope @@ -44,7 +42,6 @@ import java.util.concurrent.atomic.AtomicInteger class DefaultNetworkMonitor( @ApplicationContext context: Context, @AppCoroutineScope appCoroutineScope: CoroutineScope, - private val buildMeta: BuildMeta, ) : NetworkMonitor { private val connectivityManager: ConnectivityManager = context.getSystemService(ConnectivityManager::class.java) @@ -76,17 +73,10 @@ class DefaultNetworkMonitor( } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { - if (!buildMeta.isEnterpriseBuild) { - // The air-gapped environment detection is only relevant for the enterprise build. - return - } - if (network.networkHandle == connectivityManager.activeNetwork?.networkHandle) { // If the network doesn't have the NET_CAPABILITY_VALIDATED capability, it means that the network is not able to reach the internet // (according to Google), which is a common case in air-gapped environments. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - isInAirGappedEnvironment.value = !networkCapabilities.capabilities.contains(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - } + isInAirGappedEnvironment.value = !networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncPendingNotificationsRequestBuilder.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncPendingNotificationsRequestBuilder.kt index bdb8389feb..4c1da42660 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncPendingNotificationsRequestBuilder.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/SyncPendingNotificationsRequestBuilder.kt @@ -76,7 +76,6 @@ class DefaultSyncPendingNotificationsRequestBuilder( .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) // If we're in an air-gapped environment, we shouldn't validate internet connectivity, as the checker will fail and the worker won't run at all. - // Note this will always be false for FOSS, since the feature is only enabled in Element Pro. if (networkMonitor.isInAirGappedEnvironment.first()) { Timber.d("In an air-gapped environment, not adding NET_CAPABILITY_VALIDATED to the network request") networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/DefaultSyncPendingNotificationsRequestBuilderTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/DefaultSyncPendingNotificationsRequestBuilderTest.kt index 796d5d192f..e65bea20a9 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/DefaultSyncPendingNotificationsRequestBuilderTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/DefaultSyncPendingNotificationsRequestBuilderTest.kt @@ -80,6 +80,9 @@ class DefaultSyncPendingNotificationsRequestBuilderTest { sessionId = A_SESSION_ID, sdkVersion = 33, isInAirGapEnvironment = false, + featureFlagService = FakeFeatureFlagService(initialState = mapOf( + FeatureFlags.ValidateNetworkWhenSchedulingNotificationFetching.key to true + )), ) val results = request.build() @@ -100,6 +103,9 @@ class DefaultSyncPendingNotificationsRequestBuilderTest { sessionId = A_SESSION_ID, sdkVersion = 33, isInAirGapEnvironment = true, + featureFlagService = FakeFeatureFlagService(initialState = mapOf( + FeatureFlags.ValidateNetworkWhenSchedulingNotificationFetching.key to true + )), ) val results = request.build() From 29e4771b22ead2e5bf79fd9aeac5f2fd73cda8e0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:56:35 +0000 Subject: [PATCH 0130/1083] Update dependency com.google.testparameterinjector:test-parameter-injector to v1.22 --- 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 7ab0cc6ee3..2288b09220 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -165,7 +165,7 @@ test_mockk = "io.mockk:mockk:1.14.9" test_konsist = "com.lemonappdev:konsist:0.17.3" test_turbine = "app.cash.turbine:turbine:1.2.1" test_truth = "com.google.truth:truth:1.4.5" -test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.21" +test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.22" test_robolectric = "org.robolectric:robolectric:4.16.1" test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" } test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.8.2" From fd3c4c2b2b8eff400541550ba237b25cbb93a54b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Apr 2026 16:51:00 +0200 Subject: [PATCH 0131/1083] Refresh Element Classic state each time ClassicFlowNode is resumed. This ensure that Element X is always up to date regarding Element Classic state. --- .../impl/classic/ElementClassicConnection.kt | 28 ++++++++++++----- .../impl/screens/classic/ClassicFlowNode.kt | 6 ++++ .../screens/classic/ClassicFlowNodeHelper.kt | 4 +++ .../loginwithclassic/LoginWithClassicEvent.kt | 1 - .../LoginWithClassicPresenter.kt | 7 ----- .../loginwithclassic/LoginWithClassicView.kt | 6 ---- .../missingkeybackup/MissingKeyBackupEvent.kt | 12 -------- .../MissingKeyBackupPresenter.kt | 20 ------------- .../missingkeybackup/MissingKeyBackupState.kt | 1 - .../MissingKeyBackupStateProvider.kt | 2 -- .../missingkeybackup/MissingKeyBackupView.kt | 7 ----- .../classic/FakeElementClassicConnection.kt | 3 -- .../LoginWithClassicPresenterTest.kt | 30 ------------------- .../MissingKeyBackupPresenterTest.kt | 22 -------------- 14 files changed, 30 insertions(+), 119 deletions(-) delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index 3c4dd4de3c..dfddd1d496 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -43,7 +43,6 @@ interface ElementClassicConnection { fun start() fun stop() fun requestSession() - fun requestAvatar(userId: UserId) val stateFlow: StateFlow } @@ -174,7 +173,7 @@ class DefaultElementClassicConnection( } } - override fun requestAvatar(userId: UserId) { + private fun requestAvatar(userId: UserId) { Timber.tag(loggerTag.value).d("requestAvatar()") coroutineScope.launch { val finalMessenger = messenger @@ -225,6 +224,11 @@ class DefaultElementClassicConnection( coroutineScope.launch { val updatedState = ensureHomeserverIsSupported(state) emitState(updatedState) + val userId = (updatedState as? ElementClassicConnectionState.ElementClassicReady)?.elementClassicSession?.userId + if (userId != null) { + // Step 2, request the avatar + requestAvatar(userId) + } } } @@ -241,11 +245,15 @@ class DefaultElementClassicConnection( ) } else { val avatar = BundleCompat.getParcelable(data, KEY_USER_AVATAR_PARCELABLE, Bitmap::class.java) - val updatedState = currentState.copy( - avatar = avatar, - ) - coroutineScope.launch { - emitState(updatedState) + // If the avatar is identical to the current one, do not emit a new state to avoid unnecessary recompositions + // and blink on the avatar image + if (avatar == null || !avatar.sameAs(currentState.avatar)) { + val updatedState = currentState.copy( + avatar = avatar, + ) + coroutineScope.launch { + emitState(updatedState) + } } } } else { @@ -343,6 +351,10 @@ class DefaultElementClassicConnection( append(doesContainBackupKey) } ) + // Ensure avatar is not lost when refreshing the data + val currentAvatar = (stateFlow.value as? ElementClassicConnectionState.ElementClassicReady) + ?.takeIf { it.elementClassicSession.userId == userId } + ?.avatar ElementClassicConnectionState.ElementClassicReady( elementClassicSession = ElementClassicSession( userId = userId, @@ -352,7 +364,7 @@ class DefaultElementClassicConnection( doesContainBackupKey = doesContainBackupKey, ), displayName = displayName, - avatar = null, + avatar = currentAvatar, ) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt index 8d79453318..f2ff998652 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt @@ -11,6 +11,7 @@ import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.lifecycle.lifecycleScope +import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin @@ -75,6 +76,11 @@ class ClassicFlowNode( override fun onBuilt() { super.onBuilt() observeElementClassicConnection() + lifecycle.subscribe( + onResume = { + classicFlowNodeHelper.onResume() + }, + ) } private fun observeElementClassicConnection() { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt index cae4f834d0..a5bc74c5e4 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNodeHelper.kt @@ -26,6 +26,10 @@ class ClassicFlowNodeHelper( private val elementClassicConnection: ElementClassicConnection, private val sessionStore: SessionStore, ) { + fun onResume() { + elementClassicConnection.requestSession() + } + @OptIn(ExperimentalCoroutinesApi::class) fun navigationEventFlow(): Flow { return elementClassicConnection.stateFlow diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt index e3c6ed782d..6ba9b2142a 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicEvent.kt @@ -8,7 +8,6 @@ package io.element.android.features.login.impl.screens.classic.loginwithclassic sealed interface LoginWithClassicEvent { - data object RefreshData : LoginWithClassicEvent data object Submit : LoginWithClassicEvent data object ClearError : LoginWithClassicEvent } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt index 6494ee741e..90a528c3ae 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenter.kt @@ -56,13 +56,6 @@ class LoginWithClassicPresenter( fun handleEvent(event: LoginWithClassicEvent) { when (event) { - LoginWithClassicEvent.RefreshData -> { - // Request the avatar if not known yet - val currentState = elementClassicConnection.stateFlow.value - if ((currentState as? ElementClassicConnectionState.ElementClassicReady)?.avatar == null) { - elementClassicConnection.requestAvatar(userId) - } - } LoginWithClassicEvent.Submit -> { val currentState = elementClassicConnection.stateFlow.value if (currentState is ElementClassicConnectionState.ElementClassicReady) { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt index aeb61946ff..6b5c48f1ec 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt @@ -33,8 +33,6 @@ 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 androidx.lifecycle.Lifecycle -import androidx.lifecycle.compose.LifecycleEventEffect import io.element.android.compound.theme.ElementTheme import io.element.android.features.login.impl.R import io.element.android.features.login.impl.login.LoginModeView @@ -67,10 +65,6 @@ fun LoginWithClassicView( onCreateAccountContinue: (url: String) -> Unit, modifier: Modifier = Modifier, ) { - LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { - state.eventSink(LoginWithClassicEvent.RefreshData) - } - val isLoading by remember(state.loginMode) { derivedStateOf { state.loginMode is AsyncData.Loading diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt deleted file mode 100644 index a8b86ec1bf..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupEvent.kt +++ /dev/null @@ -1,12 +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.features.login.impl.screens.classic.missingkeybackup - -sealed interface MissingKeyBackupEvent { - data object OnResume : MissingKeyBackupEvent -} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt index 7b8ea7e633..593c50dcb5 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenter.kt @@ -8,38 +8,18 @@ package io.element.android.features.login.impl.screens.classic.missingkeybackup import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject -import io.element.android.features.login.impl.classic.ElementClassicConnection import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta @Inject class MissingKeyBackupPresenter( private val buildMeta: BuildMeta, - private val elementClassicConnection: ElementClassicConnection, ) : Presenter { @Composable override fun present(): MissingKeyBackupState { - var resumeCounter by remember { mutableIntStateOf(0) } - fun handleEvent(event: MissingKeyBackupEvent) { - when (event) { - MissingKeyBackupEvent.OnResume -> { - resumeCounter++ - if (resumeCounter > 1) { - // The user has returned to this screen, we can assume they have gone to the backup flow and are now back here - elementClassicConnection.requestSession() - } - } - } - } - return MissingKeyBackupState( appName = buildMeta.applicationName, - eventSink = ::handleEvent, ) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt index 78d3d81c72..31eaf015a0 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupState.kt @@ -9,5 +9,4 @@ package io.element.android.features.login.impl.screens.classic.missingkeybackup data class MissingKeyBackupState( val appName: String, - val eventSink: (MissingKeyBackupEvent) -> Unit ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt index 85d1042985..2c6a09b3ed 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupStateProvider.kt @@ -19,8 +19,6 @@ open class MissingKeyBackupStateProvider : PreviewParameterProvider Unit = {}, ) = MissingKeyBackupState( appName = appName, - eventSink = eventSink ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt index 67865ffcb8..c4c9c5f286 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupView.kt @@ -16,7 +16,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.login.impl.R import io.element.android.libraries.designsystem.atomic.organisms.NumberedListOrganism @@ -25,7 +24,6 @@ import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import kotlinx.collections.immutable.persistentListOf @Composable @@ -35,11 +33,6 @@ fun MissingKeyBackupView( onOpenClassicClick: () -> Unit, modifier: Modifier = Modifier, ) { - OnLifecycleEvent { _, event -> - if (event == Lifecycle.Event.ON_RESUME) { - state.eventSink.invoke(MissingKeyBackupEvent.OnResume) - } - } FlowStepPage( modifier = modifier, onBackClick = onBackClick, diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt index 6b601543ce..227aa514b3 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/FakeElementClassicConnection.kt @@ -7,7 +7,6 @@ package io.element.android.features.login.impl.classic -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -17,13 +16,11 @@ class FakeElementClassicConnection( private val startResult: () -> Unit = { lambdaError() }, private val stopResult: () -> Unit = { lambdaError() }, private val requestSessionResult: () -> Unit = { lambdaError() }, - private val requestAvatarResult: (UserId) -> Unit = { lambdaError() }, initialState: ElementClassicConnectionState = ElementClassicConnectionState.Idle ) : ElementClassicConnection { override fun start() = startResult() override fun stop() = stopResult() override fun requestSession() = requestSessionResult() - override fun requestAvatar(userId: UserId) = requestAvatarResult(userId) private val mutableStateFlow = MutableStateFlow(initialState) override val stateFlow: StateFlow = mutableStateFlow.asStateFlow() suspend fun emitState(state: ElementClassicConnectionState) { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt index 3bd2dd0cf8..6b2a4fb0e1 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicPresenterTest.kt @@ -57,36 +57,6 @@ class LoginWithClassicPresenterTest { } } - @Test - fun `present - refresh data invokes the expected methods`() = runTest { - val requestAvatarResult = lambdaRecorder { } - val elementClassicConnection = FakeElementClassicConnection( - startResult = {}, - requestAvatarResult = requestAvatarResult, - ) - val presenter = createPresenter( - elementClassicConnection = elementClassicConnection, - ) - presenter.test { - skipItems(1) - elementClassicConnection.emitState( - anElementClassicReady( - elementClassicSession = anElementClassicSession( - userId = A_USER_ID, - secrets = A_SECRET, - roomKeysVersion = ROOM_KEYS_VERSION, - ), - displayName = A_USER_NAME, - ) - ) - val readyState = awaitItem() - assertThat(readyState.userId).isEqualTo(A_USER_ID) - assertThat(readyState.displayName).isEqualTo(A_USER_NAME) - readyState.eventSink(LoginWithClassicEvent.RefreshData) - requestAvatarResult.assertions().isCalledOnce() - } - } - @Test fun `present - start login with correct state - user can login`() = runTest { val authenticationService = FakeMatrixAuthenticationService( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt index 2a4af8bf5a..447b0ba77b 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/classic/missingkeybackup/MissingKeyBackupPresenterTest.kt @@ -8,12 +8,9 @@ package io.element.android.features.login.impl.screens.classic.missingkeybackup import com.google.common.truth.Truth.assertThat -import io.element.android.features.login.impl.classic.ElementClassicConnection -import io.element.android.features.login.impl.classic.FakeElementClassicConnection import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.test.AN_APPLICATION_NAME import io.element.android.libraries.matrix.test.core.aBuildMeta -import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Test @@ -27,29 +24,10 @@ class MissingKeyBackupPresenterTest { assertThat(initialState.appName).isEqualTo(AN_APPLICATION_NAME) } } - - @Test - fun `present - when the screen is resumed twice, the start over method is called`() = runTest { - val requestSessionResult = lambdaRecorder { } - val presenter = createPresenter( - elementClassicConnection = FakeElementClassicConnection( - requestSessionResult = requestSessionResult, - ), - ) - presenter.test { - val initialState = awaitItem() - initialState.eventSink(MissingKeyBackupEvent.OnResume) - expectNoEvents() - initialState.eventSink(MissingKeyBackupEvent.OnResume) - requestSessionResult.assertions().isCalledOnce() - } - } } private fun createPresenter( buildMeta: BuildMeta = aBuildMeta(applicationName = AN_APPLICATION_NAME), - elementClassicConnection: ElementClassicConnection = FakeElementClassicConnection(), ) = MissingKeyBackupPresenter( buildMeta = buildMeta, - elementClassicConnection = elementClassicConnection, ) From 4cc9c772646beb8f7d20624da0f552594e996b5a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 15 Apr 2026 08:32:26 +0200 Subject: [PATCH 0132/1083] Use @TestParameter instead of doing the work manually. --- .../screens/onboarding/OnboardingViewTest.kt | 42 ++++++------------- .../kotlin/extension/DependencyHandleScope.kt | 1 + 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt index c8dcd978c6..c3d1ff6015 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt @@ -13,7 +13,8 @@ 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 com.google.testing.junit.testparameterinjector.KotlinTestParameters.namedTestValues +import com.google.testing.junit.testparameterinjector.TestParameter import io.element.android.features.login.impl.R import io.element.android.features.login.impl.login.LoginMode import io.element.android.libraries.architecture.AsyncData @@ -31,8 +32,9 @@ import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule import org.junit.runner.RunWith +import org.robolectric.RobolectricTestParameterInjector -@RunWith(AndroidJUnit4::class) +@RunWith(RobolectricTestParameterInjector::class) class OnboardingViewTest { @get:Rule val rule = createAndroidComposeRule() @@ -83,21 +85,11 @@ class OnboardingViewTest { } @Test - fun `when can login with QR code - clicking on sign in manually calls the expected callback - can search account provider`() { - `when can login with QR code - clicking on sign in manually calls the expected callback`( - mustChooseAccountProvider = false, + fun `when can login with QR code - clicking on sign in manually calls the expected callback`( + @TestParameter mustChooseAccountProvider: Boolean = namedTestValues( + "can search account provider" to false, + "cannot search account provider" to true, ) - } - - @Test - fun `when can login with QR code - clicking on sign in manually calls the expected callback - cannot search account provider`() { - `when can login with QR code - clicking on sign in manually calls the expected callback`( - mustChooseAccountProvider = true, - ) - } - - private fun `when can login with QR code - clicking on sign in manually calls the expected callback`( - mustChooseAccountProvider: Boolean, ) { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(mustChooseAccountProvider) { callback -> @@ -114,21 +106,11 @@ class OnboardingViewTest { } @Test - fun `when cannot login with QR code or create account - clicking on continue calls the sign in callback - can search account provider`() { - `when cannot login with QR code or create account - clicking on continue calls the sign in callback`( - mustChooseAccountProvider = false, + fun `when cannot login with QR code or create account - clicking on continue calls the sign in callback`( + @TestParameter mustChooseAccountProvider: Boolean = namedTestValues( + "can search account provider" to false, + "cannot search account provider" to true, ) - } - - @Test - fun `when cannot login with QR code or create account - clicking on continue calls the sign in callback - cannot search account provider`() { - `when cannot login with QR code or create account - clicking on continue calls the sign in callback`( - mustChooseAccountProvider = true, - ) - } - - private fun `when cannot login with QR code or create account - clicking on continue calls the sign in callback`( - mustChooseAccountProvider: Boolean, ) { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(mustChooseAccountProvider) { callback -> diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 8a5dfa2c4a..ce5c324ff4 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -49,6 +49,7 @@ fun DependencyHandlerScope.testCommonDependencies( testImplementation(libs.test.arch.core) testImplementation(libs.test.junit) testImplementation(libs.test.mockk) + testImplementation(libs.test.parameter.injector) testImplementation(libs.test.robolectric) testImplementation(libs.test.truth) testImplementation(libs.test.turbine) From 937973570a5252b8824f2654ab4569a45536a9b6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 15 Apr 2026 08:39:14 +0200 Subject: [PATCH 0133/1083] Use @TestParameter instead of doing the work manually. --- .../space/impl/root/SpacePresenterTest.kt | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt index e183de6f27..ba4e10a447 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpacePresenterTest.kt @@ -11,6 +11,9 @@ package io.element.android.features.space.impl.root import com.google.common.truth.Truth.assertThat +import com.google.testing.junit.testparameterinjector.KotlinTestParameters.namedTestValues +import com.google.testing.junit.testparameterinjector.TestParameter +import com.google.testing.junit.testparameterinjector.TestParameterInjector import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteState @@ -49,8 +52,10 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith import im.vector.app.features.analytics.plan.JoinedRoom as AnalyticsJoinedRoom +@RunWith(TestParameterInjector::class) class SpacePresenterTest { @Test fun `present - initial state`() = runTest { @@ -259,21 +264,11 @@ class SpacePresenterTest { } @Test - fun `present - accept invite is transmitted to acceptDeclineInviteState`() { - `invite action is transmitted to acceptDeclineInviteState`( - acceptInvite = true, - ) - } - - @Test - fun `present - decline invite is transmitted to acceptDeclineInviteState`() { - `invite action is transmitted to acceptDeclineInviteState`( - acceptInvite = false, - ) - } - - private fun `invite action is transmitted to acceptDeclineInviteState`( - acceptInvite: Boolean, + fun `present - invite action is transmitted to acceptDeclineInviteState`( + @TestParameter acceptInvite: Boolean = namedTestValues( + "accept" to true, + "decline" to false, + ), ) = runTest { val eventRecorder = EventsRecorder() val anInvitedRoom = aSpaceRoom( From e0554bbaf38776d07b557f7b316eb064608bc93f Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Apr 2026 09:58:03 +0200 Subject: [PATCH 0134/1083] Use `Coil3` for `ZoomableAsyncImage` (#6582) The `-coil` version uses Coil 2.X, there is a `-coil3` version using the latest one, which matches the one we use in the rest of the app. --- gradle/libs.versions.toml | 2 +- .../libraries/mediaviewer/impl/local/image/MediaImageView.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2288b09220..895bad253f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -204,7 +204,7 @@ sqlcipher = "net.zetetic:sqlcipher-android:4.14.1" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" unifiedpush = "org.unifiedpush.android:connector:3.3.2" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" -telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" } +telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil3", version.ref = "telephoto" } telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" } statemachine = "com.freeletics.flowredux:compose:1.2.2" maplibre = "org.maplibre.gl:android-sdk:13.0.2" diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt index 306a18b4d6..4c73dd215d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/image/MediaImageView.kt @@ -23,7 +23,7 @@ import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.local.LocalMediaViewState import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState import io.element.android.libraries.ui.strings.CommonStrings -import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage +import me.saket.telephoto.zoomable.coil3.ZoomableAsyncImage import me.saket.telephoto.zoomable.rememberZoomableImageState @Composable From 897c68e7b7c6186f67b512fd38f7729cd6106f06 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Wed, 15 Apr 2026 10:25:58 +0100 Subject: [PATCH 0135/1083] Add confirmation dialog when inviting users with unknown identities (#6523) * feat: Add confirmation modal when inviting unknown users * tests: Add preview tests for invite confirmation modal * tests: Add unit tests for invite confirmation modal * feat: Switch confirmation sheet contents based on identity state * tests: Add history sharing unit tests for `DefaultStartDMActionTest` * tests: Update snapshots for `CreateDmConfirmationBottomSheet` * chore: Fix tiny nits * fix: Remove default param on `ConfirmingStartDmWithMatrixUser` * refactor: Use new AsyncAction over boolean flag * fix: Add sleeps to tests * refactor: Remove `PromptOrInvite` and switch on async action * fix: Remove redundant `assertThat` * feat: Alllow invite confirmation modal to be dismissed * tests: Update snapshots for InvitePeopleView * fix: Adjust `CreateDmConfirmationBottomSheet` to conform to design * feat: Use localazy translations and plurals * fix: When users are unselected, unselect them in search results too * tests: Use aMatrixUserList to provide multiple users * Update screenshots * fix: Add missing parameter in UserProfilePresenterTest --------- Co-authored-by: Andy Balaam Co-authored-by: ElementBot --- features/invitepeople/impl/build.gradle.kts | 2 + .../impl/ConfirmingUnknownUserInvitation.kt | 16 ++ .../impl/DefaultInvitePeopleEvents.kt | 2 + .../impl/DefaultInvitePeoplePresenter.kt | 86 ++++++- .../impl/DefaultInvitePeopleStateProvider.kt | 10 + .../invitepeople/impl/InvitePeopleView.kt | 71 ++++++ .../impl/DefaultInvitePeoplePresenterTest.kt | 234 ++++++++++++++++++ .../api/ConfirmingStartDmWithMatrixUser.kt | 1 + .../startchat/impl/DefaultStartDMAction.kt | 9 +- .../startchat/impl/root/StartChatPresenter.kt | 3 + .../startchat/impl/root/StartChatState.kt | 1 + .../impl/root/StartChatStateProvider.kt | 14 +- .../startchat/impl/root/StartChatView.kt | 2 + .../impl/DefaultStartDMActionTest.kt | 41 ++- .../impl/root/StartChatPresenterTest.kt | 4 +- .../userprofile/api/UserProfileState.kt | 1 + features/userprofile/impl/build.gradle.kts | 2 + .../impl/root/UserProfilePresenter.kt | 7 + .../impl/UserProfilePresenterTest.kt | 6 +- .../shared/UserProfileStateProvider.kt | 3 +- .../userprofile/shared/UserProfileView.kt | 2 + .../CreateDmConfirmationBottomSheet.kt | 133 +++++++--- ...people.impl_InvitePeopleView_Day_10_en.png | 3 + ...people.impl_InvitePeopleView_Day_11_en.png | 3 + ...ople.impl_InvitePeopleView_Night_10_en.png | 3 + ...ople.impl_InvitePeopleView_Night_11_en.png | 3 + ...eateDmConfirmationBottomSheet_Day_1_en.png | 4 +- ...eateDmConfirmationBottomSheet_Day_2_en.png | 3 + ...teDmConfirmationBottomSheet_Night_1_en.png | 4 +- ...teDmConfirmationBottomSheet_Night_2_en.png | 3 + 30 files changed, 618 insertions(+), 58 deletions(-) create mode 100644 features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/ConfirmingUnknownUserInvitation.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_10_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_10_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png diff --git a/features/invitepeople/impl/build.gradle.kts b/features/invitepeople/impl/build.gradle.kts index 0c3f988659..390ccce7b9 100644 --- a/features/invitepeople/impl/build.gradle.kts +++ b/features/invitepeople/impl/build.gradle.kts @@ -37,10 +37,12 @@ dependencies { implementation(projects.libraries.usersearch.api) implementation(libs.coil.compose) implementation(projects.services.apperror.api) + implementation(projects.libraries.featureflag.api) api(projects.features.invitepeople.api) testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.usersearch.test) testImplementation(projects.services.apperror.test) + testImplementation(projects.libraries.featureflag.test) } diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/ConfirmingUnknownUserInvitation.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/ConfirmingUnknownUserInvitation.kt new file mode 100644 index 0000000000..8f4d5e1510 --- /dev/null +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/ConfirmingUnknownUserInvitation.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.invitepeople.impl + +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.user.MatrixUser +import kotlinx.collections.immutable.ImmutableList + +data class ConfirmingUnknownUserInvitation( + val users: ImmutableList +) : AsyncAction.Confirming diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleEvents.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleEvents.kt index b1f18b1df9..449d0ce6ac 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleEvents.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleEvents.kt @@ -14,4 +14,6 @@ import io.element.android.libraries.matrix.api.user.MatrixUser sealed interface DefaultInvitePeopleEvents : InvitePeopleEvents { data class ToggleUser(val user: MatrixUser) : DefaultInvitePeopleEvents data class OnSearchActiveChanged(val active: Boolean) : DefaultInvitePeopleEvents + data object DismissUnknownUsersModal : DefaultInvitePeopleEvents + data object RemoveUnknownUsers : DefaultInvitePeopleEvents } diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt index 3450587e82..58b3fb67f6 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -36,8 +37,11 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.theme.components.SearchBarResultState 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.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState @@ -50,6 +54,7 @@ import io.element.android.services.apperror.api.AppErrorStateService import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toImmutableMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.launchIn @@ -69,6 +74,7 @@ class DefaultInvitePeoplePresenter( private val coroutineDispatchers: CoroutineDispatchers, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val appErrorStateService: AppErrorStateService, + private val featureFlagService: FeatureFlagService, private val matrixClient: MatrixClient, ) : InvitePeoplePresenter { @AssistedFactory @@ -87,6 +93,8 @@ class DefaultInvitePeoplePresenter( val showSearchLoader = rememberSaveable { mutableStateOf(false) } val sendInvitesAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } + val enableKeyShareOnInvite by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false) + val recentDirectRooms by produceState(emptyList(), roomMembers.value) { if (roomMembers.value.isSuccess()) { val activeMemberIds = roomMembers.value.dataOrNull().orEmpty() @@ -126,6 +134,40 @@ class DefaultInvitePeoplePresenter( } } + val selectedUserIdentities = produceState( + emptyMap().toImmutableMap(), + selectedUsers.value, + enableKeyShareOnInvite, + ) { + if (!enableKeyShareOnInvite) { + return@produceState + } + + val selected = selectedUsers.value + + val cached = value + .filterKeys { it in selected } + + val uncached = selected + .filterNot(cached::containsKey) + .associateWith { user -> + matrixClient.encryptionService + .getUserIdentity(user.userId, fallbackToServer = false) + .getOrNull() + } + + value = (cached + uncached).toImmutableMap() + } + + val unknownUsers by remember { + derivedStateOf { + selectedUserIdentities.value + .filterValues { it == null } + .keys + .toImmutableList() + } + } + LaunchedEffect(room.isSuccess()) { room.dataOrNull()?.let { fetchMembers(it, roomMembers) @@ -144,21 +186,41 @@ class DefaultInvitePeoplePresenter( fun handleEvent(event: InvitePeopleEvents) { when (event) { - is DefaultInvitePeopleEvents.OnSearchActiveChanged -> { - searchActive = event.active - if (!event.active) { - queryState.clearText() + // Dedicated `when` for exhaustivity. + is DefaultInvitePeopleEvents -> when (event) { + is DefaultInvitePeopleEvents.OnSearchActiveChanged -> { + searchActive = event.active + if (!event.active) { + queryState.clearText() + } + } + + is DefaultInvitePeopleEvents.ToggleUser -> { + selectedUsers.toggleUser(event.user) + searchResults.toggleUser(event.user) + // suggestions will automatically update via derivedStateOf when selectedUsers changes + } + is DefaultInvitePeopleEvents.DismissUnknownUsersModal -> { + sendInvitesAction.value = AsyncAction.Uninitialized + } + is DefaultInvitePeopleEvents.RemoveUnknownUsers -> { + val usersToRemove = selectedUsers.value.filter { it in unknownUsers } + usersToRemove.forEach { user -> + selectedUsers.toggleUser(user) + searchResults.toggleUser(user) + } + sendInvitesAction.value = AsyncAction.Uninitialized } } - - is DefaultInvitePeopleEvents.ToggleUser -> { - selectedUsers.toggleUser(event.user) - searchResults.toggleUser(event.user) - // suggestions will automatically update via derivedStateOf when selectedUsers changes - } is InvitePeopleEvents.SendInvites -> { - room.dataOrNull()?.let { - sessionCoroutineScope.sendInvites(it, selectedUsers.value, sendInvitesAction) + if (enableKeyShareOnInvite && unknownUsers.isNotEmpty() && sendInvitesAction.value !is ConfirmingUnknownUserInvitation) { + sendInvitesAction.value = ConfirmingUnknownUserInvitation( + unknownUsers + ) + } else { + room.dataOrNull()?.let { + sessionCoroutineScope.sendInvites(it, selectedUsers.value, sendInvitesAction) + } } } is InvitePeopleEvents.CloseSearch -> { diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt index 15ded2ae3f..c26b8de254 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt @@ -76,6 +76,16 @@ internal class DefaultInvitePeopleStateProvider : PreviewParameterProvider, + onDismiss: () -> Unit, + onInvite: () -> Unit, + onRemove: () -> Unit +) { + ModalBottomSheet( + onDismissRequest = onDismiss, + 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), + iconStyle = BigIcon.Style.Default(CompoundIcons.UserAddSolid()), + modifier = Modifier.padding( + top = 32.dp, + bottom = 16.dp, + start = 16.dp, + end = 16.dp, + ) + ) + + LazyColumn { + items(users) { user -> + MatrixUserRow(user) + } + } + + ButtonRowMolecule( + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.padding(16.dp) + ) { + OutlinedButton( + text = stringResource(CommonStrings.action_remove), + onClick = onRemove, + leadingIcon = IconSource.Vector(CompoundIcons.Close()), + modifier = Modifier.weight(1f) + ) + Button( + text = stringResource(CommonStrings.action_invite), + onClick = onInvite, + leadingIcon = IconSource.Vector(CompoundIcons.Check()), + modifier = Modifier.weight(1f) + ) + } + } +} + @PreviewsDayNight @Composable internal fun InvitePeopleViewPreview(@PreviewParameter(DefaultInvitePeopleStateProvider::class) state: DefaultInvitePeopleState) = diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index ab9e20437e..a1d72010f6 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -15,9 +15,13 @@ import io.element.android.features.invitepeople.api.InvitePeopleEvents import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMembersState @@ -28,6 +32,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID 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.FakeMatrixClient +import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo @@ -43,6 +48,7 @@ import io.element.android.libraries.usersearch.test.FakeUserRepository import io.element.android.services.apperror.api.AppErrorStateService import io.element.android.services.apperror.test.FakeAppErrorStateService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.awaitLastSequentialItem import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -56,6 +62,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +@Suppress("LargeClass") internal class DefaultInvitePeoplePresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -605,6 +612,231 @@ internal class DefaultInvitePeoplePresenterTest { } } + @Test + fun `present - users are prompted for confirmation if they attempt to invite unknown users`() = runTest { + val alice = aMatrixUser("@alice:example.com") + val bob = aMatrixUser("@bob:example.com") + val charlie = aMatrixUser("@charlie:example.com") + + val getUserIdentityResult = lambdaRecorder> { userId -> + when (userId.value) { + alice.userId.value -> Result.success(IdentityState.Pinned) + bob.userId.value -> Result.success(null) + else -> Result.failure(AN_EXCEPTION) + } + } + + val inviteUserResult = lambdaRecorder> { userId: UserId -> + Result.success(Unit) + } + val encryptionService = FakeEncryptionService( + getUserIdentityResult = getUserIdentityResult + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) + } + + val presenter = createDefaultInvitePeoplePresenter( + coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), + inviteUserResult = inviteUserResult, + matrixClient = FakeMatrixClient(encryptionService = encryptionService), + featureFlagService = featureFlagService + ) + presenter.test { + val initialState = awaitItem() + skipItems(1) + + // When we toggle a user not in the list, they are added, and we fetch their identity. + initialState.eventSink(DefaultInvitePeopleEvents.ToggleUser(alice)) + delay(100) + awaitItemAsDefault().eventSink(DefaultInvitePeopleEvents.ToggleUser(bob)) + delay(100) + awaitItemAsDefault().eventSink(DefaultInvitePeopleEvents.ToggleUser(charlie)) + delay(100) + + // If we do not have their identity cached, or fail to fetch it, we should mark them as unknown. + awaitItemAsDefault().run { + assertThat(selectedUsers).containsExactly(alice, bob, charlie) + eventSink(InvitePeopleEvents.SendInvites) + } + + getUserIdentityResult.assertions().isCalledExactly(3).withSequence( + listOf(value(alice.userId)), + listOf(value(bob.userId)), + listOf(value(charlie.userId)) + ) + + // When we then try to invite these users, we should prompt for confirmation first. + awaitItemAsDefault().run { + assertThat(sendInvitesAction).isInstanceOf(ConfirmingUnknownUserInvitation::class.java) + assertThat(canInvite).isTrue() + eventSink(InvitePeopleEvents.SendInvites) + } + + delay(1_000) + inviteUserResult.assertions().isCalledExactly(3).withSequence( + listOf(value(alice.userId)), + listOf(value(bob.userId)), + listOf(value(charlie.userId)) + ) + + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - selecting remove on confirmation prompt unselects unknown users`() = runTest { + val alice = aMatrixUser("@alice:example.com") + val bob = aMatrixUser("@bob:example.com") + val charlie = aMatrixUser("@charlie:example.com") + + val repository = FakeUserRepository() + + val getUserIdentityResult = lambdaRecorder> { userId -> + when (userId.value) { + alice.userId.value -> Result.success(IdentityState.Pinned) + bob.userId.value -> Result.success(null) + else -> Result.failure(AN_EXCEPTION) + } + } + + val encryptionService = FakeEncryptionService( + getUserIdentityResult = getUserIdentityResult + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) + } + + val presenter = createDefaultInvitePeoplePresenter( + userRepository = repository, + coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), + matrixClient = FakeMatrixClient(encryptionService = encryptionService), + featureFlagService = featureFlagService + ) + presenter.test { + val initialState = awaitItemAsDefault() + skipItems(1) + + // When we toggle a user not in the list, they are added, and we fetch their identity. + initialState.eventSink(DefaultInvitePeopleEvents.ToggleUser(alice)) + delay(100) + awaitItemAsDefault().eventSink(DefaultInvitePeopleEvents.ToggleUser(bob)) + delay(100) + awaitItemAsDefault().eventSink(DefaultInvitePeopleEvents.ToggleUser(charlie)) + delay(100) + + // And the search is matching Alice and Bob + initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query") + assertThat(repository.providedQuery).isEqualTo("some query") + repository.emitState( + UserSearchResultState( + results = listOf(UserSearchResult(alice), UserSearchResult(bob)), + isSearching = true + ) + ) + skipItems(3) + + awaitItemAsDefault().run { + assertThat(selectedUsers).containsExactly(alice, bob, charlie) + + // Both Alice and Bob are selected in searchResults + assertThat( + searchResults.users().map { Pair(it.matrixUser, it.isSelected) } + ).containsExactly(Pair(alice, true), Pair(bob, true)) + + eventSink(InvitePeopleEvents.SendInvites) + } + + getUserIdentityResult.assertions().isCalledExactly(3).withSequence( + listOf(value(alice.userId)), + listOf(value(bob.userId)), + listOf(value(charlie.userId)) + ) + + // When we then try to invite these user, we should prompt for confirmation first. + awaitItemAsDefault().run { + assertThat(sendInvitesAction).isInstanceOf(ConfirmingUnknownUserInvitation::class.java) + assertThat(canInvite).isTrue() + eventSink(DefaultInvitePeopleEvents.RemoveUnknownUsers) + } + + // Selecting "remove" should remove all unknown users, but keeps those who are known. + (awaitLastSequentialItem() as DefaultInvitePeopleState).run { + assertThat(sendInvitesAction.isUninitialized()).isTrue() + assertThat(selectedUsers).containsExactly(alice) + + // Bob is no longer selected in searchResults + assertThat( + searchResults.users().map { Pair(it.matrixUser, it.isSelected) } + ).containsExactly(Pair(alice, true), Pair(bob, false)) + } + } + } + + @Test + fun `present - dismissing confirmation prompt does not affect selection`() = runTest { + val alice = aMatrixUser("@alice:example.com") + val bob = aMatrixUser("@bob:example.com") + val charlie = aMatrixUser("@charlie:example.com") + + val getUserIdentityResult = lambdaRecorder> { userId -> + when (userId.value) { + alice.userId.value -> Result.success(IdentityState.Pinned) + bob.userId.value -> Result.success(null) + else -> Result.failure(AN_EXCEPTION) + } + } + + val encryptionService = FakeEncryptionService( + getUserIdentityResult = getUserIdentityResult + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) + } + + val presenter = createDefaultInvitePeoplePresenter( + coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), + matrixClient = FakeMatrixClient(encryptionService = encryptionService), + featureFlagService = featureFlagService + ) + presenter.test { + val initialState = awaitItem() + skipItems(1) + + // When we toggle a user not in the list, they are added, and we fetch their identity. + initialState.eventSink(DefaultInvitePeopleEvents.ToggleUser(alice)) + delay(100) + awaitItemAsDefault().eventSink(DefaultInvitePeopleEvents.ToggleUser(bob)) + delay(100) + awaitItemAsDefault().eventSink(DefaultInvitePeopleEvents.ToggleUser(charlie)) + delay(100) + + awaitItemAsDefault().run { + assertThat(selectedUsers).containsExactly(alice, bob, charlie) + eventSink(InvitePeopleEvents.SendInvites) + } + + getUserIdentityResult.assertions().isCalledExactly(3).withSequence( + listOf(value(alice.userId)), + listOf(value(bob.userId)), + listOf(value(charlie.userId)) + ) + + // When we then try to invite these user, we should prompt for confirmation first. + awaitItemAsDefault().run { + assertThat(sendInvitesAction).isInstanceOf(ConfirmingUnknownUserInvitation::class.java) + assertThat(canInvite).isTrue() + eventSink(DefaultInvitePeopleEvents.DismissUnknownUsersModal) + } + + // Dismissing should not modify the selection at all + (awaitLastSequentialItem() as DefaultInvitePeopleState).run { + assertThat(sendInvitesAction.isUninitialized()).isTrue() + assertThat(selectedUsers).containsExactly(alice, bob, charlie) + } + } + } + private suspend fun FakeUserRepository.emitStateWithUsers( users: List, isSearching: Boolean = false @@ -646,6 +878,7 @@ fun TestScope.createDefaultInvitePeoplePresenter( userRepository: UserRepository = FakeUserRepository(), coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), appErrorStateService: AppErrorStateService = FakeAppErrorStateService(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService(), matrixClient: MatrixClient = FakeMatrixClient(), ): DefaultInvitePeoplePresenter { return DefaultInvitePeoplePresenter( @@ -655,6 +888,7 @@ fun TestScope.createDefaultInvitePeoplePresenter( coroutineDispatchers = coroutineDispatchers, sessionCoroutineScope = backgroundScope, appErrorStateService = appErrorStateService, + featureFlagService = featureFlagService, matrixClient = matrixClient, ) } diff --git a/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt index 5bf015c0f0..059002d983 100644 --- a/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt +++ b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt @@ -13,4 +13,5 @@ import io.element.android.libraries.matrix.api.user.MatrixUser data class ConfirmingStartDmWithMatrixUser( val matrixUser: MatrixUser, + val isUserIdentityUnknown: Boolean, ) : AsyncAction.Confirming diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt index a484fe2e72..3bfbd1ca18 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt @@ -15,6 +15,8 @@ import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.features.startchat.api.StartDMAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.StartDMResult @@ -26,6 +28,7 @@ import io.element.android.services.analytics.api.AnalyticsService class DefaultStartDMAction( private val matrixClient: MatrixClient, private val analyticsService: AnalyticsService, + private val featureFlagService: FeatureFlagService, ) : StartDMAction { override suspend fun execute( matrixUser: MatrixUser, @@ -44,7 +47,11 @@ class DefaultStartDMAction( actionState.value = AsyncAction.Failure(result.throwable) } StartDMResult.DmDoesNotExist -> { - actionState.value = ConfirmingStartDmWithMatrixUser(matrixUser = matrixUser) + val identityState = matrixClient.encryptionService.getUserIdentity(matrixUser.userId, fallbackToServer = false).getOrNull() + actionState.value = ConfirmingStartDmWithMatrixUser( + matrixUser = matrixUser, + isUserIdentityUnknown = featureFlagService.isFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite) && identityState == null + ) } } } diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt index e176f202ad..7afbe19c3d 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt @@ -58,6 +58,8 @@ class StartChatPresenter( featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch) }.collectAsState(initial = false) + val enableKeyShareOnInvite = featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(false) + fun handleEvent(event: StartChatEvents) { when (event) { is StartChatEvents.StartDM -> localCoroutineScope.launch { @@ -76,6 +78,7 @@ class StartChatPresenter( userListState = userListState, startDmAction = startDmActionState.value, isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled, + enableKeyShareOnInvite = enableKeyShareOnInvite.value, eventSink = ::handleEvent, ) } diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt index 65f977d3e3..989a5b8d20 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt @@ -17,5 +17,6 @@ data class StartChatState( val userListState: UserListState, val startDmAction: AsyncAction, val isRoomDirectorySearchEnabled: Boolean, + val enableKeyShareOnInvite: Boolean, val eventSink: (StartChatEvents) -> Unit, ) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt index 448ad1a80a..17d83a9e11 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt @@ -16,6 +16,7 @@ import io.element.android.features.startchat.impl.userlist.aUserListState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.usersearch.api.UserSearchResult import kotlinx.collections.immutable.persistentListOf @@ -52,7 +53,7 @@ open class StartChatStateProvider : PreviewParameterProvider { ) ), aCreateRoomRootState( - startDmAction = ConfirmingStartDmWithMatrixUser(aMatrixUser()), + startDmAction = aConfirmingStartDmWithMatrixUser() ), aCreateRoomRootState( isRoomDirectorySearchEnabled = true, @@ -60,6 +61,16 @@ open class StartChatStateProvider : PreviewParameterProvider { ) } +fun aConfirmingStartDmWithMatrixUser( + matrixUser: MatrixUser = aMatrixUser(), + isUserIdentityUnknown: Boolean = false +): ConfirmingStartDmWithMatrixUser { + return ConfirmingStartDmWithMatrixUser( + matrixUser, + isUserIdentityUnknown + ) +} + fun aCreateRoomRootState( applicationName: String = "Element X Preview", userListState: UserListState = aUserListState(), @@ -71,5 +82,6 @@ fun aCreateRoomRootState( userListState = userListState, startDmAction = startDmAction, isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled, + enableKeyShareOnInvite = false, eventSink = eventSink, ) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt index 0b8da1bd94..28bf52549e 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt @@ -130,6 +130,8 @@ fun StartChatView( if (data is ConfirmingStartDmWithMatrixUser) { CreateDmConfirmationBottomSheet( matrixUser = data.matrixUser, + enableKeyShareOnInvite = state.enableKeyShareOnInvite, + isUserIdentityUnknown = data.isUserIdentityUnknown, onSendInvite = { state.eventSink(StartChatEvents.StartDM(data.matrixUser)) }, diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt index 122775f2cc..88b935e47d 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt @@ -13,14 +13,21 @@ import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.CreatedRoom import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.encryption.identity.IdentityState 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.FakeMatrixClient +import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.test.runTest import org.junit.Test @@ -67,7 +74,12 @@ class DefaultStartDMActionTest { @Test fun `when dm is not found, and createIfDmDoesNotExist is false, assert dm is not created and state is updated to confirmation state`() = runTest { - val matrixClient = FakeMatrixClient().apply { + val encryptionService = FakeEncryptionService( + getUserIdentityResult = { Result.success(null) } + ) + val matrixClient = FakeMatrixClient( + encryptionService = encryptionService + ).apply { givenFindDmResult(Result.success(null)) givenCreateDmResult(Result.success(A_ROOM_ID)) } @@ -76,7 +88,7 @@ class DefaultStartDMActionTest { val state = mutableStateOf>(AsyncAction.Uninitialized) val matrixUser = aMatrixUser() action.execute(matrixUser, false, state) - assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(matrixUser)) + assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = false)) assertThat(analyticsService.capturedEvents).isEmpty() } @@ -94,13 +106,38 @@ class DefaultStartDMActionTest { assertThat(analyticsService.capturedEvents).isEmpty() } + @Test + fun `when history sharing enabled, user identity fetched and identity unknown`() = runTest { + val getUserIdentityResult = lambdaRecorder> { _ -> Result.success(null) } + val encryptionService = FakeEncryptionService(getUserIdentityResult = getUserIdentityResult) + val matrixClient = FakeMatrixClient(encryptionService = encryptionService).apply { + givenFindDmResult(Result.success(null)) + } + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) + } + + val action = createStartDMAction( + matrixClient = matrixClient, + featureFlagService = featureFlagService + ) + val state = mutableStateOf>(AsyncAction.Uninitialized) + + action.execute(aMatrixUser(), false, state) + + assertThat(getUserIdentityResult.assertions().isCalledOnce()) + assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(aMatrixUser(), isUserIdentityUnknown = true)) + } + private fun createStartDMAction( matrixClient: MatrixClient = FakeMatrixClient(), analyticsService: AnalyticsService = FakeAnalyticsService(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService() ): DefaultStartDMAction { return DefaultStartDMAction( matrixClient = matrixClient, analyticsService = analyticsService, + featureFlagService = featureFlagService, ) } } diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt index 7c209d9052..2bc15e989d 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt @@ -102,7 +102,7 @@ class StartChatPresenterTest { @Test fun `present - start DM action confirmation scenario - cancel`() = runTest { val matrixUser = MatrixUser(UserId("@name:domain")) - val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser) + val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = false) val executeResult = lambdaRecorder>, Unit> { _, _, actionState -> actionState.value = startDMConfirmationResult } @@ -130,7 +130,7 @@ class StartChatPresenterTest { @Test fun `present - start DM action confirmation scenario - confirm`() = runTest { val matrixUser = MatrixUser(UserId("@name:domain")) - val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser) + val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = false) val executeResult = lambdaRecorder>, Unit> { _, _, actionState -> actionState.value = startDMConfirmationResult } diff --git a/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt b/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt index 0e0016ee14..e2a309c17f 100644 --- a/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt +++ b/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt @@ -26,6 +26,7 @@ data class UserProfileState( val dmRoomId: RoomId?, val canCall: Boolean, val snackbarMessage: SnackbarMessage?, + val enableKeyShareOnInvite: Boolean, val eventSink: (UserProfileEvents) -> Unit ) { enum class ConfirmationDialog { diff --git a/features/userprofile/impl/build.gradle.kts b/features/userprofile/impl/build.gradle.kts index 0b65441cc3..3e68fb2b9c 100644 --- a/features/userprofile/impl/build.gradle.kts +++ b/features/userprofile/impl/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.libraries.androidutils) implementation(projects.libraries.mediaviewer.api) + implementation(projects.libraries.featureflag.api) implementation(projects.features.call.api) implementation(projects.features.enterprise.api) implementation(projects.features.verifysession.api) @@ -46,6 +47,7 @@ dependencies { testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediaviewer.test) + testImplementation(projects.libraries.featureflag.test) testImplementation(projects.features.call.test) testImplementation(projects.features.verifysession.test) testImplementation(projects.features.startchat.test) diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt index 7e09a03ec3..a451d86b70 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState @@ -31,6 +32,8 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.bool.orFalse +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -50,6 +53,7 @@ class UserProfilePresenter( private val client: MatrixClient, private val startDMAction: StartDMAction, private val sessionEnterpriseService: SessionEnterpriseService, + private val featureFlagService: FeatureFlagService, ) : Presenter { @AssistedFactory interface Factory { @@ -101,6 +105,8 @@ class UserProfilePresenter( } val userProfile by produceState(null) { value = client.getProfile(userId).getOrNull() } + val enableKeyShareOnInvite = featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(false) + fun handleEvent(event: UserProfileEvents) { when (event) { is UserProfileEvents.BlockUser -> { @@ -153,6 +159,7 @@ class UserProfilePresenter( dmRoomId = dmRoomId, canCall = canCall, snackbarMessage = null, + enableKeyShareOnInvite = enableKeyShareOnInvite.value, eventSink = ::handleEvent, ) } diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt index 511effe750..1325b46bc0 100644 --- a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt @@ -24,6 +24,7 @@ import io.element.android.features.userprofile.api.UserProfileVerificationState import io.element.android.features.userprofile.impl.root.UserProfilePresenter import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -324,7 +325,7 @@ class UserProfilePresenterTest { @Test fun `present - start DM action confirmation scenario - cancel`() = runTest { val matrixUser = MatrixUser(UserId("@alice:server.org")) - val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser) + val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser, false) val executeResult = lambdaRecorder>, Unit> { _, _, actionState -> actionState.value = startDMConfirmationResult } @@ -354,7 +355,7 @@ class UserProfilePresenterTest { @Test fun `present - start DM action confirmation scenario - confirm`() = runTest { val matrixUser = MatrixUser(UserId("@alice:server.org")) - val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser) + val startDMConfirmationResult = ConfirmingStartDmWithMatrixUser(matrixUser, false) val executeResult = lambdaRecorder>, Unit> { _, _, actionState -> actionState.value = startDMConfirmationResult } @@ -414,6 +415,7 @@ class UserProfilePresenterTest { sessionEnterpriseService = FakeSessionEnterpriseService( isElementCallAvailableResult = { isElementCallAvailable }, ), + featureFlagService = FakeFeatureFlagService() ) } } diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt index 49a2fee4b5..a4bbcd6aa4 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt @@ -31,7 +31,7 @@ open class UserProfileStateProvider : PreviewParameterProvider aUserProfileState(isBlocked = AsyncData.Loading(true), verificationState = UserProfileVerificationState.UNKNOWN), aUserProfileState(startDmActionState = AsyncAction.Loading), aUserProfileState(canCall = true), - aUserProfileState(startDmActionState = ConfirmingStartDmWithMatrixUser(aMatrixUser())), + aUserProfileState(startDmActionState = ConfirmingStartDmWithMatrixUser(aMatrixUser(), isUserIdentityUnknown = false)), aUserProfileState(verificationState = UserProfileVerificationState.VERIFICATION_VIOLATION), ) } @@ -61,5 +61,6 @@ fun aUserProfileState( dmRoomId = dmRoomId, canCall = canCall, snackbarMessage = snackbarMessage, + enableKeyShareOnInvite = false, eventSink = eventSink, ) diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt index 380bb006ab..34f992f77d 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt @@ -114,6 +114,8 @@ fun UserProfileView( if (data is ConfirmingStartDmWithMatrixUser) { CreateDmConfirmationBottomSheet( matrixUser = data.matrixUser, + enableKeyShareOnInvite = state.enableKeyShareOnInvite, + isUserIdentityUnknown = data.isUserIdentityUnknown, onSendInvite = { state.eventSink(UserProfileEvents.StartDM) }, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt index dca173d780..7e0e51050a 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.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.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -22,9 +23,13 @@ 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.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule +import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType @@ -33,6 +38,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet +import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.R @@ -48,10 +54,23 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun CreateDmConfirmationBottomSheet( matrixUser: MatrixUser, + enableKeyShareOnInvite: Boolean, + isUserIdentityUnknown: Boolean, onSendInvite: () -> Unit, onDismiss: () -> Unit, modifier: Modifier = Modifier, ) { + val titleContent = if (enableKeyShareOnInvite && isUserIdentityUnknown) { + stringResource(R.string.screen_bottom_sheet_create_dm_unknown_user_title) + } else { + stringResource(R.string.screen_bottom_sheet_create_dm_title) + } + val descriptionContent = if (enableKeyShareOnInvite && isUserIdentityUnknown) { + stringResource(R.string.screen_bottom_sheet_create_dm_unknown_user_content) + } else { + stringResource(R.string.screen_bottom_sheet_create_dm_message, matrixUser.getFullName()) + } + ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, @@ -63,47 +82,95 @@ fun CreateDmConfirmationBottomSheet( .padding(top = 24.dp, bottom = 16.dp, start = 16.dp, end = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Avatar( - avatarData = matrixUser.getAvatarData(AvatarSize.DmCreationConfirmation), - avatarType = AvatarType.User, - ) - Spacer(modifier = Modifier.height(16.dp)) - Text( - text = stringResource(R.string.screen_bottom_sheet_create_dm_title), - style = ElementTheme.typography.fontHeadingMdBold, - color = ElementTheme.colors.textPrimary, - textAlign = TextAlign.Center, - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = stringResource(R.string.screen_bottom_sheet_create_dm_message, matrixUser.getFullName()), - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - Spacer(modifier = Modifier.height(40.dp)) - Button( - modifier = Modifier.fillMaxWidth(), - onClick = onSendInvite, - leadingIcon = IconSource.Vector(CompoundIcons.UserAdd()), - text = stringResource(R.string.screen_bottom_sheet_create_dm_confirmation_button_title), - ) - Spacer(modifier = Modifier.height(16.dp)) - TextButton( - modifier = Modifier.fillMaxWidth(), - onClick = onDismiss, - text = stringResource(CommonStrings.action_cancel), - ) + if (isUserIdentityUnknown) { + IconTitleSubtitleMolecule( + modifier = Modifier.padding( + bottom = 16.dp, + start = 16.dp, + end = 16.dp, + ), + title = titleContent, + subTitle = descriptionContent, + iconStyle = BigIcon.Style.Default(CompoundIcons.UserAddSolid()), + ) + MatrixUserRow(matrixUser) + Spacer(modifier = Modifier.height(32.dp)) + ButtonRowMolecule( + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + OutlinedButton( + modifier = Modifier.weight(1f), + text = stringResource(CommonStrings.action_cancel), + onClick = onDismiss + ) + Button( + modifier = Modifier.weight(1f), + text = stringResource(CommonStrings.action_continue), + onClick = onSendInvite + ) + } + Spacer(modifier = Modifier.height(32.dp)) + } else { + Avatar( + avatarData = matrixUser.getAvatarData(AvatarSize.DmCreationConfirmation), + avatarType = AvatarType.User, + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = titleContent, + style = ElementTheme.typography.fontHeadingMdBold, + color = ElementTheme.colors.textPrimary, + textAlign = TextAlign.Center, + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = descriptionContent, + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + Spacer(modifier = Modifier.height(40.dp)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = onSendInvite, + leadingIcon = IconSource.Vector(CompoundIcons.UserAdd()), + text = stringResource(R.string.screen_bottom_sheet_create_dm_confirmation_button_title), + ) + Spacer(modifier = Modifier.height(16.dp)) + TextButton( + modifier = Modifier.fillMaxWidth(), + onClick = onDismiss, + text = stringResource(CommonStrings.action_cancel), + ) + } } } } @PreviewsDayNight @Composable -internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview { +internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter( + CreateDmConfirmationBottomSheetStateProvider::class +) state: CreateDmConfirmationBottomSheetState) = ElementPreview { CreateDmConfirmationBottomSheet( - matrixUser = matrixUser, + matrixUser = state.matrixUser, + enableKeyShareOnInvite = state.enableKeyShareOnInvite, + isUserIdentityUnknown = state.isUserIdentityUnknown, onSendInvite = {}, onDismiss = {}, ) } + +data class CreateDmConfirmationBottomSheetState( + val matrixUser: MatrixUser, + val enableKeyShareOnInvite: Boolean, + val isUserIdentityUnknown: Boolean, +) + +class CreateDmConfirmationBottomSheetStateProvider : PreviewParameterProvider { + override val values = sequenceOf( + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = false, isUserIdentityUnknown = false), + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = true, isUserIdentityUnknown = false), + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = true, isUserIdentityUnknown = true), + ) +} 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 new file mode 100644 index 0000000000..8c6b1bd7cc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_10_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8ee76c2369a9671cbe370f367718fcda5bb08a89ed5116accc96928a64e9724 +size 55689 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_11_en.png new file mode 100644 index 0000000000..35f633b3a1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:029b19808dd54b74ef30737242a10af31b80e579b313d001dd9fa377bc2cca58 +size 58319 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 new file mode 100644 index 0000000000..7983ef5e8a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_10_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21a24fade9819efdb9114ec0ba3db21ec87cf93e32d896e22117fcd4f23e07ce +size 53601 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_11_en.png new file mode 100644 index 0000000000..1c50d23117 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eca54577cffddb66921623ede7ab39e017f5cd95e5049d6ad2763fa4f1f88ad4 +size 58133 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png index acec20812f..c7e3599c58 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c5a4487507334ec43c9d659f57f2ec0d86856d941f8b1b437c101b696a5b49d -size 24223 +oid sha256:bb4d6bfb9c412de00a2b4956032dd42906b5451eb99e6ebb1880dc01f6b55af5 +size 26077 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png new file mode 100644 index 0000000000..d7ff4a1d2f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26bf76ccdb56d042422553f557d91d0f26d874a710f696ac106c5c2b5590d332 +size 38833 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png index 0c60a3da07..fe44b8941c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab0ba9a693ede4106d09170710f215bccfd82dbfbadfdafa5fb49fe39a03c25d -size 23471 +oid sha256:b8c422787b67d477d3b7c8d5dee8879f33d47153dc93dd29bb3883e4ed863a41 +size 25232 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png new file mode 100644 index 0000000000..f5ff7856b2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8413aed02383572cfe8c481c6ba8b0db4cfb3402334c37f2d8b54a73fe4bf594 +size 37343 From e4bee737b1ea715441ed9c7a80fe4f5363ce404a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 15 Apr 2026 12:00:29 +0200 Subject: [PATCH 0136/1083] Take into account the value of FeatureFlags.SignInWithClassic --- .../impl/classic/ElementClassicConnection.kt | 12 +++++++++ .../DefaultElementClassicConnectionTest.kt | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index dfddd1d496..c928c05239 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -28,6 +28,8 @@ import io.element.android.libraries.androidutils.service.ServiceBinder import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.uri.ensureProtocol 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.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService @@ -69,6 +71,7 @@ class DefaultElementClassicConnection( private val coroutineScope: CoroutineScope, private val matrixAuthenticationService: MatrixAuthenticationService, private val homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker, + private val featureFlagService: FeatureFlagService, ) : ElementClassicConnection { // Messenger for communicating with the service. private var messenger: Messenger? = null @@ -116,6 +119,10 @@ class DefaultElementClassicConnection( override fun start() { Timber.tag(loggerTag.value).d("start()") coroutineScope.launch { + if (!featureFlagService.isFeatureEnabled(FeatureFlags.SignInWithClassic)) { + Timber.tag(loggerTag.value).d("Login with Element Classic is disabled, not starting connection") + return@launch + } // Establish a connection with the service. We use an explicit // class name because there is no reason to be able to let other // applications replace our component. @@ -151,6 +158,11 @@ class DefaultElementClassicConnection( override fun requestSession() { Timber.tag(loggerTag.value).d("requestSession()") coroutineScope.launch { + if (!featureFlagService.isFeatureEnabled(FeatureFlags.SignInWithClassic)) { + Timber.tag(loggerTag.value).d("Login with Element Classic is disabled") + emitState(ElementClassicConnectionState.Error("The feature is disabled")) + return@launch + } val finalMessenger = messenger if (finalMessenger == null) { Timber.tag(loggerTag.value).d("The messenger is null, can't request data") diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt index 8ea1b2e3d3..5da3c97f3c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt @@ -15,6 +15,9 @@ import androidx.core.graphics.createBitmap import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.service.ServiceBinder +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService @@ -109,6 +112,21 @@ class DefaultElementClassicConnectionTest { } } + @Test + fun `requestSession when the feature is disabled emits an error`() = runTest { + val connection = createDefaultElementClassicConnection( + matrixAuthenticationService = FakeMatrixAuthenticationService( + setElementClassicSessionResult = {}, + ), + isFeatureEnabled = false, + ) + connection.stateFlow.test { + assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) + connection.requestSession() + assertThat(awaitItem()).isInstanceOf(ElementClassicConnectionState.Error::class.java) + } + } + @Test fun `when an error is received, an error is emitted`() = runTest { val connection = createDefaultElementClassicConnection( @@ -496,10 +514,17 @@ class DefaultElementClassicConnectionTest { homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( checkResult = { Result.success(true) } ), + isFeatureEnabled: Boolean = true, + featureFlagService: FeatureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.SignInWithClassic.key to isFeatureEnabled, + ) + ), ) = DefaultElementClassicConnection( serviceBinder = serviceBinder, coroutineScope = coroutineScope, matrixAuthenticationService = matrixAuthenticationService, homeServerLoginCompatibilityChecker = homeServerLoginCompatibilityChecker, + featureFlagService = featureFlagService, ) } From 1b03dd1dcbc109fda1a533b5797a1623732b19ac Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 15 Apr 2026 10:31:54 +0200 Subject: [PATCH 0137/1083] Split developer settings into 2 screens to be able to access global settings when no logged in. --- features/login/impl/build.gradle.kts | 1 + .../features/login/impl/LoginFlowNode.kt | 21 +++ .../impl/screens/onboarding/OnBoardingNode.kt | 2 + .../screens/onboarding/OnBoardingPresenter.kt | 2 + .../screens/onboarding/OnBoardingState.kt | 1 + .../onboarding/OnBoardingStateProvider.kt | 3 + .../impl/screens/onboarding/OnBoardingView.kt | 16 ++ .../preferences/api/PreferencesEntryPoint.kt | 10 ++ .../impl/DefaultPreferencesEntryPoint.kt | 12 ++ .../impl/developer/DeveloperSettingsEvents.kt | 7 - .../developer/DeveloperSettingsPresenter.kt | 134 +------------- .../impl/developer/DeveloperSettingsState.kt | 17 +- .../DeveloperSettingsStateProvider.kt | 29 +-- .../impl/developer/DeveloperSettingsView.kt | 114 +----------- .../appsettings/AppDeveloperSettingsEvent.kt | 19 ++ .../appsettings/AppDeveloperSettingsNode.kt | 50 ++++++ .../appsettings/AppDeveloperSettingsPage.kt | 54 ++++++ .../AppDeveloperSettingsPresenter.kt | 168 ++++++++++++++++++ .../appsettings/AppDeveloperSettingsState.kt | 29 +++ .../AppDeveloperSettingsStateProvider.kt | 49 +++++ .../appsettings/AppDeveloperSettingsView.kt | 161 +++++++++++++++++ .../developer/di/DeveloperSettingsModule.kt | 23 +++ .../DeveloperSettingsPresenterTest.kt | 128 +------------ .../developer/DeveloperSettingsViewTest.kt | 40 +---- .../AppDeveloperSettingsPageTest.kt | 113 ++++++++++++ .../AppDeveloperSettingsPresenterTest.kt | 168 ++++++++++++++++++ 26 files changed, 924 insertions(+), 447 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsEvent.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsState.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsStateProvider.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/di/DeveloperSettingsModule.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index f19ba61783..83dd4cf7bd 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -55,6 +55,7 @@ setupDependencyInjection() dependencies { implementation(projects.appconfig) implementation(projects.features.enterprise.api) + implementation(projects.features.preferences.api) implementation(projects.features.rageshake.api) implementation(projects.libraries.core) implementation(projects.libraries.androidutils) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt index bc928a936f..fb384d505a 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt @@ -41,6 +41,7 @@ import io.element.android.features.login.impl.screens.createaccount.CreateAccoun import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordNode import io.element.android.features.login.impl.screens.onboarding.OnBoardingNode import io.element.android.features.login.impl.screens.searchaccountprovider.SearchAccountProviderNode +import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode @@ -67,6 +68,7 @@ class LoginFlowNode( @AppCoroutineScope private val appCoroutineScope: CoroutineScope, private val elementClassicConnection: ElementClassicConnection, + private val preferencesEntryPoint: PreferencesEntryPoint, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.CheckClassicFlow, @@ -117,6 +119,9 @@ class LoginFlowNode( @Parcelize data object QrCode : NavTarget + @Parcelize + data object AppDeveloperSettings : NavTarget + @Parcelize data class ConfirmAccountProvider( val isAccountCreation: Boolean, @@ -200,6 +205,10 @@ class LoginFlowNode( backstack.push(NavTarget.CreateAccount(url)) } + override fun navigateToDeveloperSettings() { + backstack.push(NavTarget.AppDeveloperSettings) + } + override fun navigateToLoginPassword() { backstack.push(NavTarget.LoginPassword()) } @@ -220,6 +229,18 @@ class LoginFlowNode( ) createNode(buildContext, listOf(callback, inputs)) } + NavTarget.AppDeveloperSettings -> { + val callback = object : PreferencesEntryPoint.DeveloperSettingsCallback { + override fun onDone() { + backstack.pop() + } + } + preferencesEntryPoint.createAppDeveloperSettingsNode( + parentNode = this, + buildContext = buildContext, + callback = callback, + ) + } NavTarget.ChooseAccountProvider -> { val callback = object : ChooseAccountProviderNode.Callback { override fun navigateToOidc(oidcDetails: OidcDetails) { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt index 030d65eae9..5572c412a0 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt @@ -42,6 +42,7 @@ class OnBoardingNode( fun navigateToLoginPassword() fun navigateToOidc(oidcDetails: OidcDetails) fun navigateToCreateAccount(url: String) + fun navigateToDeveloperSettings() fun onDone() } @@ -75,6 +76,7 @@ class OnBoardingNode( onLearnMoreClick = { openLearnMorePage(context) }, onCreateAccountContinue = callback::navigateToCreateAccount, onBackClick = callback::onDone, + onDeveloperSettingsClick = callback::navigateToDeveloperSettings, ) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt index 60fa34f4d0..306549d11b 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt @@ -29,6 +29,7 @@ import io.element.android.features.login.impl.login.LoginHelper import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.ui.utils.MultipleTapToUnlock import kotlinx.coroutines.launch @@ -125,6 +126,7 @@ class OnBoardingPresenter( return OnBoardingState( isAddingAccount = isAddingAccount, showBackButton = params.showBackButton, + showDeveloperSettings = buildMeta.buildType != BuildType.RELEASE, productionApplicationName = buildMeta.productionApplicationName, defaultAccountProvider = defaultAccountProvider, mustChooseAccountProvider = mustChooseAccountProvider, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt index a1c49e0d45..316efb03ef 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingState.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.architecture.AsyncData data class OnBoardingState( val isAddingAccount: Boolean, val showBackButton: Boolean, + val showDeveloperSettings: Boolean, val productionApplicationName: String, val defaultAccountProvider: String?, val mustChooseAccountProvider: Boolean, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt index ec76404686..249a904dc3 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingStateProvider.kt @@ -31,6 +31,7 @@ open class OnBoardingStateProvider : PreviewParameterProvider { ), anOnBoardingState( showBackButton = true, + showDeveloperSettings = true, ), ) } @@ -38,6 +39,7 @@ open class OnBoardingStateProvider : PreviewParameterProvider { fun anOnBoardingState( isAddingAccount: Boolean = false, showBackButton: Boolean = false, + showDeveloperSettings: Boolean = false, productionApplicationName: String = "Element", defaultAccountProvider: String? = null, mustChooseAccountProvider: Boolean = false, @@ -52,6 +54,7 @@ fun anOnBoardingState( ) = OnBoardingState( isAddingAccount = isAddingAccount, showBackButton = showBackButton, + showDeveloperSettings = showDeveloperSettings, productionApplicationName = productionApplicationName, defaultAccountProvider = defaultAccountProvider, mustChooseAccountProvider = mustChooseAccountProvider, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt index 6549e21e41..5ee7ab6ac4 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt @@ -64,6 +64,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun OnBoardingView( state: OnBoardingState, onBackClick: () -> Unit, + onDeveloperSettingsClick: () -> Unit, onSignInWithQrCode: () -> Unit, onSignIn: (mustChooseAccountProvider: Boolean) -> Unit, onCreateAccount: () -> Unit, @@ -110,6 +111,7 @@ fun OnBoardingView( loginView = loginView, buttons = buttons, onBackClick = onBackClick, + onDeveloperSettingsClick = onDeveloperSettingsClick, ) } } @@ -120,6 +122,7 @@ private fun AddFirstAccountScaffold( loginView: @Composable () -> Unit, buttons: @Composable () -> Unit, onBackClick: () -> Unit, + onDeveloperSettingsClick: () -> Unit, modifier: Modifier = Modifier, ) { OnBoardingPage( @@ -136,6 +139,18 @@ private fun AddFirstAccountScaffold( } else { OnBoardingContent(state = state) } + if (state.showDeveloperSettings) { + IconButton( + onClick = onDeveloperSettingsClick, + modifier = Modifier + .align(Alignment.TopStart), + ) { + Icon( + imageVector = CompoundIcons.SettingsSolid(), + contentDescription = stringResource(CommonStrings.common_developer_options), + ) + } + } if (state.showBackButton) { // Add icon button to "navigate back" IconButton( @@ -334,6 +349,7 @@ internal fun OnBoardingViewPreview( OnBoardingView( state = state, onBackClick = {}, + onDeveloperSettingsClick = {}, onSignInWithQrCode = {}, onSignIn = {}, onCreateAccount = {}, diff --git a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt index 04b471a498..e7fbe6069f 100644 --- a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt +++ b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/PreferencesEntryPoint.kt @@ -50,4 +50,14 @@ interface PreferencesEntryPoint : FeatureEntryPoint { fun navigateToRoomNotificationSettings(roomId: RoomId) fun navigateToEvent(roomId: RoomId, eventId: EventId) } + + fun createAppDeveloperSettingsNode( + parentNode: Node, + buildContext: BuildContext, + callback: DeveloperSettingsCallback, + ): Node + + interface DeveloperSettingsCallback : Plugin { + fun onDone() + } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt index 57c561400c..bacf1bfb48 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPoint.kt @@ -13,6 +13,7 @@ import com.bumble.appyx.core.node.Node import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.features.preferences.api.PreferencesEntryPoint +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsNode import io.element.android.libraries.architecture.createNode @ContributesBinding(AppScope::class) @@ -28,6 +29,17 @@ class DefaultPreferencesEntryPoint : PreferencesEntryPoint { plugins = listOf(params, callback) ) } + + override fun createAppDeveloperSettingsNode( + parentNode: Node, + buildContext: BuildContext, + callback: PreferencesEntryPoint.DeveloperSettingsCallback, + ): Node { + return parentNode.createNode( + buildContext = buildContext, + plugins = listOf(callback), + ) + } } internal fun PreferencesEntryPoint.InitialTarget.toNavTarget() = when (this) { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt index 1804d7e070..12de2be746 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsEvents.kt @@ -9,15 +9,8 @@ package io.element.android.features.preferences.impl.developer import androidx.compose.ui.graphics.Color -import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem -import io.element.android.libraries.featureflag.ui.model.FeatureUiModel -import io.element.android.libraries.matrix.api.tracing.TraceLogPack sealed interface DeveloperSettingsEvents { - data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : DeveloperSettingsEvents - data class SetCustomElementCallBaseUrl(val baseUrl: String?) : DeveloperSettingsEvents - data class SetTracingLogLevel(val logLevel: LogLevelItem) : DeveloperSettingsEvents - data class ToggleTracingLogPack(val logPack: TraceLogPack, val enabled: Boolean) : DeveloperSettingsEvents data class SetShowColorPicker(val show: Boolean) : DeveloperSettingsEvents data class ChangeBrandColor(val color: Color?) : DeveloperSettingsEvents data object ClearCache : DeveloperSettingsEvents diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt index a0d96be540..1598c2ef27 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt @@ -11,61 +11,37 @@ package io.element.android.features.preferences.impl.developer import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.key -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.ui.graphics.toArgb import dev.zacsweers.metro.Inject import io.element.android.features.enterprise.api.EnterpriseService -import io.element.android.features.preferences.impl.developer.tracing.toLogLevel -import io.element.android.features.preferences.impl.developer.tracing.toLogLevelItem -import io.element.android.features.preferences.impl.model.EnabledFeature +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsState import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase import io.element.android.features.preferences.impl.tasks.VacuumStoresUseCase -import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState import io.element.android.libraries.androidutils.filesize.FileSizeFormatter import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.core.data.ByteUnit -import io.element.android.libraries.core.extensions.runCatchingExceptions -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.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.matrix.api.analytics.GetDatabaseSizesUseCase import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.preferences.api.store.AppPreferencesStore -import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableMap import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -import java.net.URL @Inject class DeveloperSettingsPresenter( + private val appDeveloperSettingsPresenter: Presenter, private val sessionId: SessionId, - private val featureFlagService: FeatureFlagService, private val computeCacheSizeUseCase: ComputeCacheSizeUseCase, private val clearCacheUseCase: ClearCacheUseCase, - private val rageshakePresenter: Presenter, - private val appPreferencesStore: AppPreferencesStore, - private val buildMeta: BuildMeta, private val enterpriseService: EnterpriseService, private val vacuumStoresUseCase: VacuumStoresUseCase, private val databaseSizesUseCase: GetDatabaseSizesUseCase, @@ -73,10 +49,6 @@ class DeveloperSettingsPresenter( ) : Presenter { @Composable override fun present(): DeveloperSettingsState { - val rageshakeState = rageshakePresenter.present() - val enabledFeatures = remember { - mutableStateListOf() - } val cacheSize = remember { mutableStateOf>(AsyncData.Uninitialized) } @@ -89,38 +61,9 @@ class DeveloperSettingsPresenter( var showColorPicker by remember { mutableStateOf(false) } - val customElementCallBaseUrl by remember { - appPreferencesStore - .getCustomElementCallBaseUrlFlow() - }.collectAsState(initial = null) - - val tracingLogLevelFlow = remember { - appPreferencesStore.getTracingLogLevelFlow().map { AsyncData.Success(it.toLogLevelItem()) } - } - val tracingLogLevel by tracingLogLevelFlow.collectAsState(initial = AsyncData.Uninitialized) - val tracingLogPacks by produceState(persistentListOf()) { - appPreferencesStore.getTracingLogPacksFlow() - // Sort the entries alphabetically by its title - .map { it.sortedBy { pack -> pack.title } } - .collectLatest { value = it.toImmutableList() } - } - LaunchedEffect(Unit) { computeDatabaseSizes(databaseSizes) - featureFlagService.getAvailableFeatures() - .run { - // Never display room directory search in release builds for Play Store - if (buildMeta.flavorDescription == "GooglePlay" && buildMeta.buildType == BuildType.RELEASE) { - filterNot { it.key == FeatureFlags.RoomDirectorySearch.key } - } else { - this - } - } - .forEach { feature -> - enabledFeatures.add(EnabledFeature(feature, featureFlagService.isFeatureEnabled(feature))) - } } - val featureUiModels = createUiModels(enabledFeatures) val coroutineScope = rememberCoroutineScope() // Compute cache size each time the clear cache action value is changed LaunchedEffect(clearCacheAction.value.isSuccess()) { @@ -129,29 +72,7 @@ class DeveloperSettingsPresenter( fun handleEvent(event: DeveloperSettingsEvents) { when (event) { - is DeveloperSettingsEvents.UpdateEnabledFeature -> coroutineScope.updateEnabledFeature( - enabledFeatures = enabledFeatures, - featureKey = event.feature.key, - enabled = event.isEnabled, - triggerClearCache = { handleEvent(DeveloperSettingsEvents.ClearCache) } - ) - is DeveloperSettingsEvents.SetCustomElementCallBaseUrl -> coroutineScope.launch { - val urlToSave = event.baseUrl.takeIf { !it.isNullOrEmpty() } - appPreferencesStore.setCustomElementCallBaseUrl(urlToSave) - } DeveloperSettingsEvents.ClearCache -> coroutineScope.clearCache(clearCacheAction) - is DeveloperSettingsEvents.SetTracingLogLevel -> coroutineScope.launch { - appPreferencesStore.setTracingLogLevel(event.logLevel.toLogLevel()) - } - is DeveloperSettingsEvents.ToggleTracingLogPack -> coroutineScope.launch { - val currentPacks = tracingLogPacks.toMutableSet() - if (currentPacks.contains(event.logPack)) { - currentPacks.remove(event.logPack) - } else { - currentPacks.add(event.logPack) - } - appPreferencesStore.setTracingLogPacks(currentPacks) - } is DeveloperSettingsEvents.ChangeBrandColor -> coroutineScope.launch { showColorPicker = false val color = event.color @@ -170,56 +91,18 @@ class DeveloperSettingsPresenter( } } + val appDeveloperSettingsState = appDeveloperSettingsPresenter.present() return DeveloperSettingsState( - features = featureUiModels, + appDeveloperSettingsState = appDeveloperSettingsState, cacheSize = cacheSize.value, databaseSizes = databaseSizes.value, clearCacheAction = clearCacheAction.value, - rageshakeState = rageshakeState, - customElementCallBaseUrlState = CustomElementCallBaseUrlState( - baseUrl = customElementCallBaseUrl, - validator = ::customElementCallUrlValidator, - ), - tracingLogLevel = tracingLogLevel, - tracingLogPacks = tracingLogPacks, isEnterpriseBuild = enterpriseService.isEnterpriseBuild, showColorPicker = showColorPicker, eventSink = ::handleEvent, ) } - @Composable - private fun createUiModels( - enabledFeatures: SnapshotStateList, - ): ImmutableList { - return enabledFeatures.map { enabledFeature -> - key(enabledFeature.feature.key) { - remember(enabledFeature) { - FeatureUiModel( - key = enabledFeature.feature.key, - title = enabledFeature.feature.title, - description = enabledFeature.feature.description, - icon = null, - isEnabled = enabledFeature.isEnabled - ) - } - } - }.toImmutableList() - } - - private fun CoroutineScope.updateEnabledFeature( - enabledFeatures: SnapshotStateList, - featureKey: String, - enabled: Boolean, - @Suppress("UNUSED_PARAMETER") triggerClearCache: () -> Unit, - ) = launch { - val featureIndex = enabledFeatures.indexOfFirst { it.feature.key == featureKey }.takeIf { it != -1 } ?: return@launch - val feature = enabledFeatures[featureIndex].feature - if (featureFlagService.setFeatureEnabled(feature, enabled)) { - enabledFeatures[featureIndex] = enabledFeatures[featureIndex].copy(isEnabled = enabled) - } - } - private fun CoroutineScope.computeCacheSize(cacheSize: MutableState>) = launch { suspend { computeCacheSizeUseCase() @@ -253,12 +136,3 @@ class DeveloperSettingsPresenter( }.runCatchingUpdatingState(clearCacheAction) } } - -private fun customElementCallUrlValidator(url: String?): Boolean { - return runCatchingExceptions { - if (url.isNullOrEmpty()) return@runCatchingExceptions - val parsedUrl = URL(url) - if (parsedUrl.protocol !in listOf("http", "https")) error("Incorrect protocol") - if (parsedUrl.host.isNullOrBlank()) error("Missing host") - }.isSuccess -} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt index 920c8ec95c..fa5859a028 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsState.kt @@ -8,32 +8,19 @@ package io.element.android.features.preferences.impl.developer -import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem -import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.featureflag.ui.model.FeatureUiModel -import io.element.android.libraries.matrix.api.tracing.TraceLogPack -import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap data class DeveloperSettingsState( - val features: ImmutableList, + val appDeveloperSettingsState: AppDeveloperSettingsState, val cacheSize: AsyncData, val databaseSizes: AsyncData>, - val rageshakeState: RageshakePreferencesState, val clearCacheAction: AsyncAction, - val customElementCallBaseUrlState: CustomElementCallBaseUrlState, - val tracingLogLevel: AsyncData, - val tracingLogPacks: ImmutableList, val isEnterpriseBuild: Boolean, val showColorPicker: Boolean, val eventSink: (DeveloperSettingsEvents) -> Unit ) { val showLoader = clearCacheAction is AsyncAction.Loading } - -data class CustomElementCallBaseUrlState( - val baseUrl: String?, - val validator: (String?) -> Boolean, -) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt index b925eabe9e..28aefd3ad1 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsStateProvider.kt @@ -9,14 +9,11 @@ package io.element.android.features.preferences.impl.developer import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem -import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsState +import io.element.android.features.preferences.impl.developer.appsettings.anAppDeveloperSettingsState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList -import io.element.android.libraries.matrix.api.tracing.TraceLogPack import kotlinx.collections.immutable.persistentMapOf -import kotlinx.collections.immutable.toImmutableList open class DeveloperSettingsStateProvider : PreviewParameterProvider { override val values: Sequence @@ -25,11 +22,6 @@ open class DeveloperSettingsStateProvider : PreviewParameterProvider = AsyncAction.Uninitialized, - customElementCallBaseUrlState: CustomElementCallBaseUrlState = aCustomElementCallBaseUrlState(), - traceLogPacks: List = emptyList(), isEnterpriseBuild: Boolean = false, showColorPicker: Boolean = false, eventSink: (DeveloperSettingsEvents) -> Unit = {}, ) = DeveloperSettingsState( - features = aFeatureUiModelList(), - rageshakeState = aRageshakePreferencesState(), + appDeveloperSettingsState = appDeveloperSettingsState, cacheSize = AsyncData.Success("1.2 MB"), databaseSizes = AsyncData.Success(persistentMapOf("state_store" to "1.2MB")), clearCacheAction = clearCacheAction, - customElementCallBaseUrlState = customElementCallBaseUrlState, - tracingLogLevel = AsyncData.Success(LogLevelItem.INFO), - tracingLogPacks = traceLogPacks.toImmutableList(), isEnterpriseBuild = isEnterpriseBuild, showColorPicker = showColorPicker, eventSink = eventSink, ) - -fun aCustomElementCallBaseUrlState( - baseUrl: String? = null, - validator: (String?) -> Boolean = { true }, -) = CustomElementCallBaseUrlState( - baseUrl = baseUrl, - validator = validator, -) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 444a391d43..3adf9a13de 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -10,40 +10,28 @@ package io.element.android.features.preferences.impl.developer import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.progressSemantics -import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.runtime.Composable import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import io.element.android.compound.theme.ElementTheme import io.element.android.features.preferences.impl.R -import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem -import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsView import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory -import io.element.android.libraries.designsystem.components.preferences.PreferenceDropdown import io.element.android.libraries.designsystem.components.preferences.PreferencePage -import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch -import io.element.android.libraries.designsystem.components.preferences.PreferenceTextField 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.ListItem import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.featureflag.ui.FeatureListView -import io.element.android.libraries.featureflag.ui.model.FeatureUiModel -import io.element.android.libraries.matrix.api.tracing.TraceLogPack import io.element.android.libraries.ui.strings.CommonStrings import io.mhssn.colorpicker.ColorPickerDialog import io.mhssn.colorpicker.ColorPickerType -import kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalComposeUiApi::class) @Composable @@ -71,52 +59,12 @@ fun DeveloperSettingsView( title = stringResource(id = CommonStrings.common_developer_options) ) { // Note: this is OK to hardcode strings in this debug screen. - PreferenceCategory( - title = "Feature flags", - ) { - FeatureListContent(state) - } - NotificationCategory(onPushHistoryClick) - ElementCallCategory(state = state) - - PreferenceCategory(title = "Rust SDK") { - PreferenceDropdown( - title = "Tracing log level", - supportingText = "Requires app reboot", - selectedOption = state.tracingLogLevel.dataOrNull(), - options = LogLevelItem.entries.toImmutableList(), - onSelectOption = { logLevel -> - state.eventSink(DeveloperSettingsEvents.SetTracingLogLevel(logLevel)) - } - ) - } - PreferenceCategory(title = "Enable trace logs per SDK feature") { - Text( - text = "Requires app reboot", - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 8.dp) - ) - for (logPack in TraceLogPack.entries) { - PreferenceSwitch( - title = logPack.title, - isChecked = state.tracingLogPacks.contains(logPack), - onCheckedChange = { isChecked -> state.eventSink(DeveloperSettingsEvents.ToggleTracingLogPack(logPack, isChecked)) } - ) - } - } - - PreferenceCategory(title = "Showkase") { - ListItem( - headlineContent = { - Text("Open Showkase browser") - }, - onClick = onOpenShowkase - ) - } - RageshakePreferencesView( - state = state.rageshakeState, + AppDeveloperSettingsView( + state = state.appDeveloperSettingsState, + onOpenShowkase = onOpenShowkase, ) + NotificationCategory(onPushHistoryClick) + if (state.isEnterpriseBuild) { PreferenceCategory(title = "Theme") { ListItem( @@ -137,14 +85,6 @@ fun DeveloperSettingsView( ) } } - PreferenceCategory(title = "Crash") { - ListItem( - headlineContent = { - Text("Crash the app 💥") - }, - onClick = { error("This crash is a test.") } - ) - } val cache = state.cacheSize PreferenceCategory(title = "Cache") { ListItem( @@ -212,32 +152,6 @@ fun DeveloperSettingsView( ) } -@Composable -private fun ElementCallCategory( - state: DeveloperSettingsState, -) { - PreferenceCategory(title = "Element Call") { - val callUrlState = state.customElementCallBaseUrlState - - val supportingText = if (callUrlState.baseUrl.isNullOrEmpty()) { - stringResource(R.string.screen_advanced_settings_element_call_base_url_description) - } else { - callUrlState.baseUrl - } - PreferenceTextField( - headline = stringResource(R.string.screen_advanced_settings_element_call_base_url), - value = callUrlState.baseUrl, - placeholder = "https://.../room", - supportingText = supportingText, - validation = callUrlState.validator, - onValidationErrorMessage = stringResource(R.string.screen_advanced_settings_element_call_base_url_validation_error), - displayValue = { value -> !value.isNullOrEmpty() }, - keyboardOptions = KeyboardOptions.Default.copy(autoCorrectEnabled = false, keyboardType = KeyboardType.Uri), - onChange = { state.eventSink(DeveloperSettingsEvents.SetCustomElementCallBaseUrl(it)) } - ) - } -} - @Composable private fun NotificationCategory(onPushHistoryClick: () -> Unit) { PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_title)) { @@ -250,20 +164,6 @@ private fun NotificationCategory(onPushHistoryClick: () -> Unit) { } } -@Composable -private fun FeatureListContent( - state: DeveloperSettingsState, -) { - fun onFeatureEnabled(feature: FeatureUiModel, isEnabled: Boolean) { - state.eventSink(DeveloperSettingsEvents.UpdateEnabledFeature(feature, isEnabled)) - } - - FeatureListView( - features = state.features, - onCheckedChange = ::onFeatureEnabled, - ) -} - @PreviewsDayNight @Composable internal fun DeveloperSettingsViewPreview( @@ -273,6 +173,6 @@ internal fun DeveloperSettingsViewPreview( state = state, onOpenShowkase = {}, onPushHistoryClick = {}, - onBackClick = {} + onBackClick = {}, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsEvent.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsEvent.kt new file mode 100644 index 0000000000..d9641a2810 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsEvent.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.preferences.impl.developer.appsettings + +import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.libraries.featureflag.ui.model.FeatureUiModel +import io.element.android.libraries.matrix.api.tracing.TraceLogPack + +sealed interface AppDeveloperSettingsEvent { + data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : AppDeveloperSettingsEvent + data class SetCustomElementCallBaseUrl(val baseUrl: String?) : AppDeveloperSettingsEvent + data class SetTracingLogLevel(val logLevel: LogLevelItem) : AppDeveloperSettingsEvent + data class ToggleTracingLogPack(val logPack: TraceLogPack, val enabled: Boolean) : AppDeveloperSettingsEvent +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt new file mode 100644 index 0000000000..ae5e710d4b --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt @@ -0,0 +1,50 @@ +/* + * 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.developer.appsettings + +import androidx.activity.compose.LocalActivity +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.airbnb.android.showkase.models.Showkase +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode +import io.element.android.features.preferences.api.PreferencesEntryPoint +import io.element.android.libraries.architecture.callback +import io.element.android.libraries.designsystem.showkase.getBrowserIntent + +@ContributesNode(AppScope::class) +@AssistedInject +class AppDeveloperSettingsNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: AppDeveloperSettingsPresenter, +) : Node(buildContext, plugins = plugins) { + private val callback: PreferencesEntryPoint.DeveloperSettingsCallback = callback() + + @Composable + override fun View(modifier: Modifier) { + val activity = requireNotNull(LocalActivity.current) + fun openShowkase() { + val intent = Showkase.getBrowserIntent(activity) + activity.startActivity(intent) + } + + val state = presenter.present() + AppDeveloperSettingsPage( + state = state, + modifier = modifier, + onOpenShowkase = ::openShowkase, + onBackClick = callback::onDone, + ) + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt new file mode 100644 index 0000000000..81e1304e7b --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt @@ -0,0 +1,54 @@ +/* + * 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.developer.appsettings + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.preferences.PreferencePage +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun AppDeveloperSettingsPage( + state: AppDeveloperSettingsState, + onOpenShowkase: () -> Unit, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + BackHandler( + onBack = onBackClick, + ) + PreferencePage( + modifier = modifier, + onBackClick = { + onBackClick() + }, + title = "Application developer options", + ) { + AppDeveloperSettingsView( + state = state, + onOpenShowkase = onOpenShowkase, + modifier = Modifier.padding(top = 8.dp) + ) + } +} + +@PreviewsDayNight +@Composable +internal fun AppDeveloperSettingsPagePreview() = ElementPreview { + AppDeveloperSettingsPage( + state = anAppDeveloperSettingsState(), + onOpenShowkase = {}, + onBackClick = {}, + ) +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt new file mode 100644 index 0000000000..4c76c6ec7e --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt @@ -0,0 +1,168 @@ +/* + * 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.developer.appsettings + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.snapshots.SnapshotStateList +import dev.zacsweers.metro.Inject +import io.element.android.features.preferences.impl.developer.tracing.toLogLevel +import io.element.android.features.preferences.impl.developer.tracing.toLogLevelItem +import io.element.android.features.preferences.impl.model.EnabledFeature +import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.extensions.runCatchingExceptions +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.featureflag.ui.model.FeatureUiModel +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import java.net.URL + +@Inject +class AppDeveloperSettingsPresenter( + private val featureFlagService: FeatureFlagService, + private val rageshakePresenter: Presenter, + private val appPreferencesStore: AppPreferencesStore, + private val buildMeta: BuildMeta, +) : Presenter { + @Composable + override fun present(): AppDeveloperSettingsState { + val rageshakeState = rageshakePresenter.present() + val enabledFeatures = remember { + mutableStateListOf() + } + val customElementCallBaseUrl by remember { + appPreferencesStore + .getCustomElementCallBaseUrlFlow() + }.collectAsState(initial = null) + + val tracingLogLevelFlow = remember { + appPreferencesStore.getTracingLogLevelFlow().map { AsyncData.Success(it.toLogLevelItem()) } + } + val tracingLogLevel by tracingLogLevelFlow.collectAsState(initial = AsyncData.Uninitialized) + val tracingLogPacks by produceState(persistentListOf()) { + appPreferencesStore.getTracingLogPacksFlow() + // Sort the entries alphabetically by its title + .map { it.sortedBy { pack -> pack.title } } + .collectLatest { value = it.toImmutableList() } + } + + LaunchedEffect(Unit) { + featureFlagService.getAvailableFeatures() + .run { + // Never display room directory search in release builds for Play Store + if (buildMeta.flavorDescription == "GooglePlay" && buildMeta.buildType == BuildType.RELEASE) { + filterNot { it.key == FeatureFlags.RoomDirectorySearch.key } + } else { + this + } + } + .forEach { feature -> + enabledFeatures.add(EnabledFeature(feature, featureFlagService.isFeatureEnabled(feature))) + } + } + val featureUiModels = createUiModels(enabledFeatures) + val coroutineScope = rememberCoroutineScope() + // Compute cache size each time the clear cache action value is changed + + fun handleEvent(event: AppDeveloperSettingsEvent) { + when (event) { + is AppDeveloperSettingsEvent.UpdateEnabledFeature -> coroutineScope.updateEnabledFeature( + enabledFeatures = enabledFeatures, + featureKey = event.feature.key, + enabled = event.isEnabled, + ) + is AppDeveloperSettingsEvent.SetCustomElementCallBaseUrl -> coroutineScope.launch { + val urlToSave = event.baseUrl.takeIf { !it.isNullOrEmpty() } + appPreferencesStore.setCustomElementCallBaseUrl(urlToSave) + } + is AppDeveloperSettingsEvent.SetTracingLogLevel -> coroutineScope.launch { + appPreferencesStore.setTracingLogLevel(event.logLevel.toLogLevel()) + } + is AppDeveloperSettingsEvent.ToggleTracingLogPack -> coroutineScope.launch { + val currentPacks = tracingLogPacks.toMutableSet() + if (currentPacks.contains(event.logPack)) { + currentPacks.remove(event.logPack) + } else { + currentPacks.add(event.logPack) + } + appPreferencesStore.setTracingLogPacks(currentPacks) + } + } + } + + return AppDeveloperSettingsState( + features = featureUiModels, + rageshakeState = rageshakeState, + customElementCallBaseUrlState = CustomElementCallBaseUrlState( + baseUrl = customElementCallBaseUrl, + validator = ::customElementCallUrlValidator, + ), + tracingLogLevel = tracingLogLevel, + tracingLogPacks = tracingLogPacks, + eventSink = ::handleEvent, + ) + } + + @Composable + private fun createUiModels( + enabledFeatures: SnapshotStateList, + ): ImmutableList { + return enabledFeatures.map { enabledFeature -> + key(enabledFeature.feature.key) { + remember(enabledFeature) { + FeatureUiModel( + key = enabledFeature.feature.key, + title = enabledFeature.feature.title, + description = enabledFeature.feature.description, + icon = null, + isEnabled = enabledFeature.isEnabled + ) + } + } + }.toImmutableList() + } + + private fun CoroutineScope.updateEnabledFeature( + enabledFeatures: SnapshotStateList, + featureKey: String, + enabled: Boolean, + ) = launch { + val featureIndex = enabledFeatures.indexOfFirst { it.feature.key == featureKey }.takeIf { it != -1 } ?: return@launch + val feature = enabledFeatures[featureIndex].feature + if (featureFlagService.setFeatureEnabled(feature, enabled)) { + enabledFeatures[featureIndex] = enabledFeatures[featureIndex].copy(isEnabled = enabled) + } + } +} + +private fun customElementCallUrlValidator(url: String?): Boolean { + return runCatchingExceptions { + if (url.isNullOrEmpty()) return@runCatchingExceptions + val parsedUrl = URL(url) + if (parsedUrl.protocol !in listOf("http", "https")) error("Incorrect protocol") + if (parsedUrl.host.isNullOrBlank()) error("Missing host") + }.isSuccess +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsState.kt new file mode 100644 index 0000000000..1eb5fd7fd3 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsState.kt @@ -0,0 +1,29 @@ +/* + * 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.developer.appsettings + +import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.featureflag.ui.model.FeatureUiModel +import io.element.android.libraries.matrix.api.tracing.TraceLogPack +import kotlinx.collections.immutable.ImmutableList + +data class AppDeveloperSettingsState( + val features: ImmutableList, + val rageshakeState: RageshakePreferencesState, + val customElementCallBaseUrlState: CustomElementCallBaseUrlState, + val tracingLogLevel: AsyncData, + val tracingLogPacks: ImmutableList, + val eventSink: (AppDeveloperSettingsEvent) -> Unit +) + +data class CustomElementCallBaseUrlState( + val baseUrl: String?, + val validator: (String?) -> Boolean, +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsStateProvider.kt new file mode 100644 index 0000000000..494b3b6bbd --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsStateProvider.kt @@ -0,0 +1,49 @@ +/* + * 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.developer.appsettings + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList +import io.element.android.libraries.matrix.api.tracing.TraceLogPack +import kotlinx.collections.immutable.toImmutableList + +open class AppDeveloperSettingsStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + anAppDeveloperSettingsState(), + anAppDeveloperSettingsState( + customElementCallBaseUrlState = aCustomElementCallBaseUrlState( + baseUrl = "https://call.element.ahoy", + ) + ), + ) +} + +fun anAppDeveloperSettingsState( + customElementCallBaseUrlState: CustomElementCallBaseUrlState = aCustomElementCallBaseUrlState(), + traceLogPacks: List = emptyList(), + eventSink: (AppDeveloperSettingsEvent) -> Unit = {}, +) = AppDeveloperSettingsState( + features = aFeatureUiModelList(), + rageshakeState = aRageshakePreferencesState(), + customElementCallBaseUrlState = customElementCallBaseUrlState, + tracingLogLevel = AsyncData.Success(LogLevelItem.INFO), + tracingLogPacks = traceLogPacks.toImmutableList(), + eventSink = eventSink, +) + +fun aCustomElementCallBaseUrlState( + baseUrl: String? = null, + validator: (String?) -> Boolean = { true }, +) = CustomElementCallBaseUrlState( + baseUrl = baseUrl, + validator = validator, +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt new file mode 100644 index 0000000000..71051cf829 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt @@ -0,0 +1,161 @@ +/* + * 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.developer.appsettings + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.runtime.Composable +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.features.preferences.impl.R +import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView +import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory +import io.element.android.libraries.designsystem.components.preferences.PreferenceDropdown +import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch +import io.element.android.libraries.designsystem.components.preferences.PreferenceTextField +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.ListItem +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.featureflag.ui.FeatureListView +import io.element.android.libraries.featureflag.ui.model.FeatureUiModel +import io.element.android.libraries.matrix.api.tracing.TraceLogPack +import kotlinx.collections.immutable.toImmutableList + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun AppDeveloperSettingsView( + state: AppDeveloperSettingsState, + onOpenShowkase: () -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.fillMaxWidth(), + ) { + // Note: this is OK to hardcode strings in this debug screen. + PreferenceCategory( + title = "Feature flags", + showTopDivider = false, + ) { + FeatureListContent(state) + } + ElementCallCategory(state = state) + PreferenceCategory(title = "Rust SDK") { + PreferenceDropdown( + title = "Tracing log level", + supportingText = "Requires app reboot", + selectedOption = state.tracingLogLevel.dataOrNull(), + options = LogLevelItem.entries.toImmutableList(), + onSelectOption = { logLevel -> + state.eventSink(AppDeveloperSettingsEvent.SetTracingLogLevel(logLevel)) + } + ) + } + PreferenceCategory(title = "Enable trace logs per SDK feature") { + Text( + text = "Requires app reboot", + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 8.dp) + ) + for (logPack in TraceLogPack.entries) { + PreferenceSwitch( + title = logPack.title, + isChecked = state.tracingLogPacks.contains(logPack), + onCheckedChange = { isChecked -> state.eventSink(AppDeveloperSettingsEvent.ToggleTracingLogPack(logPack, isChecked)) } + ) + } + } + PreferenceCategory(title = "Showkase") { + ListItem( + headlineContent = { + Text("Open Showkase browser") + }, + onClick = onOpenShowkase + ) + } + PreferenceCategory(title = "Crash") { + ListItem( + headlineContent = { + Text("Crash the app 💥") + }, + onClick = { error("This crash is a test.") } + ) + } + RageshakePreferencesView( + state = state.rageshakeState, + ) + PreferenceCategory(title = "Crash") { + ListItem( + headlineContent = { + Text("Crash the app 💥") + }, + onClick = { error("This crash is a test.") } + ) + } + } +} + +@Composable +private fun ElementCallCategory( + state: AppDeveloperSettingsState, +) { + PreferenceCategory(title = "Element Call") { + val callUrlState = state.customElementCallBaseUrlState + + val supportingText = if (callUrlState.baseUrl.isNullOrEmpty()) { + stringResource(R.string.screen_advanced_settings_element_call_base_url_description) + } else { + callUrlState.baseUrl + } + PreferenceTextField( + headline = stringResource(R.string.screen_advanced_settings_element_call_base_url), + value = callUrlState.baseUrl, + placeholder = "https://.../room", + supportingText = supportingText, + validation = callUrlState.validator, + onValidationErrorMessage = stringResource(R.string.screen_advanced_settings_element_call_base_url_validation_error), + displayValue = { value -> !value.isNullOrEmpty() }, + keyboardOptions = KeyboardOptions.Default.copy(autoCorrectEnabled = false, keyboardType = KeyboardType.Uri), + onChange = { state.eventSink(AppDeveloperSettingsEvent.SetCustomElementCallBaseUrl(it)) } + ) + } +} + +@Composable +private fun FeatureListContent( + state: AppDeveloperSettingsState, +) { + fun onFeatureEnabled(feature: FeatureUiModel, isEnabled: Boolean) { + state.eventSink(AppDeveloperSettingsEvent.UpdateEnabledFeature(feature, isEnabled)) + } + + FeatureListView( + features = state.features, + onCheckedChange = ::onFeatureEnabled, + ) +} + +@PreviewsDayNight +@Composable +internal fun AppDeveloperSettingsViewPreview( + @PreviewParameter(AppDeveloperSettingsStateProvider::class) state: AppDeveloperSettingsState +) = ElementPreview { + AppDeveloperSettingsView( + state = state, + onOpenShowkase = {}, + ) +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/di/DeveloperSettingsModule.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/di/DeveloperSettingsModule.kt new file mode 100644 index 0000000000..bad0ccae0f --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/di/DeveloperSettingsModule.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.features.preferences.impl.developer.di + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.BindingContainer +import dev.zacsweers.metro.Binds +import dev.zacsweers.metro.ContributesTo +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsPresenter +import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsState +import io.element.android.libraries.architecture.Presenter + +@ContributesTo(AppScope::class) +@BindingContainer +interface DeveloperSettingsModule { + @Binds + fun bindAppDeveloperSettingsPresenter(presenter: AppDeveloperSettingsPresenter): Presenter +} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt index 1fcf9bff70..ec70b19eab 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt @@ -14,27 +14,18 @@ import androidx.compose.ui.graphics.Color import com.google.common.truth.Truth.assertThat import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.enterprise.test.FakeEnterpriseService -import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.features.preferences.impl.developer.appsettings.anAppDeveloperSettingsState import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase import io.element.android.features.preferences.impl.tasks.VacuumStoresUseCase -import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.data.megaBytes -import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.core.meta.BuildType -import io.element.android.libraries.featureflag.api.Feature -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeature -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.analytics.GetDatabaseSizesUseCase import io.element.android.libraries.matrix.api.analytics.SdkStoreSizes import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.test.A_SESSION_ID -import io.element.android.libraries.matrix.test.core.aBuildMeta -import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -51,17 +42,7 @@ class DeveloperSettingsPresenterTest { @Test fun `present - ensures initial states are correct`() = runTest { - val getAvailableFeaturesResult = lambdaRecorder> { _, _ -> - listOf( - FakeFeature( - key = "feature_1", - title = "Feature 1", - isInLabs = false, - ) - ) - } val presenter = createDeveloperSettingsPresenter( - featureFlagService = FakeFeatureFlagService(getAvailableFeaturesResult = getAvailableFeaturesResult), databaseSizesUseCase = GetDatabaseSizesUseCase { Result.success( SdkStoreSizes(stateStore = 10.megaBytes, eventCacheStore = 10.megaBytes, mediaStore = 10.megaBytes, cryptoStore = 10.megaBytes) @@ -70,22 +51,14 @@ class DeveloperSettingsPresenterTest { ) presenter.test { awaitItem().also { state -> - assertThat(state.features).isEmpty() + assertThat(state.appDeveloperSettingsState.features).isNotEmpty() assertThat(state.clearCacheAction).isEqualTo(AsyncAction.Uninitialized) assertThat(state.cacheSize).isEqualTo(AsyncData.Uninitialized) - assertThat(state.customElementCallBaseUrlState).isNotNull() - assertThat(state.customElementCallBaseUrlState.baseUrl).isNull() - assertThat(state.rageshakeState.isEnabled).isFalse() - assertThat(state.rageshakeState.isSupported).isTrue() - assertThat(state.rageshakeState.sensitivity).isEqualTo(0.3f) - assertThat(state.tracingLogLevel).isEqualTo(AsyncData.Uninitialized) assertThat(state.isEnterpriseBuild).isFalse() assertThat(state.showColorPicker).isFalse() } awaitItem().also { state -> - assertThat(state.features).isNotEmpty() - assertThat(state.features).hasSize(1) - assertThat(state.tracingLogLevel.dataOrNull()).isEqualTo(LogLevelItem.INFO) + assertThat(state.cacheSize.isLoading()).isTrue() } awaitItem().also { state -> assertThat(state.cacheSize).isInstanceOf(AsyncData.Success::class.java) @@ -98,37 +71,6 @@ class DeveloperSettingsPresenterTest { ) ) } - getAvailableFeaturesResult.assertions().isCalledOnce() - .with(value(false), value(false)) - } - } - - @Test - fun `present - ensures Room directory search is not present on release Google Play builds`() = runTest { - val buildMeta = aBuildMeta(buildType = BuildType.RELEASE, flavorDescription = "GooglePlay") - val presenter = createDeveloperSettingsPresenter(buildMeta = buildMeta) - presenter.test { - skipItems(2) - awaitItem().also { state -> - assertThat(state.features).doesNotContain(FeatureFlags.RoomDirectorySearch) - } - } - } - - @Test - fun `present - ensures state is updated when enabled feature event is triggered`() = runTest { - val presenter = createDeveloperSettingsPresenter() - presenter.test { - skipItems(2) - awaitItem().also { state -> - val feature = state.features.first { !it.isEnabled } - state.eventSink(DeveloperSettingsEvents.UpdateEnabledFeature(feature, !feature.isEnabled)) - } - awaitItem().also { state -> - val feature = state.features.first() - assertThat(feature.isEnabled).isTrue() - assertThat(feature.key).isEqualTo(feature.key) - } } } @@ -158,52 +100,6 @@ class DeveloperSettingsPresenterTest { } } - @Test - fun `present - custom element call base url`() = runTest { - val preferencesStore = InMemoryAppPreferencesStore() - val presenter = createDeveloperSettingsPresenter(preferencesStore = preferencesStore) - presenter.test { - skipItems(2) - awaitItem().also { state -> - assertThat(state.customElementCallBaseUrlState.baseUrl).isNull() - state.eventSink(DeveloperSettingsEvents.SetCustomElementCallBaseUrl("https://call.element.ahoy")) - } - awaitItem().also { state -> - assertThat(state.customElementCallBaseUrlState.baseUrl).isEqualTo("https://call.element.ahoy") - } - } - } - - @Test - fun `present - custom element call base url validator needs at least an HTTP scheme and host`() = runTest { - val presenter = createDeveloperSettingsPresenter() - presenter.test { - skipItems(2) - val urlValidator = awaitItem().customElementCallBaseUrlState.validator - assertThat(urlValidator("")).isTrue() // We allow empty string to clear the value and use the default one - assertThat(urlValidator("test")).isFalse() - assertThat(urlValidator("http://")).isFalse() - assertThat(urlValidator("geo://test")).isFalse() - assertThat(urlValidator("https://call.element.io")).isTrue() - } - } - - @Test - fun `present - changing tracing log level`() = runTest { - val preferences = InMemoryAppPreferencesStore() - val presenter = createDeveloperSettingsPresenter(preferencesStore = preferences) - presenter.test { - skipItems(2) - awaitItem().also { state -> - assertThat(state.tracingLogLevel.dataOrNull()).isEqualTo(LogLevelItem.INFO) - state.eventSink(DeveloperSettingsEvents.SetTracingLogLevel(LogLevelItem.TRACE)) - } - awaitItem().also { state -> - assertThat(state.tracingLogLevel.dataOrNull()).isEqualTo(LogLevelItem.TRACE) - } - } - } - @Test fun `present - enterprise build can change the brand color`() = runTest { val overrideBrandColorResult = lambdaRecorder { _, _ -> } @@ -250,33 +146,17 @@ class DeveloperSettingsPresenterTest { private fun createDeveloperSettingsPresenter( sessionId: SessionId = A_SESSION_ID, - featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService( - getAvailableFeaturesResult = { _, _ -> - listOf( - FakeFeature( - key = "feature_1", - title = "Feature 1", - isInLabs = false, - ) - ) - } - ), cacheSizeUseCase: FakeComputeCacheSizeUseCase = FakeComputeCacheSizeUseCase(), clearCacheUseCase: FakeClearCacheUseCase = FakeClearCacheUseCase(), - preferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), - buildMeta: BuildMeta = aBuildMeta(), enterpriseService: EnterpriseService = FakeEnterpriseService(), vacuumStoresUseCase: VacuumStoresUseCase = VacuumStoresUseCase {}, databaseSizesUseCase: GetDatabaseSizesUseCase = GetDatabaseSizesUseCase { Result.success(SdkStoreSizes(null, null, null, null)) }, ): DeveloperSettingsPresenter { return DeveloperSettingsPresenter( + appDeveloperSettingsPresenter = { anAppDeveloperSettingsState() }, sessionId = sessionId, - featureFlagService = featureFlagService, computeCacheSizeUseCase = cacheSizeUseCase, clearCacheUseCase = clearCacheUseCase, - rageshakePresenter = { aRageshakePreferencesState() }, - appPreferencesStore = preferencesStore, - buildMeta = buildMeta, enterpriseService = enterpriseService, vacuumStoresUseCase = vacuumStoresUseCase, databaseSizesUseCase = databaseSizesUseCase, diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt index 3854e3f4a1..d4d02d7de9 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt @@ -9,20 +9,12 @@ package io.element.android.features.preferences.impl.developer import androidx.activity.ComponentActivity -import androidx.compose.ui.test.filterToOne -import androidx.compose.ui.test.hasAnyAncestor -import androidx.compose.ui.test.isDialog -import androidx.compose.ui.test.isEditable -import androidx.compose.ui.test.isFocusable 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.compose.ui.test.performTextInput import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.preferences.impl.R -import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem -import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn @@ -53,7 +45,7 @@ class DeveloperSettingsViewTest { } } - @Config(qualifiers = "h1500dp") + @Config(qualifiers = "h2000dp") @Test fun `clicking on push history notification invokes the expected callback`() { val eventsRecorder = EventsRecorder(expectEvents = false) @@ -68,22 +60,6 @@ class DeveloperSettingsViewTest { } } - @Config(qualifiers = "h1500dp") - @Test - fun `clicking on element call url open the dialogs and submit emits the expected event`() { - val eventsRecorder = EventsRecorder() - rule.setDeveloperSettingsView( - state = aDeveloperSettingsState( - eventSink = eventsRecorder - ), - ) - rule.clickOn(R.string.screen_advanced_settings_element_call_base_url) - val textInputNode = rule.onAllNodes(isEditable().and(isFocusable())).filterToOne(hasAnyAncestor(isDialog())) - textInputNode.performTextInput("https://call.element.dev") - rule.clickOn(CommonStrings.action_ok) - eventsRecorder.assertSingle(DeveloperSettingsEvents.SetCustomElementCallBaseUrl("https://call.element.dev")) - } - @Config(qualifiers = "h2000dp") @Test fun `clicking on open showkase invokes the expected callback`() { @@ -99,20 +75,6 @@ class DeveloperSettingsViewTest { } } - @Config(qualifiers = "h1024dp") - @Test - fun `clicking on log level emits the expected event`() { - val eventsRecorder = EventsRecorder() - rule.setDeveloperSettingsView( - state = aDeveloperSettingsState( - eventSink = eventsRecorder - ), - ) - rule.onNodeWithText("Tracing log level").performClick() - rule.onNodeWithText("Debug").performClick() - eventsRecorder.assertSingle(DeveloperSettingsEvents.SetTracingLogLevel(LogLevelItem.DEBUG)) - } - @Config(qualifiers = "h2200dp") @Test fun `clicking on clear cache emits the expected event`() { diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt new file mode 100644 index 0000000000..123f31ae8e --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt @@ -0,0 +1,113 @@ +/* + * 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.developer.appsettings + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.filterToOne +import androidx.compose.ui.test.hasAnyAncestor +import androidx.compose.ui.test.isDialog +import androidx.compose.ui.test.isEditable +import androidx.compose.ui.test.isFocusable +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.compose.ui.test.performTextInput +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.preferences.impl.R +import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.EnsureNeverCalled +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.pressBack +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith +import org.robolectric.annotation.Config + +@RunWith(AndroidJUnit4::class) +class AppDeveloperSettingsPageTest { + @get:Rule + val rule = createAndroidComposeRule() + + @Test + fun `clicking on back invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { + rule.setAppDeveloperSettingsView( + state = anAppDeveloperSettingsState( + eventSink = eventsRecorder + ), + onBackClick = it + ) + rule.pressBack() + } + } + + @Config(qualifiers = "h1500dp") + @Test + fun `clicking on element call url open the dialogs and submit emits the expected event`() { + val eventsRecorder = EventsRecorder() + rule.setAppDeveloperSettingsView( + state = anAppDeveloperSettingsState( + eventSink = eventsRecorder + ), + ) + rule.clickOn(R.string.screen_advanced_settings_element_call_base_url) + val textInputNode = rule.onAllNodes(isEditable().and(isFocusable())).filterToOne(hasAnyAncestor(isDialog())) + textInputNode.performTextInput("https://call.element.dev") + rule.clickOn(CommonStrings.action_ok) + eventsRecorder.assertSingle(AppDeveloperSettingsEvent.SetCustomElementCallBaseUrl("https://call.element.dev")) + } + + @Config(qualifiers = "h2000dp") + @Test + fun `clicking on open showkase invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { + rule.setAppDeveloperSettingsView( + state = anAppDeveloperSettingsState( + eventSink = eventsRecorder + ), + onOpenShowkase = it + ) + rule.onNodeWithText("Open Showkase browser").performClick() + } + } + + @Config(qualifiers = "h1024dp") + @Test + fun `clicking on log level emits the expected event`() { + val eventsRecorder = EventsRecorder() + rule.setAppDeveloperSettingsView( + state = anAppDeveloperSettingsState( + eventSink = eventsRecorder + ), + ) + rule.onNodeWithText("Tracing log level").performClick() + rule.onNodeWithText("Debug").performClick() + eventsRecorder.assertSingle(AppDeveloperSettingsEvent.SetTracingLogLevel(LogLevelItem.DEBUG)) + } +} + +private fun AndroidComposeTestRule.setAppDeveloperSettingsView( + state: AppDeveloperSettingsState, + onOpenShowkase: () -> Unit = EnsureNeverCalled(), + onBackClick: () -> Unit = EnsureNeverCalled(), +) { + setContent { + AppDeveloperSettingsPage( + state = state, + onOpenShowkase = onOpenShowkase, + onBackClick = onBackClick, + ) + } +} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt new file mode 100644 index 0000000000..0e9d774e84 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt @@ -0,0 +1,168 @@ +/* + * 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.preferences.impl.developer.appsettings + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem +import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.featureflag.api.Feature +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeature +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore +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.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class AppDeveloperSettingsPresenterTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - ensures initial states are correct`() = runTest { + val getAvailableFeaturesResult = lambdaRecorder> { _, _ -> + listOf( + FakeFeature( + key = "feature_1", + title = "Feature 1", + isInLabs = false, + ) + ) + } + val presenter = createAppDeveloperSettingsPresenter( + featureFlagService = FakeFeatureFlagService(getAvailableFeaturesResult = getAvailableFeaturesResult), + ) + presenter.test { + awaitItem().also { state -> + assertThat(state.features).isEmpty() + assertThat(state.customElementCallBaseUrlState).isNotNull() + assertThat(state.customElementCallBaseUrlState.baseUrl).isNull() + assertThat(state.rageshakeState.isEnabled).isFalse() + assertThat(state.rageshakeState.isSupported).isTrue() + assertThat(state.rageshakeState.sensitivity).isEqualTo(0.3f) + assertThat(state.tracingLogLevel).isEqualTo(AsyncData.Uninitialized) + } + awaitItem().also { state -> + assertThat(state.features).isNotEmpty() + assertThat(state.features).hasSize(1) + assertThat(state.tracingLogLevel.dataOrNull()).isEqualTo(LogLevelItem.INFO) + } + getAvailableFeaturesResult.assertions().isCalledOnce() + .with(value(false), value(false)) + } + } + + @Test + fun `present - ensures Room directory search is not present on release Google Play builds`() = runTest { + val buildMeta = aBuildMeta(buildType = BuildType.RELEASE, flavorDescription = "GooglePlay") + val presenter = createAppDeveloperSettingsPresenter(buildMeta = buildMeta) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.features).doesNotContain(FeatureFlags.RoomDirectorySearch) + } + } + } + + @Test + fun `present - ensures state is updated when enabled feature event is triggered`() = runTest { + val presenter = createAppDeveloperSettingsPresenter() + presenter.test { + skipItems(1) + awaitItem().also { state -> + val feature = state.features.first { !it.isEnabled } + state.eventSink(AppDeveloperSettingsEvent.UpdateEnabledFeature(feature, !feature.isEnabled)) + } + awaitItem().also { state -> + val feature = state.features.first() + assertThat(feature.isEnabled).isTrue() + assertThat(feature.key).isEqualTo(feature.key) + } + } + } + + @Test + fun `present - custom element call base url`() = runTest { + val preferencesStore = InMemoryAppPreferencesStore() + val presenter = createAppDeveloperSettingsPresenter(preferencesStore = preferencesStore) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.customElementCallBaseUrlState.baseUrl).isNull() + state.eventSink(AppDeveloperSettingsEvent.SetCustomElementCallBaseUrl("https://call.element.ahoy")) + } + awaitItem().also { state -> + assertThat(state.customElementCallBaseUrlState.baseUrl).isEqualTo("https://call.element.ahoy") + } + } + } + + @Test + fun `present - custom element call base url validator needs at least an HTTP scheme and host`() = runTest { + val presenter = createAppDeveloperSettingsPresenter() + presenter.test { + skipItems(1) + val urlValidator = awaitItem().customElementCallBaseUrlState.validator + assertThat(urlValidator("")).isTrue() // We allow empty string to clear the value and use the default one + assertThat(urlValidator("test")).isFalse() + assertThat(urlValidator("http://")).isFalse() + assertThat(urlValidator("geo://test")).isFalse() + assertThat(urlValidator("https://call.element.io")).isTrue() + } + } + + @Test + fun `present - changing tracing log level`() = runTest { + val preferences = InMemoryAppPreferencesStore() + val presenter = createAppDeveloperSettingsPresenter(preferencesStore = preferences) + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.tracingLogLevel.dataOrNull()).isEqualTo(LogLevelItem.INFO) + state.eventSink(AppDeveloperSettingsEvent.SetTracingLogLevel(LogLevelItem.TRACE)) + } + awaitItem().also { state -> + assertThat(state.tracingLogLevel.dataOrNull()).isEqualTo(LogLevelItem.TRACE) + } + } + } + + private fun createAppDeveloperSettingsPresenter( + featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService( + getAvailableFeaturesResult = { _, _ -> + listOf( + FakeFeature( + key = "feature_1", + title = "Feature 1", + isInLabs = false, + ) + ) + } + ), + preferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), + buildMeta: BuildMeta = aBuildMeta(), + ): AppDeveloperSettingsPresenter { + return AppDeveloperSettingsPresenter( + featureFlagService = featureFlagService, + rageshakePresenter = { aRageshakePreferencesState() }, + appPreferencesStore = preferencesStore, + buildMeta = buildMeta, + ) + } +} From 6d3b4aaaeef3f68145342e411a6986bd67a0c17b Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 15 Apr 2026 10:27:54 +0000 Subject: [PATCH 0138/1083] Update screenshots --- ....login.impl.screens.onboarding_OnBoardingView_Day_8_en.png | 4 ++-- ...ogin.impl.screens.onboarding_OnBoardingView_Night_8_en.png | 4 ++-- ...eveloper.appsettings_AppDeveloperSettingsPage_Day_0_en.png | 3 +++ ...eloper.appsettings_AppDeveloperSettingsPage_Night_0_en.png | 3 +++ ...eveloper.appsettings_AppDeveloperSettingsView_Day_0_en.png | 3 +++ ...eveloper.appsettings_AppDeveloperSettingsView_Day_1_en.png | 3 +++ ...eloper.appsettings_AppDeveloperSettingsView_Night_0_en.png | 3 +++ ...eloper.appsettings_AppDeveloperSettingsView_Night_1_en.png | 3 +++ ...ferences.impl.developer_DeveloperSettingsView_Day_0_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_1_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_2_en.png | 4 ++-- ...ferences.impl.developer_DeveloperSettingsView_Day_3_en.png | 3 --- ...rences.impl.developer_DeveloperSettingsView_Night_0_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_1_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_2_en.png | 4 ++-- ...rences.impl.developer_DeveloperSettingsView_Night_3_en.png | 3 --- 16 files changed, 34 insertions(+), 22 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png index b5f0eb7fcf..133535c6d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5015f504040a0141d40bc14bf8a3a3be43c9c95a3702a6dc53bb253746e5a3aa -size 311553 +oid sha256:01fa1c9b917b65afc2d1464fad177f7420dea1625eeb7c8335d8105664134e67 +size 312145 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png index 4669c0b972..30d5478a90 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.onboarding_OnBoardingView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8972af96ba5624f92c826ef0e20595b6193a44b6b0a0ea03cb133c516a93a90e -size 391678 +oid sha256:7e622d9b43664c5a31b83b41801ed07769384ab9ab84aad57605cdb67b16c58d +size 392254 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en.png new file mode 100644 index 0000000000..708313c475 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62068492969ad00e1a8e4a44189f93d83c98fee40612e4eecb68d3076d00ed07 +size 56425 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en.png new file mode 100644 index 0000000000..b69265cf41 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d92e220d675097c37b60312ca4c4e821eb6ff6475bcd004437dde0d2e964cce +size 54756 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en.png new file mode 100644 index 0000000000..b56ed34048 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf121c0ea1fb3cc7a47a292877535c9c0a1ae1ac11bf7f5ce169d0cd79844246 +size 53775 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en.png new file mode 100644 index 0000000000..d0a5500209 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37ae25b9f9c659164c006c9bdb9f94379398ee8215e8a2dd9167620ef994b6d1 +size 52347 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en.png new file mode 100644 index 0000000000..d2929c43be --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db439869d2b8843cd58251bbca638e0dad7ed2b1ae4b22507e052e3d5521214d +size 52090 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en.png new file mode 100644 index 0000000000..540b910b54 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cae56bb14ae7bc1f6c73884c2efb333b7da22c82d69026854a59c380657a5bbe +size 50705 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png index 4026c0e658..503b9ad61c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e24299f25ffd7095887bb52214c25de8de2cf0380b374d11f65d78c86f49dae1 -size 45507 +oid sha256:d18a2e9ba19401f958483bf06ecd7b311ed7383de0df3d89f3bb4d3a57f8e9e7 +size 54191 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png index dd9d30850a..16be314a0d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d84781b107e2f25bdc88cbfe84a1933dd20bf4c1dd372cb69f136f36df2607c0 -size 41951 +oid sha256:aafbc1f791f067fd0084db3bf293511e3cf7557329e7599c3f3e3c66f01435c4 +size 45472 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png index dff4e9fa71..503b9ad61c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:577c00e6e45e1da5ac1b1deee380d7a087b1f32e077f8e5b9430497bf6f7012e -size 44083 +oid sha256:d18a2e9ba19401f958483bf06ecd7b311ed7383de0df3d89f3bb4d3a57f8e9e7 +size 54191 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_3_en.png deleted file mode 100644 index 4026c0e658..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e24299f25ffd7095887bb52214c25de8de2cf0380b374d11f65d78c86f49dae1 -size 45507 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png index c8188fbaaa..430756b5b3 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9750c0ae52dce1ba63c1cff7a22a3e3c75c15b5a556ba7fff49815b55836372b -size 44198 +oid sha256:dcca87aa6eee7e45bedb8f58c3b776e3932d94843573eea70aa686c3de82e03f +size 52290 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png index d3c89a0735..4225562f66 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31a3e5f9abaed21c87052ef7642dc8456d75580b79988ebe271f09d1381e9a03 -size 40820 +oid sha256:25e311c9bd46defd9659004d2d36088985c0578189a41906b51bfe683ddb6488 +size 43889 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png index 5bfd54ce11..430756b5b3 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7aab145e8ca2cd9de64a145c7966420a474b3500016a46100dad798f33acba9 -size 42792 +oid sha256:dcca87aa6eee7e45bedb8f58c3b776e3932d94843573eea70aa686c3de82e03f +size 52290 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_3_en.png deleted file mode 100644 index c8188fbaaa..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9750c0ae52dce1ba63c1cff7a22a3e3c75c15b5a556ba7fff49815b55836372b -size 44198 From f5683f9c8b5e753e47fefc19563b142737be0e0e Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Apr 2026 13:46:31 +0200 Subject: [PATCH 0139/1083] 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 0140/1083] 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 80470b37920a4f8443eb5f09d5be7ceedfe71378 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Apr 2026 14:14:22 +0200 Subject: [PATCH 0141/1083] Feature: add room threads list (#6575) Add threads list screen for rooms: - Add `ThreadsListService` to subscribe to thread changes in the room. - Create `ThreadsListView` and its associated node a presenters (the UI may change). - Add a menu icon in the room screen to open it. This is still pending info about unread threads, so several UI components related to it will be hidden. * Add feature flag and use it to hide the access to this new screen --------- Co-authored-by: ElementBot --- .../messages/impl/MessagesFlowNode.kt | 16 + .../features/messages/impl/MessagesNode.kt | 3 + .../messages/impl/MessagesPresenter.kt | 17 + .../features/messages/impl/MessagesState.kt | 6 + .../messages/impl/MessagesStateProvider.kt | 5 + .../features/messages/impl/MessagesView.kt | 44 +- .../MessagesViewWithIdentityChangePreview.kt | 3 +- .../impl/threads/ThreadedMessagesNode.kt | 1 + .../impl/threads/list/ThreadListRowItem.kt | 17 + .../impl/threads/list/ThreadsListNode.kt | 44 ++ .../impl/threads/list/ThreadsListPresenter.kt | 141 +++++++ .../impl/threads/list/ThreadsListView.kt | 380 ++++++++++++++++++ .../impl/topbars/MessagesViewTopBar.kt | 31 +- .../messages/impl/MessagesPresenterTest.kt | 32 ++ .../messages/impl/MessagesViewTest.kt | 20 + .../fixtures/TimelineItemsFactoryFixtures.kt | 50 +-- .../impl/threads/ThreadsListPresenterTest.kt | 74 ++++ .../components/avatar/AvatarSize.kt | 2 + .../libraries/featureflag/api/FeatureFlags.kt | 7 + .../libraries/matrix/api/room/JoinedRoom.kt | 3 + .../matrix/api/room/threads/ThreadListItem.kt | 34 ++ .../threads/ThreadListPaginationStatus.kt | 16 + .../api/room/threads/ThreadsListService.kt | 18 + .../matrix/impl/room/JoinedRustRoom.kt | 10 + .../room/threads/RustThreadsListService.kt | 157 ++++++++ .../fakes/FakeFfiThreadListService.kt | 58 +++ .../threads/RustThreadsListServiceTest.kt | 143 +++++++ .../matrix/test/room/FakeJoinedRoom.kt | 2 + .../room/threads/FakeThreadsListService.kt | 48 +++ ...hreads.list_ThreadListItemRow_Day_0_en.png | 3 + ...eads.list_ThreadListItemRow_Night_0_en.png | 3 + ....threads.list_ThreadsListView_Day_0_en.png | 3 + ...hreads.list_ThreadsListView_Night_0_en.png | 3 + ...pl.topbars_MessagesViewTopBar_Day_0_en.png | 4 +- ....topbars_MessagesViewTopBar_Night_0_en.png | 4 +- 35 files changed, 1357 insertions(+), 45 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadListRowItem.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListNode.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListPresenter.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/threads/ThreadsListPresenterTest.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListItem.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListPaginationStatus.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadsListService.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListService.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiThreadListService.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListServiceTest.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/threads/FakeThreadsListService.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Night_0_en.png 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 f77f06fad3..646a19895a 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 @@ -39,6 +39,7 @@ import io.element.android.features.messages.impl.pinned.DefaultPinnedEventsTimel import io.element.android.features.messages.impl.pinned.list.PinnedMessagesListNode import io.element.android.features.messages.impl.report.ReportMessageNode import io.element.android.features.messages.impl.threads.ThreadedMessagesNode +import io.element.android.features.messages.impl.threads.list.ThreadsListNode import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.debug.EventDebugInfoNode import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -179,6 +180,9 @@ class MessagesFlowNode( @Parcelize data class Thread(val threadRootId: ThreadId, val focusedEventId: EventId?) : NavTarget + + @Parcelize + data object ThreadsList : NavTarget } private val callback: MessagesEntryPoint.Callback = callback() @@ -294,6 +298,10 @@ class MessagesFlowNode( backstack.push(NavTarget.Thread(threadRootId, focusedEventId)) } + override fun navigateToThreadsList() { + backstack.push(NavTarget.ThreadsList) + } + override fun navigateToDeveloperSettings() { callback.navigateToDeveloperSettings() } @@ -517,6 +525,14 @@ class MessagesFlowNode( } createNode(buildContext, listOf(inputs, callback)) } + NavTarget.ThreadsList -> { + val callback = object : ThreadsListNode.Callback { + override fun openThread(threadId: ThreadId) { + backstack.push(NavTarget.Thread(threadId, focusedEventId = null)) + } + } + createNode(buildContext, listOf(callback)) + } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index 20cdc51035..a2cf4a3da0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -131,6 +131,8 @@ class MessagesNode( fun navigateToPinnedMessagesList() fun navigateToKnockRequestsList() fun navigateToDeveloperSettings() + + fun navigateToThreadsList() } override fun onBuilt() { @@ -299,6 +301,7 @@ class MessagesNode( onViewRequestsClick = callback::navigateToKnockRequestsList, ) }, + onThreadsListClick = callback::navigateToThreadsList, ) roomMemberModerationRenderer.Render( state = state.roomMemberModerationState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index edb11ff389..f115dd2799 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.collectAsState 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.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable @@ -27,6 +28,7 @@ import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.PinUnpinAction import io.element.android.appconfig.MessageComposerConfig import io.element.android.features.messages.api.timeline.HtmlConverterProvider +import io.element.android.features.messages.impl.MessagesState.Threads import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState @@ -85,8 +87,11 @@ import io.element.android.libraries.recentemojis.api.AddRecentEmoji import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.api.AnalyticsService +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber @@ -160,6 +165,13 @@ class MessagesPresenter( val pinnedMessagesBannerState = pinnedMessagesBannerPresenter.present() val roomCallState = roomCallStatePresenter.present() val roomMemberModerationState = roomMemberModerationPresenter.present() + val threadsList by produceState(persistentListOf()) { + room.threadsListService.subscribeToItemUpdates() + .onStart { room.threadsListService.paginate() } + .collectLatest { value = it.toImmutableList() } + } + + val canOpenThreadList by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomThreadList).collectAsState(initial = false) val userEventPermissions by room.permissionsAsState(UserEventPermissions.DEFAULT) { perms -> perms.userEventPermissions() @@ -294,6 +306,11 @@ class MessagesPresenter( roomMemberModerationState = roomMemberModerationState, topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = roomInfo.successorRoom, + threads = Threads( + hasThreads = canOpenThreadList && threadsList.isNotEmpty(), + // TODO calculate this properly based on the thread list and the read state of each thread + hasUnreadThreads = false, + ), eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index c18fb461e0..862f30832b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -57,9 +57,15 @@ data class MessagesState( /** Type of "shared history" icon to show in the top bar. */ val topBarSharedHistoryIcon: SharedHistoryIcon, val successorRoom: SuccessorRoom?, + val threads: Threads, val eventSink: (MessagesEvent) -> Unit ) { val isTombstoned = successorRoom != null + + data class Threads( + val hasThreads: Boolean, + val hasUnreadThreads: Boolean, + ) } /** Type of "shared history" icon to show in the top bar. */ diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index d969ae1491..16021df3e9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -122,6 +122,10 @@ fun aMessagesState( roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(), topBarSharedHistoryIcon: SharedHistoryIcon = SharedHistoryIcon.NONE, successorRoom: SuccessorRoom? = null, + threads: MessagesState.Threads = MessagesState.Threads( + hasThreads = false, + hasUnreadThreads = false, + ), eventSink: (MessagesEvent) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), @@ -150,6 +154,7 @@ fun aMessagesState( roomMemberModerationState = roomMemberModerationState, topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = successorRoom, + threads = threads, eventSink = eventSink, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 8e81ee74a7..bf20c8dc6b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -12,10 +12,12 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.expandVertically import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement 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.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize @@ -26,6 +28,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -52,6 +55,7 @@ import androidx.compose.ui.tooling.preview.Preview 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.messages.api.timeline.voicemessages.composer.VoiceMessageComposerEvent import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListView @@ -74,6 +78,7 @@ import io.element.android.features.messages.impl.timeline.aGroupedEvents import io.element.android.features.messages.impl.timeline.aTimelineItemDaySeparator import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineState +import io.element.android.features.messages.impl.timeline.components.CallMenuItem import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent @@ -88,6 +93,7 @@ import io.element.android.features.messages.impl.topbars.MessagesViewTopBar import io.element.android.features.messages.impl.topbars.ThreadTopBar import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessagePermissionRationaleDialog import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageSendingFailedDialog +import io.element.android.features.roomcall.api.RoomCallState import io.element.android.libraries.androidutils.ui.hideKeyboard import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule import io.element.android.libraries.designsystem.components.ExpandableBottomSheetLayout @@ -99,6 +105,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.theme.components.BottomSheetDragHandle +import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.HideKeyboardWhenDisposed @@ -133,6 +140,7 @@ fun MessagesView( onCreatePollClick: () -> Unit, onJoinCallClick: (isAudioCall: Boolean) -> Unit, onViewAllPinnedMessagesClick: () -> Unit, + onThreadsListClick: () -> Unit, modifier: Modifier = Modifier, forceJumpToBottomVisibility: Boolean = false, knockRequestsBannerView: @Composable () -> Unit, @@ -224,12 +232,18 @@ fun MessagesView( roomAvatar = state.roomAvatar, isTombstoned = state.isTombstoned, heroes = state.heroes, - roomCallState = state.roomCallState, dmUserIdentityState = state.dmUserVerificationState, sharedHistoryIcon = state.topBarSharedHistoryIcon, onBackClick = { hidingKeyboard { onBackClick() } }, onRoomDetailsClick = { hidingKeyboard { onRoomDetailsClick() } }, - onJoinCallClick = onJoinCallClick, + menuActions = { + MessagesMenuActions( + displayThreads = state.timelineState.timelineMode !is Timeline.Mode.Thread && state.threads.hasThreads, + roomCallState = state.roomCallState, + onJoinCallClick = onJoinCallClick, + onThreadsListClick = onThreadsListClick + ) + } ) } }, @@ -397,6 +411,28 @@ fun MessagesView( ) } +@Composable +internal fun MessagesMenuActions( + displayThreads: Boolean, + roomCallState: RoomCallState, + onJoinCallClick: (isAudioCall: Boolean) -> Unit, + onThreadsListClick: () -> Unit, +) { + if (displayThreads) { + Icon( + modifier = Modifier.clickable(enabled = true, onClick = onThreadsListClick), + imageVector = CompoundIcons.ThreadsSolid(), + contentDescription = stringResource(CommonStrings.common_threads), + ) + Spacer(Modifier.width(8.dp)) + } + CallMenuItem( + roomCallState = roomCallState, + onJoinCallClick = onJoinCallClick, + ) + Spacer(Modifier.width(8.dp)) +} + @Composable private fun ReinviteDialog(state: MessagesState) { if (state.showReinvitePrompt) { @@ -601,6 +637,7 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) onViewAllPinnedMessagesClick = { }, forceJumpToBottomVisibility = true, knockRequestsBannerView = {}, + onThreadsListClick = {}, ) } @@ -652,7 +689,8 @@ internal fun MessagesViewA11yPreview() = ElementPreview { onSendLocationClick = {}, onCreatePollClick = {}, onJoinCallClick = {}, - onViewAllPinnedMessagesClick = { }, + onViewAllPinnedMessagesClick = {}, + onThreadsListClick = {}, forceJumpToBottomVisibility = true, knockRequestsBannerView = {}, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/MessagesViewWithIdentityChangePreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/MessagesViewWithIdentityChangePreview.kt index b434656f7a..2c1a1bbe23 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/MessagesViewWithIdentityChangePreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/MessagesViewWithIdentityChangePreview.kt @@ -41,6 +41,7 @@ internal fun MessagesViewWithIdentityChangePreview( onCreatePollClick = {}, onJoinCallClick = {}, onViewAllPinnedMessagesClick = {}, - knockRequestsBannerView = {} + knockRequestsBannerView = {}, + onThreadsListClick = {}, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 4bb3471660..0949237862 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -300,6 +300,7 @@ class ThreadedMessagesNode( onViewAllPinnedMessagesClick = {}, modifier = modifier, knockRequestsBannerView = {}, + onThreadsListClick = {}, ) roomMemberModerationRenderer.Render( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadListRowItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadListRowItem.kt new file mode 100644 index 0000000000..3380a32f61 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadListRowItem.kt @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.threads.list + +import io.element.android.libraries.matrix.api.room.threads.ThreadListItem + +data class ThreadListRowItem( + val item: ThreadListItem, + val rootEventText: String?, + val latestEventText: String?, + val formattedTimestamp: String, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListNode.kt new file mode 100644 index 0000000000..1954dc60a5 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListNode.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.threads.list + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode +import io.element.android.libraries.architecture.callback +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.matrix.api.core.ThreadId + +@ContributesNode(RoomScope::class) +@AssistedInject +class ThreadsListNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: ThreadsListPresenter, +) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun openThread(threadId: ThreadId) + } + + private val callback: Callback = callback() + + @Composable + override fun View(modifier: Modifier) { + ThreadsListView( + state = presenter.present(), + modifier = modifier, + onThreadClick = callback::openThread, + onBackClick = this::navigateUp, + ) + } +} 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 new file mode 100644 index 0000000000..9d15376e9f --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListPresenter.kt @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.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 +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.dateformatter.api.DateFormatter +import io.element.android.libraries.dateformatter.api.DateFormatterMode +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.threads.ThreadListPaginationStatus +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.launch +import timber.log.Timber + +@Inject +class ThreadsListPresenter( + private val room: JoinedRoom, + private val timelineItemContentFactory: TimelineItemContentFactory, + private val messageSummaryFormatter: MessageSummaryFormatter, + private val dateFormatter: DateFormatter, +) : Presenter { + @Composable + override fun present(): ThreadsListState { + val coroutineScope = rememberCoroutineScope() + val threadsListService = room.threadsListService + + val threads by produceState(initialValue = persistentListOf(), key1 = threadsListService) { + threadsListService.subscribeToItemUpdates() + .onStart { threadsListService.paginate() } + .collect { items -> + Timber.d("Received thread list update with ${items.size} items") + value = items.map { item -> + val rootTimelineEvent = item.rootEvent.content?.let { + timelineItemContentFactory.create( + itemContent = it, + eventId = item.rootEvent.eventId, + isEditable = false, + sender = item.rootEvent.senderId, + senderProfile = item.rootEvent.senderProfile, + ) + } + val rootEventText = rootTimelineEvent?.let { messageSummaryFormatter.format(it) } + + val latestTimelineEvent = item.latestEvent?.content?.let { + timelineItemContentFactory.create( + itemContent = it, + eventId = item.latestEvent!!.eventId, + isEditable = false, + sender = item.latestEvent!!.senderId, + senderProfile = item.latestEvent!!.senderProfile, + ) + } + val latestEventText = latestTimelineEvent?.let { messageSummaryFormatter.format(it) } + + val formattedTimestamp = dateFormatter.format( + timestamp = item.latestEvent?.timestamp ?: item.rootEvent.timestamp, + mode = DateFormatterMode.TimeOrDate, + useRelative = true, + ) + + ThreadListRowItem( + item = item, + rootEventText = rootEventText, + latestEventText = latestEventText, + formattedTimestamp = formattedTimestamp, + ) + }.toImmutableList() + } + } + + val paginationStatus by produceState( + initialValue = ThreadListPaginationStatus.Idle(hasMoreToLoad = true), + key1 = threadsListService + ) { + threadsListService + .subscribeToPaginationUpdates() + .collect { value = it } + } + + 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) { + coroutineScope.launch { + Timber.d("Paginating thread list: $paginationStatus") + threadsListService.paginate() + } + } else { + Timber.d("Not paginating since there is nothing else to load, current status: $paginationStatus") + } + } + } + + return ThreadsListState( + threads = threads, + roomId = room.roomId, + roomName = roomInfo.name ?: room.roomId.value, + roomAvatarUrl = roomInfo.avatarUrl, + isRoomTombstoned = roomInfo.successorRoom != null, + eventSink = ::handleEvent, + ) + } +} + +data class ThreadsListState( + val roomId: RoomId, + val roomName: String, + val roomAvatarUrl: String?, + val isRoomTombstoned: Boolean, + val threads: ImmutableList, + val eventSink: (ThreadsListEvents) -> Unit, +) + +sealed interface ThreadsListEvents { + data object Paginate : ThreadsListEvents +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt new file mode 100644 index 0000000000..c93af5c162 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.threads.list + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +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.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.preview.ElementPreview +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.Icon +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.ThreadId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.core.asEventId +import io.element.android.libraries.matrix.api.room.threads.ThreadListItem +import io.element.android.libraries.matrix.api.room.threads.ThreadListItemEvent +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails +import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl +import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.delay + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ThreadsListView( + state: ThreadsListState, + onThreadClick: (ThreadId) -> Unit, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) { + Avatar( + avatarData = AvatarData( + id = state.roomId.value, + name = state.roomName, + url = state.roomAvatarUrl, + size = AvatarSize.CurrentUserTopBar, + ), + avatarType = AvatarType.Room(isTombstoned = state.isRoomTombstoned), + contentDescription = null, + ) + Column { + Text( + text = stringResource(CommonStrings.common_threads), + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( + text = state.roomName, + style = ElementTheme.typography.fontBodyXsRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } + }, + navigationIcon = { + BackButton(onBackClick) + } + ) + } + ) { padding -> + val lazyListState = rememberLazyListState() + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = padding, + state = lazyListState, + ) { + itemsIndexed(state.threads, key = { _, row -> row.item.threadId }) { index, row -> + ThreadListItemRow( + threadItem = row, + onClick = onThreadClick, + ) + + if (index < state.threads.size - 1) { + HorizontalDivider() + } + } + } + + ScrollHelper(lazyListState) { + state.eventSink(ThreadsListEvents.Paginate) + } + } +} + +@Composable +private fun ScrollHelper( + listState: LazyListState, + onPaginate: () -> Unit, +) { + val lastVisibleItemIndex by remember { + derivedStateOf { listState.firstVisibleItemIndex + listState.layoutInfo.visibleItemsInfo.size - 1 } + } + val needsPagination by remember { + derivedStateOf { + val canLoadNewItems = listState.isScrollInProgress || listState.firstVisibleItemScrollOffset == 0 + canLoadNewItems && lastVisibleItemIndex == listState.layoutInfo.totalItemsCount - 1 + } + } + LaunchedEffect(needsPagination, lastVisibleItemIndex) { + if (needsPagination) { + onPaginate() + delay(400L) + } + } +} + +@Composable +private fun ThreadListItemRow( + threadItem: ThreadListRowItem, + onClick: (ThreadId) -> Unit, +) { + Row( + modifier = Modifier + .clickable { onClick(threadItem.item.threadId) } + .fillMaxWidth() + .padding(top = 4.dp, bottom = 8.dp, start = 16.dp, end = 16.dp), + ) { + val rootEvent = threadItem.item.rootEvent + val senderProfile = rootEvent.senderProfile + Avatar( + modifier = Modifier.align(Alignment.CenterVertically), + avatarData = AvatarData( + id = rootEvent.senderId.value, + name = senderProfile.getDisambiguatedDisplayName(rootEvent.senderId), + url = senderProfile.getAvatarUrl(), + size = AvatarSize.ThreadsListItem, + ), + avatarType = AvatarType.User, + contentDescription = null, + ) + + Spacer(modifier = Modifier.width(16.dp)) + + Column(modifier = Modifier.fillMaxWidth()) { + // TODO actually compute these values based on the thread state (not available yet) + val hasMentions = false + val hasUnreadNotifications = false + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = senderProfile.getDisambiguatedDisplayName(rootEvent.senderId), + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + + Text( + text = threadItem.formattedTimestamp, + style = ElementTheme.typography.fontBodySmRegular, + color = if (hasUnreadNotifications || hasMentions) ElementTheme.colors.textActionAccent else ElementTheme.colors.textSecondary, + ) + } + + Spacer(modifier = Modifier.height(2.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + modifier = Modifier.weight(1f), + text = threadItem.rootEventText.orEmpty(), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(7.dp) + ) { + if (hasMentions) { + Icon( + modifier = Modifier.size(14.dp), + imageVector = CompoundIcons.Mention(), + contentDescription = null, + tint = ElementTheme.colors.textActionAccent, + ) + } + + UnreadIndicatorAtom( + size = 14.dp, + isVisible = hasUnreadNotifications, + ) + } + } + + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = "${threadItem.item.numberOfReplies}", + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + + Spacer(modifier = Modifier.width(4.dp)) + + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.ThreadsSolid(), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary + ) + + Spacer(modifier = Modifier.width(8.dp)) + + threadItem.item.latestEvent?.let { latestEvent -> + Avatar( + avatarData = AvatarData( + id = latestEvent.senderId.value, + name = latestEvent.senderProfile.getDisambiguatedDisplayName(latestEvent.senderId), + url = latestEvent.senderProfile.getAvatarUrl(), + size = AvatarSize.TimelineThreadLatestEventSender, + ), + avatarType = AvatarType.User, + contentDescription = null, + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Text( + text = threadItem.latestEventText.orEmpty(), + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun ThreadsListViewPreview() { + ElementPreview { + ThreadsListView( + state = ThreadsListState( + roomId = RoomId("!room-id:server"), + roomName = "Room name", + roomAvatarUrl = null, + threads = List(10) { aThreadListRowItem(threadId = ThreadId("\$thread-$it")) }.toImmutableList(), + isRoomTombstoned = false, + eventSink = {}, + ), + onThreadClick = {}, + onBackClick = {}, + ) + } +} + +@PreviewsDayNight +@Composable +internal fun ThreadListItemRowPreview() { + ElementPreview { + ThreadListItemRow( + threadItem = aThreadListRowItem(), + onClick = {}, + ) + } +} + +fun aThreadListRowItem( + threadId: ThreadId = ThreadId("\$a-thread-id"), + rootEvent: ThreadListItemEvent = aThreadListItemEvent(threadId = threadId), + latestEvent: ThreadListItemEvent? = aThreadListItemEvent(threadId = threadId), + numberOfReplies: Long = 42, + rootEventText: String? = "Hello world!", + latestEventText: String? = "Hello again!", + formattedTimestamp: String = "12:34", +) = ThreadListRowItem( + item = aThreadListItem( + threadId = threadId, + rootEvent = rootEvent, + latestEvent = latestEvent, + numberOfReplies = numberOfReplies, + ), + rootEventText = rootEventText, + latestEventText = latestEventText, + formattedTimestamp = formattedTimestamp, +) + +fun aThreadListItem( + threadId: ThreadId = ThreadId("\$a-thread-id"), + rootEvent: ThreadListItemEvent = aThreadListItemEvent(threadId = threadId), + latestEvent: ThreadListItemEvent? = aThreadListItemEvent(threadId = threadId), + numberOfReplies: Long = 42, +) = ThreadListItem( + rootEvent = rootEvent, + latestEvent = latestEvent, + numberOfReplies = numberOfReplies, +) + +fun aThreadListItemEvent( + threadId: ThreadId = ThreadId("\$a-thread-id"), + senderId: UserId = UserId("@a-user-id:server"), + senderProfile: ProfileDetails = ProfileDetails.Ready(displayName = "Alice", displayNameAmbiguous = false, avatarUrl = null), + isOwn: Boolean = false, + content: EventContent = MessageContent( + body = "Hello world!", + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = TextMessageType("Hello world!", null), + ), + timestamp: Long = 0L, +) = ThreadListItemEvent( + eventId = threadId.asEventId(), + senderId = senderId, + senderProfile = senderProfile, + isOwn = isOwn, + content = content, + timestamp = timestamp, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index 24cd71ae84..4d7242ebf5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -12,10 +12,9 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable @@ -30,8 +29,8 @@ import androidx.compose.ui.text.style.TextOverflow 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.messages.impl.MessagesMenuActions import io.element.android.features.messages.impl.SharedHistoryIcon -import io.element.android.features.messages.impl.timeline.components.CallMenuItem import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.aStandByCallState import io.element.android.features.roomcall.api.anOngoingCallState @@ -62,13 +61,12 @@ internal fun MessagesViewTopBar( roomAvatar: AvatarData, isTombstoned: Boolean, heroes: ImmutableList, - roomCallState: RoomCallState, dmUserIdentityState: IdentityState?, sharedHistoryIcon: SharedHistoryIcon, onRoomDetailsClick: () -> Unit, - onJoinCallClick: (isAudioCall: Boolean) -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, + menuActions: @Composable RowScope.() -> Unit, ) { TopAppBar( modifier = modifier, @@ -126,13 +124,7 @@ internal fun MessagesViewTopBar( } } }, - actions = { - CallMenuItem( - roomCallState = roomCallState, - onJoinCallClick = onJoinCallClick, - ) - Spacer(Modifier.width(8.dp)) - }, + actions = menuActions, windowInsets = WindowInsets(0.dp) ) } @@ -186,17 +178,24 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { roomCallState: RoomCallState = RoomCallState.Unavailable, dmUserIdentityState: IdentityState? = null, sharedHistoryIcon: SharedHistoryIcon = SharedHistoryIcon.NONE, + displayThreads: Boolean = false, ) = MessagesViewTopBar( roomName = roomName, roomAvatar = roomAvatar, isTombstoned = isTombstoned, heroes = heroes, - roomCallState = roomCallState, dmUserIdentityState = dmUserIdentityState, sharedHistoryIcon = sharedHistoryIcon, onRoomDetailsClick = {}, - onJoinCallClick = {}, onBackClick = {}, + menuActions = { + MessagesMenuActions( + roomCallState = roomCallState, + displayThreads = displayThreads, + onJoinCallClick = {}, + onThreadsListClick = {}, + ) + } ) Column { AMessagesViewTopBar() @@ -237,5 +236,9 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { roomName = "A room with world_readable history", sharedHistoryIcon = SharedHistoryIcon.WORLD_READABLE, ) + HorizontalDivider() + AMessagesViewTopBar( + displayThreads = true, + ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index f6967de0e5..6e12c607d8 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState +import io.element.android.features.messages.impl.threads.list.aThreadListItem import io.element.android.features.messages.impl.timeline.FakeMarkAsFullyRead import io.element.android.features.messages.impl.timeline.MarkAsFullyRead import io.element.android.features.messages.impl.timeline.TimelineController @@ -88,6 +89,7 @@ import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions +import io.element.android.libraries.matrix.test.room.threads.FakeThreadsListService import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.aTimelineItemDebugInfo import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails @@ -110,6 +112,7 @@ import io.element.android.tests.testutils.testWithLifecycleOwner import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runCurrent @@ -1258,6 +1261,35 @@ class MessagesPresenterTest { } } + @Test + fun `present - only has threads enabled if the feature flag is on`() = runTest { + val itemsFlow = MutableStateFlow(listOf(aThreadListItem())) + val room = FakeJoinedRoom( + threadsListService = FakeThreadsListService(items = itemsFlow) + ) + val featureFlagService = FakeFeatureFlagService( + initialState = mapOf(FeatureFlags.Threads.key to false) + ) + val presenter = createMessagesPresenter( + joinedRoom = room, + featureFlagService = featureFlagService + ) + presenter.testWithLifecycleOwner { + val initialState = awaitItem() + // The feature flag is disabled, so even if the thread list has items, it will return it doesn't have any + assertThat(initialState.threads.hasThreads).isFalse() + + // Enable the feature flag, now it should reflect the thread list state + featureFlagService.setFeatureEnabled(FeatureFlags.RoomThreadList, true) + skipItems(1) + assertThat(awaitItem().threads.hasThreads).isTrue() + + // And if we remove the items, it should update accordingly + itemsFlow.value = emptyList() + assertThat(awaitItem().threads.hasThreads).isFalse() + } + } + private fun roomPermissions( canStartCall: Boolean = true, canRedactOther: Boolean = true, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index c78aa39265..ff4bc37fa3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -73,6 +73,7 @@ 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.ensureCalledOnceWithParam +import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.setSafeContent import kotlinx.collections.immutable.persistentListOf @@ -606,6 +607,23 @@ class MessagesViewTest { eventsRecorder.assertSingle(TimelineEvent.NavigateToPredecessorOrSuccessorRoom(successorRoomId)) } + @Test + fun `clicking on threads list button calls the expected function`() { + val state = aMessagesState( + threads = MessagesState.Threads( + hasThreads = true, + hasUnreadThreads = false, + ) + ) + val onThreadsListClicked = lambdaRecorder {} + rule.setMessagesView( + state = state, + onThreadsListClicked = onThreadsListClicked, + ) + rule.onNodeWithContentDescription("Threads").performClick() + onThreadsListClicked.assertions().isCalledOnce() + } + @Test fun `no banner shown when there is no successor room`() { val eventsRecorder = EventsRecorder(expectEvents = false) @@ -630,6 +648,7 @@ private fun AndroidComposeTestRule.setMessa onCreatePollClick: () -> Unit = EnsureNeverCalled(), onJoinCallClick: (Boolean) -> Unit = EnsureNeverCalledWithParam(), onViewAllPinnedMessagesClick: () -> Unit = EnsureNeverCalled(), + onThreadsListClicked: () -> Unit = EnsureNeverCalled(), ) { setSafeContent { // Cannot use the RichTextEditor, so simulate a LocalInspectionMode @@ -646,6 +665,7 @@ private fun AndroidComposeTestRule.setMessa onJoinCallClick = onJoinCallClick, onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, knockRequestsBannerView = {}, + onThreadsListClick = onThreadsListClicked, ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt index c7eb7c0bce..2f87af3df0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/TimelineItemsFactoryFixtures.kt @@ -48,38 +48,42 @@ internal fun TestScope.aTimelineItemsFactoryCreator(): TimelineItemsFactory.Crea } } +internal fun aTimelineItemContentFactory( + timelineEventFormatter: TimelineEventFormatter = aTimelineEventFormatter(), + matrixClient: FakeMatrixClient = FakeMatrixClient(), +): TimelineItemContentFactory = TimelineItemContentFactory( + messageFactory = TimelineItemContentMessageFactory( + fileSizeFormatter = FakeFileSizeFormatter(), + fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), + htmlConverterProvider = FakeHtmlConverterProvider(), + permalinkParser = FakePermalinkParser(), + textPillificationHelper = FakeTextPillificationHelper(), + ), + redactedMessageFactory = TimelineItemContentRedactedFactory(), + stickerFactory = TimelineItemContentStickerFactory( + fileSizeFormatter = FakeFileSizeFormatter(), + fileExtensionExtractor = FileExtensionExtractorWithoutValidation() + ), + pollFactory = TimelineItemContentPollFactory(FakePollContentStateFactory()), + utdFactory = TimelineItemContentUTDFactory(), + roomMembershipFactory = TimelineItemContentRoomMembershipFactory(timelineEventFormatter), + profileChangeFactory = TimelineItemContentProfileChangeFactory(timelineEventFormatter), + stateFactory = TimelineItemContentStateFactory(timelineEventFormatter), + failedToParseMessageFactory = TimelineItemContentFailedToParseMessageFactory(), + failedToParseStateFactory = TimelineItemContentFailedToParseStateFactory(), + sessionId = matrixClient.sessionId, +) + internal fun TestScope.aTimelineItemsFactory( config: TimelineItemsFactoryConfig, ): TimelineItemsFactory { - val timelineEventFormatter = aTimelineEventFormatter() val matrixClient = FakeMatrixClient() return TimelineItemsFactory( dispatchers = testCoroutineDispatchers(), eventItemFactoryCreator = object : TimelineItemEventFactory.Creator { override fun create(config: TimelineItemsFactoryConfig): TimelineItemEventFactory { return TimelineItemEventFactory( - contentFactory = TimelineItemContentFactory( - messageFactory = TimelineItemContentMessageFactory( - fileSizeFormatter = FakeFileSizeFormatter(), - fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), - htmlConverterProvider = FakeHtmlConverterProvider(), - permalinkParser = FakePermalinkParser(), - textPillificationHelper = FakeTextPillificationHelper(), - ), - redactedMessageFactory = TimelineItemContentRedactedFactory(), - stickerFactory = TimelineItemContentStickerFactory( - fileSizeFormatter = FakeFileSizeFormatter(), - fileExtensionExtractor = FileExtensionExtractorWithoutValidation() - ), - pollFactory = TimelineItemContentPollFactory(FakePollContentStateFactory()), - utdFactory = TimelineItemContentUTDFactory(), - roomMembershipFactory = TimelineItemContentRoomMembershipFactory(timelineEventFormatter), - profileChangeFactory = TimelineItemContentProfileChangeFactory(timelineEventFormatter), - stateFactory = TimelineItemContentStateFactory(timelineEventFormatter), - failedToParseMessageFactory = TimelineItemContentFailedToParseMessageFactory(), - failedToParseStateFactory = TimelineItemContentFailedToParseStateFactory(), - sessionId = matrixClient.sessionId, - ), + contentFactory = aTimelineItemContentFactory(matrixClient = matrixClient), matrixClient = matrixClient, dateFormatter = FakeDateFormatter(), permalinkParser = FakePermalinkParser(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/threads/ThreadsListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/threads/ThreadsListPresenterTest.kt new file mode 100644 index 0000000000..9f8d210a16 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/threads/ThreadsListPresenterTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.threads + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.fixtures.aTimelineItemContentFactory +import io.element.android.features.messages.impl.messagesummary.FakeMessageSummaryFormatter +import io.element.android.features.messages.impl.threads.list.ThreadsListEvents +import io.element.android.features.messages.impl.threads.list.ThreadsListPresenter +import io.element.android.features.messages.impl.threads.list.aThreadListItem +import io.element.android.libraries.dateformatter.test.FakeDateFormatter +import io.element.android.libraries.matrix.test.AN_AVATAR_URL +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_NAME +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.threads.FakeThreadsListService +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class ThreadsListPresenterTest { + @Test + fun `present - initial state`() = runTest { + createThreadsListPresenter().test { + awaitItem().run { + assertThat(threads).isEmpty() + assertThat(roomId).isEqualTo(A_ROOM_ID) + assertThat(roomName).isEqualTo(A_ROOM_NAME) + assertThat(roomAvatarUrl).isEqualTo(AN_AVATAR_URL) + } + } + } + + @Test + fun `present - paginate`() = runTest { + val paginateRecorder = lambdaRecorder> { Result.success(Unit) } + val threadsListService = FakeThreadsListService(paginate = paginateRecorder) + val room = FakeJoinedRoom(threadsListService = threadsListService) + createThreadsListPresenter(room).test { + val initialItem = awaitItem() + + // Pagination is automatically triggered on start, so we should have one call to paginate already + paginateRecorder.assertions().isCalledOnce() + + initialItem.eventSink(ThreadsListEvents.Paginate) + + // Simulate a pagination result + threadsListService.emit(listOf(aThreadListItem())) + + // We should have a second call to paginate after the event is sent + paginateRecorder.assertions().isCalledExactly(2) + + // And we receive the new items + assertThat(awaitItem().threads).isNotEmpty() + } + } + + private fun createThreadsListPresenter( + room: FakeJoinedRoom = FakeJoinedRoom(), + ): ThreadsListPresenter { + return ThreadsListPresenter( + room = room, + timelineItemContentFactory = aTimelineItemContentFactory(), + messageSummaryFormatter = FakeMessageSummaryFormatter(), + dateFormatter = FakeDateFormatter(), + ) + } +} 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 53d5a7c281..b1e3356fc3 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 @@ -13,10 +13,12 @@ import androidx.compose.ui.unit.dp enum class AvatarSize(val dp: Dp) { CurrentUserTopBar(32.dp), + CurrentRoomTopBar(32.dp), IncomingCall(140.dp), RoomDetailsHeader(96.dp), RoomListItem(52.dp), + ThreadsListItem(52.dp), SpaceListItem(52.dp), 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 5b65a32f61..eaa32e8adc 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 @@ -155,4 +155,11 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + RoomThreadList( + key = "feature.room_thread_list", + title = "Add a list of threads in a room", + description = "Add a new screen with a list of threads in a room.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt index 808f37c7c9..32a6f2e409 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.room.knock.KnockRequest import io.element.android.libraries.matrix.api.room.location.LiveLocationShare import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange +import io.element.android.libraries.matrix.api.room.threads.ThreadsListService import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver @@ -44,6 +45,8 @@ interface JoinedRoom : BaseRoom { */ val liveTimeline: Timeline + val threadsListService: ThreadsListService + /** * Create a new timeline. * @param createTimelineParams contains parameters about how to filter the timeline. Will also configure the date separators. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListItem.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListItem.kt new file mode 100644 index 0000000000..8282caafd1 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListItem.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.threads + +import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.core.toThreadId +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails + +@Immutable +data class ThreadListItem( + val rootEvent: ThreadListItemEvent, + val latestEvent: ThreadListItemEvent?, + val numberOfReplies: Long, +) { + val threadId = rootEvent.eventId.toThreadId() +} + +@Immutable +data class ThreadListItemEvent( + val eventId: EventId, + val senderId: UserId, + val senderProfile: ProfileDetails, + val isOwn: Boolean, + val content: EventContent?, + val timestamp: Long, +) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListPaginationStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListPaginationStatus.kt new file mode 100644 index 0000000000..0716ca7c11 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadListPaginationStatus.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.threads + +sealed interface ThreadListPaginationStatus { + data class Idle( + val hasMoreToLoad: Boolean, + ) : ThreadListPaginationStatus + + data object Loading : ThreadListPaginationStatus +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadsListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadsListService.kt new file mode 100644 index 0000000000..7f819c540c --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/threads/ThreadsListService.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.threads + +import kotlinx.coroutines.flow.Flow + +interface ThreadsListService { + fun subscribeToItemUpdates(): Flow> + fun subscribeToPaginationUpdates(): Flow + suspend fun paginate(): Result + suspend fun reset(): Result + fun destroy() +} 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 73e76f73a8..e6287d0d16 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 @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.room.location.LiveLocationShare import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange import io.element.android.libraries.matrix.api.room.roomNotificationSettings +import io.element.android.libraries.matrix.api.room.threads.ThreadsListService import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver @@ -44,8 +45,10 @@ 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.member.RoomMemberListFetcher +import io.element.android.libraries.matrix.impl.room.threads.RustThreadsListService import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.timeline.RustTimeline +import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.util.MessageEventContent import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver @@ -145,6 +148,12 @@ class JoinedRustRoom( override val liveTimeline = liveInnerTimeline.map(mode = Timeline.Mode.Live) + override val threadsListService: ThreadsListService = RustThreadsListService( + inner = innerRoom.threadListService(), + contentMapper = TimelineEventContentMapper(), + roomCoroutineScope = roomCoroutineScope, + ) + override val syncUpdateFlow = flow { var counter = 0L liveTimeline.onSyncedEventReceived.collect { @@ -528,6 +537,7 @@ class JoinedRustRoom( override fun destroy() { baseRoom.destroy() liveInnerTimeline.destroy() + threadsListService.destroy() Timber.d("Room $roomId destroyed") } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListService.kt new file mode 100644 index 0000000000..a74c5bc378 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListService.kt @@ -0,0 +1,157 @@ +/* + * 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.threads + +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.threads.ThreadListItem +import io.element.android.libraries.matrix.api.room.threads.ThreadListItemEvent +import io.element.android.libraries.matrix.api.room.threads.ThreadListPaginationStatus +import io.element.android.libraries.matrix.api.room.threads.ThreadsListService +import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper +import io.element.android.libraries.matrix.impl.timeline.item.event.map +import io.element.android.libraries.matrix.impl.util.mxCallbackFlow +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart +import org.matrix.rustcomponents.sdk.ThreadListEntriesListener +import org.matrix.rustcomponents.sdk.ThreadListPaginationStateListener +import org.matrix.rustcomponents.sdk.ThreadListUpdate +import uniffi.matrix_sdk_ui.ThreadListPaginationState +import org.matrix.rustcomponents.sdk.ThreadListService as InnerThreadListService + +class RustThreadsListService( + private val inner: InnerThreadListService, + private val roomCoroutineScope: CoroutineScope, + private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper(), +) : ThreadsListService { + private var itemSubscriptionJob: Job? = null + + private val items = MutableStateFlow>(emptyList()) + + override fun subscribeToItemUpdates(): Flow> { + if (itemSubscriptionJob?.isActive != true) { + itemSubscriptionJob = doSubscribeToItemUpdates() + } + + return items + } + + private fun doSubscribeToItemUpdates(): Job { + val updatesFlow = mxCallbackFlow { + inner.subscribeToItemsUpdates(object : ThreadListEntriesListener { + override fun onUpdate(diff: List) { + trySend(diff) + } + }) + } + + return updatesFlow + .onStart { items.value = inner.items().map { it.map(contentMapper) } } + .onEach { diff -> + val updated = items.value.toMutableList() + updated.apply(diff, contentMapper) + items.value = updated + } + .launchIn(roomCoroutineScope) + } + + override fun subscribeToPaginationUpdates(): Flow { + return mxCallbackFlow { + inner.subscribeToPaginationStateUpdates(object : ThreadListPaginationStateListener { + override fun onUpdate(state: ThreadListPaginationState) { + trySend(state.map()) + } + }).also { + // Send the initial state + trySend(inner.paginationState().map()) + } + } + } + + override suspend fun paginate(): Result = runCatchingExceptions { + inner.paginate() + } + + override suspend fun reset(): Result = runCatchingExceptions { + inner.reset() + } + + override fun destroy() { + itemSubscriptionJob?.cancel() + inner.destroy() + } +} + +private fun MutableList.apply( + diff: List, + contentMapper: TimelineEventContentMapper +) { + for (diffItem in diff) { + when (diffItem) { + is ThreadListUpdate.Append -> { + val newItems = diffItem.values.map { it.map(contentMapper) } + addAll(newItems) + } + ThreadListUpdate.Clear -> clear() + is ThreadListUpdate.Insert -> { + add(diffItem.index.toInt(), diffItem.value.map(contentMapper)) + } + ThreadListUpdate.PopBack -> { + removeAt(lastIndex) + } + ThreadListUpdate.PopFront -> { + removeAt(0) + } + is ThreadListUpdate.PushBack -> { + add(diffItem.value.map(contentMapper)) + } + is ThreadListUpdate.PushFront -> { + add(0, diffItem.value.map(contentMapper)) + } + is ThreadListUpdate.Remove -> { + removeAt(diffItem.index.toInt()) + } + is ThreadListUpdate.Reset -> { + clear() + addAll(diffItem.values.map { it.map(contentMapper) }) + } + is ThreadListUpdate.Set -> { + set(diffItem.index.toInt(), diffItem.value.map(contentMapper)) + } + is ThreadListUpdate.Truncate -> { + subList(diffItem.length.toInt(), size).clear() + } + } + } +} + +fun org.matrix.rustcomponents.sdk.ThreadListItem.map(contentMapper: TimelineEventContentMapper): ThreadListItem = ThreadListItem( + rootEvent = rootEvent.map(contentMapper), + latestEvent = latestEvent?.map(contentMapper), + numberOfReplies = numReplies.toLong(), +) + +fun org.matrix.rustcomponents.sdk.ThreadListItemEvent.map(contentMapper: TimelineEventContentMapper): ThreadListItemEvent = ThreadListItemEvent( + eventId = EventId(eventId), + senderId = UserId(sender), + isOwn = isOwn, + senderProfile = senderProfile.map(), + content = content?.let(contentMapper::map), + timestamp = timestamp.toLong(), +) + +fun ThreadListPaginationState.map(): ThreadListPaginationStatus = when (this) { + is ThreadListPaginationState.Idle -> ThreadListPaginationStatus.Idle(hasMoreToLoad = !endReached) + ThreadListPaginationState.Loading -> ThreadListPaginationStatus.Loading +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiThreadListService.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiThreadListService.kt new file mode 100644 index 0000000000..009e6a3348 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiThreadListService.kt @@ -0,0 +1,58 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoHandle +import org.matrix.rustcomponents.sdk.TaskHandle +import org.matrix.rustcomponents.sdk.ThreadListEntriesListener +import org.matrix.rustcomponents.sdk.ThreadListItem +import org.matrix.rustcomponents.sdk.ThreadListPaginationStateListener +import org.matrix.rustcomponents.sdk.ThreadListService +import org.matrix.rustcomponents.sdk.ThreadListUpdate +import uniffi.matrix_sdk_ui.ThreadListPaginationState + +class FakeFfiThreadListService( + private val subscribeToItemsUpdates: (ThreadListEntriesListener) -> TaskHandle = { FakeFfiTaskHandle() }, + private val subscribeToPaginationStateUpdates: (ThreadListPaginationStateListener) -> TaskHandle = { FakeFfiTaskHandle() }, + private val items: () -> List = { emptyList() }, + private val paginationState: () -> ThreadListPaginationState = { ThreadListPaginationState.Idle(endReached = false) }, + private val paginate: suspend () -> Unit = {}, + private val reset: suspend () -> Unit = {}, + private val destroy: () -> Unit = {}, +) : ThreadListService(NoHandle) { + private var itemsListener: ThreadListEntriesListener? = null + private var paginationStateListener: ThreadListPaginationStateListener? = null + + override fun subscribeToItemsUpdates(listener: ThreadListEntriesListener): TaskHandle { + itemsListener = listener + return subscribeToItemsUpdates.invoke(listener) + } + + override fun subscribeToPaginationStateUpdates(listener: ThreadListPaginationStateListener): TaskHandle { + paginationStateListener = listener + return subscribeToPaginationStateUpdates.invoke(listener) + } + + override fun items(): List = items.invoke() + + override fun paginationState(): ThreadListPaginationState = paginationState.invoke() + + override suspend fun paginate() = paginate.invoke() + + override suspend fun reset() = reset.invoke() + + override fun destroy() = destroy.invoke() + + fun emitUpdates(updates: List) { + itemsListener?.onUpdate(updates) + } + + fun emitPaginationState(state: ThreadListPaginationState) { + paginationStateListener?.onUpdate(state) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListServiceTest.kt new file mode 100644 index 0000000000..0fc9ad0603 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/threads/RustThreadsListServiceTest.kt @@ -0,0 +1,143 @@ +/* + * 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.threads + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.threads.ThreadListPaginationStatus +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustTimelineItemContentMsgLike +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTaskHandle +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiThreadListService +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_TIMESTAMP +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.ProfileDetails +import org.matrix.rustcomponents.sdk.TaskHandle +import org.matrix.rustcomponents.sdk.ThreadListEntriesListener +import org.matrix.rustcomponents.sdk.ThreadListItem +import org.matrix.rustcomponents.sdk.ThreadListItemEvent +import org.matrix.rustcomponents.sdk.ThreadListPaginationStateListener +import org.matrix.rustcomponents.sdk.ThreadListUpdate +import uniffi.matrix_sdk_ui.ThreadListPaginationState + +@OptIn(ExperimentalCoroutinesApi::class) +class RustThreadsListServiceTest { + @Test + fun `subscribing to item updates calls the FFI method and allows retrieving new items`() = runTest { + val subscribeToItemsUpdatesRecorder = lambdaRecorder { FakeFfiTaskHandle() } + val inner = FakeFfiThreadListService(subscribeToItemsUpdates = subscribeToItemsUpdatesRecorder) + val service = createThreadsListService(inner = inner) + + service.subscribeToItemUpdates().test { + assertThat(awaitItem()).isEmpty() + + runCurrent() + subscribeToItemsUpdatesRecorder.assertions().isCalledOnce() + + inner.emitUpdates(listOf(aRustThreadListUpdate())) + + assertThat(awaitItem()).isNotEmpty() + } + } + + @Suppress("UnusedFlow") + @Test + fun `subscribing to item updates twice only calls the FFI method once`() = runTest { + val subscribeToItemsUpdatesRecorder = lambdaRecorder { FakeFfiTaskHandle() } + val inner = FakeFfiThreadListService(subscribeToItemsUpdates = subscribeToItemsUpdatesRecorder) + val service = createThreadsListService(inner = inner) + + service.subscribeToItemUpdates() + service.subscribeToItemUpdates() + + runCurrent() + + subscribeToItemsUpdatesRecorder.assertions().isCalledOnce() + } + + @Test + fun `subscribing to pagination updates calls the FFI method and allows retrieving new items`() = runTest { + val subscribeToPaginationUpdatesRecorder = lambdaRecorder { FakeFfiTaskHandle() } + val inner = FakeFfiThreadListService(subscribeToPaginationStateUpdates = subscribeToPaginationUpdatesRecorder) + val service = createThreadsListService(inner = inner) + + service.subscribeToPaginationUpdates().test { + assertThat(awaitItem()).isEqualTo(ThreadListPaginationStatus.Idle(hasMoreToLoad = true)) + + runCurrent() + subscribeToPaginationUpdatesRecorder.assertions().isCalledOnce() + + inner.emitPaginationState(ThreadListPaginationState.Loading) + + assertThat(awaitItem()).isEqualTo(ThreadListPaginationStatus.Loading) + } + } + + @Test + fun `paginate calls the FFI method`() = runTest { + val paginateRecorder = lambdaRecorder {} + val inner = FakeFfiThreadListService(paginate = paginateRecorder) + val service = createThreadsListService(inner = inner) + + service.paginate() + + paginateRecorder.assertions().isCalledOnce() + } + + @Test + fun `reset calls the FFI method`() = runTest { + val resetRecorder = lambdaRecorder {} + val inner = FakeFfiThreadListService(reset = resetRecorder) + val service = createThreadsListService(inner = inner) + + service.reset() + + resetRecorder.assertions().isCalledOnce() + } + + @Test + fun `destroy calls the FFI method`() = runTest { + val destroyRecorder = lambdaRecorder {} + val inner = FakeFfiThreadListService(destroy = destroyRecorder) + val service = createThreadsListService(inner = inner) + + service.destroy() + + destroyRecorder.assertions().isCalledOnce() + } + + private fun TestScope.createThreadsListService( + inner: FakeFfiThreadListService = FakeFfiThreadListService(), + ) = RustThreadsListService( + inner = inner, + roomCoroutineScope = backgroundScope, + ) + + private fun aRustThreadListUpdate() = ThreadListUpdate.Append( + values = listOf( + ThreadListItem( + rootEvent = ThreadListItemEvent( + eventId = AN_EVENT_ID.value, + timestamp = A_TIMESTAMP.toULong(), + sender = A_USER_ID.value, + senderProfile = ProfileDetails.Pending, + isOwn = true, + content = aRustTimelineItemContentMsgLike(), + ), + numReplies = 0u, + latestEvent = null, + ) + ), + ) +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index a4580334e4..84497b38de 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService +import io.element.android.libraries.matrix.test.room.threads.FakeThreadsListService import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask @@ -56,6 +57,7 @@ class FakeJoinedRoom( override val roomNotificationSettingsStateFlow: StateFlow = MutableStateFlow(RoomNotificationSettingsState.Unknown), override val knockRequestsFlow: Flow> = MutableStateFlow(emptyList()), + override val threadsListService: FakeThreadsListService = FakeThreadsListService(), private val roomNotificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), private var createTimelineResult: (CreateTimelineParams) -> Result = { lambdaError() }, private val editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() }, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/threads/FakeThreadsListService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/threads/FakeThreadsListService.kt new file mode 100644 index 0000000000..a1e719ffb2 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/threads/FakeThreadsListService.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.room.threads + +import io.element.android.libraries.matrix.api.room.threads.ThreadListItem +import io.element.android.libraries.matrix.api.room.threads.ThreadListPaginationStatus +import io.element.android.libraries.matrix.api.room.threads.ThreadsListService +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class FakeThreadsListService( + private val items: MutableStateFlow> = MutableStateFlow(emptyList()), + private val paginationStatus: MutableStateFlow = MutableStateFlow(ThreadListPaginationStatus.Idle(hasMoreToLoad = true)), + private val subscribeToItemUpdates: () -> Flow> = { items }, + private val subscribeToPaginationUpdates: () -> Flow = { paginationStatus }, + private val paginate: suspend () -> Result = { Result.success(Unit) }, + private val reset: suspend () -> Result = { Result.success(Unit) }, + private val destroy: () -> Unit = {}, +) : ThreadsListService { + override fun subscribeToItemUpdates(): Flow> { + return subscribeToItemUpdates.invoke() + } + + override fun subscribeToPaginationUpdates(): Flow { + return subscribeToPaginationUpdates.invoke() + } + + override suspend fun paginate(): Result { + return paginate.invoke() + } + + override suspend fun reset(): Result { + return reset.invoke() + } + + override fun destroy() { + return destroy.invoke() + } + + suspend fun emit(items: List) { + this.items.emit(items) + } +} diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Day_0_en.png new file mode 100644 index 0000000000..ac6836af2b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c523f3a502600b837c07ecd5804831da2d9aba5a74886b7001affbb90169112a +size 12455 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Night_0_en.png new file mode 100644 index 0000000000..05f2571669 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadListItemRow_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:528c2f3183a153b9129606806fc457265819ececd71cf5021d1d843970c0b774 +size 12366 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Day_0_en.png new file mode 100644 index 0000000000..adeb4f7c4d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c02999b2d0eba92f1e9b1f5fac52bcff303401f177459d1a439b7db906e5c2a +size 64622 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Night_0_en.png new file mode 100644 index 0000000000..d89f062c11 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.threads.list_ThreadsListView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7f6b64bfe0b47546a009efe23060ba091adbad32288ce546cb3b030d7a9ec88 +size 66177 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png index 8c023c5e17..b2c131b124 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3136c95bc9134eba4cfdfe8d552473a54287c356bd3895291b9cd4ec11969d9c -size 52706 +oid sha256:e26887bd81e10726414e1833029b4b51e22e534684a230777ca50f86024af994 +size 56430 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png index 3b3133cf67..41b8b16bcc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6770e720477c2547f593c626cfe3bdafb9b7c78d0b66e910fb9eb1163730045f -size 51707 +oid sha256:ce44cf850169736008a3f3fc21a2be4fb044badfae631b0284ce379b325879df +size 55533 From 66513bc905e9517bad8ace365b233b8c83527dd1 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Apr 2026 14:29:41 +0200 Subject: [PATCH 0142/1083] Take into account homeserver capabilities (#6507) * Take into account homeserver capabilities: add `HomeserverCapabilitiesProvider` to check if the HS allows changing the user's display name or avatar. Also, modify the edit user profile screen to reflect these values. * Add `/myavatar` command. Filter both `/nick` and `/myavatar` commands based on the homeserver capabilities. * Update screenshots * Assume the use can change their display name and avatar url if the capabilities check fails: if they try to change those, the HS will return an error anyway. * Disable also `/myroomname` and `/myroomavatar` based on the HS capabilities. --------- Co-authored-by: ElementBot --- .../appnav/loggedin/LoggedInPresenter.kt | 11 ++++ .../appnav/loggedin/LoggedInPresenterTest.kt | 28 ++++++++ .../editprofile/EditUserProfilePresenter.kt | 11 ++++ .../user/editprofile/EditUserProfileState.kt | 2 + .../EditUserProfileStateProvider.kt | 5 ++ .../user/editprofile/EditUserProfileView.kt | 2 + .../api/HomeserverCapabilitiesProvider.kt | 30 +++++++++ .../libraries/matrix/api/MatrixClient.kt | 2 + .../RustHomeserverCapabilitiesProvider.kt | 28 ++++++++ .../libraries/matrix/impl/RustMatrixClient.kt | 5 ++ .../matrix/impl/di/SessionMatrixModule.kt | 6 ++ .../RustHomeserverCapabilitiesProviderTest.kt | 64 +++++++++++++++++++ .../impl/fixtures/fakes/FakeFfiClient.kt | 6 ++ .../fakes/FakeFfiHomeserverCapabilities.kt | 33 ++++++++++ .../FakeHomeserverCapabilitiesProvider.kt | 20 ++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 6 ++ .../slashcommands/api/SlashCommand.kt | 1 + .../libraries/slashcommands/impl/Command.kt | 9 +++ .../slashcommands/impl/CommandExecutor.kt | 5 ++ .../slashcommands/impl/CommandParser.kt | 12 ++++ .../impl/DefaultSlashCommandService.kt | 52 +++++++++++---- .../impl/src/main/res/values/temporary.xml | 1 + .../slashcommands/impl/CommandParserTest.kt | 9 ++- .../impl/DefaultSlashCommandServiceTest.kt | 23 +++++++ ...itprofile_EditUserProfileView_Day_3_en.png | 3 + ...profile_EditUserProfileView_Night_3_en.png | 3 + 26 files changed, 363 insertions(+), 14 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/HomeserverCapabilitiesProvider.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProvider.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProviderTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverCapabilities.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeHomeserverCapabilitiesProvider.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en.png 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 757dd73395..8dc2de5e4e 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 @@ -21,6 +21,8 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import im.vector.app.features.analytics.plan.CryptoSessionStateChange import im.vector.app.features.analytics.plan.UserProperties +import io.element.android.features.networkmonitor.api.NetworkMonitor +import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.extensions.runCatchingExceptions @@ -56,6 +58,7 @@ class LoggedInPresenter( private val analyticsService: AnalyticsService, private val encryptionService: EncryptionService, private val buildMeta: BuildMeta, + private val networkMonitor: NetworkMonitor, ) : Presenter { @Composable override fun present(): LoggedInState { @@ -107,6 +110,14 @@ class LoggedInPresenter( }.launchIn(this) } + val networkConnectivity by networkMonitor.connectivity.collectAsState() + LaunchedEffect(networkConnectivity) { + if (networkConnectivity == NetworkStatus.Connected) { + // Refresh homeserver capabilities when the network is back + matrixClient.homeserverCapabilities().refresh() + } + } + fun handleEvent(event: LoggedInEvents) { when (event) { is LoggedInEvents.CloseErrorDialog -> { 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 f1759eab3e..d147a4ed68 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 @@ -14,6 +14,8 @@ import app.cash.turbine.ReceiveTurbine import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.CryptoSessionStateChange import im.vector.app.features.analytics.plan.UserProperties +import io.element.android.features.networkmonitor.api.NetworkStatus +import io.element.android.features.networkmonitor.test.FakeNetworkMonitor import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.SessionId @@ -27,6 +29,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationS import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.FakeHomeserverCapabilitiesProvider import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService @@ -109,6 +112,7 @@ class LoggedInPresenterTest { val verificationService = FakeSessionVerificationService() val encryptionService = FakeEncryptionService() val buildMeta = aBuildMeta() + val networkMonitor = FakeNetworkMonitor() LoggedInPresenter( matrixClient = FakeMatrixClient( roomListService = roomListService, @@ -122,6 +126,7 @@ class LoggedInPresenterTest { analyticsService = analyticsService, encryptionService = encryptionService, buildMeta = buildMeta, + networkMonitor = networkMonitor, ).test { encryptionService.emitRecoveryState(RecoveryState.UNKNOWN) encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE) @@ -319,6 +324,27 @@ class LoggedInPresenterTest { } } + @Test + fun `present - refreshes homeserver capabilities when network is back`() = runTest { + val refreshLambda = lambdaRecorder> { Result.success(Unit) } + val matrixClient = FakeMatrixClient( + homeserverCapabilitiesProvider = FakeHomeserverCapabilitiesProvider(refresh = refreshLambda), + accountManagementUrlResult = { Result.success(null) }, + ) + val networkMonitor = FakeNetworkMonitor() + createLoggedInPresenter( + matrixClient = matrixClient, + networkMonitor = networkMonitor, + ).test { + awaitItem() + networkMonitor.connectivity.value = NetworkStatus.Connected + + advanceUntilIdle() + + refreshLambda.assertions().isCalledOnce() + } + } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { skipItems(1) return awaitItem() @@ -334,6 +360,7 @@ class LoggedInPresenterTest { accountManagementUrlResult = { Result.success(null) }, ), buildMeta: BuildMeta = aBuildMeta(), + networkMonitor: FakeNetworkMonitor = FakeNetworkMonitor(), ): LoggedInPresenter { return LoggedInPresenter( matrixClient = matrixClient, @@ -343,6 +370,7 @@ class LoggedInPresenterTest { analyticsService = analyticsService, encryptionService = encryptionService, buildMeta = buildMeta, + networkMonitor = networkMonitor, ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index bddae2fffb..1ab69f6007 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.MutableState 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.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable @@ -103,6 +104,14 @@ class EditUserProfilePresenter( } } + val homeserverCapabilities = matrixClient.homeserverCapabilities() + val canChangeDisplayName = produceState(true) { + value = homeserverCapabilities.canChangeDisplayName().getOrDefault(true) + } + val canChangeAvatar = produceState(true) { + value = homeserverCapabilities.canChangeAvatarUrl().getOrDefault(true) + } + val saveAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val localCoroutineScope = rememberCoroutineScope() @@ -169,6 +178,8 @@ class EditUserProfilePresenter( saveButtonEnabled = canSave && saveAction.value !is AsyncAction.Loading, saveAction = saveAction.value, cameraPermissionState = cameraPermissionState, + canChangeDisplayName = canChangeDisplayName.value, + canChangeAvatarUrl = canChangeAvatar.value, eventSink = ::handleEvent, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt index a638ed8378..a40f1710e2 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt @@ -22,5 +22,7 @@ data class EditUserProfileState( val saveButtonEnabled: Boolean, val saveAction: AsyncAction, val cameraPermissionState: PermissionsState, + val canChangeDisplayName: Boolean, + val canChangeAvatarUrl: Boolean, val eventSink: (EditUserProfileEvent) -> Unit ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt index ca9571aea5..13f69a7e1e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt @@ -22,6 +22,7 @@ open class EditUserProfileStateProvider : PreviewParameterProvider = AsyncAction.Uninitialized, cameraPermissionState: PermissionsState = aPermissionsState(showDialog = false), + canChangeDisplayName: Boolean = true, + canChangeAvatarUrl: Boolean = true, eventSink: (EditUserProfileEvent) -> Unit = {}, ) = EditUserProfileState( userId = userId, @@ -42,5 +45,7 @@ fun aEditUserProfileState( saveButtonEnabled = saveButtonEnabled, saveAction = saveAction, cameraPermissionState = cameraPermissionState, + canChangeDisplayName = canChangeDisplayName, + canChangeAvatarUrl = canChangeAvatarUrl, eventSink = eventSink, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt index 774dcedae0..d4571d7be5 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt @@ -120,6 +120,7 @@ fun EditUserProfileView( state = avatarPickerState, onClick = ::onAvatarClick, modifier = Modifier.align(Alignment.CenterHorizontally), + enabled = state.canChangeAvatarUrl, ) Spacer(modifier = Modifier.height(16.dp)) Text( @@ -134,6 +135,7 @@ fun EditUserProfileView( value = state.displayName, placeholder = stringResource(CommonStrings.common_room_name_placeholder), singleLine = true, + enabled = state.canChangeDisplayName, onValueChange = { state.eventSink(EditUserProfileEvent.UpdateDisplayName(it)) }, ) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/HomeserverCapabilitiesProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/HomeserverCapabilitiesProvider.kt new file mode 100644 index 0000000000..e914656f5f --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/HomeserverCapabilitiesProvider.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api + +/** + * Provides information about the capabilities of the homeserver. + * + * Spec: https://spec.matrix.org/latest/client-server-api/#capabilities-negotiation + */ +interface HomeserverCapabilitiesProvider { + /** + * Manually refresh the capabilities of the homeserver performing a network request. + */ + suspend fun refresh(): Result + + /** + * Indicates whether the homeserver allows the user to change their display name. + */ + suspend fun canChangeDisplayName(): Result + + /** + * Indicates whether the homeserver allows the user to change their avatar URL. + */ + suspend fun canChangeAvatarUrl(): Result +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 773dbaaa07..35fd7e8551 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -223,6 +223,8 @@ interface MatrixClient { * Resets the cached client `well-known` config by the SDK. */ suspend fun resetWellKnownConfig(): Result + + fun homeserverCapabilities(): HomeserverCapabilitiesProvider } /** diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProvider.kt new file mode 100644 index 0000000000..d82e389aa7 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProvider.kt @@ -0,0 +1,28 @@ +/* + * 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 + +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider +import org.matrix.rustcomponents.sdk.HomeserverCapabilities + +class RustHomeserverCapabilitiesProvider( + private val homeserverCapabilities: HomeserverCapabilities, +) : HomeserverCapabilitiesProvider { + override suspend fun refresh(): Result = runCatchingExceptions { + homeserverCapabilities.refresh() + } + + override suspend fun canChangeDisplayName(): Result = runCatchingExceptions { + homeserverCapabilities.canChangeDisplayname() + } + + override suspend fun canChangeAvatarUrl(): Result = runCatchingExceptions { + homeserverCapabilities.canChangeAvatar() + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 1c87e73ba2..bb6806b5d4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.analytics.SdkStoreSizes import io.element.android.libraries.matrix.api.core.DeviceId @@ -835,6 +836,10 @@ class RustMatrixClient( val request = PerformDatabaseVacuumRequestBuilder(sessionId) sessionCoroutineScope.launch { workManagerScheduler.submit(request) } } + + override fun homeserverCapabilities(): HomeserverCapabilitiesProvider { + return RustHomeserverCapabilitiesProvider(innerClient.homeserverCapabilities()) + } } private fun defaultRoomCreationPowerLevels(isPublic: Boolean, isSpace: Boolean) = PowerLevels( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt index 6ca7d27a8f..bef24003b9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt @@ -13,6 +13,7 @@ import dev.zacsweers.metro.ContributesTo import dev.zacsweers.metro.Provides import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope +import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.encryption.EncryptionService @@ -90,4 +91,9 @@ object SessionMatrixModule { fun providesSpaceService(matrixClient: MatrixClient): SpaceService { return matrixClient.spaceService } + + @Provides + fun providesHomeserverCapabilitiesProvider(matrixClient: MatrixClient): HomeserverCapabilitiesProvider { + return matrixClient.homeserverCapabilities() + } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProviderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProviderTest.kt new file mode 100644 index 0000000000..8d3377d698 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustHomeserverCapabilitiesProviderTest.kt @@ -0,0 +1,64 @@ +/* + * 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 + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverCapabilities +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class RustHomeserverCapabilitiesProviderTest { + @Test + fun `refresh calls client refresh`() = runTest { + val refreshLambda = lambdaRecorder {} + val provider = createCapabilitiesProvider( + capabilities = FakeFfiHomeserverCapabilities(refresh = refreshLambda), + ) + assertThat(provider.refresh().isSuccess).isTrue() + refreshLambda.assertions().isCalledOnce() + } + + @Test + fun `refresh fails when client refresh does`() = runTest { + val refreshLambda = lambdaRecorder { throw IllegalStateException("Failed to refresh capabilities") } + val provider = createCapabilitiesProvider( + capabilities = FakeFfiHomeserverCapabilities(refresh = refreshLambda), + ) + assertThat(provider.refresh().isFailure).isTrue() + refreshLambda.assertions().isCalledOnce() + } + + @Test + fun `canChangeDisplayName returns expected value`() = runTest { + val provider = createCapabilitiesProvider( + capabilities = FakeFfiHomeserverCapabilities(canChangeDisplayName = { true }), + ) + assertThat(provider.canChangeDisplayName().getOrNull()).isTrue() + } + + @Test + fun `canChangeAvatarUrl returns expected value`() = runTest { + val provider = createCapabilitiesProvider( + capabilities = FakeFfiHomeserverCapabilities(canChangeAvatar = { true }), + ) + assertThat(provider.canChangeAvatarUrl().getOrNull()).isTrue() + } + + @Test + fun `canChangeDisplayName returns failure when client throws`() = runTest { + val provider = createCapabilitiesProvider( + capabilities = FakeFfiHomeserverCapabilities(canChangeDisplayName = { throw IllegalStateException("Failed to get display name capability") }), + ) + assert(provider.canChangeDisplayName().isFailure) + } + + private fun createCapabilitiesProvider( + capabilities: FakeFfiHomeserverCapabilities = FakeFfiHomeserverCapabilities(), + ) = RustHomeserverCapabilitiesProvider(capabilities) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt index 2aec38fcde..57ffcddb37 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt @@ -17,6 +17,7 @@ import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientDelegate import org.matrix.rustcomponents.sdk.CreateRoomParameters import org.matrix.rustcomponents.sdk.Encryption +import org.matrix.rustcomponents.sdk.HomeserverCapabilities import org.matrix.rustcomponents.sdk.HomeserverLoginDetails import org.matrix.rustcomponents.sdk.IgnoredUsersListener import org.matrix.rustcomponents.sdk.NoHandle @@ -50,6 +51,7 @@ class FakeFfiClient( private val homeserverLoginDetailsResult: () -> HomeserverLoginDetails = { lambdaError() }, private val getStoreSizesResult: () -> StoreSizes = { lambdaError() }, private val createRoomResult: (CreateRoomParameters) -> String = { lambdaError() }, + private val homeserverCapabilities: HomeserverCapabilities = FakeFfiHomeserverCapabilities(), private val closeResult: () -> Unit = {}, ) : Client(NoHandle) { override fun userId(): String = userId @@ -103,5 +105,9 @@ class FakeFfiClient( return createRoomResult(request) } + override fun homeserverCapabilities(): HomeserverCapabilities { + return homeserverCapabilities + } + override fun close() = closeResult() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverCapabilities.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverCapabilities.kt new file mode 100644 index 0000000000..4c60cbbb49 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverCapabilities.kt @@ -0,0 +1,33 @@ +/* + * 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.fixtures.fakes + +import io.element.android.tests.testutils.lambda.lambdaError +import org.matrix.rustcomponents.sdk.ExtendedProfileFields +import org.matrix.rustcomponents.sdk.HomeserverCapabilities +import org.matrix.rustcomponents.sdk.NoHandle + +class FakeFfiHomeserverCapabilities( + private val refresh: () -> Unit = { lambdaError() }, + private val canChangeDisplayName: () -> Boolean = { lambdaError() }, + private val canChangeAvatar: () -> Boolean = { lambdaError() }, + private val canChangePassword: () -> Boolean = { lambdaError() }, + private val canChangeThirdPartyIds: () -> Boolean = { lambdaError() }, + private val canGetLoginToken: () -> Boolean = { lambdaError() }, + private val forgetsRoomWhenLeaving: () -> Boolean = { lambdaError() }, + private val extendedProfileFields: () -> ExtendedProfileFields = { lambdaError() }, +) : HomeserverCapabilities(NoHandle) { + override suspend fun refresh() = refresh.invoke() + override suspend fun canChangeDisplayname(): Boolean = canChangeDisplayName.invoke() + override suspend fun canChangeAvatar(): Boolean = canChangeAvatar.invoke() + override suspend fun canChangePassword(): Boolean = canChangePassword.invoke() + override suspend fun canChangeThirdpartyIds(): Boolean = canChangeThirdPartyIds.invoke() + override suspend fun canGetLoginToken(): Boolean = canGetLoginToken.invoke() + override suspend fun forgetsRoomWhenLeaving(): Boolean = forgetsRoomWhenLeaving.invoke() + override suspend fun extendedProfileFields(): ExtendedProfileFields = extendedProfileFields.invoke() +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeHomeserverCapabilitiesProvider.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeHomeserverCapabilitiesProvider.kt new file mode 100644 index 0000000000..c098388c89 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeHomeserverCapabilitiesProvider.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.libraries.matrix.test + +import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider + +class FakeHomeserverCapabilitiesProvider( + private val refresh: () -> Result = { Result.success(Unit) }, + private val canChangeDisplayName: () -> Result = { Result.success(true) }, + private val canChangeAvatarUrl: () -> Result = { Result.success(true) }, +) : HomeserverCapabilitiesProvider { + override suspend fun refresh(): Result = refresh.invoke() + override suspend fun canChangeDisplayName(): Result = canChangeDisplayName.invoke() + override suspend fun canChangeAvatarUrl(): Result = canChangeAvatarUrl.invoke() +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 56527574d7..742af160ae 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.test +import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.analytics.SdkStoreSizes import io.element.android.libraries.matrix.api.core.DeviceId @@ -84,6 +85,7 @@ class FakeMatrixClient( override val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(), override val mediaPreviewService: MediaPreviewService = FakeMediaPreviewService(), override val roomMembershipObserver: RoomMembershipObserver = RoomMembershipObserver(), + private val homeserverCapabilitiesProvider: FakeHomeserverCapabilitiesProvider = FakeHomeserverCapabilitiesProvider(), private val accountManagementUrlResult: (AccountManagementAction?) -> Result = { lambdaError() }, private val resolveRoomAliasResult: (RoomAlias) -> Result> = { Result.success( @@ -384,4 +386,8 @@ class FakeMatrixClient( override suspend fun resetWellKnownConfig(): Result { return resetWellKnownConfigLambda() } + + override fun homeserverCapabilities(): HomeserverCapabilitiesProvider { + return homeserverCapabilitiesProvider + } } diff --git a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt index 770543e548..50d5a5ce32 100644 --- a/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt +++ b/libraries/slashcommands/api/src/main/kotlin/io/element/android/libraries/slashcommands/api/SlashCommand.kt @@ -51,6 +51,7 @@ sealed interface SlashCommand { data class ChangeDisplayName(val displayName: String) : SlashCommandAdmin data class ChangeDisplayNameForRoom(val displayName: String) : SlashCommandAdmin data class ChangeRoomAvatar(val url: String) : SlashCommandAdmin + data class ChangeAvatar(val url: String) : SlashCommandAdmin data class ChangeAvatarForRoom(val url: String) : SlashCommandAdmin data class SendSpoiler(val message: String) : SlashCommandSendMessage data class SendWithPrefix(val prefix: MessagePrefix, val message: CharSequence) : SlashCommandSendMessage diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt index 0b7b58a15f..0d9e1e8c72 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt @@ -120,6 +120,15 @@ enum class Command( isDevCommand = true, isSupported = false, ), + CHANGE_AVATAR( + command = "/myavatar", + parameters = "", + description = R.string.slash_command_description_avatar, + isAllowedInThread = false, + // Dev command since user has to know the mxc url + isDevCommand = true, + isSupported = false, + ), CHANGE_AVATAR_FOR_ROOM( command = "/myroomavatar", parameters = "", diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt index 0acd3af6f8..ad252cb224 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt @@ -44,6 +44,7 @@ class CommandExecutor( ): Result { return when (slashCommand) { is SlashCommand.BanUser -> banUser(slashCommand) + is SlashCommand.ChangeAvatar -> changeAvatar() is SlashCommand.ChangeAvatarForRoom -> changeAvatarForRoom() is SlashCommand.ChangeDisplayName -> changeDisplayName(slashCommand) is SlashCommand.ChangeDisplayNameForRoom -> changeDisplayNameForRoom() @@ -178,6 +179,10 @@ class CommandExecutor( return matrixClient.setDisplayName(slashCommand.displayName) } + private fun changeAvatar(): Result { + return Result.failure(Exception("Not yet implemented")) + } + private fun changeAvatarForRoom(): Result { return Result.failure(Exception("Not yet implemented")) } diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt index 85a045f50c..55125af20b 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandParser.kt @@ -107,6 +107,18 @@ class CommandParser( syntaxError(Command.ROOM_AVATAR) } } + Command.CHANGE_AVATAR.matches(slashCommand) -> { + if (messageParts.size == 2) { + val url = messageParts[1] + if (url.isMxcUrl()) { + SlashCommand.ChangeAvatar(url) + } else { + syntaxError(Command.CHANGE_AVATAR) + } + } else { + syntaxError(Command.CHANGE_AVATAR) + } + } Command.CHANGE_AVATAR_FOR_ROOM.matches(slashCommand) -> { if (messageParts.size == 2) { val url = messageParts[1] diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt index ba2786c944..6cd8688cad 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt @@ -11,6 +11,7 @@ import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.di.RoomScope import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.HomeserverCapabilitiesProvider import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.slashcommands.api.SlashCommand @@ -18,6 +19,8 @@ import io.element.android.libraries.slashcommands.api.SlashCommandService import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.coroutines.flow.first +import kotlinx.coroutines.withTimeoutOrNull +import kotlin.time.Duration.Companion.seconds @ContributesBinding(RoomScope::class) class DefaultSlashCommandService( @@ -26,6 +29,7 @@ class DefaultSlashCommandService( private val stringProvider: StringProvider, private val appPreferencesStore: AppPreferencesStore, private val featureFlagService: FeatureFlagService, + private val capabilitiesProvider: HomeserverCapabilitiesProvider, ) : SlashCommandService { override suspend fun getSuggestions( text: String, @@ -33,19 +37,41 @@ class DefaultSlashCommandService( ): List { if (!featureFlagService.isFeatureEnabled(FeatureFlags.SlashCommand)) return emptyList() val isDeveloperModeEnabled = appPreferencesStore.isDeveloperModeEnabledFlow().first() - return Command.entries.filter { - it.startsWith(text) - }.filter { - !isInThread || it.isAllowedInThread - }.filter { - !it.isDevCommand || isDeveloperModeEnabled - }.map { - SlashCommandSuggestion( - command = it.command, - parameters = it.parameters, - description = stringProvider.getString(it.description), - ) - } + return Command.entries + .asSequence() + .filter { it.startsWith(text) } + .filter { !isInThread || it.isAllowedInThread } + .filter { !it.isDevCommand || isDeveloperModeEnabled } + // Don't include the change display name commands if the user can't change their display name + .run { + val canUserChangeDisplayName = withTimeoutOrNull(5.seconds) { + capabilitiesProvider.canChangeDisplayName().getOrNull() + } ?: false + if (!canUserChangeDisplayName) { + filterNot { it == Command.CHANGE_DISPLAY_NAME || it == Command.CHANGE_DISPLAY_NAME_FOR_ROOM } + } else { + this + } + } + // Don't include the change avatar commands if the user can't change their avatar url + .run { + val canUserChangeAvatar = withTimeoutOrNull(5.seconds) { + capabilitiesProvider.canChangeAvatarUrl().getOrNull() + } ?: false + if (!canUserChangeAvatar) { + filterNot { it == Command.CHANGE_AVATAR || it == Command.CHANGE_AVATAR_FOR_ROOM } + } else { + this + } + } + .map { + SlashCommandSuggestion( + command = it.command, + parameters = it.parameters, + description = stringProvider.getString(it.description), + ) + } + .toList() } override suspend fun parse( diff --git a/libraries/slashcommands/impl/src/main/res/values/temporary.xml b/libraries/slashcommands/impl/src/main/res/values/temporary.xml index 0a8f2a0034..26232ea9b3 100644 --- a/libraries/slashcommands/impl/src/main/res/values/temporary.xml +++ b/libraries/slashcommands/impl/src/main/res/values/temporary.xml @@ -26,6 +26,7 @@ Set the room topic Removes user with given id from this room Changes your display nickname + Changes your profile picture in all rooms Sends the given message with confetti Sends the given message with snowfall Sends a message as plain text, without interpreting it as markdown diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt index 0887847a40..f5a6f54dfd 100644 --- a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandParserTest.kt @@ -78,12 +78,19 @@ class CommandParserTest { } @Test - fun parseSlashCommandPlainAndNick() = runTest { + fun parseSlashCommandPlain() = runTest { test("/plain hello", SlashCommand.SendPlainText("hello")) test("/plain", SlashCommand.ErrorSyntax("A string/plain, /plain ")) + } + @Test + fun parseSlashCommandNickAndMyAvatar() = runTest { test("/nick John", SlashCommand.ChangeDisplayName("John")) test("/nick", SlashCommand.ErrorSyntax("A string/nick, /nick ")) + + test("/myavatar mxc://matrix.org/abc", SlashCommand.ChangeAvatar("mxc://matrix.org/abc")) + test("/myavatar http://notmxc", SlashCommand.ErrorSyntax("A string/myavatar, /myavatar ")) + test("/myavatar", SlashCommand.ErrorSyntax("A string/myavatar, /myavatar ")) } @Test diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt index 243f25666c..cee4d17b21 100644 --- a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandServiceTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.timeline.MsgType +import io.element.android.libraries.matrix.test.FakeHomeserverCapabilitiesProvider import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom @@ -116,6 +117,26 @@ class DefaultSlashCommandServiceTest { sendMessage.assertions().isCalledOnce() } + @Test + fun `canChangeDisplayName is respected in suggestions`() = runTest { + var result = false + val capabilitiesProvider = FakeHomeserverCapabilitiesProvider( + canChangeDisplayName = { Result.success(result) }, + ) + val sut = createDefaultSlashCommandService(capabilitiesProvider = capabilitiesProvider) + + // Initially, with a disabled capability, the change display name command should not be in the suggestions + var changeNameCommand = sut.getSuggestions("", isInThread = false) + .find { it.command == Command.CHANGE_DISPLAY_NAME.command } + assertThat(changeNameCommand).isNull() + + // When the capability is true, the command should be included in the suggestions + result = true + changeNameCommand = sut.getSuggestions("", isInThread = false) + .find { it.command == Command.CHANGE_DISPLAY_NAME.command } + assertThat(changeNameCommand).isNotNull() + } + @Test fun `proceedAdmin delegates to commandExecutor`() = runTest { val leaveRoomLambda = lambdaRecorder> { @@ -155,11 +176,13 @@ class DefaultSlashCommandServiceTest { commandExecutor: CommandExecutor = createCommandExecutor( stringProvider = stringProvider, ), + capabilitiesProvider: FakeHomeserverCapabilitiesProvider = FakeHomeserverCapabilitiesProvider(), ) = DefaultSlashCommandService( commandParser = commandParser, commandExecutor = commandExecutor, stringProvider = stringProvider, appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService, + capabilitiesProvider = capabilitiesProvider, ) } diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en.png new file mode 100644 index 0000000000..8517440a90 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4dbcac95e6fd72ee2eb683a4f25d49f4d181be9b1386ec01670fb078bc46a52 +size 18966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en.png new file mode 100644 index 0000000000..75ce9869d4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:901c40d524de6de6fd70cbfcfc8b1d86cc896734254452535a07830587adafcf +size 18987 From 8503d1c5488abf98a1b0f2465b5abc6a2d2bccd1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 15 Apr 2026 14:45:38 +0200 Subject: [PATCH 0143/1083] Fix tests compilation --- features/login/impl/build.gradle.kts | 1 + .../login/impl/DefaultLoginEntryPointTest.kt | 2 ++ .../screens/onboarding/OnboardingViewTest.kt | 23 +++++++++++++ features/preferences/test/build.gradle.kts | 19 +++++++++++ .../test/FakePreferencesEntryPoint.kt | 32 +++++++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 features/preferences/test/build.gradle.kts create mode 100644 features/preferences/test/src/main/kotlin/io/element/android/features/preferences/test/FakePreferencesEntryPoint.kt diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index 83dd4cf7bd..12af922cbe 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -80,6 +80,7 @@ dependencies { testCommonDependencies(libs, true) testImplementation(projects.features.login.test) testImplementation(projects.features.enterprise.test) + testImplementation(projects.features.preferences.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oidc.test) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt index 1d24d775be..86a629270f 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt @@ -16,6 +16,7 @@ import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.classic.FakeElementClassicConnection +import io.element.android.features.preferences.test.FakePreferencesEntryPoint import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode @@ -41,6 +42,7 @@ class DefaultLoginEntryPointTest { oidcActionFlow = FakeOidcActionFlow(), appCoroutineScope = backgroundScope, elementClassicConnection = FakeElementClassicConnection(), + preferencesEntryPoint = FakePreferencesEntryPoint(), ) } val callback = object : LoginEntryPoint.Callback { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt index c3d1ff6015..ad09445075 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt @@ -11,6 +11,7 @@ package io.element.android.features.login.impl.screens.onboarding import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import com.google.testing.junit.testparameterinjector.KotlinTestParameters.namedTestValues @@ -46,11 +47,15 @@ class OnboardingViewTest { rule.setOnboardingView( state = anOnBoardingState( canCreateAccount = true, + showDeveloperSettings = false, eventSink = eventSink, ), onCreateAccount = callback, ) rule.clickOn(R.string.screen_onboarding_sign_up) + // Developer settings should not be shown + val developerSettingsText = rule.activity.getString(CommonStrings.common_developer_options) + rule.onNodeWithContentDescription(developerSettingsText).assertDoesNotExist() } } @@ -172,6 +177,22 @@ class OnboardingViewTest { } } + @Test + fun `clicking on settings calls the developer settings callback`() { + val eventSink = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setOnboardingView( + state = anOnBoardingState( + showDeveloperSettings = true, + eventSink = eventSink, + ), + onDeveloperSettingsClick = callback, + ) + val text = rule.activity.getString(CommonStrings.common_developer_options) + rule.onNodeWithContentDescription(text).performClick() + } + } + @Test fun `cannot report a problem when the feature is disabled`() { val eventSink = EventsRecorder(expectEvents = false) @@ -235,6 +256,7 @@ class OnboardingViewTest { private fun AndroidComposeTestRule.setOnboardingView( state: OnBoardingState, onBackClick: () -> Unit = EnsureNeverCalled(), + onDeveloperSettingsClick: () -> Unit = EnsureNeverCalled(), onSignInWithQrCode: () -> Unit = EnsureNeverCalled(), onSignIn: (Boolean) -> Unit = EnsureNeverCalledWithParam(), onCreateAccount: () -> Unit = EnsureNeverCalled(), @@ -248,6 +270,7 @@ class OnboardingViewTest { OnBoardingView( state = state, onBackClick = onBackClick, + onDeveloperSettingsClick = onDeveloperSettingsClick, onSignInWithQrCode = onSignInWithQrCode, onSignIn = onSignIn, onCreateAccount = onCreateAccount, diff --git a/features/preferences/test/build.gradle.kts b/features/preferences/test/build.gradle.kts new file mode 100644 index 0000000000..7e3da4a6e8 --- /dev/null +++ b/features/preferences/test/build.gradle.kts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.preferences.test" +} + +dependencies { + implementation(projects.features.preferences.api) + implementation(projects.tests.testutils) +} diff --git a/features/preferences/test/src/main/kotlin/io/element/android/features/preferences/test/FakePreferencesEntryPoint.kt b/features/preferences/test/src/main/kotlin/io/element/android/features/preferences/test/FakePreferencesEntryPoint.kt new file mode 100644 index 0000000000..c57ed434fa --- /dev/null +++ b/features/preferences/test/src/main/kotlin/io/element/android/features/preferences/test/FakePreferencesEntryPoint.kt @@ -0,0 +1,32 @@ +/* + * 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.test + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import io.element.android.features.preferences.api.PreferencesEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError + +class FakePreferencesEntryPoint : PreferencesEntryPoint { + override fun createNode( + parentNode: Node, + buildContext: BuildContext, + params: PreferencesEntryPoint.Params, + callback: PreferencesEntryPoint.Callback, + ): Node { + lambdaError() + } + + override fun createAppDeveloperSettingsNode( + parentNode: Node, + buildContext: BuildContext, + callback: PreferencesEntryPoint.DeveloperSettingsCallback, + ): Node { + lambdaError() + } +} From 0058de9bca31949ce3817ac6160d4e8cafa8fc24 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Apr 2026 15:14:42 +0200 Subject: [PATCH 0144/1083] Add extra logs for timeline pagination (#6589) We found some possible rare issues with pagination these could help understand. --- .../matrix/impl/timeline/RustTimeline.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 8a184311de..7b398529a0 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -130,6 +130,8 @@ class RustTimeline( Timeline.PaginationStatus(isPaginating = false, hasMoreToLoad = mode is Timeline.Mode.FocusedOnEvent) ) + private val loggerTag = "Timeline($mode)" + init { when (mode) { is Timeline.Mode.Live, is Timeline.Mode.FocusedOnEvent -> coroutineScope.fetchMembers() @@ -177,10 +179,11 @@ class RustTimeline( } private fun updatePaginationStatus(direction: Timeline.PaginationDirection, update: (Timeline.PaginationStatus) -> Timeline.PaginationStatus) { - when (direction) { + val result = when (direction) { Timeline.PaginationDirection.BACKWARDS -> backwardPaginationStatus.getAndUpdate(update) Timeline.PaginationDirection.FORWARDS -> forwardPaginationStatus.getAndUpdate(update) } + Timber.tag(loggerTag).d("updatePaginationStatus $direction: $result") } // Use NonCancellable to avoid breaking the timeline when the coroutine is cancelled. @@ -195,12 +198,13 @@ class RustTimeline( } }.onFailure { error -> if (error is TimelineException.CannotPaginate) { - Timber.d("Can't paginate $direction on room ${joinedRoom.roomId} with paginationStatus: ${backwardPaginationStatus.value}") + Timber.tag(loggerTag).d("Can't paginate $direction on room ${joinedRoom.roomId} with paginationStatus: ${backwardPaginationStatus.value}") } else { updatePaginationStatus(direction) { it.copy(isPaginating = false) } - Timber.e(error, "Error paginating $direction on room ${joinedRoom.roomId}") + Timber.tag(loggerTag).e(error, "Error paginating $direction on room ${joinedRoom.roomId}") } }.onSuccess { hasReachedEnd -> + Timber.tag(loggerTag).d("Finished paginating $direction on room ${joinedRoom.roomId}, hasReachedEnd: $hasReachedEnd") updatePaginationStatus(direction) { it.copy(isPaginating = false, hasMoreToLoad = !hasReachedEnd) } } } @@ -264,7 +268,7 @@ class RustTimeline( try { inner.fetchMembers() } catch (exception: Exception) { - Timber.e(exception, "Error fetching members for room ${joinedRoom.roomId}") + Timber.tag(loggerTag).e(exception, "Error fetching members for room ${joinedRoom.roomId}") } } @@ -370,7 +374,7 @@ class RustTimeline( formattedCaption: String?, inReplyToEventId: EventId?, ): Result { - Timber.d("Sending image ${file.path.hash()}") + Timber.tag(loggerTag).d("Sending image ${file.path.hash()}") return sendAttachment(listOfNotNull(file, thumbnailFile)) { inner.sendImage( params = UploadParameters( @@ -396,7 +400,7 @@ class RustTimeline( formattedCaption: String?, inReplyToEventId: EventId?, ): Result { - Timber.d("Sending video ${file.path.hash()}") + Timber.tag(loggerTag).d("Sending video ${file.path.hash()}") return sendAttachment(listOfNotNull(file, thumbnailFile)) { inner.sendVideo( params = UploadParameters( @@ -421,7 +425,7 @@ class RustTimeline( formattedCaption: String?, inReplyToEventId: EventId?, ): Result { - Timber.d("Sending audio ${file.path.hash()}") + Timber.tag(loggerTag).d("Sending audio ${file.path.hash()}") return sendAttachment(listOf(file)) { inner.sendAudio( params = UploadParameters( @@ -445,7 +449,7 @@ class RustTimeline( formattedCaption: String?, inReplyToEventId: EventId?, ): Result { - Timber.d("Sending file ${file.path.hash()}") + Timber.tag(loggerTag).d("Sending file ${file.path.hash()}") return sendAttachment(listOf(file)) { inner.sendFile( params = UploadParameters( @@ -475,7 +479,7 @@ class RustTimeline( runCatchingExceptions { roomContentForwarder.forward(fromTimeline = inner, eventId = eventId, toRoomIds = roomIds) }.onFailure { - Timber.e(it) + Timber.tag(loggerTag).e(it) } } From f389eae8684e334c7faddf86467245ca56398eea Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Wed, 15 Apr 2026 10:46:18 +0300 Subject: [PATCH 0145/1083] Make media captions scrollable (#6498) --- .../impl/viewer/MediaViewerStateProvider.kt | 24 +++++++++++ .../impl/viewer/MediaViewerView.kt | 43 ++++++++++++++++--- ...ewer.impl.viewer_MediaViewerView_17_en.png | 3 ++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index 85aecc41a8..b1a2bde350 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -29,6 +29,14 @@ import io.element.android.libraries.mediaviewer.impl.details.aMediaDeleteConfirm import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState import kotlinx.collections.immutable.toImmutableList +private const val LONG_CAPTION = "This is a very long caption that should be scrollable in the media viewer. " + + "It contains multiple lines of text to demonstrate the scrolling behavior. " + + "Line 1: Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Line 2: Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " + + "Line 3: Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. " + + "Line 4: Duis aute irure dolor in reprehenderit in voluptate velit esse cillum. " + + "Line 5: Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia." + open class MediaViewerStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( @@ -170,6 +178,22 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) ) ), + anImageMediaInfo( + senderName = "Alice", + dateSent = "21 NOV, 2024", + caption = LONG_CAPTION, + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 7439909330..e5bed86eee 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -20,10 +20,13 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.TopAppBarDefaults @@ -39,6 +42,7 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged @@ -538,19 +542,44 @@ private fun MediaViewerBottomBar( if (showDivider) { HorizontalDivider() } - Text( + val scrollState = rememberScrollState() + val showBottomShadow = scrollState.value < scrollState.maxValue + Box( modifier = Modifier .fillMaxWidth() - .padding(16.dp), - text = caption, - maxLines = 5, - overflow = TextOverflow.Ellipsis, - style = ElementTheme.typography.fontBodyLgRegular, - ) + .heightIn(max = maxCaptionHeight), + ) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .verticalScroll(scrollState), + text = caption, + style = ElementTheme.typography.fontBodyLgRegular, + ) + if (showBottomShadow) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + .align(Alignment.BottomCenter) + .background( + brush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + bgCanvasWithTransparency, + ), + ), + ), + ) + } + } } } } +private val maxCaptionHeight = 200.dp + @Composable private fun ThumbnailView( thumbnailSource: MediaSource?, diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png new file mode 100644 index 0000000000..dc06b5afc9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e353d24c2b9b49abaa11e064b1581215ad65154d0e67372fe24684ba2695a0e +size 442063 From 70e45d9bfec67e465a58806b53aac976f8f67937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Apr 2026 09:34:29 +0200 Subject: [PATCH 0146/1083] Some tweaks for landscape and insets --- .../impl/viewer/MediaViewerView.kt | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index e5bed86eee..01f616aaca 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -17,10 +17,12 @@ import androidx.compose.animation.fadeOut import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager @@ -32,6 +34,7 @@ import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf @@ -46,7 +49,9 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics @@ -157,10 +162,11 @@ fun MediaViewerView( // So we need to update this value only when the `settledPage` value changes. It seems like a bug that needs to be fixed in Compose. page == pagerState.settledPage } + val navigationBarPadding = WindowInsets.navigationBars.getBottom(LocalDensity.current) MediaViewerPage( isDisplayed = isDisplayed, showOverlay = showOverlay, - bottomPaddingInPixels = bottomPaddingInPixels, + bottomPaddingInPixels = (bottomPaddingInPixels - navigationBarPadding).coerceAtLeast(0), data = dataForPage, textFileViewer = textFileViewer, onDismiss = onBackClick, @@ -179,9 +185,7 @@ fun MediaViewerView( // Bottom bar AnimatedVisibility(visible = showOverlay, enter = fadeIn(), exit = fadeOut()) { Box( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() + modifier = Modifier.fillMaxSize() ) { MediaViewerBottomBar( modifier = Modifier.align(Alignment.BottomCenter), @@ -543,17 +547,21 @@ private fun MediaViewerBottomBar( HorizontalDivider() } val scrollState = rememberScrollState() - val showBottomShadow = scrollState.value < scrollState.maxValue + val showBottomShadow by remember { derivedStateOf { scrollState.value < scrollState.maxValue } } + val isLandscape = with(LocalWindowInfo.current) { + containerDpSize.width > containerDpSize.height + } Box( modifier = Modifier .fillMaxWidth() - .heightIn(max = maxCaptionHeight), + .heightIn(max = if (isLandscape) maxCaptionHeightLandscape else maxCaptionHeightPortrait), ) { Text( modifier = Modifier .fillMaxWidth() .padding(16.dp) - .verticalScroll(scrollState), + .verticalScroll(scrollState) + .navigationBarsPadding(), text = caption, style = ElementTheme.typography.fontBodyLgRegular, ) @@ -578,7 +586,8 @@ private fun MediaViewerBottomBar( } } -private val maxCaptionHeight = 200.dp +private val maxCaptionHeightPortrait = 200.dp +private val maxCaptionHeightLandscape = 128.dp @Composable private fun ThumbnailView( From 42a572cce2c374c55ba4297d5a6fed556e4b266b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Apr 2026 10:00:20 +0200 Subject: [PATCH 0147/1083] Add landscape previews --- .../mediaviewer/impl/viewer/MediaViewerView.kt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 01f616aaca..b27e8017d6 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -111,8 +111,12 @@ fun MediaViewerView( val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) var showOverlay by remember { mutableStateOf(true) } - val defaultBottomPaddingInPixels = if (LocalInspectionMode.current) 303 else 0 val currentData = state.listData.getOrNull(state.currentIndex) + val isLandscape = with(LocalWindowInfo.current) { + containerDpSize.width > containerDpSize.height + } + val defaultBottomPaddingInPixels = if (LocalInspectionMode.current && !isLandscape) 303 else 0 + BackHandler { onBackClick() } Scaffold( modifier, @@ -642,3 +646,14 @@ internal fun MediaViewerViewPreview(@PreviewParameter(MediaViewerStateProvider:: onBackClick = {}, ) } + +@Preview(device = "spec:width=411dp,height=891dp, orientation=landscape") +@Composable +internal fun MediaViewerViewLandscapePreview(@PreviewParameter(MediaViewerStateProvider::class) state: MediaViewerState) = ElementPreviewDark { + MediaViewerView( + state = state, + audioFocus = null, + textFileViewer = { _, _ -> }, + onBackClick = {}, + ) +} From 9a5ed43f801c2267b41378226a34c3c81e7a3d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Apr 2026 10:24:57 +0200 Subject: [PATCH 0148/1083] Try generating landscape screenshots again --- tests/uitests/src/test/kotlin/base/ScreenshotTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt b/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt index 0b088b5de0..a611fa83cf 100644 --- a/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt +++ b/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt @@ -23,6 +23,7 @@ import app.cash.paparazzi.Paparazzi import app.cash.paparazzi.RenderExtension import app.cash.paparazzi.TestName import com.android.resources.NightMode +import com.android.resources.ScreenOrientation import io.element.android.compound.theme.ElementTheme import sergio.sastre.composable.preview.scanner.android.AndroidPreviewInfo import sergio.sastre.composable.preview.scanner.core.preview.ComposablePreview @@ -122,6 +123,7 @@ object PaparazziPreviewRule { ): Paparazzi { val densityScale = deviceConfig.density.dpiValue / 160f val customScreenHeight = preview.previewInfo.heightDp.takeIf { it >= 0 }?.let { it * densityScale }?.toInt() + val isLandscape = preview.previewInfo.device.contains("landscape") return Paparazzi( deviceConfig = deviceConfig.copy( nightMode = when (preview.previewInfo.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) { @@ -131,6 +133,7 @@ object PaparazziPreviewRule { locale = locale, softButtons = false, screenHeight = customScreenHeight ?: deviceConfig.screenHeight, + orientation = if (isLandscape) ScreenOrientation.LANDSCAPE else ScreenOrientation.PORTRAIT, ), maxPercentDifference = 0.01, renderExtensions = renderExtensions, From 15eca13ff8d0d5849c9439e035ebc483440a77da Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 15 Apr 2026 08:43:40 +0000 Subject: [PATCH 0149/1083] Update screenshots --- ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png | 3 +++ ...s.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png | 3 +++ 18 files changed, 54 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png new file mode 100644 index 0000000000..60c5e812ba --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e514d7f36fe25150d66c2d2092982a696196a5a0a2674eef97b7231c0c03bef +size 699410 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png new file mode 100644 index 0000000000..5a96554c0a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:712af2723a0656ffe927f1cd488d3117f5b450fa405dad307b0c88a9f2483f9c +size 698704 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png new file mode 100644 index 0000000000..e4424188e6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d6ab1331e65a4d02accb4d20c899a06c37a022d9f9080133799e30763969300 +size 26774 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png new file mode 100644 index 0000000000..3dccb4c068 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:010120cbcbfed1e7bfa3fb4c88df6e1098d0382cb1834f1a8046e312434f201d +size 26549 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png new file mode 100644 index 0000000000..d0139ec184 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52174b55b1737787260a454c59f243b0e3f6327ef5ec71464744def928d165d4 +size 206785 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en.png new file mode 100644 index 0000000000..71ca7c633d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47c2e2194283803c55553c0220400ed8991539f25b772e0dbdde6d5defa3d3d4 +size 7343 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en.png new file mode 100644 index 0000000000..4e8d03c6a4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1e56f491ccc4c9ab82dde36a8fca588bdf037fb59b70ea47ffe13a56e22f801 +size 4457 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png new file mode 100644 index 0000000000..a32a45029c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99478fe3d9d44e9cda39f33748c70017203a2cce5cb855605740a29360221bd5 +size 184910 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png new file mode 100644 index 0000000000..a855818ac6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:062f8342a3a3715498ca34488c2d9ffe09c1e6dbbe04df09e88fd107a33b174a +size 653228 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png new file mode 100644 index 0000000000..accbd26985 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3effa629295c12d2248924cf298599f3bd28975ecc76fac84f771c16266d738e +size 698895 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png new file mode 100644 index 0000000000..b9dabc97ee --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fd3b7065860d1e51fe51a0a6e3f4a9e61a77ea91cefe85cc3aa3560c4cc6bb2 +size 252253 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png new file mode 100644 index 0000000000..f11d4fc3fc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f9ee78e2a034f34d77a438d305a5cc63ea583df80f83a14b1d81fcf74ca93f4 +size 665416 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png new file mode 100644 index 0000000000..5e081d3c4e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1e91c66363a5af74d4345f7837db178410c078e390b0cf9296d0ba4b3dfd7cb +size 207004 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png new file mode 100644 index 0000000000..d61e0a50b9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9eb950f3c0d34a796ebd7635ff736023742d5e6a243912f3ad2234ecf08694b2 +size 183220 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png new file mode 100644 index 0000000000..f2352c88f8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f6c84fbd21949a3d9d355bfb627b8a70f65fc669cb6b6818a325fe4577351f9 +size 196092 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png new file mode 100644 index 0000000000..bd37e3eb79 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26bd927acc578cb3585f6e101c066f0a6adb6a6e424dcd196388d5a838d8b22b +size 196396 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png new file mode 100644 index 0000000000..69515d4326 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c4440f5ed01f2c1b405bb2d444c52455ea8ee1c094baf7d2f85bd9a9ff98b02 +size 210117 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png new file mode 100644 index 0000000000..5d254988c9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11f140569061e21e6b546118b57340a0830779580498a31627acb2e6c7313471 +size 210490 From 69fb344517af8bfe512a0cb48e391b2288c5e340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Apr 2026 13:16:37 +0200 Subject: [PATCH 0150/1083] Use `WindowSizeClass` instead of just checking portrait/landscape orientation --- .../utils/WindowSizeClassUtils.kt | 19 +++++++++++++++++++ .../impl/viewer/MediaViewerView.kt | 12 +++--------- 2 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/WindowSizeClassUtils.kt diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/WindowSizeClassUtils.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/WindowSizeClassUtils.kt new file mode 100644 index 0000000000..ba0752e8a2 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/WindowSizeClassUtils.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.designsystem.utils + +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo +import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass +import androidx.compose.runtime.Composable + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +fun hasCompactHeightWindowSize(): Boolean { + return currentWindowAdaptiveInfo().windowSizeClass.heightSizeClass == WindowHeightSizeClass.Compact +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index b27e8017d6..a3cc0e2b9f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -51,7 +51,6 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics @@ -78,6 +77,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.hasCompactHeightWindowSize 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.media.MediaSource @@ -112,10 +112,7 @@ fun MediaViewerView( var showOverlay by remember { mutableStateOf(true) } val currentData = state.listData.getOrNull(state.currentIndex) - val isLandscape = with(LocalWindowInfo.current) { - containerDpSize.width > containerDpSize.height - } - val defaultBottomPaddingInPixels = if (LocalInspectionMode.current && !isLandscape) 303 else 0 + val defaultBottomPaddingInPixels = if (LocalInspectionMode.current && !hasCompactHeightWindowSize()) 303 else 0 BackHandler { onBackClick() } Scaffold( @@ -552,13 +549,10 @@ private fun MediaViewerBottomBar( } val scrollState = rememberScrollState() val showBottomShadow by remember { derivedStateOf { scrollState.value < scrollState.maxValue } } - val isLandscape = with(LocalWindowInfo.current) { - containerDpSize.width > containerDpSize.height - } Box( modifier = Modifier .fillMaxWidth() - .heightIn(max = if (isLandscape) maxCaptionHeightLandscape else maxCaptionHeightPortrait), + .heightIn(max = if (hasCompactHeightWindowSize()) maxCaptionHeightLandscape else maxCaptionHeightPortrait), ) { Text( modifier = Modifier From 7cdad11753007cd7fc2d32e9a335155b0b189e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Apr 2026 15:14:09 +0200 Subject: [PATCH 0151/1083] Use `Devices.PHONE` directly in the landscape preview --- .../libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index a3cc0e2b9f..95ce7c631f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -55,6 +55,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -641,7 +642,7 @@ internal fun MediaViewerViewPreview(@PreviewParameter(MediaViewerStateProvider:: ) } -@Preview(device = "spec:width=411dp,height=891dp, orientation=landscape") +@Preview(device = "${Devices.PHONE}, orientation=landscape") @Composable internal fun MediaViewerViewLandscapePreview(@PreviewParameter(MediaViewerStateProvider::class) state: MediaViewerState) = ElementPreviewDark { MediaViewerView( From 67729f87c911bfc16279cfc8151f75e0d835df0b Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Wed, 15 Apr 2026 18:17:31 +0200 Subject: [PATCH 0152/1083] 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 b21f7cd18ffc85a231564abe3cd1989ec36e4891 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:32:12 +0000 Subject: [PATCH 0153/1083] Update dependency io.element.android:element-call-embedded to v0.19.1 --- 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 b867bef5f1..71e31f6cf6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -233,7 +233,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.19.0" +element_call_embedded = "io.element.android:element-call-embedded:0.19.1" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From 42bd404a20bc7bbad68c78782e50e38b51ead4c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:39:35 +0000 Subject: [PATCH 0154/1083] Update dependency androidx.annotation:annotation-jvm to v1.10.0 --- 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 b867bef5f1..4f4d9a82be 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -89,7 +89,7 @@ google_tink = "com.google.crypto.tink:tink-android:1.21.0" # AndroidX androidx_core = { module = "androidx.core:core", version.ref = "core" } androidx_corektx = { module = "androidx.core:core-ktx", version.ref = "core" } -androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.9.1" +androidx_annotationjvm = "androidx.annotation:annotation-jvm:1.10.0" androidx_datastore_preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" } androidx_datastore_datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" } androidx_exifinterface = "androidx.exifinterface:exifinterface:1.4.2" From d8c540956a563e6eb40e4bc694bb8a78b860ae21 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 09:56:48 +0200 Subject: [PATCH 0155/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.04.15 (#6595) 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 b867bef5f1..068516bcd1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.13" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.15" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 67c0e4c1406f9d147930310c4e5c9e386760449a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:26:20 +0200 Subject: [PATCH 0156/1083] Update nschloe/action-cached-lfs-checkout action to v1.2.5 (#6600) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/nightlyReports.yml | 2 +- .github/workflows/recordScreenshots.yml | 4 ++-- .github/workflows/tests.yml | 2 +- .github/workflows/validate-lfs.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index ae87dd6d50..55a300dd88 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -16,7 +16,7 @@ jobs: contents: write steps: - name: ⏬ Checkout with LFS - uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 + uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 33660b1184..314929d801 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -34,7 +34,7 @@ jobs: swap-storage: false - name: ⏬ Checkout with LFS - uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 + uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 70bbbe5d0a..0f4c8ee581 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -43,13 +43,13 @@ jobs: labels: Record-Screenshots - name: ⏬ Checkout with LFS (PR) if: github.event.label.name == 'Record-Screenshots' - uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 + uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 with: persist-credentials: false ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref }} - name: ⏬ Checkout with LFS (Branch) if: github.event_name == 'workflow_dispatch' - uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 + uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 with: persist-credentials: false - name: ☕️ Use JDK 21 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 03882c7d44..0ce66df478 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -49,7 +49,7 @@ jobs: sudo swapon /mnt/swapfile sudo swapon --show - name: ⏬ Checkout with LFS - uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 + uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/validate-lfs.yml b/.github/workflows/validate-lfs.yml index c3158291c3..027c7d68e9 100644 --- a/.github/workflows/validate-lfs.yml +++ b/.github/workflows/validate-lfs.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest name: Validate steps: - - uses: nschloe/action-cached-lfs-checkout@1c185ad576953eab13e35ffe1bffef437d97e9d2 # v1.2.4 + - uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - run: | ./tools/git/validate_lfs.sh From 704ddc9132e80d12050b9899f6963b65d862516b Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Apr 2026 22:06:00 +0200 Subject: [PATCH 0157/1083] 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 0158/1083] 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 0159/1083] 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 c349f74ce80860256bcb2eb40cfcef469f81583c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 16 Apr 2026 16:19:29 +0200 Subject: [PATCH 0160/1083] Fix loading initial items of non-live timelines (#6598) This was done automatically by the SDK in the past by returning a `Reset` timeline update, but this behaviour changed and now we have to do it. --- .../messages/impl/timeline/TimelineView.kt | 10 ++++-- .../messages/impl/MessagesViewTest.kt | 9 +++++ .../impl/timeline/TimelineViewTest.kt | 33 +++++++++++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 0137b1736d..0c5bb28890 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -84,6 +84,7 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.transform import kotlinx.coroutines.launch import timber.log.Timber @@ -262,11 +263,16 @@ private fun TimelinePrefetchingHelper( firstVisibleItemIndex + layoutInfo.visibleItemsInfo.size >= layoutInfo.totalItemsCount - 40 } + // If we have no timeline items, we need to back paginate to load some messages. This usually happens on all timelines except for live ones. + // This automatic pagination was previously done by the SDK, and we received a `Reset` update, but now we need to do it ourselves. + val isEmptyTimelineFlow = layoutInfoFlow.map { it.totalItemsCount == 0 } + combine( isCloseToStartOfLoadedTimelineFlow.distinctUntilChanged(), isScrollingFlow.distinctUntilChanged(), - ) { needsPrefetch, isScrolling -> - needsPrefetch && isScrolling + isEmptyTimelineFlow, + ) { needsPrefetch, isScrolling, isEmptyAndNeedsBackPagination -> + isEmptyAndNeedsBackPagination || needsPrefetch && isScrolling } .distinctUntilChanged() .collectLatest { needsPrefetch -> diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index ff4bc37fa3..62b9eac68d 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -522,6 +522,9 @@ class MessagesViewTest { rule.setMessagesView( state = stateWithActionListState, ) + // Clear initial 'LoadMore' event emitted when setting the state + eventsRecorder.clear() + val verifiedUserSendFailure = rule.activity.getString(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, "Alice") rule.onNodeWithText(verifiedUserSendFailure).performClick() // Give time for the close animation to complete @@ -585,6 +588,9 @@ class MessagesViewTest { ), ) rule.setMessagesView(state = state) + // Clear initial 'LoadMore' event emitted when setting the state + eventsRecorder.clear() + rule.onNodeWithText("This is a pinned message").performClick() eventsRecorder.assertSingle(TimelineEvent.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)) } @@ -601,6 +607,9 @@ class MessagesViewTest { timelineState = aTimelineState(eventSink = eventsRecorder) ) rule.setMessagesView(state = state) + // Clear initial 'LoadMore' event emitted when setting the state + eventsRecorder.clear() + val text = rule.activity.getString(R.string.screen_room_timeline_tombstoned_room_action) // The bottomsheet subcompose seems to make the node to appear twice rule.onAllNodesWithText(text).onFirst().performClick() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt index 3a97fbd9dc..c05625e2d3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt @@ -67,24 +67,31 @@ class TimelineViewTest { @Test fun `reaching the end of the timeline does not send a LoadMore event`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), eventSink = eventsRecorder, ), ) + eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) } @Test fun `scroll to bottom on live timeline does not emit the Event`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), isLive = true, eventSink = eventsRecorder, ), forceJumpToBottomVisibility = true, ) + + eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) + eventsRecorder.clear() + val contentDescription = rule.activity.getString(CommonStrings.a11y_jump_to_bottom) rule.onNodeWithContentDescription(contentDescription).performClick() } @@ -94,15 +101,33 @@ class TimelineViewTest { val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), isLive = false, eventSink = eventsRecorder, ), ) + + eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) + eventsRecorder.clear() + val contentDescription = rule.activity.getString(CommonStrings.a11y_jump_to_bottom) rule.onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertSingle(TimelineEvent.JumpToLive) } + @Test + fun `an empty timeline triggers a prefetch`() { + val eventsRecorder = EventsRecorder() + rule.setTimelineView( + state = aTimelineState( + timelineItems = persistentListOf(), + eventSink = eventsRecorder, + ), + ) + + eventsRecorder.assertSingle(TimelineEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS)) + } + @Test fun `show shield dialog`() { val eventsRecorder = EventsRecorder() @@ -133,11 +158,15 @@ class TimelineViewTest { val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), isLive = false, eventSink = eventsRecorder, messageShield = aCriticalShield(), ), ) + eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) + eventsRecorder.clear() + rule.clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(TimelineEvent.HideShieldDialog) } From 3f9b8b822e8115193eedc48dc72ce6ae43fe6142 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 16 Apr 2026 16:35:28 +0200 Subject: [PATCH 0161/1083] cleaning: Remove join button from call notify timelineItemView --- .../features/messages/impl/MessagesView.kt | 3 -- .../pinned/list/PinnedMessagesListView.kt | 1 - .../messages/impl/timeline/TimelineView.kt | 3 -- .../TimelineViewMessageShieldPreview.kt | 1 - .../components/TimelineItemCallNotifyView.kt | 51 ++++++++----------- .../TimelineItemGroupedEventsRow.kt | 1 - .../timeline/components/TimelineItemRow.kt | 3 -- .../event/TimelineItemContentFactory.kt | 4 +- .../impl/timeline/groups/Groupability.kt | 2 +- .../TimelineItemRtcNotificationContent.kt | 4 +- .../api/timeline/item/event/EventContent.kt | 5 +- .../item/event/TimelineEventContentMapper.kt | 11 +++- .../impl/datasource/EventItemFactory.kt | 2 +- 13 files changed, 43 insertions(+), 48 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index bf20c8dc6b..5a0b14b820 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -282,7 +282,6 @@ fun MessagesView( state.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, targetEvent)) }, forceJumpToBottomVisibility = forceJumpToBottomVisibility, - onJoinCallClick = onJoinCallClick, onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, knockRequestsBannerView = knockRequestsBannerView, ) @@ -460,7 +459,6 @@ private fun MessagesViewContent( onMessageLongClick: (TimelineItem.Event) -> Unit, onSendLocationClick: () -> Unit, onCreatePollClick: () -> Unit, - onJoinCallClick: (isAudioCall: Boolean) -> Unit, onViewAllPinnedMessagesClick: () -> Unit, forceJumpToBottomVisibility: Boolean, onSwipeToReply: (TimelineItem.Event) -> Unit, @@ -517,7 +515,6 @@ private fun MessagesViewContent( onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, - onJoinCallClick = onJoinCallClick, nestedScrollConnection = scrollBehavior.nestedScrollConnection, floatingDateTopOffset = pinnedBannerHeightDp, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index b212549a22..7190aa174f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -235,7 +235,6 @@ private fun PinnedMessagesListLoaded( onMoreReactionsClick = {}, onReadReceiptClick = {}, onSwipeToReply = {}, - onJoinCallClick = {}, eventSink = { timelineItemEvent -> when (timelineItemEvent) { is TimelineEvent.OpenThread -> state.eventSink(PinnedMessagesListEvent.OpenThread(timelineItemEvent.threadRootEventId)) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 0137b1736d..afe1f25d24 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -102,7 +102,6 @@ fun TimelineView( onReactionLongClick: (emoji: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, - onJoinCallClick: (isAudioCall: Boolean) -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState(), forceJumpToBottomVisibility: Boolean = false, @@ -186,7 +185,6 @@ fun TimelineView( onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, onSwipeToReply = onSwipeToReply, - onJoinCallClick = onJoinCallClick, eventSink = state.eventSink, ) } @@ -425,7 +423,6 @@ internal fun TimelineViewPreview( onReactionLongClick = { _, _ -> }, onMoreReactionsClick = {}, onReadReceiptClick = {}, - onJoinCallClick = {}, forceJumpToBottomVisibility = true, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt index 5f9c3d0364..f0a11081e1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewMessageShieldPreview.kt @@ -49,7 +49,6 @@ internal fun TimelineViewMessageShieldPreview() = ElementPreview { onReactionLongClick = { _, _ -> }, onMoreReactionsClick = {}, onReadReceiptClick = {}, - onJoinCallClick = {}, forceJumpToBottomVisibility = true, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index a6ae2d9ee5..bf55503665 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -31,24 +31,22 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent -import io.element.android.features.roomcall.api.RoomCallState -import io.element.android.features.roomcall.api.RoomCallStateProvider import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toDp +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun TimelineItemCallNotifyView( event: TimelineItem.Event, - roomCallState: RoomCallState, onLongClick: (TimelineItem.Event) -> Unit, - onJoinCallClick: (isAudioCall: Boolean) -> Unit, modifier: Modifier = Modifier ) { + val intent = (event.content as? TimelineItemRtcNotificationContent)?.callIntent Row( modifier = modifier .fillMaxWidth() @@ -81,7 +79,8 @@ internal fun TimelineItemCallNotifyView( ) { Icon( modifier = Modifier.size(20.sp.toDp()), - imageVector = CompoundIcons.VideoCallSolid(), + imageVector = + if (intent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), contentDescription = null, tint = ElementTheme.colors.iconSecondary, ) @@ -94,20 +93,13 @@ internal fun TimelineItemCallNotifyView( ) } } - if (roomCallState is RoomCallState.OnGoing) { - CallMenuItem( - roomCallState = roomCallState, - onJoinCallClick = onJoinCallClick, - ) - } else { - Text( - text = event.sentTime, - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } + Text( + text = event.sentTime, + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) } } @@ -115,16 +107,15 @@ internal fun TimelineItemCallNotifyView( @Composable internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { - RoomCallStateProvider() - .values - .filter { it !is RoomCallState.Unavailable } - .forEach { roomCallState -> - TimelineItemCallNotifyView( - event = aTimelineItemEvent(content = TimelineItemRtcNotificationContent()), - roomCallState = roomCallState, - onLongClick = {}, - onJoinCallClick = {}, - ) - } + listOf( + aTimelineItemEvent(content = TimelineItemRtcNotificationContent(null)), + aTimelineItemEvent(content = TimelineItemRtcNotificationContent(CallIntent.AUDIO)), + aTimelineItemEvent(content = TimelineItemRtcNotificationContent(CallIntent.VIDEO)), + ).forEach { event -> + TimelineItemCallNotifyView( + event = event, + onLongClick = {}, + ) + } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt index 505d76b24b..8316911843 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt @@ -188,7 +188,6 @@ private fun TimelineItemGroupedEventsRowContent( onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, onSwipeToReply = {}, - onJoinCallClick = {}, eventSink = eventSink, eventContentView = eventContentView, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 469afe494e..28b05c29fb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -72,7 +72,6 @@ internal fun TimelineItemRow( onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, onSwipeToReply: (TimelineItem.Event) -> Unit, - onJoinCallClick: (isAudioCall: Boolean) -> Unit, eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = @@ -127,9 +126,7 @@ internal fun TimelineItemRow( TimelineItemCallNotifyView( modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp), event = timelineItem, - roomCallState = timelineRoomInfo.roomCallState, onLongClick = onLongClick, - onJoinCallClick = onJoinCallClick, ) } else -> { 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..d228a45371 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 @@ -97,7 +97,9 @@ class TimelineItemContentFactory( is StickerContent -> stickerFactory.create(itemContent) is PollContent -> pollFactory.create(eventId, isEditable, isOutgoing, itemContent) is UnableToDecryptContent -> utdFactory.create(itemContent) - is CallNotifyContent -> TimelineItemRtcNotificationContent() + is CallNotifyContent -> TimelineItemRtcNotificationContent( + itemContent.callIntent + ) is UnknownContent -> TimelineItemUnknownContent is LiveLocationContent -> { val lastKnownLocation = itemContent.locations.mapNotNull { beacon -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt index 6f369417dd..837692ae6f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt @@ -90,7 +90,7 @@ internal fun MatrixTimelineItem.Event.canBeDisplayedInBubbleBlock(): Boolean { is RoomMembershipContent, UnknownContent, is LegacyCallInviteContent, - CallNotifyContent, + is CallNotifyContent, is StateContent -> false } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index 00ad32ba5f..168d11af16 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -8,6 +8,8 @@ package io.element.android.features.messages.impl.timeline.model.event -class TimelineItemRtcNotificationContent : TimelineItemEventContent { +import io.element.android.libraries.matrix.api.notification.CallIntent + +class TimelineItemRtcNotificationContent(val callIntent: CallIntent?) : TimelineItemEventContent { override val type: String = "org.matrix.msc4075.rtc.notification" } 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 95d4327c07..12fb0b5f81 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 @@ -12,6 +12,7 @@ import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.poll.PollAnswer import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.location.AssetType @@ -115,6 +116,8 @@ data class LiveLocationContent( data object LegacyCallInviteContent : EventContent -data object CallNotifyContent : EventContent +data class CallNotifyContent( + val callIntent: CallIntent? +) : EventContent data object UnknownContent : 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 d617df60db..d9e47b00c7 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 @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.impl.timeline.item.event import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.timeline.item.EmbeddedEventInfo import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary @@ -137,7 +138,15 @@ class TimelineEventContentMapper( ) } is TimelineItemContent.CallInvite -> LegacyCallInviteContent - is TimelineItemContent.RtcNotification -> CallNotifyContent + is TimelineItemContent.RtcNotification -> CallNotifyContent( + it.callIntent?.let { intentString -> + if (intentString == "audio") { + CallIntent.AUDIO + } else { + CallIntent.VIDEO + } + } + ) } } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt index 67b73d616d..379c70f960 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt @@ -65,7 +65,7 @@ class EventItemFactory( mode = DateFormatterMode.Full, ) return when (val content = event.content) { - CallNotifyContent, + is CallNotifyContent, is FailedToParseMessageLikeContent, is FailedToParseStateContent, LegacyCallInviteContent, From 228f188b5ab36c5e60d60a6b8a30ef4ff0ec02ed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Apr 2026 16:39:44 +0200 Subject: [PATCH 0162/1083] Setting version for the release 26.04.3 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index f46abc71bf..93e92b81ce 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 4 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 2 +private const val versionReleaseNumber = 3 object Versions { /** From d7118bfad8bb846bae67b904da28c85efa346cf6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Apr 2026 16:40:04 +0200 Subject: [PATCH 0163/1083] Adding fastlane file for version 26.04.3 --- fastlane/metadata/android/en-US/changelogs/202604030.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202604030.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202604030.txt b/fastlane/metadata/android/en-US/changelogs/202604030.txt new file mode 100644 index 0000000000..a4b397f1bb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202604030.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 2966ccc96d4fc5660abaa07c128ee568b08cda4d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 16 Apr 2026 15:25:42 +0000 Subject: [PATCH 0164/1083] Update screenshots --- ...imeline.components_TimelineItemCallNotifyView_Day_0_en.png | 4 ++-- ...eline.components_TimelineItemCallNotifyView_Night_0_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png index 2a713b1b39..3ded87a38d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:155ad78cfadaab78089293eca38ab8c404f227e38c451dddbbe3c59cccb82bc5 -size 51391 +oid sha256:53068e2713cc73cf8492f960ff36aad79ae2a964d08e72ae35815b6614c7b061 +size 23873 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png index 77fd3bfa80..24e62daad5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b54d16054565d3ba0280ff704c350227a03db0fad93750ad6d41f6e67f605f3 -size 51582 +oid sha256:fb140f4fb625affba7ca229b2e596476b37c5787431215b3f9ecc5c93001b328 +size 23789 From 2e4c9954b77ffd4be2a212626afe407c9066bd41 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Apr 2026 17:34:48 +0200 Subject: [PATCH 0165/1083] Changelog for version 26.04.3 --- CHANGES.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a3d7870288..68848d491f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,62 @@ +Changes in Element X v26.04.3 +============================= + + + +## What's Changed +### ✨ Features +* Sign in with element classic final by @bmarty in https://github.com/element-hq/element-x-android/pull/6296 +* Take into account homeserver capabilities by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6507 +### 🙌 Improvements +* feat: Default to camera muted when joining ongoing voice call by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6574 +### 🐛 Bugfixes +* Fix crash in FetchPushForegroundService: No super method onTimeout by @bmarty in https://github.com/element-hq/element-x-android/pull/6547 +* Ensure mark as fully read is called only once when leaving the timeline by @bmarty in https://github.com/element-hq/element-x-android/pull/6550 +* Fix `isInAirGappedEnvironment` check for older APIs by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6573 +* Fix loading initial items of non-live timelines by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6598 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6537 +* Sync Strings - new translations in Japanese and Vietnamese by @ElementBot in https://github.com/element-hq/element-x-android/pull/6568 +### 🧱 Build +* Fix module dependencies by @bmarty in https://github.com/element-hq/element-x-android/pull/6559 +### 🚧 In development 🚧 +* Add confirmation dialog when inviting users with unknown identities by @kaylendog in https://github.com/element-hq/element-x-android/pull/6523 +* Feature: add room threads list by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6575 +### Dependency upgrades +* fix(deps): update media3 to v1.10.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6529 +* fix(deps): update dependency io.github.sergio-sastre.composablepreviewscanner:android to v0.8.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6525 +* fix(deps): update metro to v0.12.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6543 +* fix(deps): update kotlinpoet to v2.3.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6528 +* Sync compound tokens https://github.com/element-hq/compound-design-tokens/releases/tag/v10.0.0 by @bmarty in https://github.com/element-hq/element-x-android/pull/6517 +* fix(deps): update dependency io.sentry:sentry-android to v8.37.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6508 +* fix(deps): update dependency org.maplibre.gl:android-sdk to v13.0.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6546 +* Update codecov/codecov-action action to v6 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6521 +* Update telephoto to v0.19.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6558 +* Update dependency net.zetetic:sqlcipher-android to v4.14.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6552 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.04.8 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6553 +* Update gradle/actions action to v6.1.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6562 +* Update metro to v0.13.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6565 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.04.13 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6570 +* Update wysiwyg to v2.41.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6572 +* Update dependency com.google.testparameterinjector:test-parameter-injector to v1.22 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6576 +* Use `Coil3` for `ZoomableAsyncImage` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6582 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.04.15 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6595 +* Update nschloe/action-cached-lfs-checkout action to v1.2.5 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6600 +### Others +* Fix portrait image metadata when uploading without media optimization by @kalix127 in https://github.com/element-hq/element-x-android/pull/6362 +* Fix Threads not tappable in pinned messages list by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6535 +* Reduce log level of activity lifecycle from warning to debug. by @bmarty in https://github.com/element-hq/element-x-android/pull/6548 +* Remove spaces features flags by @bmarty in https://github.com/element-hq/element-x-android/pull/6560 +* Remove space announcement by @bmarty in https://github.com/element-hq/element-x-android/pull/6561 +* Update metro to v0.13.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6571 +* Take into account the value of FeatureFlags.SignInWithClassic by @bmarty in https://github.com/element-hq/element-x-android/pull/6586 +* Add extra logs for timeline pagination by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6589 +* Scrollable media caption - tweaks by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6583 +* Split developer settings into 2 screens to be able to access global settings when no logged in. by @bmarty in https://github.com/element-hq/element-x-android/pull/6587 + + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.04.2...v26.04.3 + Changes in Element X v26.04.2 ============================= 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 0166/1083] 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 5b3f91ff7877ce46a275c2963296a0a7d04dc4be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:01:20 +0200 Subject: [PATCH 0167/1083] Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.11.0 (#6605) 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 63428fd6f4..427bbd1042 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ roborazzi = "1.59.0" # Jetbrain datetime = "0.7.1" -serialization_json = "1.10.0" +serialization_json = "1.11.0" #other coil = "3.4.0" From f661ccf25ae6667fa0cec56d5bff1a57613e6293 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:43:32 +0200 Subject: [PATCH 0168/1083] Update dependency com.google.firebase:firebase-bom to v34.12.0 (#6604) 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 427bbd1042..07442e3c62 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -80,7 +80,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:34.11.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.12.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } From a1c9994385797a71c0007e33b6adc6ac92ac91a4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Apr 2026 12:39:08 +0200 Subject: [PATCH 0169/1083] 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 0170/1083] 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 6d134375f6a81f52a6db8f5797207ec23efbd55a Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 17 Apr 2026 10:07:22 +0200 Subject: [PATCH 0171/1083] review: pass the RtcNotificationContent in the view to avoid casting --- .../components/TimelineItemCallNotifyView.kt | 17 +++++++++-------- .../impl/timeline/components/TimelineItemRow.kt | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index bf55503665..063a84dbeb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -43,10 +43,10 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun TimelineItemCallNotifyView( event: TimelineItem.Event, + content: TimelineItemRtcNotificationContent, onLongClick: (TimelineItem.Event) -> Unit, modifier: Modifier = Modifier ) { - val intent = (event.content as? TimelineItemRtcNotificationContent)?.callIntent Row( modifier = modifier .fillMaxWidth() @@ -54,7 +54,7 @@ internal fun TimelineItemCallNotifyView( .combinedClickable( enabled = true, onClick = {}, - onLongClick = { onLongClick(event) }, + onLongClick = { onLongClick() }, onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), ) .onKeyboardContextMenuAction { onLongClick(event) } @@ -80,7 +80,7 @@ internal fun TimelineItemCallNotifyView( Icon( modifier = Modifier.size(20.sp.toDp()), imageVector = - if (intent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), + if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), contentDescription = null, tint = ElementTheme.colors.iconSecondary, ) @@ -108,12 +108,13 @@ internal fun TimelineItemCallNotifyView( internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { listOf( - aTimelineItemEvent(content = TimelineItemRtcNotificationContent(null)), - aTimelineItemEvent(content = TimelineItemRtcNotificationContent(CallIntent.AUDIO)), - aTimelineItemEvent(content = TimelineItemRtcNotificationContent(CallIntent.VIDEO)), - ).forEach { event -> + TimelineItemRtcNotificationContent(null), + TimelineItemRtcNotificationContent(CallIntent.AUDIO), + TimelineItemRtcNotificationContent(CallIntent.VIDEO), + ).forEach { content -> TimelineItemCallNotifyView( - event = event, + event = aTimelineItemEvent(content = content), + content = content, onLongClick = {}, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 28b05c29fb..e75df2f89f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -126,6 +126,7 @@ internal fun TimelineItemRow( TimelineItemCallNotifyView( modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp), event = timelineItem, + content = timelineItem.content, onLongClick = onLongClick, ) } 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 0172/1083] 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 d7963ddb5a1b9aaa87037e216a345207706cce75 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 17 Apr 2026 12:52:25 +0200 Subject: [PATCH 0173/1083] fixup: missing param --- .../impl/timeline/components/TimelineItemCallNotifyView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index 063a84dbeb..0ba3c9b7d9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -54,7 +54,7 @@ internal fun TimelineItemCallNotifyView( .combinedClickable( enabled = true, onClick = {}, - onLongClick = { onLongClick() }, + onLongClick = { onLongClick(event) }, onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), ) .onKeyboardContextMenuAction { onLongClick(event) } From a341a1a59e42321aeb126228bc32f83d8cd7346a Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 17 Apr 2026 14:48:50 +0200 Subject: [PATCH 0174/1083] 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 0175/1083] 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 0176/1083] 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 0177/1083] 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 0178/1083] 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 09e57e077a8d195ecbf850c4a3f66bceb01d3efd Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 17 Apr 2026 11:52:07 +0200 Subject: [PATCH 0179/1083] audio: Let EC decide alone what communication device to use --- .../call/impl/utils/WebViewAudioManager.kt | 78 ++++--------------- 1 file changed, 13 insertions(+), 65 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index 0c1ecf83cb..80cc9b535a 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -113,23 +113,7 @@ class WebViewAudioManager( @get:RequiresApi(Build.VERSION_CODES.S) private val commsDeviceChangedListener by lazy { AudioManager.OnCommunicationDeviceChangedListener { device -> - if (device != null && device.id == expectedNewCommunicationDeviceId) { - expectedNewCommunicationDeviceId = null - Timber.d("Audio device changed, type: ${device.type}") - updateSelectedAudioDeviceInWebView(device.id.toString()) - } else if (device != null && device.id != expectedNewCommunicationDeviceId) { - // We were expecting a device change but it didn't happen, so we should retry - val expectedDeviceId = expectedNewCommunicationDeviceId - if (expectedDeviceId != null) { - // Remove the expected id so we only retry once - expectedNewCommunicationDeviceId = null - audioManager.selectAudioDevice(expectedDeviceId.toString()) - } - } else { - Timber.d("Audio device cleared") - expectedNewCommunicationDeviceId = null - audioManager.selectAudioDevice(null) - } + Timber.d("Audio device changed, type: ${device?.id}") } } @@ -144,39 +128,20 @@ class WebViewAudioManager( // We need to calculate the available devices ourselves, since calling `listAudioDevices` will return an outdated list val audioDevices = (listAudioDevices() + validNewDevices).distinctBy { it.id }.sortedWith(audioDeviceComparator) setAvailableAudioDevices(audioDevices.map(SerializableAudioDevice::fromAudioDeviceInfo)) - // This should automatically switch to a new device if it has a higher priority than the current one - selectDefaultAudioDevice(audioDevices) } override fun onAudioDevicesRemoved(removedDevices: Array?) { // Update the available devices + // Element Call will then decide to switch devices if needed setAvailableAudioDevices() - - // Unless the removed device is the current one, we don't need to do anything else - val removedCurrentDevice = removedDevices.orEmpty().any { it.id == currentDeviceId } - if (!removedCurrentDevice) return - - val previousDevice = previousSelectedDevice - if (previousDevice != null) { - previousSelectedDevice = null - // If we have a previous device, we should select it again - audioManager.selectAudioDevice(previousDevice.id.toString()) - } else { - // If we don't have a previous device, we should select the default one - selectDefaultAudioDevice() - } } } - - /** - * The currently used audio device id. - */ - private var currentDeviceId: Int? = null - - /** - * When a new audio device is selected but not yet set as the communication device by the OS, this id is used to check if the device is the expected one. - */ - private var expectedNewCommunicationDeviceId: Int? = null +// +// +// /** +// * When a new audio device is selected but not yet set as the communication device by the OS, this id is used to check if the device is the expected one. +// */ +// private var expectedNewCommunicationDeviceId: Int? = null /** * Previously selected device, used to restore the selection when the selected device is removed. @@ -330,23 +295,6 @@ class WebViewAudioManager( }) } - /** - * Selects the default audio device based on the sorted available devices. - * - * @param availableDevices The list of available audio devices to select from. If not provided, it will use the current list of audio devices. - */ - private fun selectDefaultAudioDevice(availableDevices: List = listAudioDevices()) { - val selectedDevice = availableDevices.firstOrNull() - expectedNewCommunicationDeviceId = selectedDevice?.id - audioManager.selectAudioDevice(selectedDevice) - - selectedDevice?.let { - updateSelectedAudioDeviceInWebView(it.id.toString()) - } ?: run { - Timber.w("Audio: unable to select default audio device") - } - } - /** * Updates the WebView's UI to reflect the selected audio device. * @@ -381,14 +329,14 @@ class WebViewAudioManager( * * @param device The info of the audio device to select, or none to clear the selected device. */ - @Suppress("DEPRECATION") private fun AudioManager.selectAudioDevice(device: AudioDeviceInfo?) { - currentDeviceId = device?.id if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (device != null) { runCatchingExceptions { Timber.d("Setting communication device: ${device.id} - ${deviceName(device.type, device.productName.toString())}") - setCommunicationDevice(device) + if (!setCommunicationDevice(device)) { + Timber.w("Failed to setCommunication device") + } }.onFailure { Timber.e(it, "Could not set communication device.") } @@ -410,16 +358,16 @@ class WebViewAudioManager( return } setAudioEnabled(true) + @Suppress("DEPRECATION") isSpeakerphoneOn = device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER isBluetoothScoOn = device.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO } else { + @Suppress("DEPRECATION") isSpeakerphoneOn = false isBluetoothScoOn = false } } - expectedNewCommunicationDeviceId = null - coroutineScope.launch { proximitySensorMutex.withLock { @Suppress("WakeLock", "WakeLockTimeout") From 58bde16b81faeb0e1e75699c0b59d1fd98d3a50f Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 17 Apr 2026 18:00:25 +0200 Subject: [PATCH 0180/1083] enforce selecting the EC preferred device --- .../call/impl/utils/WebViewAudioManager.kt | 29 ++++++++----------- .../libraries/audio/impl/DefaultAudioFocus.kt | 3 ++ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index 80cc9b535a..c6e8557ff9 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -64,6 +64,11 @@ class WebViewAudioManager( */ private val isWebViewAudioEnabled = AtomicBoolean(true) + /** + * Store the device id requested by EC, and re-set it if something try to switch (only android S+). + */ + private var ecRequestedDeviceId: String? = null + /** * The list of device types that are considered as communication devices, sorted by likelihood of it being used for communication. */ @@ -114,6 +119,12 @@ class WebViewAudioManager( private val commsDeviceChangedListener by lazy { AudioManager.OnCommunicationDeviceChangedListener { device -> Timber.d("Audio device changed, type: ${device?.id}") + val wantedDevice = this.ecRequestedDeviceId + if (wantedDevice != null && this.ecRequestedDeviceId != device?.id?.toString()) { + // We want to ensure that we stick to what EC selected even if it was changed outside + Timber.d("Audio device changed to unwanted device ${device?.id}, enforce using the expected device $wantedDevice") + audioManager.selectAudioDevice(wantedDevice) + } } } @@ -136,12 +147,6 @@ class WebViewAudioManager( setAvailableAudioDevices() } } -// -// -// /** -// * When a new audio device is selected but not yet set as the communication device by the OS, this id is used to check if the device is the expected one. -// */ -// private var expectedNewCommunicationDeviceId: Int? = null /** * Previously selected device, used to restore the selection when the selected device is removed. @@ -228,6 +233,7 @@ class WebViewAudioManager( val webViewAudioDeviceSelectedCallback = AndroidWebViewAudioBridge( onAudioDeviceSelected = { selectedDeviceId -> previousSelectedDevice = listAudioDevices().find { it.id.toString() == selectedDeviceId } + this.ecRequestedDeviceId = selectedDeviceId audioManager.selectAudioDevice(selectedDeviceId) }, onAudioPlaybackStarted = { @@ -295,17 +301,6 @@ class WebViewAudioManager( }) } - /** - * Updates the WebView's UI to reflect the selected audio device. - * - * @param deviceId The id of the selected audio device. - */ - private fun updateSelectedAudioDeviceInWebView(deviceId: String) { - coroutineScope.launch(Dispatchers.Main) { - webView.evaluateJavascript("controls.setOutputDevice('$deviceId');", null) - } - } - /** * Selects the audio device on the OS based on the provided device id. * diff --git a/libraries/audio/impl/src/main/kotlin/io/element/android/libraries/audio/impl/DefaultAudioFocus.kt b/libraries/audio/impl/src/main/kotlin/io/element/android/libraries/audio/impl/DefaultAudioFocus.kt index faab73593e..bc6a42d2f9 100644 --- a/libraries/audio/impl/src/main/kotlin/io/element/android/libraries/audio/impl/DefaultAudioFocus.kt +++ b/libraries/audio/impl/src/main/kotlin/io/element/android/libraries/audio/impl/DefaultAudioFocus.kt @@ -19,6 +19,7 @@ import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.audio.api.AudioFocus import io.element.android.libraries.audio.api.AudioFocusRequester import io.element.android.libraries.di.annotations.ApplicationContext +import timber.log.Timber @ContributesBinding(AppScope::class) class DefaultAudioFocus( @@ -38,9 +39,11 @@ class DefaultAudioFocus( when (it) { AudioManager.AUDIOFOCUS_GAIN -> { // Do nothing + Timber.d("AudioFocus: AUDIOFOCUS_GAIN") } AudioManager.AUDIOFOCUS_LOSS -> { // Permanent focus loss (e.g., phone call) — always stop/pause. + Timber.d("AudioFocus: AUDIOFOCUS_LOSS") onFocusLost() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT, From 18d4924171e0f1a62b89abcb8fe8184dacbe3930 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 20 Apr 2026 11:24:38 +0200 Subject: [PATCH 0181/1083] fix: proximity sensor was wrongly disabled --- .../features/call/impl/utils/WebViewAudioManager.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index c6e8557ff9..2d674d21af 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -366,9 +366,11 @@ class WebViewAudioManager( coroutineScope.launch { proximitySensorMutex.withLock { @Suppress("WakeLock", "WakeLockTimeout") - if (device?.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && proximitySensorWakeLock?.isHeld == false) { - // If the device is the built-in earpiece, we need to acquire the proximity sensor wake lock - proximitySensorWakeLock?.acquire() + if (device?.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE) { + if (proximitySensorWakeLock?.isHeld == false) { + // If the device is the built-in earpiece, we need to acquire the proximity sensor wake lock + proximitySensorWakeLock?.acquire() + } } else if (proximitySensorWakeLock?.isHeld == true) { // If the device is no longer the earpiece, we need to release the wake lock proximitySensorWakeLock?.release() 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 0182/1083] 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 0183/1083] 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 0184/1083] 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 0185/1083] 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 0186/1083] 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 0187/1083] 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 0188/1083] 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" From b0e9073efbdcb1f1965a9397cb6d0ff9405d7a0b Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 10:49:08 +0200 Subject: [PATCH 0189/1083] fix test compilation --- .../messages/impl/actionlist/ActionListPresenterTest.kt | 3 ++- .../features/messages/impl/timeline/TimelineViewTest.kt | 2 -- .../mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index 7a99ad39aa..8c7f290441 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -28,6 +28,7 @@ import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState @@ -1168,7 +1169,7 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, - content = TimelineItemRtcNotificationContent(), + content = TimelineItemRtcNotificationContent(callIntent = CallIntent.VIDEO), ) initialState.eventSink.invoke( ActionListEvent.ComputeForMessage( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt index c05625e2d3..3a0b0e1224 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt @@ -219,7 +219,6 @@ private fun AndroidComposeTestRule.setTimel onReactionLongClick: (emoji: String, TimelineItem.Event) -> Unit = EnsureNeverCalledWithTwoParams(), onMoreReactionsClick: (TimelineItem.Event) -> Unit = EnsureNeverCalledWithParam(), onReadReceiptClick: (TimelineItem.Event) -> Unit = EnsureNeverCalledWithParam(), - onJoinCallClick: (Boolean) -> Unit = EnsureNeverCalledWithParam(), forceJumpToBottomVisibility: Boolean = false, ) { setSafeContent(clearAndroidUiDispatcher = true) { @@ -235,7 +234,6 @@ private fun AndroidComposeTestRule.setTimel onReactionLongClick = onReactionLongClick, onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, - onJoinCallClick = onJoinCallClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, ) } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt index 6c88f1c33f..6602f475eb 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.matrix.api.media.FileInfo import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.VideoInfo +import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent @@ -61,7 +62,7 @@ class DefaultEventItemFactoryTest { fun `create check all null cases`() { val factory = createEventItemFactory() val contents = listOf( - CallNotifyContent, + CallNotifyContent(callIntent = CallIntent.VIDEO), FailedToParseMessageLikeContent("", ""), FailedToParseStateContent("", "", ""), LegacyCallInviteContent, From e158be86aa14c487ec3204bf58c613d859395537 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 11:03:48 +0200 Subject: [PATCH 0190/1083] review: Make call intent not optional in content --- .../components/TimelineItemCallNotifyView.kt | 1 - .../event/TimelineItemRtcNotificationContent.kt | 2 +- .../matrix/api/timeline/item/event/EventContent.kt | 2 +- .../item/event/TimelineEventContentMapper.kt | 12 +++++------- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index 0ba3c9b7d9..dfd1b2ed0e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -108,7 +108,6 @@ internal fun TimelineItemCallNotifyView( internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { listOf( - TimelineItemRtcNotificationContent(null), TimelineItemRtcNotificationContent(CallIntent.AUDIO), TimelineItemRtcNotificationContent(CallIntent.VIDEO), ).forEach { content -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index 168d11af16..53facfc675 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -10,6 +10,6 @@ package io.element.android.features.messages.impl.timeline.model.event import io.element.android.libraries.matrix.api.notification.CallIntent -class TimelineItemRtcNotificationContent(val callIntent: CallIntent?) : TimelineItemEventContent { +class TimelineItemRtcNotificationContent(val callIntent: CallIntent) : TimelineItemEventContent { override val type: String = "org.matrix.msc4075.rtc.notification" } 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 12fb0b5f81..9cecb57800 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 @@ -117,7 +117,7 @@ data class LiveLocationContent( data object LegacyCallInviteContent : EventContent data class CallNotifyContent( - val callIntent: CallIntent? + val callIntent: CallIntent ) : EventContent data object UnknownContent : 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 d9e47b00c7..11514d73c6 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 @@ -110,7 +110,7 @@ class TimelineEventContentMapper( } is MsgLikeKind.LiveLocation -> { // Live location messages are a special kind of message that we want to treat as unknown content for now - UnknownContent + UnknownContent } is MsgLikeKind.Other -> UnknownContent } @@ -139,12 +139,10 @@ class TimelineEventContentMapper( } is TimelineItemContent.CallInvite -> LegacyCallInviteContent is TimelineItemContent.RtcNotification -> CallNotifyContent( - it.callIntent?.let { intentString -> - if (intentString == "audio") { - CallIntent.AUDIO - } else { - CallIntent.VIDEO - } + callIntent = if (it.callIntent == "audio") { + CallIntent.AUDIO + } else { + CallIntent.VIDEO } ) } From 8eb5a556736ce6245176b9df0ce4cb94a420d902 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 11:22:43 +0200 Subject: [PATCH 0191/1083] Introduce `simplePluralStringResource` methods, as Composable and in `StringProvider`. --- features/invitepeople/impl/build.gradle.kts | 1 + .../invitepeople/impl/InvitePeopleView.kt | 21 ++++++----- .../impl/previews/PreviewStringProvider.kt | 5 +++ .../libraries/ui/utils/strings/Plurals.kt | 37 +++++++++++++++++++ .../toolbox/api/strings/StringProvider.kt | 25 +++++++++++++ .../impl/strings/AndroidStringProvider.kt | 10 +++++ .../test/strings/FakeStringProvider.kt | 10 +++++ .../InstrumentationStringProvider.kt | 5 +++ 8 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/strings/Plurals.kt diff --git a/features/invitepeople/impl/build.gradle.kts b/features/invitepeople/impl/build.gradle.kts index 390ccce7b9..185497c25b 100644 --- a/features/invitepeople/impl/build.gradle.kts +++ b/features/invitepeople/impl/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) + implementation(projects.libraries.uiUtils) implementation(projects.libraries.androidutils) implementation(projects.libraries.usersearch.api) implementation(libs.coil.compose) 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 e8ce5222eb..289ac193d4 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 @@ -55,6 +55,7 @@ import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getBestName import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.ui.utils.strings.simplePluralStringResource import kotlinx.collections.immutable.ImmutableList @Composable @@ -263,16 +264,16 @@ private fun InvitePeopleConfirmModal( dragHandle = null, ) { IconTitleSubtitleMolecule( - 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) - }, + title = simplePluralStringResource( + resIdForOne = R.string.screen_invite_users_confirm_dialog_title_one_user, + resIdForOthers = R.string.screen_invite_users_confirm_dialog_title_mutiple_users, + count = users.size, + ), + subTitle = simplePluralStringResource( + resIdForOne = R.string.screen_invite_users_confirm_dialog_subtitle_one_user, + resIdForOthers = R.string.screen_invite_users_confirm_dialog_subtitle_multiple_users, + count = users.size, + ), iconStyle = BigIcon.Style.Default(CompoundIcons.UserAddSolid()), modifier = Modifier.padding( top = 32.dp, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewStringProvider.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewStringProvider.kt index 3cd004f8a8..07e55410d1 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewStringProvider.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewStringProvider.kt @@ -27,4 +27,9 @@ class PreviewStringProvider( override fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String { return resources.getQuantityString(resId, quantity, *formatArgs) } + + override fun getSimpleQuantityString(resIdForOne: Int, resIdForOthers: Int, quantity: Int, vararg formatArgs: Any?): String { + val resId = if (quantity == 1) resIdForOne else resIdForOthers + return resources.getString(resId, *formatArgs) + } } diff --git a/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/strings/Plurals.kt b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/strings/Plurals.kt new file mode 100644 index 0000000000..fe927e725d --- /dev/null +++ b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/strings/Plurals.kt @@ -0,0 +1,37 @@ +/* + * 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.ui.utils.strings + +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.ui.res.stringResource + +/** + * Similar to [androidx.compose.ui.res.pluralStringResource] but with separate resource ids for singular and plural values. + * Useful when we want to use different strings for singular and plural forms but not mentioning the actual quantity in the string. + * In this case, we cannot use getQuantityString, because some locales have more than two plural forms, and require the quantity to + * be part of the resulting strings. + * @param resIdForOne Resource id for the case when [count] is 1. + * @param resIdForOthers Resource id for the other cases ([count] is not 1). + * @param count The quantity to determine whether to use singular or plural form. Must be greater than or equal to 1. + * @param formatArgs The format arguments that will be used for substitution in the resulting string. Will be applied to either + * the singular or plural string depending on the quantity. + * @return The localized string corresponding to the given quantity. + */ +@Composable +@ReadOnlyComposable +fun simplePluralStringResource( + @StringRes resIdForOne: Int, + @StringRes resIdForOthers: Int, + count: Int, + vararg formatArgs: Any, +): String { + val resId = if (count == 1) resIdForOne else resIdForOthers + return stringResource(resId, *formatArgs) +} diff --git a/services/toolbox/api/src/main/kotlin/io/element/android/services/toolbox/api/strings/StringProvider.kt b/services/toolbox/api/src/main/kotlin/io/element/android/services/toolbox/api/strings/StringProvider.kt index 9a8ff23eb5..4570e09921 100644 --- a/services/toolbox/api/src/main/kotlin/io/element/android/services/toolbox/api/strings/StringProvider.kt +++ b/services/toolbox/api/src/main/kotlin/io/element/android/services/toolbox/api/strings/StringProvider.kt @@ -34,5 +34,30 @@ interface StringProvider { * stripped of styled text information. */ fun getString(@StringRes resId: Int, vararg formatArgs: Any?): String + + /** + * Returns a localized formatted string from the application's package's + * default string table, substituting the format arguments as defined in + * [java.util.Formatter] and [java.lang.String.format], based on the given quantity. + */ fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String + + /** + * Similar to [getQuantityString] but with separate resource ids for singular and plural values. + * Useful when we want to use different strings for singular and plural forms but not mentioning the actual quantity in the string. + * In this case, we cannot use getQuantityString, because some locales have more than two plural forms, and require the quantity to + * be part of the resulting strings. + * @param resIdForOne Resource id for the case when [quantity] is 1. + * @param resIdForOthers Resource id for the other cases ([quantity] is not 1). + * @param quantity The quantity to determine whether to use singular or plural form. Must be greater than or equal to 1. + * @param formatArgs The format arguments that will be used for substitution in the resulting string. Will be applied to either + * the singular or plural string depending on the quantity. + * @return The localized string corresponding to the given quantity. + */ + fun getSimpleQuantityString( + @StringRes resIdForOne: Int, + @StringRes resIdForOthers: Int, + quantity: Int, + vararg formatArgs: Any?, + ): String } diff --git a/services/toolbox/impl/src/main/kotlin/io/element/android/services/toolbox/impl/strings/AndroidStringProvider.kt b/services/toolbox/impl/src/main/kotlin/io/element/android/services/toolbox/impl/strings/AndroidStringProvider.kt index b095348c41..b0e14c1db9 100644 --- a/services/toolbox/impl/src/main/kotlin/io/element/android/services/toolbox/impl/strings/AndroidStringProvider.kt +++ b/services/toolbox/impl/src/main/kotlin/io/element/android/services/toolbox/impl/strings/AndroidStringProvider.kt @@ -28,4 +28,14 @@ class AndroidStringProvider(private val resources: Resources) : StringProvider { override fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String { return resources.getQuantityString(resId, quantity, *formatArgs) } + + override fun getSimpleQuantityString( + resIdForOne: Int, + resIdForOthers: Int, + quantity: Int, + vararg formatArgs: Any?, + ): String { + val resId = if (quantity == 1) resIdForOne else resIdForOthers + return resources.getString(resId, *formatArgs) + } } diff --git a/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/strings/FakeStringProvider.kt b/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/strings/FakeStringProvider.kt index c2867dca3b..0412a8a03a 100644 --- a/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/strings/FakeStringProvider.kt +++ b/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/strings/FakeStringProvider.kt @@ -28,4 +28,14 @@ class FakeStringProvider( lastResIdParam = resId return defaultResult + " ($quantity) " + formatArgs.joinToString() } + + override fun getSimpleQuantityString( + resIdForOne: Int, + resIdForOthers: Int, + quantity: Int, + vararg formatArgs: Any?, + ): String { + lastResIdParam = if (quantity == 1) resIdForOne else resIdForOthers + return defaultResult + " ($quantity) " + formatArgs.joinToString() + } } diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/InstrumentationStringProvider.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/InstrumentationStringProvider.kt index 75d91c4a88..93df350c44 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/InstrumentationStringProvider.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/InstrumentationStringProvider.kt @@ -24,4 +24,9 @@ class InstrumentationStringProvider : StringProvider { override fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any?): String { return resource.getQuantityString(resId, quantity, *formatArgs) } + + override fun getSimpleQuantityString(resIdForOne: Int, resIdForOthers: Int, quantity: Int, vararg formatArgs: Any?): String { + val resId = if (quantity == 1) resIdForOne else resIdForOthers + return resource.getString(resId, *formatArgs) + } } From 3c06e0a260bca34a8ab25e045ade58db8e31f870 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 21 Apr 2026 09:26:51 +0000 Subject: [PATCH 0192/1083] Update screenshots --- ...imeline.components_TimelineItemCallNotifyView_Day_0_en.png | 4 ++-- ...eline.components_TimelineItemCallNotifyView_Night_0_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png index 3ded87a38d..afec980e10 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53068e2713cc73cf8492f960ff36aad79ae2a964d08e72ae35815b6614c7b061 -size 23873 +oid sha256:3624fe8448ae4af2481e2023a978ffab2d69f2784b7cef41e5ae2e2dbe8fdbd5 +size 17804 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png index 24e62daad5..8f7f14e64a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb140f4fb625affba7ca229b2e596476b37c5787431215b3f9ecc5c93001b328 -size 23789 +oid sha256:6bd02d39619efbcaa6d96f1e75a0d14a572c43e60bad0c3f84d6a5a48b6fbda1 +size 17395 From 168782e04998800f968ea18835b8096408b6f892 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 11:35:26 +0200 Subject: [PATCH 0193/1083] Update deactivate account wording. Closes #6608 --- features/deactivation/impl/src/main/res/values/localazy.xml | 6 +++--- features/login/impl/src/main/res/values/localazy.xml | 2 +- libraries/ui-strings/src/main/res/values/localazy.xml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/features/deactivation/impl/src/main/res/values/localazy.xml b/features/deactivation/impl/src/main/res/values/localazy.xml index 0380cf1c94..fc12c7d2f8 100644 --- a/features/deactivation/impl/src/main/res/values/localazy.xml +++ b/features/deactivation/impl/src/main/res/values/localazy.xml @@ -1,14 +1,14 @@ - "Please confirm that you want to deactivate your account. This action cannot be undone." + "Please confirm that you want to delete your account. This action cannot be undone." "Delete all my messages" "Warning: Future users may see incomplete conversations." - "Deactivating your account is %1$s, it will:" + "Deleting your account is %1$s, it will:" "irreversible" "%1$s your account (you can\'t log back in, and your ID can\'t be reused)." "Permanently disable" "Remove you from all chat rooms." "Delete your account information from our identity server." "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them." - "Deactivate account" + "Delete account" diff --git a/features/login/impl/src/main/res/values/localazy.xml b/features/login/impl/src/main/res/values/localazy.xml index dce4f1a77b..f8d5ffa651 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -28,7 +28,7 @@ "What is the address of your server?" "Select your server" "Create account" - "This account has been deactivated." + "This account has been deleted." "Incorrect username and/or password" "This is not a valid user identifier. Expected format: ‘@user:homeserver.org’" "This server is configured to use refresh tokens. These aren\'t supported when using password based login." diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ff865de038..2982c78ca9 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -84,8 +84,8 @@ "Create" "Create room" "Create space" - "Deactivate" - "Deactivate account" + "Delete" + "Delete account" "Decline" "Decline and block" "Delete Poll" From c343df8351135257867a5e49ecbe1e4bb0bc6f33 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 21 Apr 2026 09:50:46 +0000 Subject: [PATCH 0194/1083] Update screenshots --- .../features.logout.impl_AccountDeactivationView_Day_0_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_1_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_2_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_3_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_4_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_0_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_1_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_2_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_3_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_4_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_1_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_4_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_1_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_4_en.png | 4 ++-- 14 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png index 05df1938e8..e35ea91583 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e186c2798642148ef8e1f02a23600a594378ca094f6e11adc46c74ef421e8a8b -size 77187 +oid sha256:891555a0886151040ebc4b9e3e4d25c3b2dbcd5af000a10236e292dd2f43c09c +size 75570 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_1_en.png index b59547825f..81e769c771 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ca225207ee507d079b91b41a2335ad021eba3dc5d84744fd6c131cfd4b0951c -size 75708 +oid sha256:7ef0f01ee15b681536a4f6f29cf6a7d1c5907f9e072cf3aa9bba122848a7507a +size 74085 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png index ddcbf9d296..35e15394e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b70a67dc7317be9e3c14d05d5c83efb09bbef086e8e77ef9d8e243f8cf3e359 -size 61058 +oid sha256:3d6dfb5695cfd24ae8207d66d5fee7695c1b12e1e9310a2ce92f07447f567225 +size 57192 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_3_en.png index 05da4b6f40..2fc9e99769 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fd997ceab36234f4c66871bdf8809caaef106b2108b24718441e8af61a70e8c -size 55414 +oid sha256:2b551591af19b7ff970159df80ac752961d63fbd468217cf935ec39e6dc4f5bb +size 54146 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_4_en.png index 20d502fe90..ba112abfdc 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0a2a4ab19d5f32e5945d55d7eae9d8db198e7f5951051d35ee703e60f63b679 -size 52432 +oid sha256:cd5b298306dc0d435067bb5f9b4e49a8f9d467e108d8715250540b80aea17c08 +size 51156 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_0_en.png index 7b87a30db3..35cb8afc49 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4ce88cb56905fcdcdb511fe54edd4f0f8bb579e6de9a7bfcce5629937b192d0 -size 75027 +oid sha256:546b6f6a18dd79a8baac9907bc8c3a19727b6bbf28db3f379873a56f7c960d8a +size 73549 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_1_en.png index 1c8ac57c29..e2a186c3aa 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45b95831771832d69d8e5b8dbb1224fa66f3790f6d8beb546f57087db0600906 -size 73382 +oid sha256:19b2715dfeeee653d97a98f7b12741ae289fd7864e4ccb1fe17e9c02dc3fc826 +size 71941 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png index fd3f6b8b68..332b169553 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87154a19bb45a01d125c6bf4a1e6a9f0a35842989cdaca07387956fa372b9357 -size 57952 +oid sha256:ccaa46d8df1a2ab720a50a081cdfe159e9bb28a37c66ffd48340ac45f241a3af +size 54033 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_3_en.png index 3083916d7b..617ed1b8d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1c45208ce974f2c8bf8fdb45653b2a1e604d646d1d5f4ae302b3e8739dbfa59 -size 52893 +oid sha256:8e72138fef757a0b4877b8caf199163dc091fb2539a7aab9dadc9e1cd9e762d0 +size 51684 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_4_en.png index 29f5b5d345..145d76ae43 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83822e71afc34ccfe3c9c2aec30f480cfc01eb51e92db21216d457be00de24c0 -size 49460 +oid sha256:9fc8e670655f4981a9a01d8ea60391eb5362c130717cf1c88044d8833e6ad06c +size 48249 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 f4750d4a46..3ad13553de 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:da32161bd9a1fa8173d3f9713cab610500e5de95a369b3b57e0267db243b4705 -size 25418 +oid sha256:be4cbe72c73d76252f902e122bd62ba51ff89cf2cb20ddd61ed6615e983c65cf +size 25153 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 index 5e115162c8..e9cb1772f7 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:821a13ed4effd98ad459e3697a33d9d42500d7f1f46115a97c9b7444303a3bb2 -size 27645 +oid sha256:76caf93913c979f3327dec4331d3a5bea5027df45c5cacf55a786b8f677e3162 +size 27340 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 d90b4810bd..933a646f6b 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:2dd256cb0782cc6ebbc3e432646b2d3abe92a72886311b4010b38d389703b939 -size 26329 +oid sha256:8d3a7ae9522da2911bf256273a4972020fc1677f026fbb9f17d27f549ab03ea3 +size 25978 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 index 3346ad327d..7e4a6475b1 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6c20d715bfa287ca0fa78bab1166ff0370b5124455c87f1956e7dc3cb9b3d36 -size 28253 +oid sha256:a4f8571893bf9292a7d298c7419ea2e3f0363e1c2eca8c5f6aaea7d39143039c +size 27855 From 064c606b536d01fd7b3d17d966a2a597ba67fe79 Mon Sep 17 00:00:00 2001 From: mxandreas Date: Tue, 21 Apr 2026 11:53:01 +0100 Subject: [PATCH 0195/1083] Updates to new features and some refactoring. (#6591) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updates to new features and some refactoring. * Update CONTRIBUTING.md * Typo fixes. * Some final touches. * Update the table of contents in `CONTRIBUTING.md` --------- Co-authored-by: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Co-authored-by: Jorge Martín --- CONTRIBUTING.md | 102 ++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f0191d43e0..0126d89a9c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,16 +2,16 @@ -* [Developer onboarding](#developer-onboarding) -* [Contributing code to Matrix](#contributing-code-to-matrix) -* [Android Studio settings](#android-studio-settings) -* [Compilation](#compilation) -* [Strings](#strings) - * [I want to add new strings to the project](#i-want-to-add-new-strings-to-the-project) +* [Contributing to Element](#contributing-to-element) * [I want to help translating Element](#i-want-to-help-translating-element) + * [I want to fix a bug](#i-want-to-fix-a-bug) + * [I want to add a new feature or enhancement](#i-want-to-add-a-new-feature-or-enhancement) +* [Developer onboarding](#developer-onboarding) + * [Submitting the PRs](#submitting-the-prs) + * [Android Studio settings](#android-studio-settings) + * [Compilation](#compilation) + * [Strings](#strings) * [Element X Android Gallery](#element-x-android-gallery) -* [I want to add a new feature to Element X Android](#i-want-to-add-a-new-feature-to-element-x-android) -* [I want to submit a PR to fix an issue](#i-want-to-submit-a-pr-to-fix-an-issue) * [Kotlin](#kotlin) * [Changelog](#changelog) * [Code quality](#code-quality) @@ -29,69 +29,67 @@ -## Developer onboarding - -For a detailed overview of the project, see [Developer Onboarding](./docs/_developer_onboarding.md). - -## Contributing code to Matrix - -If instead of contributing to the Element X Android project, you want to contribute to Synapse, the homeserver implementation, please read the [Synapse contribution guide](https://element-hq.github.io/synapse/latest/development/contributing_guide.html). +## Contributing to Element Element X Android support can be found in this room: [![Element X Android Matrix room #element-x-android:matrix.org](https://img.shields.io/matrix/element-x-android:matrix.org.svg?label=%23element-x-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-x-android:matrix.org). The rest of the document contains specific rules for Matrix Android projects. -## Android Studio settings - -Please set the "hard wrap" setting of Android Studio to 160 chars, this is the setting we use internally to format the source code (Menu `Settings/Editor/Code Style` then `Hard wrap at`). -Please ensure that you're using the project formatting rules (which are in the project at .idea/codeStyles/), and format the file before committing them. - -## Compilation - -This project should compile without any special action. Just clone it and open it with Android Studio, or compile from command line using `gradlew`. - -## Strings - -The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with Element X iOS. - -### I want to add new strings to the project - -Only the core team can modify or add English strings to Localazy. As an external contributor, if you want to add new strings, feel free to add an Android resource file to the project (for instance a file named `temporary.xml`), with a note in the description of the PR for the reviewer to integrate the String into `Localazy`. If accepted, the reviewer will add the String(s) for you, and then you can download them on your branch (following these [instructions](./tools/localazy/README.md#download-translations)) and remove the temporary file. - -Please follow the naming rules for the key. More details in [the dedicated section in this README.md](./tools/localazy/README.md#key-naming-rules) - ### I want to help translating Element To help translating, please go to [https://localazy.com/p/element](https://localazy.com/p/element). -- If you want to fix an issue with an English string, please open an issue on the github project of Element X (Android or iOS). Only the core team can modify or add English strings. - If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please go to [https://localazy.com/p/element](https://localazy.com/p/element). - -More information can be found [in this README.md](./tools/localazy/README.md). +- If you want to fix an issue with an English string, please open an issue on the github project of Element X (Android or iOS). Only the core team can modify or add English strings. As an external contributor, if you want to add new strings, feel free to add an Android resource file to the project (for instance a file named `temporary.xml`), with a note in the description of the PR for the reviewer to integrate the String into `Localazy`. If accepted, the reviewer will add the String(s) for you, and then you can download them on your branch (following these [instructions](./tools/localazy/README.md#download-translations)) and remove the temporary file. Please follow the naming rules for the key. More details in [the dedicated section in this README.md](./tools/localazy/README.md#key-naming-rules) More information can be found [in this README.md](./tools/localazy/README.md). Once a language is sufficiently translated, it will be added to the app. The core team will decide when a language is sufficiently translated. +### I want to fix a bug + +Please check if a corresponding issue exists, if not please create one. In both cases, let us know in the comment that you've started working on it. + +### I want to add a new feature or enhancement + +To make a great product with a great user experience, all the small efforts need to go in the same direction and be aligned and consistent with each other. + +Before making your contribution, please consider the following: + +* One product can’t do everything well. Element is focusing on private end-to-end encrypted messaging and voice - this can either be for consumers (e.g. friends and family) or for professional teams and organizations. Public forums and other types of chats without E2EE remain supported but are not the primary use case in case UX compromises need to be made. +* There are 3 platforms - Android, [iOS](https://github.com/element-hq/element-x-ios) and [Web/Desktop](https://github.com/element-hq/element-web). These platforms need to have feature parity and design consistency. For some features, supporting all platforms is a must have, in some cases exceptions can be made to have it on one platform only. +* To make sure your idea fits both from a design/solution and use case perspective, please open a new issue (or find an existing issue) in [element-meta](https://github.com/element-hq/element-meta/issues) repository describing the use case and how you plan to tackle it. Do not just describe what feature is missing, explain why the users need it with a couple of real life examples from the field. + * In case of an existing issue, please comment that you're planning to contribute. If you create a new issue, please specify that in the issue. In such a case we will try to review the issue ASAP and provide you with initial feedback so you can be confident if and at which conditions your contributions will be accepted. + +Once we know that you want to contribute and have confirmed that the new feature is overall aligned with the product direction, the designers of the core team will help you with the designs and any other type of guidance when it comes to the user experience. We will try to unblock you as quickly as we can, but it may not be instant. Having a clear understanding of the use case and the impact of the feature will help us with the prioritization and faster responses. + +Only once all of the above is met should you open a PR with your proposed changes. + +## Developer onboarding + +For a detailed overview of the project, see [Developer Onboarding](./docs/_developer_onboarding.md). + +### Submitting the PRs + +Please have a look in the [dedicated documentation](./docs/pull_request.md) about pull request. + +### Android Studio settings + +Please set the "hard wrap" setting of Android Studio to 160 chars, this is the setting we use internally to format the source code (Menu `Settings/Editor/Code Style` then `Hard wrap at`). +Please ensure that you're using the project formatting rules (which are in the project at .idea/codeStyles/), and format the file before committing them. + +### Compilation + +This project should compile without any special action. Just clone it and open it with Android Studio, or compile from command line using `gradlew`. + +### Strings + +The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with Element X iOS. + ### Element X Android Gallery Once added to Localazy, translations can be checked screen per screen using our tool Element X Android Gallery, available at https://element-hq.github.io/element-x-android/. Localazy syncs occur every Monday and the screenshots on this page are generated every Tuesday, so you'll have to wait to see your change appearing on Element X Android Gallery. -## I want to add a new feature to Element X Android - -Thank you for contributing to the project! Please have a look in the [dedicated documentation](./docs/pull_request.md) about pull request. - -Also, please keep in mind that any feature added to Element X Android needs to be added to [the iOS client](https://github.com/element-hq/element-x-ios) too, unless it's related to an Android OS only behaviour. - -**IMPORTANT:** if you are adding new screens or modifying existing ones, this needs acceptance from the product and design teams before being merged. For this, it's better to start with a [feature request issue](https://github.com/element-hq/element-x-android/issues/new?template=enhancement.yml) describing the change you want to make and the motivation behind it instead of directly creating a pull request. This will allow the product and design teams to give feedback on the change before you start working on it, and avoid you doing work that might end up being rejected. - -## I want to submit a PR to fix an issue - -Please have a look in the [dedicated documentation](./docs/pull_request.md) about pull request. - -Please check if a corresponding issue exists. If yes, please let us know in a comment that you're working on it. -If an issue does not exist yet, it may be relevant to open a new issue and let us know that you're implementing it. - ### Kotlin This project is full Kotlin. Please do not write Java classes. From a662a5a04573ee0af4f499beff910931d4995274 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 14:32:11 +0200 Subject: [PATCH 0196/1083] Use new `action_delete` and `action_delete_account` --- .../android/features/logout/impl/AccountDeactivationView.kt | 2 +- .../logout/impl/ui/AccountDeactivationConfirmationDialog.kt | 2 +- .../features/logout/impl/AccountDeactivationViewTest.kt | 2 +- .../features/preferences/impl/root/PreferencesRootView.kt | 2 +- .../preferences/impl/root/PreferencesRootViewTest.kt | 4 ++-- libraries/ui-strings/src/main/res/values/localazy.xml | 6 ++++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index c0d625a45e..352efdfb92 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -135,7 +135,7 @@ private fun ColumnScope.Buttons( ) { val logoutAction = state.accountDeactivationAction Button( - text = stringResource(CommonStrings.action_deactivate), + text = stringResource(CommonStrings.action_delete), showProgress = logoutAction is AsyncAction.Loading, destructive = true, enabled = state.submitEnabled, diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt index 905112a78d..ab9d87c543 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt @@ -22,7 +22,7 @@ fun AccountDeactivationConfirmationDialog( ConfirmationDialog( title = stringResource(id = R.string.screen_deactivate_account_title), content = stringResource(R.string.screen_deactivate_account_confirmation_dialog_content), - submitText = stringResource(id = CommonStrings.action_deactivate), + submitText = stringResource(id = CommonStrings.action_delete), onSubmitClick = onSubmitClick, onDismiss = onDismiss, destructiveSubmit = true, diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt index eff479d21c..26c942da1f 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt @@ -60,7 +60,7 @@ class AccountDeactivationViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_deactivate) + rule.clickOn(CommonStrings.action_delete) eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) } 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 32ecfc2b13..4afc2d27bf 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 @@ -278,7 +278,7 @@ private fun ColumnScope.GeneralSection( ) if (state.canDeactivateAccount) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_deactivate_account)) }, + headlineContent = { Text(stringResource(id = CommonStrings.action_delete_account)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), style = ListItemStyle.Destructive, onClick = onDeactivateClick, 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 index e3c0d6e44d..da91bdbf86 100644 --- 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 @@ -407,7 +407,7 @@ class PreferencesRootViewTest { ), onDeactivateClick = callback, ) - rule.clickOn(CommonStrings.action_deactivate_account) + rule.clickOn(CommonStrings.action_delete_account) } } @@ -420,7 +420,7 @@ class PreferencesRootViewTest { eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_deactivate_account)).assertDoesNotExist() + rule.onNodeWithText(rule.activity.getString(CommonStrings.action_delete_account)).assertDoesNotExist() } @Test diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 2982c78ca9..a8a7b90dee 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -84,10 +84,12 @@ "Create" "Create room" "Create space" - "Delete" - "Delete account" + "Deactivate" + "Deactivate account" "Decline" "Decline and block" + "Delete" + "Delete account" "Delete Poll" "Deselect all" "Disable" From 2d4ed987388b51a4a6c9f32ed81cc98ca1d9671f Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 21 Apr 2026 15:30:50 +0200 Subject: [PATCH 0197/1083] Fix media viewer bottom sheets not being scrollable (#6631) Both the info and confirm deletion bottom sheets were not scrollable, which made them useless on devices with low resolution or landscape orientation in most devices --- .../impl/details/MediaDeleteConfirmationBottomSheet.kt | 5 +++++ .../mediaviewer/impl/details/MediaDetailsBottomSheet.kt | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt index 3850f3a0f8..e3b16df684 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt @@ -17,8 +17,11 @@ 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.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -54,10 +57,12 @@ fun MediaDeleteConfirmationBottomSheet( ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) ) { Column( modifier = Modifier .fillMaxWidth() + .verticalScroll(rememberScrollState()) .padding(horizontal = 16.dp), ) { IconTitleSubtitleMolecule( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index a6c30796af..e25f2ffde1 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.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.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -62,7 +64,8 @@ fun MediaDetailsBottomSheet( ) { Column( modifier = Modifier - .fillMaxWidth(), + .fillMaxWidth() + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(24.dp), ) { From 283fd2970aa52b036fc10a00db99cb086091bb4d Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 15:34:01 +0200 Subject: [PATCH 0198/1083] devx: fix build sdk script options for macos --- docs/_developer_onboarding.md | 5 +++++ tools/sdk/build-rust-sdk | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/_developer_onboarding.md b/docs/_developer_onboarding.md index a264bfec63..74020ead98 100644 --- a/docs/_developer_onboarding.md +++ b/docs/_developer_onboarding.md @@ -144,6 +144,11 @@ Prerequisites: export ANDROID_HOME=$HOME/android/sdk ``` +* On macos ensure gnu-getopt is installed + ``` + brew install gnu-getopt + ``` + You can then build the Rust SDK by running the script [`tools/sdk/build-rust-sdk`](../tools/sdk/build-rust-sdk). Type `./tools/sdk/build-rust-sdk --help` for help. diff --git a/tools/sdk/build-rust-sdk b/tools/sdk/build-rust-sdk index 2012af8741..eddff9f7e4 100755 --- a/tools/sdk/build-rust-sdk +++ b/tools/sdk/build-rust-sdk @@ -41,7 +41,14 @@ sdkArg="" ## Argument parsing -TEMP=$(getopt -o 'rs:b:at:h' --long 'remote,sdk:,branch:,build-app,target-arch:,help' -- "$@") +# Use GNU getopt (required for --long support on macOS) +if [[ "$OSTYPE" == "darwin"* ]]; then + GNU_GETOPT="$(brew --prefix gnu-getopt)/bin/getopt" +else + GNU_GETOPT="getopt" +fi + +TEMP=$("$GNU_GETOPT" -o 'rs:b:at:h' --long 'remote,sdk:,branch:,build-app,target-arch:,help' -- "$@") if [ $? -ne 0 ]; then echo 'Terminating...' >&2 @@ -53,32 +60,32 @@ unset TEMP while true; do case "$1" in - 'r'|'--remote') + '-r'|'--remote') buildLocal=1 shift continue ;; - 's'|'--sdk') + '-s'|'--sdk') sdkArg="$2" shift 2 continue ;; - 'b'|'--branch') + '-b'|'--branch') rustSdkBranch="$2" shift 2 continue ;; - 'a'|'--build-app') + '-a'|'--build-app') buildApp=0 shift continue ;; - 't'|'--target-arch') + '-t'|'--target-arch') target_arch="$2" shift 2 continue ;; - 'h'|'--help') + '-h'|'--help') cat << END SYNOPSIS From 54efb462943311c4a0d5240564082ecd9b5906e9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 15:50:59 +0200 Subject: [PATCH 0199/1083] `MediaViewerEvents` -> `MediaViewerEvent` --- ...diaViewerEvents.kt => MediaViewerEvent.kt} | 28 ++++----- .../impl/viewer/MediaViewerPresenter.kt | 28 ++++----- .../impl/viewer/MediaViewerState.kt | 2 +- .../impl/viewer/MediaViewerStateProvider.kt | 2 +- .../impl/viewer/MediaViewerView.kt | 32 +++++----- .../impl/viewer/MediaViewerPresenterTest.kt | 44 +++++++------- .../impl/viewer/MediaViewerViewTest.kt | 58 +++++++++---------- 7 files changed, 97 insertions(+), 97 deletions(-) rename libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/{MediaViewerEvents.kt => MediaViewerEvent.kt} (67%) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt similarity index 67% rename from libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt index 3f1436b9b6..1960b69e4c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt @@ -11,22 +11,22 @@ package io.element.android.libraries.mediaviewer.impl.viewer import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline -sealed interface MediaViewerEvents { - data class LoadMedia(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents - data class SaveOnDisk(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents - data class Share(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents - data class OpenWith(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents - data class ClearLoadingError(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents - data class ViewInTimeline(val eventId: EventId) : MediaViewerEvents - data class Forward(val eventId: EventId) : MediaViewerEvents - data class OpenInfo(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents +sealed interface MediaViewerEvent { + data class LoadMedia(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent + data class SaveOnDisk(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent + data class Share(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent + data class OpenWith(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent + data class ClearLoadingError(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent + data class ViewInTimeline(val eventId: EventId) : MediaViewerEvent + data class Forward(val eventId: EventId) : MediaViewerEvent + data class OpenInfo(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent data class ConfirmDelete( val eventId: EventId, val data: MediaViewerPageData.MediaViewerData, - ) : MediaViewerEvents + ) : MediaViewerEvent - data object CloseBottomSheet : MediaViewerEvents - data class Delete(val eventId: EventId) : MediaViewerEvents - data class OnNavigateTo(val index: Int) : MediaViewerEvents - data class LoadMore(val direction: Timeline.PaginationDirection) : MediaViewerEvents + data object CloseBottomSheet : MediaViewerEvent + data class Delete(val eventId: EventId) : MediaViewerEvent + data class OnNavigateTo(val index: Int) : MediaViewerEvent + data class LoadMore(val direction: Timeline.PaginationDirection) : MediaViewerEvent } 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 ae581fa8d4..0128e40e65 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 @@ -95,42 +95,42 @@ class MediaViewerPresenter( } localMediaActions.Configure() - fun handleEvent(event: MediaViewerEvents) { + fun handleEvent(event: MediaViewerEvent) { when (event) { - is MediaViewerEvents.LoadMedia -> { + is MediaViewerEvent.LoadMedia -> { coroutineScope.downloadMedia(data = event.data) } - is MediaViewerEvents.ClearLoadingError -> { + is MediaViewerEvent.ClearLoadingError -> { dataSource.clearLoadingError(event.data) } - is MediaViewerEvents.SaveOnDisk -> { + is MediaViewerEvent.SaveOnDisk -> { mediaBottomSheetState = MediaBottomSheetState.Hidden coroutineScope.saveOnDisk(event.data.downloadedMedia.value) } - is MediaViewerEvents.Share -> { + is MediaViewerEvent.Share -> { mediaBottomSheetState = MediaBottomSheetState.Hidden coroutineScope.share(event.data.downloadedMedia.value) } - is MediaViewerEvents.OpenWith -> { + is MediaViewerEvent.OpenWith -> { mediaBottomSheetState = MediaBottomSheetState.Hidden coroutineScope.open(event.data.downloadedMedia.value) } - is MediaViewerEvents.Delete -> { + is MediaViewerEvent.Delete -> { mediaBottomSheetState = MediaBottomSheetState.Hidden coroutineScope.delete(event.eventId) } - is MediaViewerEvents.ViewInTimeline -> { + is MediaViewerEvent.ViewInTimeline -> { mediaBottomSheetState = MediaBottomSheetState.Hidden navigator.onViewInTimelineClick(event.eventId) } - is MediaViewerEvents.Forward -> { + is MediaViewerEvent.Forward -> { mediaBottomSheetState = MediaBottomSheetState.Hidden navigator.onForwardClick( eventId = event.eventId, fromPinnedEvents = inputs.mode.getTimelineMode() == Timeline.Mode.PinnedEvents, ) } - is MediaViewerEvents.OpenInfo -> coroutineScope.launch { + is MediaViewerEvent.OpenInfo -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.MediaDetailsBottomSheetState( eventId = event.data.eventId, canDelete = when (event.data.mediaInfo.senderId) { @@ -142,20 +142,20 @@ class MediaViewerPresenter( thumbnailSource = event.data.thumbnailSource, ) } - is MediaViewerEvents.ConfirmDelete -> { + is MediaViewerEvent.ConfirmDelete -> { mediaBottomSheetState = MediaBottomSheetState.MediaDeleteConfirmationState( eventId = event.eventId, mediaInfo = event.data.mediaInfo, thumbnailSource = event.data.thumbnailSource ?: event.data.mediaSource, ) } - MediaViewerEvents.CloseBottomSheet -> { + MediaViewerEvent.CloseBottomSheet -> { mediaBottomSheetState = MediaBottomSheetState.Hidden } - is MediaViewerEvents.OnNavigateTo -> { + is MediaViewerEvent.OnNavigateTo -> { currentIndex.intValue = event.index } - is MediaViewerEvents.LoadMore -> coroutineScope.launch { + is MediaViewerEvent.LoadMore -> coroutineScope.launch { dataSource.loadMore(event.direction) } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt index ae1a422a6f..8a4da2aac3 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt @@ -26,7 +26,7 @@ data class MediaViewerState( val snackbarMessage: SnackbarMessage?, val canShowInfo: Boolean, val mediaBottomSheetState: MediaBottomSheetState, - val eventSink: (MediaViewerEvents) -> Unit, + val eventSink: (MediaViewerEvent) -> Unit, ) sealed interface MediaViewerPageData { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index b1a2bde350..e7d8fd55ae 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -226,7 +226,7 @@ fun aMediaViewerState( currentIndex: Int = 0, canShowInfo: Boolean = true, mediaBottomSheetState: MediaBottomSheetState = MediaBottomSheetState.Hidden, - eventSink: (MediaViewerEvents) -> Unit = {}, + eventSink: (MediaViewerEvent) -> Unit = {}, ) = MediaViewerState( initiallySelectedEventId = EventId("\$a:b"), listData = listData.toImmutableList(), diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 95ce7c631f..aa1d95f6e5 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -126,7 +126,7 @@ fun MediaViewerView( } LaunchedEffect(pagerState) { snapshotFlow { pagerState.currentPage }.collect { page -> - state.eventSink(MediaViewerEvents.OnNavigateTo(page)) + state.eventSink(MediaViewerEvent.OnNavigateTo(page)) } } HorizontalPager( @@ -145,7 +145,7 @@ fun MediaViewerView( } is MediaViewerPageData.Loading -> { LaunchedEffect(dataForPage.timestamp) { - state.eventSink(MediaViewerEvents.LoadMore(dataForPage.direction)) + state.eventSink(MediaViewerEvent.LoadMore(dataForPage.direction)) } MediaViewerLoadingPage( onDismiss = onBackClick, @@ -154,7 +154,7 @@ fun MediaViewerView( is MediaViewerPageData.MediaViewerData -> { var bottomPaddingInPixels by remember { mutableIntStateOf(defaultBottomPaddingInPixels) } LaunchedEffect(Unit) { - state.eventSink(MediaViewerEvents.LoadMedia(dataForPage)) + state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) } Box( modifier = Modifier.fillMaxSize() @@ -173,10 +173,10 @@ fun MediaViewerView( textFileViewer = textFileViewer, onDismiss = onBackClick, onRetry = { - state.eventSink(MediaViewerEvents.LoadMedia(dataForPage)) + state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) }, onDismissError = { - state.eventSink(MediaViewerEvents.ClearLoadingError(dataForPage)) + state.eventSink(MediaViewerEvent.ClearLoadingError(dataForPage)) }, onShowOverlayChange = { showOverlay = it @@ -215,7 +215,7 @@ fun MediaViewerView( canShowInfo = state.canShowInfo, onBackClick = onBackClick, onInfoClick = { - state.eventSink(MediaViewerEvents.OpenInfo(currentData)) + state.eventSink(MediaViewerEvent.OpenInfo(currentData)) }, eventSink = state.eventSink ) @@ -251,25 +251,25 @@ fun MediaViewerView( MediaDetailsBottomSheet( state = bottomSheetState, onViewInTimeline = { - state.eventSink(MediaViewerEvents.ViewInTimeline(it)) + state.eventSink(MediaViewerEvent.ViewInTimeline(it)) }, onShare = { (currentData as? MediaViewerPageData.MediaViewerData)?.let { - state.eventSink(MediaViewerEvents.Share(currentData)) + state.eventSink(MediaViewerEvent.Share(currentData)) } }, onForward = { - state.eventSink(MediaViewerEvents.Forward(it)) + state.eventSink(MediaViewerEvent.Forward(it)) }, onDownload = { (currentData as? MediaViewerPageData.MediaViewerData)?.let { - state.eventSink(MediaViewerEvents.SaveOnDisk(currentData)) + state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) } }, onDelete = { eventId -> (currentData as? MediaViewerPageData.MediaViewerData)?.let { state.eventSink( - MediaViewerEvents.ConfirmDelete( + MediaViewerEvent.ConfirmDelete( eventId, currentData, ) @@ -277,7 +277,7 @@ fun MediaViewerView( } }, onDismiss = { - state.eventSink(MediaViewerEvents.CloseBottomSheet) + state.eventSink(MediaViewerEvent.CloseBottomSheet) }, ) } @@ -285,10 +285,10 @@ fun MediaViewerView( MediaDeleteConfirmationBottomSheet( state = bottomSheetState, onDelete = { - state.eventSink(MediaViewerEvents.Delete(it)) + state.eventSink(MediaViewerEvent.Delete(it)) }, onDismiss = { - state.eventSink(MediaViewerEvents.CloseBottomSheet) + state.eventSink(MediaViewerEvent.CloseBottomSheet) }, ) } @@ -458,7 +458,7 @@ private fun MediaViewerTopBar( canShowInfo: Boolean, onBackClick: () -> Unit, onInfoClick: () -> Unit, - eventSink: (MediaViewerEvents) -> Unit, + eventSink: (MediaViewerEvent) -> Unit, ) { val downloadedMedia by data.downloadedMedia val actionsEnabled = downloadedMedia.isSuccess() @@ -500,7 +500,7 @@ private fun MediaViewerTopBar( IconButton( enabled = actionsEnabled, onClick = { - eventSink(MediaViewerEvents.OpenWith(data)) + eventSink(MediaViewerEvent.OpenWith(data)) }, ) { when (mimeType) { 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 c217ea3306..6cf846ff78 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 @@ -226,7 +226,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.LoadMedia( + MediaViewerEvent.LoadMedia( aMediaViewerPageData( mediaSource = MediaSource(aUrl) ) @@ -266,7 +266,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.OpenInfo( + MediaViewerEvent.OpenInfo( aMediaViewerPageData( mediaSource = MediaSource(aUrl) ) @@ -275,7 +275,7 @@ class MediaViewerPresenterTest { val withInfoState = awaitItem() assertThat(withInfoState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) withInfoState.eventSink( - MediaViewerEvents.CloseBottomSheet + MediaViewerEvent.CloseBottomSheet ) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) @@ -306,7 +306,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.ClearLoadingError( + MediaViewerEvent.ClearLoadingError( aMediaViewerPageData( mediaSource = MediaSource(aUrl) ) @@ -339,7 +339,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.Share( + MediaViewerEvent.Share( aMediaViewerPageData( mediaSource = MediaSource(aUrl) ) @@ -372,7 +372,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.SaveOnDisk( + MediaViewerEvent.SaveOnDisk( aMediaViewerPageData( mediaSource = MediaSource(aUrl) ) @@ -405,7 +405,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.OpenWith( + MediaViewerEvent.OpenWith( aMediaViewerPageData( mediaSource = MediaSource(aUrl) ) @@ -438,7 +438,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.ConfirmDelete( + MediaViewerEvent.ConfirmDelete( eventId = AN_EVENT_ID, data = aMediaViewerPageData( mediaSource = MediaSource(aUrl) @@ -448,7 +448,7 @@ class MediaViewerPresenterTest { val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDeleteConfirmationState::class.java) withBottomSheetState.eventSink( - MediaViewerEvents.CloseBottomSheet + MediaViewerEvent.CloseBottomSheet ) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) @@ -498,7 +498,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.ConfirmDelete( + MediaViewerEvent.ConfirmDelete( eventId = AN_EVENT_ID, data = aMediaViewerPageData( mediaSource = MediaSource(aUrl) @@ -508,7 +508,7 @@ class MediaViewerPresenterTest { val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDeleteConfirmationState::class.java) updatedState.eventSink( - MediaViewerEvents.Delete( + MediaViewerEvent.Delete( eventId = AN_EVENT_ID, ) ) @@ -551,7 +551,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.OnNavigateTo(1) + MediaViewerEvent.OnNavigateTo(1) ) val finalState = awaitItem() assertThat(finalState.currentIndex).isEqualTo(1) @@ -606,7 +606,7 @@ class MediaViewerPresenterTest { val updatedState = awaitItem() // User navigate to the last item (forward loading indicator) updatedState.eventSink( - MediaViewerEvents.OnNavigateTo(2) + MediaViewerEvent.OnNavigateTo(2) ) // data source claims that there is no more items to load forward mediaGalleryDataSource.emitGroupedMediaItems( @@ -680,7 +680,7 @@ class MediaViewerPresenterTest { val updatedState = awaitItem() // User navigate to the first item (backward loading indicator) updatedState.eventSink( - MediaViewerEvents.OnNavigateTo(0) + MediaViewerEvent.OnNavigateTo(0) ) // data source claims that there is no more items to load backward mediaGalleryDataSource.emitGroupedMediaItems( @@ -728,7 +728,7 @@ class MediaViewerPresenterTest { val updatedState = awaitItem() // User navigate to the media updatedState.eventSink( - MediaViewerEvents.OnNavigateTo(1) + MediaViewerEvent.OnNavigateTo(1) ) skipItems(1) // data source claims that there is no more items to load at all @@ -771,7 +771,7 @@ class MediaViewerPresenterTest { ) val updatedState = awaitItem() updatedState.eventSink( - MediaViewerEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS) + MediaViewerEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS) ) loadMoreLambda.assertions().isCalledOnce().with(value(Timeline.PaginationDirection.BACKWARDS)) } @@ -796,10 +796,10 @@ class MediaViewerPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(MediaViewerEvents.OpenInfo(aMediaViewerPageData())) + initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) - initialState.eventSink(MediaViewerEvents.ViewInTimeline(AN_EVENT_ID)) + initialState.eventSink(MediaViewerEvent.ViewInTimeline(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) onViewInTimelineClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) @@ -825,10 +825,10 @@ class MediaViewerPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(MediaViewerEvents.OpenInfo(aMediaViewerPageData())) + initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) - initialState.eventSink(MediaViewerEvents.Forward(AN_EVENT_ID)) + initialState.eventSink(MediaViewerEvent.Forward(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) onForwardClickLambda.assertions().isCalledOnce() @@ -856,10 +856,10 @@ class MediaViewerPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(MediaViewerEvents.OpenInfo(aMediaViewerPageData())) + initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) - initialState.eventSink(MediaViewerEvents.Forward(AN_EVENT_ID)) + initialState.eventSink(MediaViewerEvent.Forward(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) onForwardClickLambda.assertions().isCalledOnce() diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index b1114945c2..d735497ece 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -43,7 +43,7 @@ class MediaViewerViewTest { @Test fun `clicking on back invokes expected callback`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMediaViewerState( eventSink = eventsRecorder ) @@ -56,8 +56,8 @@ class MediaViewerViewTest { } eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), ) ) } @@ -70,7 +70,7 @@ class MediaViewerViewTest { testMenuAction( data, CommonStrings.action_open_with, - MediaViewerEvents.OpenWith(data), + MediaViewerEvent.OpenWith(data), ) } @@ -82,16 +82,16 @@ class MediaViewerViewTest { testMenuAction( data, CommonStrings.a11y_view_details, - MediaViewerEvents.OpenInfo(data), + MediaViewerEvent.OpenInfo(data), ) } private fun testMenuAction( data: MediaViewerPageData.MediaViewerData, contentDescriptionRes: Int, - expectedEvent: MediaViewerEvents, + expectedEvent: MediaViewerEvent, ) { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setMediaViewerView( aMediaViewerState( listData = listOf(data), @@ -102,8 +102,8 @@ class MediaViewerViewTest { rule.onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(data), + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(data), expectedEvent, ) ) @@ -116,7 +116,7 @@ class MediaViewerViewTest { testBottomSheetAction( data, CommonStrings.action_save, - MediaViewerEvents.SaveOnDisk(data), + MediaViewerEvent.SaveOnDisk(data), ) } @@ -127,16 +127,16 @@ class MediaViewerViewTest { testBottomSheetAction( data, CommonStrings.action_share, - MediaViewerEvents.Share(data), + MediaViewerEvent.Share(data), ) } private fun testBottomSheetAction( data: MediaViewerPageData.MediaViewerData, contentDescriptionRes: Int, - expectedEvent: MediaViewerEvents, + expectedEvent: MediaViewerEvent, ) { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setMediaViewerView( aMediaViewerState( listData = listOf(data), @@ -147,8 +147,8 @@ class MediaViewerViewTest { rule.clickOn(contentDescriptionRes) eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(data), + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(data), expectedEvent, ) ) @@ -156,7 +156,7 @@ class MediaViewerViewTest { @Test fun `clicking on image hides the overlay`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMediaViewerState( eventSink = eventsRecorder ) @@ -176,15 +176,15 @@ class MediaViewerViewTest { .assertDoesNotExist() eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), ) ) } @Test fun `clicking swipe on the image invokes the expected callback`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMediaViewerState( eventSink = eventsRecorder ) @@ -199,15 +199,15 @@ class MediaViewerViewTest { } eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), ) ) } @Test fun `error case, click on retry emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val data = aMediaViewerPageData( downloadedMedia = AsyncData.Failure(IllegalStateException("error")), ) @@ -220,16 +220,16 @@ class MediaViewerViewTest { rule.clickOn(CommonStrings.action_retry) eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(data), - MediaViewerEvents.LoadMedia(data), + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(data), + MediaViewerEvent.LoadMedia(data), ) ) } @Test fun `error case, click on cancel emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val data = aMediaViewerPageData( downloadedMedia = AsyncData.Failure(IllegalStateException("error")), ) @@ -242,9 +242,9 @@ class MediaViewerViewTest { rule.clickOn(CommonStrings.action_cancel) eventsRecorder.assertList( listOf( - MediaViewerEvents.OnNavigateTo(0), - MediaViewerEvents.LoadMedia(data), - MediaViewerEvents.ClearLoadingError(data) + MediaViewerEvent.OnNavigateTo(0), + MediaViewerEvent.LoadMedia(data), + MediaViewerEvent.ClearLoadingError(data) ) ) } From 75db550ca884a21e0e5d456b140d5e87de319da8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:55:20 +0000 Subject: [PATCH 0200/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.04.21 (#6635) 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 1adfc917ab..119252e84e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.15" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.21" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From f6ed0a645a8f06007ffd3b0c81218b2c4b39bf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Apr 2026 15:56:38 +0200 Subject: [PATCH 0201/1083] Add flag for automatic back pagination feature --- .../android/libraries/featureflag/api/FeatureFlags.kt | 8 ++++++++ .../libraries/matrix/impl/RustMatrixClientFactory.kt | 5 +++++ 2 files changed, 13 insertions(+) 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 c3395d1007..d4e52bdcf6 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 @@ -161,4 +161,12 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + AutomaticBackPagination( + key = "feature.automatic_back_pagination", + title = "Automatic back pagination of rooms", + description = "Allow the app to automatically back paginate in rooms to pre-fetch older messages in background." + + "\nRequires an app restart to take effect.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index f83efd2736..6cbf122084 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -105,6 +105,11 @@ class RustMatrixClientFactory( suspend fun create(client: Client): RustMatrixClient { val (anonymizedAccessToken, anonymizedRefreshToken) = client.session().anonymizedTokens() + // Must be called before creating the sync service, timelines etc. + if (featureFlagService.isFeatureEnabled(FeatureFlags.AutomaticBackPagination)) { + client.enableAutomaticBackpagination() + } + client.setUtdDelegate(UtdTracker(analyticsService)) val syncService = client.syncService() From 97ae775df58de642a5f0d27d4db4b984f7c7edfa Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 16:14:07 +0200 Subject: [PATCH 0202/1083] MediaViewer: add Share action as a main action. --- .../mediaviewer/impl/viewer/MediaViewerView.kt | 13 +++++++++++++ .../mediaviewer/impl/viewer/MediaViewerViewTest.kt | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index aa1d95f6e5..b2a7f3fdff 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -214,6 +214,9 @@ fun MediaViewerView( data = currentData, canShowInfo = state.canShowInfo, onBackClick = onBackClick, + onShareClick = { + state.eventSink(MediaViewerEvent.Share(currentData)) + }, onInfoClick = { state.eventSink(MediaViewerEvent.OpenInfo(currentData)) }, @@ -457,6 +460,7 @@ private fun MediaViewerTopBar( data: MediaViewerPageData.MediaViewerData, canShowInfo: Boolean, onBackClick: () -> Unit, + onShareClick: () -> Unit, onInfoClick: () -> Unit, eventSink: (MediaViewerEvent) -> Unit, ) { @@ -514,6 +518,15 @@ private fun MediaViewerTopBar( ) } } + IconButton( + onClick = onShareClick, + enabled = actionsEnabled, + ) { + Icon( + imageVector = CompoundIcons.ShareAndroid(), + contentDescription = stringResource(id = CommonStrings.action_share), + ) + } if (canShowInfo) { IconButton( onClick = onInfoClick, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index d735497ece..34c67683cd 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -86,6 +86,18 @@ class MediaViewerViewTest { ) } + @Test + fun `clicking on top action share emits expected Event`() { + val data = aMediaViewerPageData( + downloadedMedia = AsyncData.Success(aLocalMedia(uri = mockMediaUrl)), + ) + testMenuAction( + data, + CommonStrings.action_share, + MediaViewerEvent.Share(data), + ) + } + private fun testMenuAction( data: MediaViewerPageData.MediaViewerData, contentDescriptionRes: Int, From 79afb1d9e07be39d591dee71ab5c09201f20811e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 16:21:01 +0200 Subject: [PATCH 0203/1083] MediaViewer: add Save action as a main action. --- .../mediaviewer/impl/viewer/MediaViewerView.kt | 13 +++++++++++++ .../mediaviewer/impl/viewer/MediaViewerViewTest.kt | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index b2a7f3fdff..ee7a235390 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -217,6 +217,9 @@ fun MediaViewerView( onShareClick = { state.eventSink(MediaViewerEvent.Share(currentData)) }, + onSaveClick = { + state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) + }, onInfoClick = { state.eventSink(MediaViewerEvent.OpenInfo(currentData)) }, @@ -461,6 +464,7 @@ private fun MediaViewerTopBar( canShowInfo: Boolean, onBackClick: () -> Unit, onShareClick: () -> Unit, + onSaveClick: () -> Unit, onInfoClick: () -> Unit, eventSink: (MediaViewerEvent) -> Unit, ) { @@ -527,6 +531,15 @@ private fun MediaViewerTopBar( contentDescription = stringResource(id = CommonStrings.action_share), ) } + IconButton( + onClick = onSaveClick, + enabled = actionsEnabled, + ) { + Icon( + imageVector = CompoundIcons.Download(), + contentDescription = stringResource(id = CommonStrings.action_save), + ) + } if (canShowInfo) { IconButton( onClick = onInfoClick, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index 34c67683cd..1522f5d5c1 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -98,6 +98,18 @@ class MediaViewerViewTest { ) } + @Test + fun `clicking on top action save emits expected Event`() { + val data = aMediaViewerPageData( + downloadedMedia = AsyncData.Success(aLocalMedia(uri = mockMediaUrl)), + ) + testMenuAction( + data, + CommonStrings.action_save, + MediaViewerEvent.SaveOnDisk(data), + ) + } + private fun testMenuAction( data: MediaViewerPageData.MediaViewerData, contentDescriptionRes: Int, From 5d270068d62c08de2184665908e1335402562f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Apr 2026 16:38:53 +0200 Subject: [PATCH 0204/1083] Setting version for the release 26.04.4 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 93e92b81ce..d6a2cbea3d 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 4 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 3 +private const val versionReleaseNumber = 4 object Versions { /** From d38ef5ba103683946c828d03f9cd6f2a6da22eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Apr 2026 16:40:30 +0200 Subject: [PATCH 0205/1083] Adding fastlane file for version 26.04.4 --- fastlane/metadata/android/en-US/changelogs/202604040.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202604040.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202604040.txt b/fastlane/metadata/android/en-US/changelogs/202604040.txt new file mode 100644 index 0000000000..cbb77b7606 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202604040.txt @@ -0,0 +1,2 @@ +Main changes in this version: several bug fixes. +Full changelog: https://github.com/element-hq/element-x-android/releases From 1e04a7345f850dd11edece90e441629b1eb620ba Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 21 Apr 2026 16:42:44 +0200 Subject: [PATCH 0206/1083] Add flag for automatic back pagination feature (#6637) --- .../android/libraries/featureflag/api/FeatureFlags.kt | 8 ++++++++ .../libraries/matrix/impl/RustMatrixClientFactory.kt | 5 +++++ 2 files changed, 13 insertions(+) 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 c3395d1007..d4e52bdcf6 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 @@ -161,4 +161,12 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + AutomaticBackPagination( + key = "feature.automatic_back_pagination", + title = "Automatic back pagination of rooms", + description = "Allow the app to automatically back paginate in rooms to pre-fetch older messages in background." + + "\nRequires an app restart to take effect.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index f83efd2736..6cbf122084 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -105,6 +105,11 @@ class RustMatrixClientFactory( suspend fun create(client: Client): RustMatrixClient { val (anonymizedAccessToken, anonymizedRefreshToken) = client.session().anonymizedTokens() + // Must be called before creating the sync service, timelines etc. + if (featureFlagService.isFeatureEnabled(FeatureFlags.AutomaticBackPagination)) { + client.enableAutomaticBackpagination() + } + client.setUtdDelegate(UtdTracker(analyticsService)) val syncService = client.syncService() From a0632b216c316dc0f9ee23678e760cde52627df1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 16:35:52 +0200 Subject: [PATCH 0207/1083] MediaDetailsBottomSheet: update wording and dividers. --- .../impl/details/MediaDetailsBottomSheet.kt | 9 +++++++-- .../mediaviewer/impl/viewer/MediaViewerView.kt | 5 ++++- .../impl/details/MediaDetailsBottomSheetTest.kt | 10 +++++----- .../mediaviewer/impl/viewer/MediaViewerViewTest.kt | 8 ++++---- libraries/ui-strings/src/main/res/values/localazy.xml | 1 + 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index e25f2ffde1..0e1e3a04c0 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -46,6 +46,9 @@ import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.ui.strings.CommonStrings +/** + * Ref: https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=2229-149220 + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun MediaDetailsBottomSheet( @@ -99,6 +102,7 @@ fun MediaDetailsBottomSheet( onViewInTimeline(state.eventId) } ) + HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), headlineContent = { Text(stringResource(CommonStrings.action_share)) }, @@ -115,9 +119,10 @@ fun MediaDetailsBottomSheet( onForward(state.eventId) } ) + HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), - headlineContent = { Text(stringResource(CommonStrings.action_save)) }, + headlineContent = { Text(stringResource(CommonStrings.action_download)) }, style = ListItemStyle.Primary, onClick = { onDownload(state.eventId) @@ -127,7 +132,7 @@ fun MediaDetailsBottomSheet( HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), - headlineContent = { Text(stringResource(CommonStrings.action_remove)) }, + headlineContent = { Text(stringResource(CommonStrings.action_delete)) }, style = ListItemStyle.Destructive, onClick = { onDelete(state.eventId) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index ee7a235390..6b62a04d0f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -101,6 +101,9 @@ import me.saket.telephoto.zoomable.rememberZoomableState val topAppBarHeight = 88.dp +/** + * Ref: https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=3361-16623 + */ @Composable fun MediaViewerView( state: MediaViewerState, @@ -537,7 +540,7 @@ private fun MediaViewerTopBar( ) { Icon( imageVector = CompoundIcons.Download(), - contentDescription = stringResource(id = CommonStrings.action_save), + contentDescription = stringResource(id = CommonStrings.action_download), ) } if (canShowInfo) { diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt index 580cd89c72..74bc1bd648 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt @@ -72,28 +72,28 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") - fun `clicking on Save invokes expected callback`() { + fun `clicking on Download invokes expected callback`() { val state = aMediaDetailsBottomSheetState() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, onDownload = callback, ) - rule.clickOn(CommonStrings.action_save) + rule.clickOn(CommonStrings.action_download) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on Remove invokes expected callback`() { + fun `clicking on Delete invokes expected callback`() { val state = aMediaDetailsBottomSheetState() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, onDelete = callback, ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_remove)).assertExists() - rule.clickOn(CommonStrings.action_remove) + rule.onNodeWithText(rule.activity.getString(CommonStrings.action_delete)).assertExists() + rule.clickOn(CommonStrings.action_delete) } } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index 1522f5d5c1..d41841a9f0 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -99,13 +99,13 @@ class MediaViewerViewTest { } @Test - fun `clicking on top action save emits expected Event`() { + fun `clicking on top action download emits expected Event`() { val data = aMediaViewerPageData( downloadedMedia = AsyncData.Success(aLocalMedia(uri = mockMediaUrl)), ) testMenuAction( data, - CommonStrings.action_save, + CommonStrings.action_download, MediaViewerEvent.SaveOnDisk(data), ) } @@ -135,11 +135,11 @@ class MediaViewerViewTest { @Test @Config(qualifiers = "h1024dp") - fun `clicking on save emit expected Event`() { + fun `clicking on download emit expected Event`() { val data = aMediaViewerPageData() testBottomSheetAction( data, - CommonStrings.action_save, + CommonStrings.action_download, MediaViewerEvent.SaveOnDisk(data), ) } diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index a8a7b90dee..28b28e814a 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -96,6 +96,7 @@ "Discard" "Dismiss" "Done" + "Download" "Edit" "Edit caption" "Edit poll" From 61c68f8d4a5dbcb463c83afb9048fd6355e74b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Apr 2026 16:38:53 +0200 Subject: [PATCH 0208/1083] Setting version for the release 26.04.4 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 93e92b81ce..d6a2cbea3d 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 4 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 3 +private const val versionReleaseNumber = 4 object Versions { /** From 0224c7e2a5ca84d047fbf1cf7902f0b06bf199b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Apr 2026 16:40:30 +0200 Subject: [PATCH 0209/1083] Adding fastlane file for version 26.04.4 --- fastlane/metadata/android/en-US/changelogs/202604040.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202604040.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202604040.txt b/fastlane/metadata/android/en-US/changelogs/202604040.txt new file mode 100644 index 0000000000..cbb77b7606 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202604040.txt @@ -0,0 +1,2 @@ +Main changes in this version: several bug fixes. +Full changelog: https://github.com/element-hq/element-x-android/releases From 24b24e511af9b3a746bb2b6d184aa1118675f8a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 21 Apr 2026 17:33:47 +0200 Subject: [PATCH 0210/1083] Changelog for version 26.04.4 --- CHANGES.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 68848d491f..df109d34a6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,45 @@ +Changes in Element X v26.04.4 +============================= + + + +## What's Changed +### 🙌 Improvements +* Natural media viewer swiping order by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6431 +* Replace `rustls-platform-verifier-android.aar` with single class by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6610 +* Cleanup FetchPushForegroundService by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6577 +* cleaning: Remove join button from call notify timelineItemView by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6603 +### 🐛 Bugfixes +* Fix crash when going back to threads list by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6620 +* audio: Let EC decide alone what communication device to use by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6609 +* Fix media viewer bottom sheets not being scrollable by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6631 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6626 +### 📄 Documentation +* Updates to new features and some refactoring. by @mxandreas in https://github.com/element-hq/element-x-android/pull/6591 +### 🚧 In development 🚧 +* WIP : live location rendering by @ganfra in https://github.com/element-hq/element-x-android/pull/6611 +### Dependency upgrades +* Update dependency io.element.android:element-call-embedded to v0.19.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6593 +* Update dependency androidx.annotation:annotation-jvm to v1.10.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6596 +* Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.11.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6605 +* Update dependency com.google.firebase:firebase-bom to v34.12.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6604 +* Update actions/upload-artifact action to v7.0.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6614 +* Update plugin dependencycheck to v12.2.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6621 +* Update actions/github-script action to v9 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6606 +* Update peter-evans/create-pull-request action to v8.1.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6615 +* Update dependencyAnalysis to v3.7.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6616 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.04.21 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6635 +### Others +* Settings UI update. by @bmarty in https://github.com/element-hq/element-x-android/pull/6602 +* Support replying to messages with voice recordings by @kalix127 in https://github.com/element-hq/element-x-android/pull/6464 +* Add Black theme option for battery saving on OLED displays by @timurgilfanov in https://github.com/element-hq/element-x-android/pull/6441 +* Fix | When selecting earpiece twice in a row the proximity sensor get wrongly disabled by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6627 +* Update wording of deactivate account screen by @bmarty in https://github.com/element-hq/element-x-android/pull/6633 + + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.04.3...v26.04.4 + Changes in Element X v26.04.3 ============================= From 3199a7dd8b9b7bf579554a4253137f4f5fa82af1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:06:08 +0000 Subject: [PATCH 0211/1083] Update dependency io.nlopez.compose.rules:detekt to v0.5.7 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 92847f39b7..dfd32f0872 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,7 +46,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.5.6") + detektPlugins("io.nlopez.compose.rules:detekt:0.5.7") detektPlugins(project(":tests:detekt-rules")) } From 83b4bfad96039923cae6caea86499778ad192766 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Apr 2026 17:22:22 +0200 Subject: [PATCH 0212/1083] Move "Open with" action to bottom sheet --- .../impl/details/MediaDetailsBottomSheet.kt | 23 +++++++++++ .../impl/gallery/MediaGalleryEvents.kt | 1 + .../impl/gallery/MediaGalleryPresenter.kt | 17 +++++++++ .../impl/gallery/MediaGalleryView.kt | 3 ++ .../impl/viewer/MediaViewerView.kt | 27 +++---------- .../details/MediaDetailsBottomSheetTest.kt | 2 + .../impl/viewer/MediaViewerViewTest.kt | 38 +++++++++---------- 7 files changed, 70 insertions(+), 41 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index 0e1e3a04c0..fc377e5cae 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -28,6 +28,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -57,6 +58,7 @@ fun MediaDetailsBottomSheet( onShare: (EventId) -> Unit, onForward: (EventId) -> Unit, onDownload: (EventId) -> Unit, + onOpenWith: (EventId) -> Unit, onDelete: (EventId) -> Unit, onDismiss: () -> Unit, modifier: Modifier = Modifier, @@ -128,6 +130,26 @@ fun MediaDetailsBottomSheet( onDownload(state.eventId) } ) + val mimeType = state.mediaInfo.mimeType + val icon = when (mimeType) { + MimeTypes.Apk -> + ListItemContent.Icon(IconSource.Resource(R.drawable.ic_apk_install)) + else -> + ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())) + } + val wording = when (mimeType) { + MimeTypes.Apk -> stringResource(id = CommonStrings.common_install_apk_android) + else -> stringResource(id = CommonStrings.action_open_with) + } + HorizontalDivider() + ListItem( + leadingContent = icon, + headlineContent = { Text(wording) }, + style = ListItemStyle.Primary, + onClick = { + onOpenWith(state.eventId) + } + ) if (state.canDelete) { HorizontalDivider() ListItem( @@ -236,6 +258,7 @@ internal fun MediaDetailsBottomSheetPreview() = ElementPreview { onShare = {}, onForward = {}, onDownload = {}, + onOpenWith = {}, onDelete = {}, onDismiss = {}, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt index 2bf4f6b37d..767ca04c31 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt @@ -20,6 +20,7 @@ sealed interface MediaGalleryEvents { data class Share(val eventId: EventId) : MediaGalleryEvents data class Forward(val eventId: EventId) : MediaGalleryEvents data class SaveOnDisk(val eventId: EventId) : MediaGalleryEvents + data class OpenWith(val eventId: EventId) : MediaGalleryEvents data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index cc26e69c33..2e669fefb2 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -105,6 +105,12 @@ class MediaGalleryPresenter( saveOnDisk(it) } } + is MediaGalleryEvents.OpenWith -> coroutineScope.launch { + mediaBottomSheetState = MediaBottomSheetState.Hidden + groupedMediaItems.dataOrNull().find(event.eventId)?.let { + openWith(it) + } + } is MediaGalleryEvents.Share -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.Hidden groupedMediaItems.dataOrNull().find(event.eventId)?.let { @@ -200,6 +206,17 @@ class MediaGalleryPresenter( } } + private suspend fun openWith(mediaItem: MediaItem.Event) { + downloadMedia(mediaItem) + .mapCatchingExceptions { localMedia -> + localMediaActions.open(localMedia) + } + .onFailure { + val snackbarMessage = SnackbarMessage(mediaActionsError(it)) + snackbarDispatcher.post(snackbarMessage) + } + } + private fun mediaActionsError(throwable: Throwable): Int { return if (throwable is ActivityNotFoundException) { R.string.error_no_compatible_app_found diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt index 6f7a201fdc..fe22376dee 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt @@ -173,6 +173,9 @@ fun MediaGalleryView( onDownload = { eventId -> state.eventSink(MediaGalleryEvents.SaveOnDisk(eventId)) }, + onOpenWith = { eventId -> + state.eventSink(MediaGalleryEvents.OpenWith(eventId)) + }, onDelete = { eventId -> state.eventSink( MediaGalleryEvents.ConfirmDelete( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 6b62a04d0f..5119198ff4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -65,7 +65,6 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.viewfolder.api.TextFileViewer import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.audio.api.AudioFocus -import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo import io.element.android.libraries.designsystem.components.async.AsyncFailure import io.element.android.libraries.designsystem.components.async.AsyncLoading @@ -85,7 +84,6 @@ import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.local.LocalMedia -import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.MediaDeleteConfirmationBottomSheet import io.element.android.libraries.mediaviewer.impl.details.MediaDetailsBottomSheet @@ -226,7 +224,6 @@ fun MediaViewerView( onInfoClick = { state.eventSink(MediaViewerEvent.OpenInfo(currentData)) }, - eventSink = state.eventSink ) } else -> { @@ -275,6 +272,11 @@ fun MediaViewerView( state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) } }, + onOpenWith = { + (currentData as? MediaViewerPageData.MediaViewerData)?.let { + state.eventSink(MediaViewerEvent.OpenWith(currentData)) + } + }, onDelete = { eventId -> (currentData as? MediaViewerPageData.MediaViewerData)?.let { state.eventSink( @@ -469,11 +471,9 @@ private fun MediaViewerTopBar( onShareClick: () -> Unit, onSaveClick: () -> Unit, onInfoClick: () -> Unit, - eventSink: (MediaViewerEvent) -> Unit, ) { val downloadedMedia by data.downloadedMedia val actionsEnabled = downloadedMedia.isSuccess() - val mimeType = data.mediaInfo.mimeType val senderName = data.mediaInfo.senderName val dateSent = data.mediaInfo.dateSent TopAppBar( @@ -508,23 +508,6 @@ private fun MediaViewerTopBar( ), navigationIcon = { BackButton(onClick = onBackClick) }, actions = { - IconButton( - enabled = actionsEnabled, - onClick = { - eventSink(MediaViewerEvent.OpenWith(data)) - }, - ) { - when (mimeType) { - MimeTypes.Apk -> Icon( - resourceId = R.drawable.ic_apk_install, - contentDescription = stringResource(id = CommonStrings.common_install_apk_android) - ) - else -> Icon( - imageVector = CompoundIcons.PopOut(), - contentDescription = stringResource(id = CommonStrings.action_open_with) - ) - } - } IconButton( onClick = onShareClick, enabled = actionsEnabled, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt index 74bc1bd648..b6b8b68466 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt @@ -116,6 +116,7 @@ private fun AndroidComposeTestRule.setMedia onShare: (EventId) -> Unit = EnsureNeverCalledWithParam(), onForward: (EventId) -> Unit = EnsureNeverCalledWithParam(), onDownload: (EventId) -> Unit = EnsureNeverCalledWithParam(), + onOpenWith: (EventId) -> Unit = EnsureNeverCalledWithParam(), onDelete: (EventId) -> Unit = EnsureNeverCalledWithParam(), onDismiss: () -> Unit = EnsureNeverCalled(), ) { @@ -126,6 +127,7 @@ private fun AndroidComposeTestRule.setMedia onShare = onShare, onForward = onForward, onDownload = onDownload, + onOpenWith = onOpenWith, onDelete = onDelete, onDismiss = onDismiss, ) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index d41841a9f0..e5eb07b871 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.mediaviewer.impl.viewer import android.net.Uri import androidx.activity.ComponentActivity +import androidx.annotation.StringRes import androidx.compose.ui.test.assertHasClickAction import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule @@ -63,19 +64,7 @@ class MediaViewerViewTest { } @Test - fun `clicking on open emit expected Event`() { - val data = aMediaViewerPageData( - downloadedMedia = AsyncData.Success(aLocalMedia(uri = mockMediaUrl)), - ) - testMenuAction( - data, - CommonStrings.action_open_with, - MediaViewerEvent.OpenWith(data), - ) - } - - @Test - fun `clicking on info emit expected Event`() { + fun `clicking on info emits expected Event`() { val data = aMediaViewerPageData( downloadedMedia = AsyncData.Success(aLocalMedia(uri = mockMediaUrl)), ) @@ -112,7 +101,7 @@ class MediaViewerViewTest { private fun testMenuAction( data: MediaViewerPageData.MediaViewerData, - contentDescriptionRes: Int, + @StringRes contentDescriptionRes: Int, expectedEvent: MediaViewerEvent, ) { val eventsRecorder = EventsRecorder() @@ -135,7 +124,7 @@ class MediaViewerViewTest { @Test @Config(qualifiers = "h1024dp") - fun `clicking on download emit expected Event`() { + fun `clicking on download emits expected Event`() { val data = aMediaViewerPageData() testBottomSheetAction( data, @@ -146,7 +135,7 @@ class MediaViewerViewTest { @Test @Config(qualifiers = "h1024dp") - fun `clicking on share emit expected Event`() { + fun `clicking on share emits expected Event`() { val data = aMediaViewerPageData() testBottomSheetAction( data, @@ -155,9 +144,20 @@ class MediaViewerViewTest { ) } + @Config(qualifiers = "h1024dp") + @Test + fun `clicking on open in emits expected Event`() { + val data = aMediaViewerPageData() + testBottomSheetAction( + data, + CommonStrings.action_open_with, + MediaViewerEvent.OpenWith(data), + ) + } + private fun testBottomSheetAction( data: MediaViewerPageData.MediaViewerData, - contentDescriptionRes: Int, + @StringRes textRes: Int, expectedEvent: MediaViewerEvent, ) { val eventsRecorder = EventsRecorder() @@ -168,7 +168,7 @@ class MediaViewerViewTest { eventSink = eventsRecorder ), ) - rule.clickOn(contentDescriptionRes) + rule.clickOn(textRes) eventsRecorder.assertList( listOf( MediaViewerEvent.OnNavigateTo(0), @@ -188,7 +188,7 @@ class MediaViewerViewTest { state = state, ) // Ensure that the action are visible - val contentDescription = rule.activity.getString(CommonStrings.action_open_with) + val contentDescription = rule.activity.getString(CommonStrings.action_share) rule.onNodeWithContentDescription(contentDescription) .assertExists() .assertHasClickAction() From 1e39736797b92c1d036ebc432799ed364e628d72 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Apr 2026 11:01:36 +0200 Subject: [PATCH 0213/1083] `MediaGalleryEvents` -> `MediaGalleryEvent` --- ...aGalleryEvents.kt => MediaGalleryEvent.kt} | 24 +++++----- .../impl/gallery/MediaGalleryPresenter.kt | 24 +++++----- .../impl/gallery/MediaGalleryState.kt | 2 +- .../impl/gallery/MediaGalleryView.kt | 44 +++++++++---------- .../impl/gallery/MediaGalleryPresenterTest.kt | 40 ++++++++--------- 5 files changed, 67 insertions(+), 67 deletions(-) rename libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/{MediaGalleryEvents.kt => MediaGalleryEvent.kt} (79%) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvent.kt similarity index 79% rename from libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvent.kt index 767ca04c31..219d5dbfb4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvent.kt @@ -14,22 +14,22 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.impl.model.MediaItem -sealed interface MediaGalleryEvents { - data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvents - data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvents - data class Share(val eventId: EventId) : MediaGalleryEvents - data class Forward(val eventId: EventId) : MediaGalleryEvents - data class SaveOnDisk(val eventId: EventId) : MediaGalleryEvents - data class OpenWith(val eventId: EventId) : MediaGalleryEvents - data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents - data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents +sealed interface MediaGalleryEvent { + data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvent + data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvent + data class Share(val eventId: EventId) : MediaGalleryEvent + data class Forward(val eventId: EventId) : MediaGalleryEvent + data class SaveOnDisk(val eventId: EventId) : MediaGalleryEvent + data class OpenWith(val eventId: EventId) : MediaGalleryEvent + data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvent + data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvent data class ConfirmDelete( val eventId: EventId, val mediaInfo: MediaInfo, val thumbnailSource: MediaSource?, - ) : MediaGalleryEvents + ) : MediaGalleryEvent - data object CloseBottomSheet : MediaGalleryEvents - data class Delete(val eventId: EventId) : MediaGalleryEvents + data object CloseBottomSheet : MediaGalleryEvent + data class Delete(val eventId: EventId) : MediaGalleryEvent } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index 2e669fefb2..e56267e291 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -88,44 +88,44 @@ class MediaGalleryPresenter( val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() localMediaActions.Configure() - fun handleEvent(event: MediaGalleryEvents) { + fun handleEvent(event: MediaGalleryEvent) { when (event) { - is MediaGalleryEvents.ChangeMode -> { + is MediaGalleryEvent.ChangeMode -> { mode = event.mode } - is MediaGalleryEvents.LoadMore -> coroutineScope.launch { + is MediaGalleryEvent.LoadMore -> coroutineScope.launch { mediaGalleryDataSource.loadMore(event.direction) } - is MediaGalleryEvents.Delete -> coroutineScope.launch { + is MediaGalleryEvent.Delete -> coroutineScope.launch { mediaGalleryDataSource.deleteItem(event.eventId) } - is MediaGalleryEvents.SaveOnDisk -> coroutineScope.launch { + is MediaGalleryEvent.SaveOnDisk -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.Hidden groupedMediaItems.dataOrNull().find(event.eventId)?.let { saveOnDisk(it) } } - is MediaGalleryEvents.OpenWith -> coroutineScope.launch { + is MediaGalleryEvent.OpenWith -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.Hidden groupedMediaItems.dataOrNull().find(event.eventId)?.let { openWith(it) } } - is MediaGalleryEvents.Share -> coroutineScope.launch { + is MediaGalleryEvent.Share -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.Hidden groupedMediaItems.dataOrNull().find(event.eventId)?.let { share(it) } } - is MediaGalleryEvents.Forward -> { + is MediaGalleryEvent.Forward -> { mediaBottomSheetState = MediaBottomSheetState.Hidden navigator.onForwardClick(event.eventId) } - is MediaGalleryEvents.ViewInTimeline -> { + is MediaGalleryEvent.ViewInTimeline -> { mediaBottomSheetState = MediaBottomSheetState.Hidden navigator.onViewInTimelineClick(event.eventId) } - is MediaGalleryEvents.OpenInfo -> coroutineScope.launch { + is MediaGalleryEvent.OpenInfo -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.MediaDetailsBottomSheetState( eventId = event.mediaItem.eventId(), canDelete = when (event.mediaItem.mediaInfo().senderId) { @@ -143,14 +143,14 @@ class MediaGalleryPresenter( }, ) } - is MediaGalleryEvents.ConfirmDelete -> { + is MediaGalleryEvent.ConfirmDelete -> { mediaBottomSheetState = MediaBottomSheetState.MediaDeleteConfirmationState( eventId = event.eventId, mediaInfo = event.mediaInfo, thumbnailSource = event.thumbnailSource, ) } - MediaGalleryEvents.CloseBottomSheet -> { + MediaGalleryEvent.CloseBottomSheet -> { mediaBottomSheetState = MediaBottomSheetState.Hidden } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryState.kt index 897e5d1e97..5dcb487632 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryState.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryState.kt @@ -20,7 +20,7 @@ data class MediaGalleryState( val groupedMediaItems: AsyncData, val mediaBottomSheetState: MediaBottomSheetState, val snackbarMessage: SnackbarMessage?, - val eventSink: (MediaGalleryEvents) -> Unit, + val eventSink: (MediaGalleryEvent) -> Unit, ) enum class MediaGalleryMode(val stringResource: Int) { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt index fe22376dee..be4faa6941 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt @@ -132,7 +132,7 @@ fun MediaGalleryView( index = mode.ordinal, count = MediaGalleryMode.entries.size, selected = state.mode == mode, - onClick = { state.eventSink(MediaGalleryEvents.ChangeMode(mode)) }, + onClick = { state.eventSink(MediaGalleryEvent.ChangeMode(mode)) }, text = stringResource(mode.stringResource), ) } @@ -162,23 +162,23 @@ fun MediaGalleryView( MediaDetailsBottomSheet( state = bottomSheetState, onViewInTimeline = { eventId -> - state.eventSink(MediaGalleryEvents.ViewInTimeline(eventId)) + state.eventSink(MediaGalleryEvent.ViewInTimeline(eventId)) }, onShare = { eventId -> - state.eventSink(MediaGalleryEvents.Share(eventId)) + state.eventSink(MediaGalleryEvent.Share(eventId)) }, onForward = { eventId -> - state.eventSink(MediaGalleryEvents.Forward(eventId)) + state.eventSink(MediaGalleryEvent.Forward(eventId)) }, onDownload = { eventId -> - state.eventSink(MediaGalleryEvents.SaveOnDisk(eventId)) + state.eventSink(MediaGalleryEvent.SaveOnDisk(eventId)) }, onOpenWith = { eventId -> - state.eventSink(MediaGalleryEvents.OpenWith(eventId)) + state.eventSink(MediaGalleryEvent.OpenWith(eventId)) }, onDelete = { eventId -> state.eventSink( - MediaGalleryEvents.ConfirmDelete( + MediaGalleryEvent.ConfirmDelete( eventId = eventId, mediaInfo = bottomSheetState.mediaInfo, thumbnailSource = bottomSheetState.thumbnailSource, @@ -186,7 +186,7 @@ fun MediaGalleryView( ) }, onDismiss = { - state.eventSink(MediaGalleryEvents.CloseBottomSheet) + state.eventSink(MediaGalleryEvent.CloseBottomSheet) }, ) } @@ -194,10 +194,10 @@ fun MediaGalleryView( MediaDeleteConfirmationBottomSheet( state = bottomSheetState, onDelete = { - state.eventSink(MediaGalleryEvents.Delete(it)) + state.eventSink(MediaGalleryEvent.Delete(it)) }, onDismiss = { - state.eventSink(MediaGalleryEvents.CloseBottomSheet) + state.eventSink(MediaGalleryEvent.CloseBottomSheet) }, ) } @@ -216,7 +216,7 @@ private fun MediaGalleryPage( val loadingItem = groupedMediaItems.dataOrNull()?.getItems(mode)?.singleOrNull() as? MediaItem.LoadingIndicator if (loadingItem != null) { LaunchedEffect(loadingItem.timestamp) { - state.eventSink(MediaGalleryEvents.LoadMore(loadingItem.direction)) + state.eventSink(MediaGalleryEvent.LoadMore(loadingItem.direction)) } } LoadingContent(mode) @@ -261,7 +261,7 @@ private fun AsyncData.isLoadingItems(mode: MediaGalleryMode): @Composable private fun MediaGalleryImages( imagesAndVideos: ImmutableList, - eventSink: (MediaGalleryEvents) -> Unit, + eventSink: (MediaGalleryEvent) -> Unit, onItemClick: (MediaItem.Event) -> Unit, ) { if (imagesAndVideos.isEmpty()) { @@ -282,7 +282,7 @@ private fun MediaGalleryImages( @Composable private fun MediaGalleryFiles( files: ImmutableList, - eventSink: (MediaGalleryEvents) -> Unit, + eventSink: (MediaGalleryEvent) -> Unit, onItemClick: (MediaItem.Event) -> Unit, ) { if (files.isEmpty()) { @@ -303,7 +303,7 @@ private fun MediaGalleryFiles( @Composable private fun MediaGalleryFilesList( files: ImmutableList, - eventSink: (MediaGalleryEvents) -> Unit, + eventSink: (MediaGalleryEvent) -> Unit, onItemClick: (MediaItem.Event) -> Unit, ) { val presenterFactories = LocalMediaItemPresenterFactories.current @@ -321,7 +321,7 @@ private fun MediaGalleryFilesList( file = item, onClick = { onItemClick(item) }, onLongClick = { - eventSink(MediaGalleryEvents.OpenInfo(item)) + eventSink(MediaGalleryEvent.OpenInfo(item)) }, ) is MediaItem.Audio -> AudioItemView( @@ -329,7 +329,7 @@ private fun MediaGalleryFilesList( audio = item, onClick = { onItemClick(item) }, onLongClick = { - eventSink(MediaGalleryEvents.OpenInfo(item)) + eventSink(MediaGalleryEvent.OpenInfo(item)) }, ) is MediaItem.Voice -> { @@ -339,7 +339,7 @@ private fun MediaGalleryFilesList( state = presenter.present(), voice = item, onLongClick = { - eventSink(MediaGalleryEvents.OpenInfo(item)) + eventSink(MediaGalleryEvent.OpenInfo(item)) }, ) } @@ -364,7 +364,7 @@ private fun MediaGalleryFilesList( @Composable private fun MediaGalleryImageGrid( imagesAndVideos: ImmutableList, - eventSink: (MediaGalleryEvents) -> Unit, + eventSink: (MediaGalleryEvent) -> Unit, onItemClick: (MediaItem.Event) -> Unit, ) { LazyVerticalGrid( @@ -406,7 +406,7 @@ private fun MediaGalleryImageGrid( image = item, onClick = { onItemClick(item) }, onLongClick = { - eventSink(MediaGalleryEvents.OpenInfo(item)) + eventSink(MediaGalleryEvent.OpenInfo(item)) }, ) is MediaItem.Video -> VideoItemView( @@ -414,7 +414,7 @@ private fun MediaGalleryImageGrid( video = item, onClick = { onItemClick(item) }, onLongClick = { - eventSink(MediaGalleryEvents.OpenInfo(item)) + eventSink(MediaGalleryEvent.OpenInfo(item)) }, ) is MediaItem.LoadingIndicator -> LoadingMoreIndicator( @@ -430,7 +430,7 @@ private fun MediaGalleryImageGrid( @Composable private fun LoadingMoreIndicator( item: MediaItem.LoadingIndicator, - eventSink: (MediaGalleryEvents) -> Unit, + eventSink: (MediaGalleryEvent) -> Unit, modifier: Modifier = Modifier ) { Box( @@ -455,7 +455,7 @@ private fun LoadingMoreIndicator( } val latestEventSink by rememberUpdatedState(eventSink) LaunchedEffect(item.timestamp) { - latestEventSink(MediaGalleryEvents.LoadMore(item.direction)) + latestEventSink(MediaGalleryEvent.LoadMore(item.direction)) } } } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt index 3069a4fd9d..9f1ad0e4a2 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt @@ -84,10 +84,10 @@ class MediaGalleryPresenterTest { presenter.test { val initialState = awaitFirstItem() assertThat(initialState.mode).isEqualTo(MediaGalleryMode.Images) - initialState.eventSink(MediaGalleryEvents.ChangeMode(MediaGalleryMode.Files)) + initialState.eventSink(MediaGalleryEvent.ChangeMode(MediaGalleryMode.Files)) val state = awaitItem() assertThat(state.mode).isEqualTo(MediaGalleryMode.Files) - state.eventSink(MediaGalleryEvents.ChangeMode(MediaGalleryMode.Images)) + state.eventSink(MediaGalleryEvent.ChangeMode(MediaGalleryMode.Images)) val imageModeState = awaitItem() assertThat(imageModeState.mode).isEqualTo(MediaGalleryMode.Images) } @@ -123,7 +123,7 @@ class MediaGalleryPresenterTest { eventId = AN_EVENT_ID, senderId = A_USER_ID, ) - initialState.eventSink(MediaGalleryEvents.OpenInfo(item)) + initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val state = awaitItem() assertThat(state.mediaBottomSheetState).isEqualTo( MediaBottomSheetState.MediaDetailsBottomSheetState( @@ -134,7 +134,7 @@ class MediaGalleryPresenterTest { ) ) // Close the bottom sheet - state.eventSink(MediaGalleryEvents.CloseBottomSheet) + state.eventSink(MediaGalleryEvent.CloseBottomSheet) val closedState = awaitItem() assertThat(closedState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) } @@ -170,7 +170,7 @@ class MediaGalleryPresenterTest { eventId = AN_EVENT_ID, senderId = A_USER_ID_2, ) - initialState.eventSink(MediaGalleryEvents.OpenInfo(item)) + initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val state = awaitItem() assertThat(state.mediaBottomSheetState).isEqualTo( MediaBottomSheetState.MediaDetailsBottomSheetState( @@ -181,7 +181,7 @@ class MediaGalleryPresenterTest { ) ) // Close the bottom sheet - state.eventSink(MediaGalleryEvents.CloseBottomSheet) + state.eventSink(MediaGalleryEvent.CloseBottomSheet) val closedState = awaitItem() assertThat(closedState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) } @@ -199,7 +199,7 @@ class MediaGalleryPresenterTest { val initialState = awaitFirstItem() // Delete bottom sheet val item = aMediaItemImage() - initialState.eventSink(MediaGalleryEvents.ConfirmDelete(AN_EVENT_ID, item.mediaInfo, item.thumbnailSource)) + initialState.eventSink(MediaGalleryEvent.ConfirmDelete(AN_EVENT_ID, item.mediaInfo, item.thumbnailSource)) val deleteState = awaitItem() assertThat(deleteState.mediaBottomSheetState).isEqualTo( MediaBottomSheetState.MediaDeleteConfirmationState( @@ -209,7 +209,7 @@ class MediaGalleryPresenterTest { ) ) // Close the bottom sheet - deleteState.eventSink(MediaGalleryEvents.CloseBottomSheet) + deleteState.eventSink(MediaGalleryEvent.CloseBottomSheet) val deleteClosedState = awaitItem() assertThat(deleteClosedState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) } @@ -226,7 +226,7 @@ class MediaGalleryPresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.Delete(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.Delete(AN_EVENT_ID)) deleteItemLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) } } @@ -236,7 +236,7 @@ class MediaGalleryPresenterTest { val presenter = createMediaGalleryPresenter() presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.Share(AN_EVENT_ID)) } } @@ -258,7 +258,7 @@ class MediaGalleryPresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.Share(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.snackbarMessage).isNull() } @@ -283,7 +283,7 @@ class MediaGalleryPresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.Share(AN_EVENT_ID)) skipItems(1) val finalState = awaitItem() assertThat(finalState.snackbarMessage).isInstanceOf(SnackbarMessage::class.java) @@ -295,7 +295,7 @@ class MediaGalleryPresenterTest { val presenter = createMediaGalleryPresenter() presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.SaveOnDisk(AN_EVENT_ID)) } } @@ -317,7 +317,7 @@ class MediaGalleryPresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.SaveOnDisk(AN_EVENT_ID)) skipItems(1) val finalState = awaitItem() assertThat(finalState.snackbarMessage?.messageResId).isEqualTo(CommonStrings.common_file_saved_on_disk_android) @@ -343,7 +343,7 @@ class MediaGalleryPresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID)) + initialState.eventSink(MediaGalleryEvent.SaveOnDisk(AN_EVENT_ID)) skipItems(1) val finalState = awaitItem() assertThat(finalState.snackbarMessage).isInstanceOf(SnackbarMessage::class.java) @@ -373,10 +373,10 @@ class MediaGalleryPresenterTest { eventId = AN_EVENT_ID, senderId = A_USER_ID, ) - initialState.eventSink(MediaGalleryEvents.OpenInfo(item)) + initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) - withBottomSheetState.eventSink(MediaGalleryEvents.ViewInTimeline(AN_EVENT_ID)) + withBottomSheetState.eventSink(MediaGalleryEvent.ViewInTimeline(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) onViewInTimelineClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) @@ -406,10 +406,10 @@ class MediaGalleryPresenterTest { eventId = AN_EVENT_ID, senderId = A_USER_ID, ) - initialState.eventSink(MediaGalleryEvents.OpenInfo(item)) + initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) - withBottomSheetState.eventSink(MediaGalleryEvents.Forward(AN_EVENT_ID)) + withBottomSheetState.eventSink(MediaGalleryEvent.Forward(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) onForwardClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) @@ -427,7 +427,7 @@ class MediaGalleryPresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(MediaGalleryEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS)) + initialState.eventSink(MediaGalleryEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS)) loadMoreLambda.assertions().isCalledOnce().with(value(Timeline.PaginationDirection.BACKWARDS)) } } From 630b0c8098b4e00e9990d00283333a47793d75e1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Apr 2026 12:07:56 +0200 Subject: [PATCH 0214/1083] Improve and add test --- .../impl/gallery/MediaGalleryPresenterTest.kt | 78 ++++++++++++++++++- .../mediaviewer/test/FakeLocalMediaActions.kt | 30 +++---- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt index 9f1ad0e4a2..6dd58a6086 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt @@ -6,6 +6,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.element.android.libraries.mediaviewer.impl.gallery import android.net.Uri @@ -27,6 +29,7 @@ import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline +import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.datasource.FakeMediaGalleryDataSource import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryDataSource import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState @@ -39,6 +42,8 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test import io.mockk.mockk +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -52,8 +57,12 @@ class MediaGalleryPresenterTest { @Test fun `present - initial state`() = runTest { + val configureLambda = lambdaRecorder { } val startLambda = lambdaRecorder { } val presenter = createMediaGalleryPresenter( + localMediaActions = FakeLocalMediaActions( + configureResult = configureLambda, + ), mediaGalleryDataSource = FakeMediaGalleryDataSource( startLambda = startLambda, ), @@ -70,6 +79,7 @@ class MediaGalleryPresenterTest { assertThat(initialState.groupedMediaItems.isUninitialized()).isTrue() assertThat(initialState.snackbarMessage).isNull() } + configureLambda.assertions().isCalledOnce() startLambda.assertions().isCalledOnce() } @@ -304,15 +314,20 @@ class MediaGalleryPresenterTest { val mediaGalleryDataSource = FakeMediaGalleryDataSource( startLambda = { }, ) + val saveOnDiskResult = lambdaRecorder> { _ -> Result.success(Unit) } + val media = aMediaItemImage(eventId = AN_EVENT_ID) mediaGalleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( - imageAndVideoItems = listOf(aMediaItemImage(eventId = AN_EVENT_ID)), + imageAndVideoItems = listOf(media), fileItems = emptyList(), ) ) ) val presenter = createMediaGalleryPresenter( + localMediaActions = FakeLocalMediaActions( + saveOnDiskResult = saveOnDiskResult, + ), mediaGalleryDataSource = mediaGalleryDataSource, ) presenter.test { @@ -321,6 +336,67 @@ class MediaGalleryPresenterTest { skipItems(1) val finalState = awaitItem() assertThat(finalState.snackbarMessage?.messageResId).isEqualTo(CommonStrings.common_file_saved_on_disk_android) + saveOnDiskResult.assertions().isCalledOnce().with( + value( + LocalMedia( + uri = mockMediaUri, + info = media.mediaInfo, + ) + ) + ) + } + } + + @Test + fun `present - open with closes the bottom sheet and invokes the navigator`() = runTest { + val mediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ) + val openWithResult = lambdaRecorder> { _ -> Result.success(Unit) } + val item = aMediaItemImage( + eventId = AN_EVENT_ID, + senderId = A_USER_ID, + ) + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + aGroupedMediaItems( + imageAndVideoItems = listOf(item), + fileItems = emptyList(), + ) + ) + ) + val presenter = createMediaGalleryPresenter( + localMediaActions = FakeLocalMediaActions( + openResult = openWithResult, + ), + mediaGalleryDataSource = mediaGalleryDataSource, + room = FakeJoinedRoom( + createTimelineResult = { Result.success(FakeTimeline()) }, + baseRoom = FakeBaseRoom( + roomPermissions = FakeRoomPermissions( + canRedactOwn = true + ), + ), + ), + ) + presenter.test { + skipItems(1) + val initialState = awaitFirstItem() + initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) + val withBottomSheetState = awaitItem() + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + withBottomSheetState.eventSink(MediaGalleryEvent.OpenWith(AN_EVENT_ID)) + val finalState = awaitItem() + assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) + advanceUntilIdle() + openWithResult.assertions().isCalledOnce().with( + value( + LocalMedia( + uri = mockMediaUri, + info = item.mediaInfo, + ) + ) + ) } } diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt index 875be941db..d048f73eab 100644 --- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt +++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaActions.kt @@ -11,37 +11,29 @@ package io.element.android.libraries.mediaviewer.test import androidx.compose.runtime.Composable import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask -class FakeLocalMediaActions : LocalMediaActions { - var shouldFail = false - +class FakeLocalMediaActions( + val configureResult: () -> Unit = { }, + val saveOnDiskResult: (LocalMedia) -> Result = { lambdaError() }, + val shareResult: (LocalMedia) -> Result = { lambdaError() }, + val openResult: (LocalMedia) -> Result = { lambdaError() }, +) : LocalMediaActions { @Composable override fun Configure() { - // NOOP + configureResult() } override suspend fun saveOnDisk(localMedia: LocalMedia): Result = simulateLongTask { - if (shouldFail) { - Result.failure(RuntimeException()) - } else { - Result.success(Unit) - } + saveOnDiskResult(localMedia) } override suspend fun share(localMedia: LocalMedia): Result = simulateLongTask { - if (shouldFail) { - Result.failure(RuntimeException()) - } else { - Result.success(Unit) - } + shareResult(localMedia) } override suspend fun open(localMedia: LocalMedia): Result = simulateLongTask { - if (shouldFail) { - Result.failure(RuntimeException()) - } else { - Result.success(Unit) - } + openResult(localMedia) } } From 769341e4f2d557da53cf9f1d17230674ad8f8804 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Apr 2026 12:16:52 +0200 Subject: [PATCH 0215/1083] Remove some dividers. --- .../mediaviewer/impl/details/MediaDetailsBottomSheet.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index fc377e5cae..3c29bd9044 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -104,7 +104,6 @@ fun MediaDetailsBottomSheet( onViewInTimeline(state.eventId) } ) - HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), headlineContent = { Text(stringResource(CommonStrings.action_share)) }, @@ -121,7 +120,6 @@ fun MediaDetailsBottomSheet( onForward(state.eventId) } ) - HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), headlineContent = { Text(stringResource(CommonStrings.action_download)) }, @@ -141,7 +139,6 @@ fun MediaDetailsBottomSheet( MimeTypes.Apk -> stringResource(id = CommonStrings.common_install_apk_android) else -> stringResource(id = CommonStrings.action_open_with) } - HorizontalDivider() ListItem( leadingContent = icon, headlineContent = { Text(wording) }, From c1678f22e6e304aa9cf907b8a063bf396bba423a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Apr 2026 12:21:20 +0200 Subject: [PATCH 0216/1083] Add more preview for MediaDetailsBottomSheetPreview --- .../impl/details/MediaDetailsBottomSheet.kt | 7 ++- .../MediaDetailsBottomSheetStateProvider.kt | 43 +++++++++++++++++++ .../mediaviewer/impl/details/Preview.kt | 15 ------- 3 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index 3c29bd9044..3450989c95 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +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 @@ -248,9 +249,11 @@ private fun SectionText( @PreviewsDayNight @Composable -internal fun MediaDetailsBottomSheetPreview() = ElementPreview { +internal fun MediaDetailsBottomSheetPreview( + @PreviewParameter(MediaDetailsBottomSheetStateProvider::class) state: MediaBottomSheetState.MediaDetailsBottomSheetState, +) = ElementPreview { MediaDetailsBottomSheet( - state = aMediaDetailsBottomSheetState(), + state = state, onViewInTimeline = {}, onShare = {}, onForward = {}, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt new file mode 100644 index 0000000000..5da48a0838 --- /dev/null +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl.details + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.mediaviewer.api.MediaInfo +import io.element.android.libraries.mediaviewer.api.anApkMediaInfo +import io.element.android.libraries.mediaviewer.api.anImageMediaInfo + +open class MediaDetailsBottomSheetStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aMediaDetailsBottomSheetState(), + aMediaDetailsBottomSheetState( + canDelete = false, + ), + aMediaDetailsBottomSheetState( + mediaInfo = anApkMediaInfo(), + ), + ) +} + +fun aMediaDetailsBottomSheetState( + dateSentFull: String = "December 6, 2024 at 12:59", + canDelete: Boolean = true, + mediaInfo: MediaInfo = anImageMediaInfo( + senderName = "Alice", + dateSentFull = dateSentFull, + ), +): MediaBottomSheetState.MediaDetailsBottomSheetState { + return MediaBottomSheetState.MediaDetailsBottomSheetState( + eventId = EventId("\$eventId"), + canDelete = canDelete, + mediaInfo = mediaInfo, + thumbnailSource = null, + ) +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt index a152a32091..17138b4fa7 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt @@ -11,21 +11,6 @@ package io.element.android.libraries.mediaviewer.impl.details import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.mediaviewer.api.anImageMediaInfo -fun aMediaDetailsBottomSheetState( - dateSentFull: String = "December 6, 2024 at 12:59", - canDelete: Boolean = true, -): MediaBottomSheetState.MediaDetailsBottomSheetState { - return MediaBottomSheetState.MediaDetailsBottomSheetState( - eventId = EventId("\$eventId"), - canDelete = canDelete, - mediaInfo = anImageMediaInfo( - senderName = "Alice", - dateSentFull = dateSentFull, - ), - thumbnailSource = null, - ) -} - fun aMediaDeleteConfirmationState(): MediaBottomSheetState.MediaDeleteConfirmationState { return MediaBottomSheetState.MediaDeleteConfirmationState( eventId = EventId("\$eventId"), From c9b48d32b0dbcbd94ef67e816bcc3986edec2079 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 22 Apr 2026 10:40:25 +0000 Subject: [PATCH 0217/1083] Update screenshots --- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png | 3 +++ ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 3 +++ ...viewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png | 3 +++ ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 3 +++ ...ies.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png | 4 ++-- ...s.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_16_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png | 4 ++-- 38 files changed, 80 insertions(+), 68 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png index 595aae659f..5a9605e9dd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:684f94bece9c9cc117eef1cdad6fca99bb085158454a890592254f27c57e9b0e -size 39715 +oid sha256:fd9027f3684b91a8867bf0cb7c1eb3925edfc4982d40cc33414997e38c068d45 +size 40887 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png new file mode 100644 index 0000000000..c48dc8fdf9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:736ac91d14dd16f8d1cc7040fc69c08c97d2525c3876b90376a85764157e2910 +size 40859 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png new file mode 100644 index 0000000000..909387767f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:070e17d4807133d5966bd3f2ae52df258294466479e2fe96a7943571b0fa81e7 +size 40068 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png index 847d2f35db..cdddf1c59c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:881a6235b66bd13269103bcc7070e389041652da49ecdba68c6caf151301b6c0 -size 38428 +oid sha256:6c9d002e8d23dc85be883fae56d1266dadfd9fbd73a9b8a396b8953be9b7ff23 +size 39445 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png new file mode 100644 index 0000000000..6c2870a35f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7982c873e18aeb3c2ae32638bc0c6be7a36f9b2326e303306c5c63a2ebeebbab +size 39429 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png new file mode 100644 index 0000000000..a77470a1b0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3b0f78545228d76ef59bd777eec4dd72b0dbcef8b7bae51b6f3c05b0f1cbd87 +size 38943 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png index acc977cd8d..f6769f22ba 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9dd2d35e1c0a3b3a9576e35b8a5ad4a3d08441b8257bb48edd0a0816c9f24c68 -size 39634 +oid sha256:41d66efcb35b7c75452311d7646c73a66e2906cda1ee6da99d9b216121a8f073 +size 40805 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png index 47027cdf92..253add27e2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa2ca41cebe2e37843f74319a56f3c18103929f06765f0950cd1945440909e63 -size 38223 +oid sha256:b704a5672030f94f4d331784c5307f38b156e11dc69e9b17890a0aef3de26241 +size 39241 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png index 60c5e812ba..9c0c4b40f2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e514d7f36fe25150d66c2d2092982a696196a5a0a2674eef97b7231c0c03bef -size 699410 +oid sha256:64d834437c7049ec9d81331b382c4bf0cdbc603de8e403e0addf6a4947e815a6 +size 700141 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png index 5a96554c0a..bcbfc91e12 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:712af2723a0656ffe927f1cd488d3117f5b450fa405dad307b0c88a9f2483f9c -size 698704 +oid sha256:398c2908d73fb30117ce917b25e930c578eaf2da5e0c41e126f262f129bda8cc +size 699710 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png index d0139ec184..d2231ed54c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52174b55b1737787260a454c59f243b0e3f6327ef5ec71464744def928d165d4 -size 206785 +oid sha256:041669475888f2f0c3b2d34502ae72098547340d8c2422ea2a674d38eb6a6241 +size 207620 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png index a32a45029c..a737f60d1b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:99478fe3d9d44e9cda39f33748c70017203a2cce5cb855605740a29360221bd5 -size 184910 +oid sha256:348a194ad17a0a0dffda47c7387edde99436d543e9bff1726608946e92558830 +size 185553 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png index a855818ac6..36ecce8294 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:062f8342a3a3715498ca34488c2d9ffe09c1e6dbbe04df09e88fd107a33b174a -size 653228 +oid sha256:5aa3bca6cd248ac4725fb35aa11a465029dc534b8b167aedbf3e9bc240577e9c +size 654171 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png index accbd26985..312b19a389 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3effa629295c12d2248924cf298599f3bd28975ecc76fac84f771c16266d738e -size 698895 +oid sha256:b23ef4fb29f51e308b74681017fcee257308edbd1e218e4daf5736501c70e0de +size 699637 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png index b9dabc97ee..88e1c15416 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fd3b7065860d1e51fe51a0a6e3f4a9e61a77ea91cefe85cc3aa3560c4cc6bb2 -size 252253 +oid sha256:af91214346ed087a8cf936b9ddc5b78e8840a48f6dab6b856ad79abb5fef1ea0 +size 252778 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png index f11d4fc3fc..c63d5a9110 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f9ee78e2a034f34d77a438d305a5cc63ea583df80f83a14b1d81fcf74ca93f4 -size 665416 +oid sha256:bd5b76aefb0fde0605556e78c7286bf8ee8dd465def0e3095ebc97ce3427eafa +size 666239 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png index 5e081d3c4e..8a6ebb2746 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1e91c66363a5af74d4345f7837db178410c078e390b0cf9296d0ba4b3dfd7cb -size 207004 +oid sha256:c56b22d79924d1f463f01428d5be1c69c8068b94a953160fae59a9f6faa112ad +size 206047 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png index d61e0a50b9..8311ff7878 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9eb950f3c0d34a796ebd7635ff736023742d5e6a243912f3ad2234ecf08694b2 -size 183220 +oid sha256:1fcaacd813136d9cb22d0542480fcef2be05cae7ec44c0c3683874086e1c7a4b +size 184107 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png index f2352c88f8..a092bf37ac 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f6c84fbd21949a3d9d355bfb627b8a70f65fc669cb6b6818a325fe4577351f9 -size 196092 +oid sha256:9e23aad00065523bf1ee0e26cd094eb6a9bdd73d65f0bd9cac62cb79e7876481 +size 196533 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png index bd37e3eb79..619bd4e8c6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26bd927acc578cb3585f6e101c066f0a6adb6a6e424dcd196388d5a838d8b22b -size 196396 +oid sha256:9d98ceaeb669342160d04783f07fbb21929d8be46d30181b60e0f09a99abfe79 +size 197127 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png index 69515d4326..bbea97e0b3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c4440f5ed01f2c1b405bb2d444c52455ea8ee1c094baf7d2f85bd9a9ff98b02 -size 210117 +oid sha256:e72ef42ad838837ce2427af5677931f5db68f876eccc297894c7a2cdd437cffa +size 210729 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png index 5d254988c9..67bec8b0d3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11f140569061e21e6b546118b57340a0830779580498a31627acb2e6c7313471 -size 210490 +oid sha256:58a323c4f06745a877ea546870fbe69ec927aea50584001b3871cad833fca1d4 +size 211343 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png index 03f85f5233..0b90eca670 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b5af8a5aae566e72e0223d40a5978ab191911c68739e417503d8fd5058f19e7 -size 389408 +oid sha256:f17669c1a3a65bafa5786ac23245117b6956d154a4ddea2e95de9070a5bff07e +size 390004 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png index 7aa5cf885d..db9cb01f26 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aec4a5e70320024eb053c56445c226758818550745f2d2ddfec16721e43b6d90 -size 388674 +oid sha256:2bd5c7a42aebb6c2ebce9a529bafb23145e5a3a1d10270385386ecde9ca03c19 +size 389486 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png index 47027cdf92..253add27e2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa2ca41cebe2e37843f74319a56f3c18103929f06765f0950cd1945440909e63 -size 38223 +oid sha256:b704a5672030f94f4d331784c5307f38b156e11dc69e9b17890a0aef3de26241 +size 39241 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png index 4094507bdd..1259041506 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e53770850ee2e0d011ed91360a2c02abf80b27cc2cee66699331684637d469a -size 30960 +oid sha256:7e15267ee448fae18a63022ab464769528b07585f13ccdb2e8c5589584759d69 +size 31485 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png index 89b6cfbfba..d5b81bb469 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c7c09c4ff8e66c23d3cdf5c79ffe2d3305d569e3aa1e239dfbb981537e467cd -size 133920 +oid sha256:55671428c52d37c3f63f8b3410817d4e893e2f4327b31b227bc7b7d9ff84b884 +size 134680 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_16_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_16_en.png index 9836fe106f..7ff9c8a971 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_16_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df718693c63e4de07d17486a80103240f8f2d56a21aaf1a2b18a9237f105364d -size 113630 +oid sha256:730cffc57e88440ec4607238b383e68aada1907e6f9829a3bdc4bf8a467c1788 +size 114080 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png index dc06b5afc9..5b167203f5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e353d24c2b9b49abaa11e064b1581215ad65154d0e67372fe24684ba2695a0e -size 442063 +oid sha256:6bddbe3b0e66e0a2ce49b39321057c94427933de81663f680237a398e9929ba3 +size 442729 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png index 5b86c94b5b..aa35a1751a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0ed6080a007c98867a5c4f9b32570ab3042b34030b5210867110374064ee8fc -size 389436 +oid sha256:9d8a4b42d3857ddaa1ea86d4ab3a872c5fa0014061b2a116895616bee25424d1 +size 390037 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png index eb7fa67df4..5663001649 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4feb42b25bd952a0305ad2b1c4cab9934586693d804336e1ba23e9b247f712c0 -size 94961 +oid sha256:1c4b715349adcfdf5c3cdd95844846170b43dc191801156b2e822f0eaeb92033 +size 95392 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png index f55ed35a60..167467d515 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eaf4fb4908967c6092de9be0d7ca33108f0f507605d7591395a08594763fb0fe -size 396202 +oid sha256:3bd4a96daaa24c01b7d0007fdd14460dc80c65c13d0ccc7a887b04fd90e9fa99 +size 396805 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png index 8a41530aee..26dcbe4099 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb6999796f9275adce6b5e05b362649cb738c759af649f7bbb9c0ff01548a579 -size 131776 +oid sha256:f7bee65567cced59131d471b5c3795347a2ef52cf64ff74b47f1c983a0b4a36f +size 130718 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png index fbddf16dfd..56e01cbc01 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04ba5da6b618ae3abf4ca06b4ae1baa13e46673b0be73ada2b15cefd79063122 -size 112146 +oid sha256:3aef5ebd6889b0fc8345db6aefeb6d2cc26a5a2349632dac2e258caa87c28b53 +size 112850 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png index f13a902fe0..31403f8980 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8273abc2f10e6c42a65fb6aef2e237d58b6e4d858df1f35be255b7030fb63c44 -size 123522 +oid sha256:b9cd21b6d9a9d0a9ef656bf895d6d135ba76160695355ce034fe985991d6955b +size 123949 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png index ce0848b5b3..bc0720e4b4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:456dc57223044ece1f4136dc01765e41a0b649c827ad6e6b08370e53a7015dbb -size 14378 +oid sha256:2dce0794e50116043fde9f6eb76b0c05ca21fc9cee26bde01618024c24c154b2 +size 14952 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png index 06e1c13225..f2ff11333d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5fdeb06fb15486d2d4949a38da2f6eed5ef94a0386e9daaa83a6b00bec9e392 -size 137096 +oid sha256:f3cea16c42488306fe29fd22362a0d37c1eeb0fbb1db48f26ad7ff18f6b196ae +size 137605 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png index dfe63cccae..62de7a4953 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b64a6f9fe548897b6b34961bc077718265acdb8f894d5d2d697d5409c633368 -size 137247 +oid sha256:58655e1846dbe73c287073ac909ee6c881a0ad800e8852653116fdbfd043b9a0 +size 137881 From 7bbdecc7a87b1790e3a8d7ec14ee726c62f3ddf8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Apr 2026 14:42:56 +0200 Subject: [PATCH 0218/1083] Rename sub classes of MediaBottomSheetState and improve preview of MediaDeleteConfirmationBottomSheet --- .../impl/details/MediaBottomSheetState.kt | 14 ++++---- ...tomSheetStateDeleteConfirmationProvider.kt | 36 +++++++++++++++++++ ...> MediaBottomSheetStateDetailsProvider.kt} | 29 +++++++-------- .../MediaDeleteConfirmationBottomSheet.kt | 11 +++--- .../impl/details/MediaDetailsBottomSheet.kt | 4 +-- .../mediaviewer/impl/details/Preview.kt | 22 ------------ .../impl/gallery/MediaGalleryPresenter.kt | 4 +-- .../impl/gallery/MediaGalleryStateProvider.kt | 4 +-- .../impl/gallery/MediaGalleryView.kt | 4 +-- .../impl/viewer/MediaViewerPresenter.kt | 4 +-- .../impl/viewer/MediaViewerStateProvider.kt | 8 ++--- .../impl/viewer/MediaViewerView.kt | 4 +-- .../MediaDeleteConfirmationBottomSheetTest.kt | 6 ++-- .../details/MediaDetailsBottomSheetTest.kt | 14 ++++---- .../impl/gallery/MediaGalleryPresenterTest.kt | 12 +++---- .../impl/viewer/MediaViewerPresenterTest.kt | 12 +++---- .../impl/viewer/MediaViewerViewTest.kt | 4 +-- 17 files changed, 103 insertions(+), 89 deletions(-) create mode 100644 libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt rename libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/{MediaDetailsBottomSheetStateProvider.kt => MediaBottomSheetStateDetailsProvider.kt} (53%) delete mode 100644 libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt index 7cd4dee318..722126fac6 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt @@ -15,16 +15,16 @@ import io.element.android.libraries.mediaviewer.api.MediaInfo sealed interface MediaBottomSheetState { data object Hidden : MediaBottomSheetState - data class MediaDeleteConfirmationState( - val eventId: EventId, - val mediaInfo: MediaInfo, - val thumbnailSource: MediaSource?, - ) : MediaBottomSheetState - - data class MediaDetailsBottomSheetState( + data class Details( val eventId: EventId?, val canDelete: Boolean, val mediaInfo: MediaInfo, val thumbnailSource: MediaSource?, ) : MediaBottomSheetState + + data class DeleteConfirmation( + val eventId: EventId, + val mediaInfo: MediaInfo, + val thumbnailSource: MediaSource?, + ) : MediaBottomSheetState } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt new file mode 100644 index 0000000000..d5fd46d507 --- /dev/null +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 2024, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl.details + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.mediaviewer.api.MediaInfo +import io.element.android.libraries.mediaviewer.api.anImageMediaInfo + +open class MediaBottomSheetStateDeleteConfirmationProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aMediaBottomSheetStateDeleteConfirmation(), + aMediaBottomSheetStateDeleteConfirmation( + thumbnailSource = MediaSource("url_thumbnail") + ), + ) +} + +fun aMediaBottomSheetStateDeleteConfirmation( + mediaInfo: MediaInfo = anImageMediaInfo( + senderName = "Alice", + ), + thumbnailSource: MediaSource? = null, +) = MediaBottomSheetState.DeleteConfirmation( + eventId = EventId("\$eventId"), + mediaInfo = mediaInfo, + thumbnailSource = thumbnailSource, +) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt similarity index 53% rename from libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt index 5da48a0838..ad8e6e30a0 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt @@ -13,31 +13,28 @@ import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.anApkMediaInfo import io.element.android.libraries.mediaviewer.api.anImageMediaInfo -open class MediaDetailsBottomSheetStateProvider : PreviewParameterProvider { - override val values: Sequence +open class MediaBottomSheetStateDetailsProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( - aMediaDetailsBottomSheetState(), - aMediaDetailsBottomSheetState( + aMediaBottomSheetStateDetails(), + aMediaBottomSheetStateDetails( canDelete = false, ), - aMediaDetailsBottomSheetState( + aMediaBottomSheetStateDetails( mediaInfo = anApkMediaInfo(), ), ) } -fun aMediaDetailsBottomSheetState( - dateSentFull: String = "December 6, 2024 at 12:59", +fun aMediaBottomSheetStateDetails( canDelete: Boolean = true, mediaInfo: MediaInfo = anImageMediaInfo( senderName = "Alice", - dateSentFull = dateSentFull, + dateSentFull = "December 6, 2024 at 12:59", ), -): MediaBottomSheetState.MediaDetailsBottomSheetState { - return MediaBottomSheetState.MediaDetailsBottomSheetState( - eventId = EventId("\$eventId"), - canDelete = canDelete, - mediaInfo = mediaInfo, - thumbnailSource = null, - ) -} +) = MediaBottomSheetState.Details( + eventId = EventId("\$eventId"), + canDelete = canDelete, + mediaInfo = mediaInfo, + thumbnailSource = null, +) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt index e3b16df684..84712eb10a 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import io.element.android.compound.theme.ElementTheme @@ -49,7 +50,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @OptIn(ExperimentalMaterial3Api::class) @Composable fun MediaDeleteConfirmationBottomSheet( - state: MediaBottomSheetState.MediaDeleteConfirmationState, + state: MediaBottomSheetState.DeleteConfirmation, onDelete: (EventId) -> Unit, onDismiss: () -> Unit, modifier: Modifier = Modifier, @@ -105,7 +106,7 @@ fun MediaDeleteConfirmationBottomSheet( @Composable private fun MediaRow( - state: MediaBottomSheetState.MediaDeleteConfirmationState, + state: MediaBottomSheetState.DeleteConfirmation, modifier: Modifier = Modifier, ) { Row( @@ -160,9 +161,11 @@ private fun MediaRow( @PreviewsDayNight @Composable -internal fun MediaDeleteConfirmationBottomSheetPreview() = ElementPreview { +internal fun MediaDeleteConfirmationBottomSheetPreview( + @PreviewParameter(provider = MediaBottomSheetStateDeleteConfirmationProvider::class) state: MediaBottomSheetState.DeleteConfirmation, +) = ElementPreview { MediaDeleteConfirmationBottomSheet( - state = aMediaDeleteConfirmationState(), + state = state, onDelete = {}, onDismiss = {}, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index 3450989c95..a3c3d02de8 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -54,7 +54,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @OptIn(ExperimentalMaterial3Api::class) @Composable fun MediaDetailsBottomSheet( - state: MediaBottomSheetState.MediaDetailsBottomSheetState, + state: MediaBottomSheetState.Details, onViewInTimeline: (EventId) -> Unit, onShare: (EventId) -> Unit, onForward: (EventId) -> Unit, @@ -250,7 +250,7 @@ private fun SectionText( @PreviewsDayNight @Composable internal fun MediaDetailsBottomSheetPreview( - @PreviewParameter(MediaDetailsBottomSheetStateProvider::class) state: MediaBottomSheetState.MediaDetailsBottomSheetState, + @PreviewParameter(MediaBottomSheetStateDetailsProvider::class) state: MediaBottomSheetState.Details, ) = ElementPreview { MediaDetailsBottomSheet( state = state, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt deleted file mode 100644 index 17138b4fa7..0000000000 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/Preview.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.mediaviewer.impl.details - -import io.element.android.libraries.matrix.api.core.EventId -import io.element.android.libraries.mediaviewer.api.anImageMediaInfo - -fun aMediaDeleteConfirmationState(): MediaBottomSheetState.MediaDeleteConfirmationState { - return MediaBottomSheetState.MediaDeleteConfirmationState( - eventId = EventId("\$eventId"), - mediaInfo = anImageMediaInfo( - senderName = "Alice", - ), - thumbnailSource = null, - ) -} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index e56267e291..ac9b365099 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -126,7 +126,7 @@ class MediaGalleryPresenter( navigator.onViewInTimelineClick(event.eventId) } is MediaGalleryEvent.OpenInfo -> coroutineScope.launch { - mediaBottomSheetState = MediaBottomSheetState.MediaDetailsBottomSheetState( + mediaBottomSheetState = MediaBottomSheetState.Details( eventId = event.mediaItem.eventId(), canDelete = when (event.mediaItem.mediaInfo().senderId) { null -> false @@ -144,7 +144,7 @@ class MediaGalleryPresenter( ) } is MediaGalleryEvent.ConfirmDelete -> { - mediaBottomSheetState = MediaBottomSheetState.MediaDeleteConfirmationState( + mediaBottomSheetState = MediaBottomSheetState.DeleteConfirmation( eventId = event.eventId, mediaInfo = event.mediaInfo, thumbnailSource = event.thumbnailSource, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt index a19f810e45..7b5edf594a 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt @@ -13,7 +13,7 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.media.WaveFormSamples import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState -import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState +import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems import io.element.android.libraries.mediaviewer.impl.model.MediaItem import io.element.android.libraries.mediaviewer.impl.model.aMediaItemAudio @@ -79,7 +79,7 @@ open class MediaGalleryStateProvider : PreviewParameterProvider Unit - is MediaBottomSheetState.MediaDetailsBottomSheetState -> { + is MediaBottomSheetState.Details -> { MediaDetailsBottomSheet( state = bottomSheetState, onViewInTimeline = { eventId -> @@ -190,7 +190,7 @@ fun MediaGalleryView( }, ) } - is MediaBottomSheetState.MediaDeleteConfirmationState -> { + is MediaBottomSheetState.DeleteConfirmation -> { MediaDeleteConfirmationBottomSheet( state = bottomSheetState, onDelete = { 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 0128e40e65..b7631a7039 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 @@ -131,7 +131,7 @@ class MediaViewerPresenter( ) } is MediaViewerEvent.OpenInfo -> coroutineScope.launch { - mediaBottomSheetState = MediaBottomSheetState.MediaDetailsBottomSheetState( + mediaBottomSheetState = MediaBottomSheetState.Details( eventId = event.data.eventId, canDelete = when (event.data.mediaInfo.senderId) { null -> false @@ -143,7 +143,7 @@ class MediaViewerPresenter( ) } is MediaViewerEvent.ConfirmDelete -> { - mediaBottomSheetState = MediaBottomSheetState.MediaDeleteConfirmationState( + mediaBottomSheetState = MediaBottomSheetState.DeleteConfirmation( eventId = event.eventId, mediaInfo = event.data.mediaInfo, thumbnailSource = event.data.thumbnailSource ?: event.data.mediaSource, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index e7d8fd55ae..ef9b533586 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -25,8 +25,8 @@ import io.element.android.libraries.mediaviewer.api.anAudioMediaInfo import io.element.android.libraries.mediaviewer.api.anImageMediaInfo import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState -import io.element.android.libraries.mediaviewer.impl.details.aMediaDeleteConfirmationState -import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState +import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDeleteConfirmation +import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails import kotlinx.collections.immutable.toImmutableList private const val LONG_CAPTION = "This is a very long caption that should be scrollable in the media viewer. " + @@ -141,10 +141,10 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) }, aMediaViewerState( - mediaBottomSheetState = aMediaDetailsBottomSheetState(), + mediaBottomSheetState = aMediaBottomSheetStateDetails(), ), aMediaViewerState( - mediaBottomSheetState = aMediaDeleteConfirmationState(), + mediaBottomSheetState = aMediaBottomSheetStateDeleteConfirmation(), ), anAudioMediaInfo( waveForm = WaveFormSamples.realisticWaveForm, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 5119198ff4..abea2f66d2 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -253,7 +253,7 @@ fun MediaViewerView( when (val bottomSheetState = state.mediaBottomSheetState) { MediaBottomSheetState.Hidden -> Unit - is MediaBottomSheetState.MediaDetailsBottomSheetState -> { + is MediaBottomSheetState.Details -> { MediaDetailsBottomSheet( state = bottomSheetState, onViewInTimeline = { @@ -292,7 +292,7 @@ fun MediaViewerView( }, ) } - is MediaBottomSheetState.MediaDeleteConfirmationState -> { + is MediaBottomSheetState.DeleteConfirmation -> { MediaDeleteConfirmationBottomSheet( state = bottomSheetState, onDelete = { diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt index 4d8b81a2dd..4cbb35a85e 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt @@ -33,7 +33,7 @@ class MediaDeleteConfirmationBottomSheetTest { @Test fun `clicking on Cancel invokes expected callback`() { - val state = aMediaDeleteConfirmationState() + val state = aMediaBottomSheetStateDeleteConfirmation() ensureCalledOnce { callback -> rule.setMediaDeleteConfirmationBottomSheet( state = state, @@ -45,7 +45,7 @@ class MediaDeleteConfirmationBottomSheetTest { @Test fun `clicking on Remove invokes expected callback`() { - val state = aMediaDeleteConfirmationState() + val state = aMediaBottomSheetStateDeleteConfirmation() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDeleteConfirmationBottomSheet( state = state, @@ -58,7 +58,7 @@ class MediaDeleteConfirmationBottomSheetTest { } private fun AndroidComposeTestRule.setMediaDeleteConfirmationBottomSheet( - state: MediaBottomSheetState.MediaDeleteConfirmationState, + state: MediaBottomSheetState.DeleteConfirmation, onDelete: (EventId) -> Unit = EnsureNeverCalledWithParam(), onDismiss: () -> Unit = EnsureNeverCalled(), ) { diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt index b6b8b68466..21a06f9568 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt @@ -34,7 +34,7 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on View in timeline invokes expected callback`() { - val state = aMediaDetailsBottomSheetState() + val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, @@ -47,7 +47,7 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on Share invokes expected callback`() { - val state = aMediaDetailsBottomSheetState() + val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, @@ -60,7 +60,7 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on Forward invokes expected callback`() { - val state = aMediaDetailsBottomSheetState() + val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, @@ -73,7 +73,7 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on Download invokes expected callback`() { - val state = aMediaDetailsBottomSheetState() + val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, @@ -86,7 +86,7 @@ class MediaDetailsBottomSheetTest { @Config(qualifiers = "h1024dp") @Test fun `clicking on Delete invokes expected callback`() { - val state = aMediaDetailsBottomSheetState() + val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> rule.setMediaDetailsBottomSheet( state = state, @@ -100,7 +100,7 @@ class MediaDetailsBottomSheetTest { @Config(qualifiers = "h1024dp") @Test fun `Remove is not present if canDelete is false`() { - val state = aMediaDetailsBottomSheetState( + val state = aMediaBottomSheetStateDetails( canDelete = false, ) rule.setMediaDetailsBottomSheet( @@ -111,7 +111,7 @@ class MediaDetailsBottomSheetTest { } private fun AndroidComposeTestRule.setMediaDetailsBottomSheet( - state: MediaBottomSheetState.MediaDetailsBottomSheetState, + state: MediaBottomSheetState.Details, onViewInTimeline: (EventId) -> Unit = EnsureNeverCalledWithParam(), onShare: (EventId) -> Unit = EnsureNeverCalledWithParam(), onForward: (EventId) -> Unit = EnsureNeverCalledWithParam(), diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt index 6dd58a6086..929f2a970e 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt @@ -136,7 +136,7 @@ class MediaGalleryPresenterTest { initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val state = awaitItem() assertThat(state.mediaBottomSheetState).isEqualTo( - MediaBottomSheetState.MediaDetailsBottomSheetState( + MediaBottomSheetState.Details( eventId = AN_EVENT_ID, canDelete = canDeleteOwn, mediaInfo = item.mediaInfo, @@ -183,7 +183,7 @@ class MediaGalleryPresenterTest { initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val state = awaitItem() assertThat(state.mediaBottomSheetState).isEqualTo( - MediaBottomSheetState.MediaDetailsBottomSheetState( + MediaBottomSheetState.Details( eventId = AN_EVENT_ID, canDelete = canDeleteOther, mediaInfo = item.mediaInfo, @@ -212,7 +212,7 @@ class MediaGalleryPresenterTest { initialState.eventSink(MediaGalleryEvent.ConfirmDelete(AN_EVENT_ID, item.mediaInfo, item.thumbnailSource)) val deleteState = awaitItem() assertThat(deleteState.mediaBottomSheetState).isEqualTo( - MediaBottomSheetState.MediaDeleteConfirmationState( + MediaBottomSheetState.DeleteConfirmation( eventId = AN_EVENT_ID, mediaInfo = item.mediaInfo, thumbnailSource = item.thumbnailSource, @@ -384,7 +384,7 @@ class MediaGalleryPresenterTest { val initialState = awaitFirstItem() initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) withBottomSheetState.eventSink(MediaGalleryEvent.OpenWith(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) @@ -451,7 +451,7 @@ class MediaGalleryPresenterTest { ) initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) withBottomSheetState.eventSink(MediaGalleryEvent.ViewInTimeline(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) @@ -484,7 +484,7 @@ class MediaGalleryPresenterTest { ) initialState.eventSink(MediaGalleryEvent.OpenInfo(item)) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) withBottomSheetState.eventSink(MediaGalleryEvent.Forward(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) 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 6cf846ff78..caacb03804 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 @@ -273,7 +273,7 @@ class MediaViewerPresenterTest { ) ) val withInfoState = awaitItem() - assertThat(withInfoState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withInfoState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) withInfoState.eventSink( MediaViewerEvent.CloseBottomSheet ) @@ -446,7 +446,7 @@ class MediaViewerPresenterTest { ) ) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDeleteConfirmationState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.DeleteConfirmation::class.java) withBottomSheetState.eventSink( MediaViewerEvent.CloseBottomSheet ) @@ -506,7 +506,7 @@ class MediaViewerPresenterTest { ) ) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDeleteConfirmationState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.DeleteConfirmation::class.java) updatedState.eventSink( MediaViewerEvent.Delete( eventId = AN_EVENT_ID, @@ -798,7 +798,7 @@ class MediaViewerPresenterTest { val initialState = awaitItem() initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) initialState.eventSink(MediaViewerEvent.ViewInTimeline(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) @@ -827,7 +827,7 @@ class MediaViewerPresenterTest { val initialState = awaitItem() initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) initialState.eventSink(MediaViewerEvent.Forward(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) @@ -858,7 +858,7 @@ class MediaViewerPresenterTest { val initialState = awaitItem() initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) val withBottomSheetState = awaitItem() - assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java) + assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) initialState.eventSink(MediaViewerEvent.Forward(AN_EVENT_ID)) val finalState = awaitItem() assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index e5eb07b871..9eded788aa 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipeDown import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState +import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -164,7 +164,7 @@ class MediaViewerViewTest { rule.setMediaViewerView( aMediaViewerState( listData = listOf(data), - mediaBottomSheetState = aMediaDetailsBottomSheetState(), + mediaBottomSheetState = aMediaBottomSheetStateDetails(), eventSink = eventsRecorder ), ) From b12a9ff2b908e18a404634754444d825b95f484a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Apr 2026 14:57:18 +0200 Subject: [PATCH 0219/1083] Improve rendering when sender does not have a display name. --- .../impl/details/MediaDetailsBottomSheet.kt | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index a3c3d02de8..b24067e807 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -192,23 +192,26 @@ private fun SenderRow( .weight(1f), ) { // Name + val bestName = mediaInfo.senderName ?: mediaInfo.senderId?.value.orEmpty() val avatarColors = AvatarColorsProvider.provide(id) Text( modifier = Modifier.clipToBounds(), - text = mediaInfo.senderName.orEmpty(), + text = bestName, maxLines = 1, overflow = TextOverflow.Ellipsis, color = avatarColors.foreground, style = ElementTheme.typography.fontBodyMdMedium, ) // Id - Text( - text = mediaInfo.senderId?.value.orEmpty(), - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = ElementTheme.typography.fontBodyMdRegular, - ) + if (!mediaInfo.senderName.isNullOrEmpty()) { + Text( + text = mediaInfo.senderId?.value.orEmpty(), + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = ElementTheme.typography.fontBodyMdRegular, + ) + } } } } From 92add858832e419e9271f1bf6a8adae389a7aeb7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 22 Apr 2026 13:54:26 +0000 Subject: [PATCH 0220/1083] Update screenshots --- ...pl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png | 3 +++ ....details_MediaDeleteConfirmationBottomSheet_Night_1_en.png | 3 +++ ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png new file mode 100644 index 0000000000..9738b22d77 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b494c43b9fa9535d7e3dd4a7b70f9b17bb630b1273495ce8318c397f4a8b5e +size 43556 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png new file mode 100644 index 0000000000..05c5ee2803 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60e267a641d11da48b69caedddb3ee8827365ebd6bf252af12f59f5ddbaceece +size 42133 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png index 909387767f..115b18844c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:070e17d4807133d5966bd3f2ae52df258294466479e2fe96a7943571b0fa81e7 -size 40068 +oid sha256:534e603e9cf5423d37f0cf710be1e49e424209306fa24ce68c53c10bc6e68c6a +size 40237 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png index a77470a1b0..8abc1bfa7e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3b0f78545228d76ef59bd777eec4dd72b0dbcef8b7bae51b6f3c05b0f1cbd87 -size 38943 +oid sha256:e29a3103f566ce4400f05366c921e1f50e6c31edb8443afd81e2873de504a397 +size 39135 From b4f1627748289cc8b3ae062a046716b0feadc17b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 22 Apr 2026 17:51:51 +0200 Subject: [PATCH 0221/1083] Remove distributed tracing of the 'timeline loading' flow (#6644) * Remove distributed tracing of the 'timeline loading' flow. This is causing crashes in the app when a debug SDK build is used * Discourage using the APIs related with distributed tracing, explaining the problem --- .../matrix/impl/room/RustRoomFactory.kt | 23 ++++++++----------- .../analytics/api/AnalyticsSdkSpan.kt | 3 +++ .../analytics/api/AnalyticsService.kt | 3 +++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt index a3af54863c..15a0850184 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt @@ -25,7 +25,6 @@ import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapp import io.element.android.libraries.matrix.impl.roomlist.roomOrNull import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction import io.element.android.services.analytics.api.AnalyticsService -import io.element.android.services.analytics.api.inBridgeSdkSpan import io.element.android.services.analytics.api.recordTransaction import io.element.android.services.analyticsproviders.api.recordChildTransaction import io.element.android.services.toolbox.api.systemclock.SystemClock @@ -128,19 +127,17 @@ class RustRoomFactory( val timeline = transaction.recordChildTransaction( operation = "sdkRoom.timelineWithConfiguration", description = "Get timeline from the SDK", - ) { timelineTransaction -> - analyticsService.inBridgeSdkSpan(parentTraceId = timelineTransaction.traceId()) { - sdkRoom.timelineWithConfiguration( - TimelineConfiguration( - focus = TimelineFocus.Live(hideThreadedEvents = hideThreadedEvents), - filter = eventFilters?.let(TimelineFilter::EventFilter) ?: TimelineFilter.All, - internalIdPrefix = "live", - dateDividerMode = DateDividerMode.DAILY, - trackReadReceipts = TimelineReadReceiptTracking.ALL_EVENTS, - reportUtds = true, - ) + ) { + sdkRoom.timelineWithConfiguration( + TimelineConfiguration( + focus = TimelineFocus.Live(hideThreadedEvents = hideThreadedEvents), + filter = eventFilters?.let(TimelineFilter::EventFilter) ?: TimelineFilter.All, + internalIdPrefix = "live", + dateDividerMode = DateDividerMode.DAILY, + trackReadReceipts = TimelineReadReceiptTracking.ALL_EVENTS, + reportUtds = true, ) - } + ) } GetRoomResult.Joined( diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsSdkSpan.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsSdkSpan.kt index 92f79da7f9..81add882a5 100644 --- a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsSdkSpan.kt +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsSdkSpan.kt @@ -7,9 +7,12 @@ package io.element.android.services.analytics.api +import androidx.annotation.Discouraged + /** * Represents an analytics span in the Rust SDK. */ +@Discouraged("This component can cause crashes of the app when using debug builds of the Rust SDK.") interface AnalyticsSdkSpan { /** Enters the span and starts collecting metrics. */ fun enter() diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt index 8c29f11197..846d5ce5b1 100644 --- a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt +++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt @@ -8,6 +8,7 @@ package io.element.android.services.analytics.api +import androidx.annotation.Discouraged import io.element.android.services.analyticsproviders.api.AnalyticsProvider import io.element.android.services.analyticsproviders.api.AnalyticsTransaction import io.element.android.services.analyticsproviders.api.trackers.AnalyticsTracker @@ -74,6 +75,7 @@ interface AnalyticsService : AnalyticsTracker, ErrorTracker { fun removeLongRunningTransaction(longRunningTransaction: AnalyticsLongRunningTransaction): AnalyticsTransaction? /** Enter a span inside the Rust SDK tracing system. If a [parentTraceId] is provided, the SDK trace will be added as a child of that trace. */ + @Discouraged("This method can cause crashes of the app when using debug builds of the Rust SDK.") fun enterSdkSpan(name: String?, parentTraceId: String?): AnalyticsSdkSpan } @@ -116,6 +118,7 @@ fun AnalyticsService.finishLongRunningTransaction( } ?: false } +@Discouraged("This method can cause crashes of the app when using debug builds of the Rust SDK.") inline fun AnalyticsService.inBridgeSdkSpan(parentTraceId: String?, block: (AnalyticsSdkSpan) -> T): T { val span = enterSdkSpan(name = null, parentTraceId = parentTraceId) return try { From d9080f54656102c496925705e335e559d0e26213 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 09:46:37 +0200 Subject: [PATCH 0222/1083] Update zizmorcore/zizmor-action action to v0.5.3 (#6630) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 6859e78baa..ceaa86016a 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -336,7 +336,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2 + - uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 upload_reports: name: Project Check Suite From 2c6f1888f472ac97104c38ca78ed8ea6ce6354d2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 09:47:17 +0200 Subject: [PATCH 0223/1083] Update dependency io.sentry:sentry-android to v8.38.0 (#6597) 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 119252e84e..2326c9aa28 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -221,7 +221,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.39.0" -sentry = "io.sentry:sentry-android:8.37.1" +sentry = "io.sentry:sentry-android:8.38.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 9dd61bbd37d83cdbed1740e6ef37714d99330924 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 09:48:15 +0200 Subject: [PATCH 0224/1083] fix(deps): update camera to v1.6.0 (#6514) * fix(deps): update camera to v1.6.0 * Add dependency to com.google.guava:guava to fix compilation issue. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Benoit Marty --- gradle/libs.versions.toml | 3 ++- libraries/qrcode/build.gradle.kts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2326c9aa28..f0078399c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ constraintlayout_compose = "1.1.1" lifecycle = "2.10.0" activity = "1.13.0" media3 = "1.10.0" -camera = "1.5.3" +camera = "1.6.0" work = "2.11.2" # Compose @@ -214,6 +214,7 @@ maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" opusencoder = "io.element.android:opusencoder:1.2.0" zxing_cpp = "io.github.zxing-cpp:android:3.0.2" google_zxing = "com.google.zxing:core:3.5.4" +google_guava = "com.google.guava:guava:33.5.0-android" haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" } haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" } diff --git a/libraries/qrcode/build.gradle.kts b/libraries/qrcode/build.gradle.kts index cf76e117c0..1cf6a8cdff 100644 --- a/libraries/qrcode/build.gradle.kts +++ b/libraries/qrcode/build.gradle.kts @@ -20,4 +20,5 @@ dependencies { implementation(libs.androidx.camera.camera2) implementation(libs.zxing.cpp) implementation(libs.google.zxing) + implementation(libs.google.guava) } From bbb4a47eff0986760138767c341372fcb5a035ae Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 11:20:20 +0200 Subject: [PATCH 0225/1083] MediaDetailsBottomSheet: iterate on design. Closes #6645 --- .../components/avatar/AvatarSize.kt | 2 +- .../impl/details/MediaDetailsBottomSheet.kt | 143 ++++++++++-------- .../impl/src/main/res/values/localazy.xml | 1 + 3 files changed, 80 insertions(+), 66 deletions(-) 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 660b071983..320457cedd 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 @@ -65,7 +65,7 @@ enum class AvatarSize(val dp: Dp) { KnockRequestItem(52.dp), KnockRequestBanner(32.dp), - MediaSender(32.dp), + MediaSender(52.dp), DmCreationConfirmation(64.dp), diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index b24067e807..74e4621066 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.mediaviewer.impl.details import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -24,6 +25,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -72,9 +74,8 @@ fun MediaDetailsBottomSheet( modifier = Modifier .fillMaxWidth() .verticalScroll(rememberScrollState()), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(24.dp), ) { + Title() Section( title = stringResource(R.string.screen_media_details_uploaded_by), ) { @@ -94,73 +95,72 @@ fun MediaDetailsBottomSheet( title = stringResource(R.string.screen_media_details_file_format), text = state.mediaInfo.mimeType + " - " + state.mediaInfo.formattedFileSize, ) + Spacer(modifier = Modifier.height(16.dp)) if (state.eventId != null) { - Column { + HorizontalDivider() + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VisibilityOn())), + headlineContent = { Text(stringResource(CommonStrings.action_view_in_timeline)) }, + style = ListItemStyle.Primary, + onClick = { + onViewInTimeline(state.eventId) + } + ) + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), + headlineContent = { Text(stringResource(CommonStrings.action_share)) }, + style = ListItemStyle.Primary, + onClick = { + onShare(state.eventId) + } + ) + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Forward())), + headlineContent = { Text(stringResource(CommonStrings.action_forward)) }, + style = ListItemStyle.Primary, + onClick = { + onForward(state.eventId) + } + ) + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), + headlineContent = { Text(stringResource(CommonStrings.action_download)) }, + style = ListItemStyle.Primary, + onClick = { + onDownload(state.eventId) + } + ) + val mimeType = state.mediaInfo.mimeType + val icon = when (mimeType) { + MimeTypes.Apk -> + ListItemContent.Icon(IconSource.Resource(R.drawable.ic_apk_install)) + else -> + ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())) + } + val wording = when (mimeType) { + MimeTypes.Apk -> stringResource(id = CommonStrings.common_install_apk_android) + else -> stringResource(id = CommonStrings.action_open_with) + } + ListItem( + leadingContent = icon, + headlineContent = { Text(wording) }, + style = ListItemStyle.Primary, + onClick = { + onOpenWith(state.eventId) + } + ) + if (state.canDelete) { HorizontalDivider() ListItem( - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VisibilityOn())), - headlineContent = { Text(stringResource(CommonStrings.action_view_in_timeline)) }, - style = ListItemStyle.Primary, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), + headlineContent = { Text(stringResource(CommonStrings.action_delete)) }, + style = ListItemStyle.Destructive, onClick = { - onViewInTimeline(state.eventId) + onDelete(state.eventId) } ) - ListItem( - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), - headlineContent = { Text(stringResource(CommonStrings.action_share)) }, - style = ListItemStyle.Primary, - onClick = { - onShare(state.eventId) - } - ) - ListItem( - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Forward())), - headlineContent = { Text(stringResource(CommonStrings.action_forward)) }, - style = ListItemStyle.Primary, - onClick = { - onForward(state.eventId) - } - ) - ListItem( - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), - headlineContent = { Text(stringResource(CommonStrings.action_download)) }, - style = ListItemStyle.Primary, - onClick = { - onDownload(state.eventId) - } - ) - val mimeType = state.mediaInfo.mimeType - val icon = when (mimeType) { - MimeTypes.Apk -> - ListItemContent.Icon(IconSource.Resource(R.drawable.ic_apk_install)) - else -> - ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())) - } - val wording = when (mimeType) { - MimeTypes.Apk -> stringResource(id = CommonStrings.common_install_apk_android) - else -> stringResource(id = CommonStrings.action_open_with) - } - ListItem( - leadingContent = icon, - headlineContent = { Text(wording) }, - style = ListItemStyle.Primary, - onClick = { - onOpenWith(state.eventId) - } - ) - if (state.canDelete) { - HorizontalDivider() - ListItem( - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), - headlineContent = { Text(stringResource(CommonStrings.action_delete)) }, - style = ListItemStyle.Destructive, - onClick = { - onDelete(state.eventId) - } - ) - } - Spacer(modifier = Modifier.height(16.dp)) } + Spacer(modifier = Modifier.height(16.dp)) } } } @@ -216,6 +216,19 @@ private fun SenderRow( } } +@Composable +private fun ColumnScope.Title() { + Text( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 16.dp, bottom = 8.dp, start = 16.dp, end = 16.dp), + text = stringResource(R.string.screen_media_details_title), + textAlign = TextAlign.Center, + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + ) +} + @Composable private fun Section( title: String, @@ -224,12 +237,12 @@ private fun Section( Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .padding(vertical = 8.dp, horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { Text( - text = title.uppercase(), - style = ElementTheme.typography.fontBodySmRegular, + text = title, + style = ElementTheme.typography.fontBodyMdMedium, color = ElementTheme.colors.textSecondary, ) content() diff --git a/libraries/mediaviewer/impl/src/main/res/values/localazy.xml b/libraries/mediaviewer/impl/src/main/res/values/localazy.xml index 2982f8002f..760ba2e7dc 100644 --- a/libraries/mediaviewer/impl/src/main/res/values/localazy.xml +++ b/libraries/mediaviewer/impl/src/main/res/values/localazy.xml @@ -16,6 +16,7 @@ "File name" "No more files to show" "No more media to show" + "File info" "Uploaded by" "Uploaded on" From 09e0d2d1665a2d6c4691aa5cd8c4bc17b372ed2e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 11:22:47 +0200 Subject: [PATCH 0226/1083] MediaDetailsBottomSheet: Add missing preview case. --- .../impl/details/MediaBottomSheetStateDetailsProvider.kt | 6 +++++- .../mediaviewer/impl/details/MediaDetailsBottomSheet.kt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt index ad8e6e30a0..de21ff667d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt @@ -23,17 +23,21 @@ open class MediaBottomSheetStateDetailsProvider : PreviewParameterProvider Date: Thu, 23 Apr 2026 09:40:14 +0000 Subject: [PATCH 0227/1083] Update screenshots --- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png | 3 +++ ...viewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png | 3 +++ ...ies.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png | 4 ++-- ...s.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png | 4 ++-- 12 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png index 5a9605e9dd..6875fb8c82 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd9027f3684b91a8867bf0cb7c1eb3925edfc4982d40cc33414997e38c068d45 -size 40887 +oid sha256:e630a264276ce61b6661bbd907c9c66d57471d5ae3a0194c4f452ad865410f21 +size 41161 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png index c48dc8fdf9..6875fb8c82 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:736ac91d14dd16f8d1cc7040fc69c08c97d2525c3876b90376a85764157e2910 -size 40859 +oid sha256:e630a264276ce61b6661bbd907c9c66d57471d5ae3a0194c4f452ad865410f21 +size 41161 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png index 115b18844c..9f41fd0cb9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534e603e9cf5423d37f0cf710be1e49e424209306fa24ce68c53c10bc6e68c6a -size 40237 +oid sha256:d842fb5cacf27fcb2bb0a983d34b5955475f8c127f129e9e22f064e1716a2ff5 +size 40596 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png new file mode 100644 index 0000000000..d8e71e8e59 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:865e66b2d88ad172deea40315da88e8d0bd4647ebeaa3327646ebaaf9101fa10 +size 31414 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png index cdddf1c59c..6e1fabefb6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c9d002e8d23dc85be883fae56d1266dadfd9fbd73a9b8a396b8953be9b7ff23 -size 39445 +oid sha256:5b637a243fdbcb212a644b5250a3b7840150bc2de250184cfd8d503ca0fa0400 +size 39983 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png index 6c2870a35f..6e1fabefb6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7982c873e18aeb3c2ae32638bc0c6be7a36f9b2326e303306c5c63a2ebeebbab -size 39429 +oid sha256:5b637a243fdbcb212a644b5250a3b7840150bc2de250184cfd8d503ca0fa0400 +size 39983 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png index 8abc1bfa7e..68241c9cfe 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e29a3103f566ce4400f05366c921e1f50e6c31edb8443afd81e2873de504a397 -size 39135 +oid sha256:273b69361a9190b0e6c0a5487f22c910e803afc5cde5bc91d2cbe920b0bcaa14 +size 39662 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png new file mode 100644 index 0000000000..e7db1044b7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:821914e5a21df26cf8cec6f391f9560bef3392f8d1ffae2ec862f87686a02149 +size 29996 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png index f6769f22ba..2449b7450a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41d66efcb35b7c75452311d7646c73a66e2906cda1ee6da99d9b216121a8f073 -size 40805 +oid sha256:a99991c09e28f2cb87dcecebc83fe62c77323cc1126e643a11cc66d198f0b2da +size 41079 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png index 253add27e2..5c7c878b2e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b704a5672030f94f4d331784c5307f38b156e11dc69e9b17890a0aef3de26241 -size 39241 +oid sha256:ca9a11f1bce2572ad55e8763470f9498754613ac2b3cc2960cc6ee22ccb2a422 +size 39764 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png index e4424188e6..09797bc372 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d6ab1331e65a4d02accb4d20c899a06c37a022d9f9080133799e30763969300 -size 26774 +oid sha256:36de9783112b421c13530eff9eda026b7ba4e6a721cfd75bb2bca7e2b32cb84a +size 26140 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png index 253add27e2..5c7c878b2e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b704a5672030f94f4d331784c5307f38b156e11dc69e9b17890a0aef3de26241 -size 39241 +oid sha256:ca9a11f1bce2572ad55e8763470f9498754613ac2b3cc2960cc6ee22ccb2a422 +size 39764 From 92ee479e912f866b197fb3916aed86483e4e118b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 23 Apr 2026 15:15:52 +0200 Subject: [PATCH 0228/1083] Set max lines for 'in reply to' view conditionally (#6612) * Set max lines for 'in reply to' view conditionally. When there is enough screen space, use 2 lines as before. If the screen space is limited, use a single one. * Reduce vertical padding for reply-to view in compose * Add screenshot test with single line in reply to view * Update screenshots --------- Co-authored-by: ElementBot --- .../matrix/ui/messages/reply/InReplyToView.kt | 17 +++++-- .../textcomposer/ComposerModeView.kt | 11 +++- .../libraries/textcomposer/TextComposer.kt | 51 +++++++++++++++++-- .../components/markdown/MarkdownTextInput.kt | 2 +- .../src/test/kotlin/base/ScreenshotTest.kt | 11 ++-- ...ts.preview_AttachmentsPreviewView_0_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_2_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_3_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_4_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_5_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_6_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_7_en.png | 4 +- ...ts.preview_AttachmentsPreviewView_8_en.png | 4 +- ...ecomposer_MessageComposerView_Day_0_en.png | 4 +- ...omposer_MessageComposerView_Night_0_en.png | 4 +- ...ures.messages.impl_MessagesViewA11y_en.png | 4 +- ...es.messages.impl_MessagesView_Day_0_en.png | 4 +- ...es.messages.impl_MessagesView_Day_3_en.png | 4 +- ...es.messages.impl_MessagesView_Day_4_en.png | 4 +- ...es.messages.impl_MessagesView_Day_5_en.png | 4 +- ...es.messages.impl_MessagesView_Day_7_en.png | 4 +- ...es.messages.impl_MessagesView_Day_9_en.png | 4 +- ....messages.impl_MessagesView_Night_0_en.png | 4 +- ....messages.impl_MessagesView_Night_3_en.png | 4 +- ....messages.impl_MessagesView_Night_4_en.png | 4 +- ....messages.impl_MessagesView_Night_5_en.png | 4 +- ....messages.impl_MessagesView_Night_7_en.png | 4 +- ....messages.impl_MessagesView_Night_9_en.png | 4 +- ...mePickerHorizontal_DateTime_pickers_en.png | 4 +- ...ts.markdown_MarkdownTextInput_Day_0_en.png | 4 +- ....markdown_MarkdownTextInput_Night_0_en.png | 4 +- ...textcomposer_ComposerModeView_Day_1_en.png | 4 +- ...textcomposer_ComposerModeView_Day_2_en.png | 4 +- ...textcomposer_ComposerModeView_Day_3_en.png | 4 +- ...xtcomposer_ComposerModeView_Night_1_en.png | 4 +- ...xtcomposer_ComposerModeView_Night_2_en.png | 4 +- ...xtcomposer_ComposerModeView_Night_3_en.png | 4 +- ...oser_MarkdownTextComposerEdit_Day_0_en.png | 4 +- ...er_MarkdownTextComposerEdit_Night_0_en.png | 4 +- ...mposer_TextComposerAddCaption_Day_0_en.png | 4 +- ...oser_TextComposerAddCaption_Night_0_en.png | 4 +- ...tcomposer_TextComposerCaption_Day_0_en.png | 4 +- ...omposer_TextComposerCaption_Night_0_en.png | 4 +- ...poser_TextComposerEditCaption_Day_0_en.png | 4 +- ...ser_TextComposerEditCaption_Night_0_en.png | 4 +- ..._TextComposerEditNotEncrypted_Day_0_en.png | 4 +- ...extComposerEditNotEncrypted_Night_0_en.png | 4 +- ...textcomposer_TextComposerEdit_Day_0_en.png | 4 +- ...xtcomposer_TextComposerEdit_Night_0_en.png | 4 +- ...omposerFormattingNotEncrypted_Day_0_en.png | 4 +- ...poserFormattingNotEncrypted_Night_0_en.png | 4 +- ...mposer_TextComposerFormatting_Day_0_en.png | 4 +- ...oser_TextComposerFormatting_Night_0_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_0_en.png | 4 +- ...extComposerReplyNotEncrypted_Day_10_en.png | 4 +- ...extComposerReplyNotEncrypted_Day_11_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_1_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_2_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_3_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_4_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_5_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_6_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_7_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_8_en.png | 4 +- ...TextComposerReplyNotEncrypted_Day_9_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_0_en.png | 4 +- ...tComposerReplyNotEncrypted_Night_10_en.png | 4 +- ...tComposerReplyNotEncrypted_Night_11_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_1_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_2_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_3_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_4_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_5_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_6_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_7_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_8_en.png | 4 +- ...xtComposerReplyNotEncrypted_Night_9_en.png | 4 +- ...extcomposer_TextComposerReply_Day_0_en.png | 4 +- ...xtcomposer_TextComposerReply_Day_10_en.png | 4 +- ...xtcomposer_TextComposerReply_Day_11_en.png | 4 +- ...extcomposer_TextComposerReply_Day_1_en.png | 4 +- ...extcomposer_TextComposerReply_Day_2_en.png | 4 +- ...extcomposer_TextComposerReply_Day_3_en.png | 4 +- ...extcomposer_TextComposerReply_Day_4_en.png | 4 +- ...extcomposer_TextComposerReply_Day_5_en.png | 4 +- ...extcomposer_TextComposerReply_Day_6_en.png | 4 +- ...extcomposer_TextComposerReply_Day_7_en.png | 4 +- ...extcomposer_TextComposerReply_Day_8_en.png | 4 +- ...extcomposer_TextComposerReply_Day_9_en.png | 4 +- ...tcomposer_TextComposerReply_Night_0_en.png | 4 +- ...composer_TextComposerReply_Night_10_en.png | 4 +- ...composer_TextComposerReply_Night_11_en.png | 4 +- ...tcomposer_TextComposerReply_Night_1_en.png | 4 +- ...tcomposer_TextComposerReply_Night_2_en.png | 4 +- ...tcomposer_TextComposerReply_Night_3_en.png | 4 +- ...tcomposer_TextComposerReply_Night_4_en.png | 4 +- ...tcomposer_TextComposerReply_Night_5_en.png | 4 +- ...tcomposer_TextComposerReply_Night_6_en.png | 4 +- ...tcomposer_TextComposerReply_Night_7_en.png | 4 +- ...tcomposer_TextComposerReply_Night_8_en.png | 4 +- ...tcomposer_TextComposerReply_Night_9_en.png | 4 +- ..._TextComposerScaledDensityWithReply_en.png | 3 ++ 102 files changed, 274 insertions(+), 205 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerScaledDensityWithReply_en.png diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt index 0dc8aac09e..4d0e02aa6f 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt @@ -56,6 +56,7 @@ fun InReplyToView( inReplyTo: InReplyToDetails, hideImage: Boolean, modifier: Modifier = Modifier, + maxLines: Int = 2, ) { when (inReplyTo) { is InReplyToDetails.Ready -> { @@ -63,11 +64,12 @@ fun InReplyToView( senderId = inReplyTo.senderId, senderProfile = inReplyTo.senderProfile, metadata = inReplyTo.metadata(hideImage), + maxLines = maxLines, modifier = modifier, ) } is InReplyToDetails.Error -> - ReplyToErrorContent(data = inReplyTo, modifier = modifier) + ReplyToErrorContent(data = inReplyTo, maxLines = maxLines, modifier = modifier) is InReplyToDetails.Loading -> ReplyToLoadingContent(modifier = modifier) } @@ -78,6 +80,7 @@ private fun ReplyToReadyContent( senderId: UserId, senderProfile: ProfileDetails, metadata: InReplyToMetadata?, + maxLines: Int, modifier: Modifier = Modifier, ) { val paddings = if (metadata is InReplyToMetadata.Thumbnail) { @@ -115,7 +118,7 @@ private fun ReplyToReadyContent( traversalIndex = 1f }, ) - ReplyToContentText(metadata) + ReplyToContentText(metadata, maxLines) } } } @@ -140,6 +143,7 @@ private fun ReplyToLoadingContent( @Composable private fun ReplyToErrorContent( data: InReplyToDetails.Error, + maxLines: Int, modifier: Modifier = Modifier, ) { val paddings = PaddingValues(horizontal = 12.dp, vertical = 4.dp) @@ -152,14 +156,17 @@ private fun ReplyToErrorContent( text = data.message, style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textCriticalPrimary, - maxLines = 2, + maxLines = maxLines, overflow = TextOverflow.Ellipsis, ) } } @Composable -private fun ReplyToContentText(metadata: InReplyToMetadata?) { +private fun ReplyToContentText( + metadata: InReplyToMetadata?, + maxLines: Int, +) { val text = when (metadata) { InReplyToMetadata.Redacted -> stringResource(id = CommonStrings.common_message_removed) InReplyToMetadata.UnableToDecrypt -> stringResource(id = CommonStrings.common_waiting_for_decryption_key) @@ -200,7 +207,7 @@ private fun ReplyToContentText(metadata: InReplyToMetadata?) { fontStyle = fontStyle, textAlign = TextAlign.Start, color = ElementTheme.colors.textSecondary, - maxLines = 2, + maxLines = maxLines, overflow = TextOverflow.Ellipsis, ) } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt index 08d89e25fb..039f516547 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ComposerModeView.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter @@ -64,7 +65,7 @@ internal fun ComposerModeView( } is MessageComposerMode.Reply -> { ReplyToModeView( - modifier = modifier.padding(8.dp), + modifier = modifier.padding(top = 8.dp, start = 8.dp, end = 8.dp), replyToDetails = composerMode.replyToDetails, hideImage = composerMode.hideImage, onResetComposerMode = onResetComposerMode, @@ -120,6 +121,9 @@ private fun EditingModeView( } } +// This combination of density DPI and font scale is an approximation to a screen with little space to display the content +private const val MAX_SCALING_VALUE = 3.5f + /** * https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2019-6286 */ @@ -137,9 +141,14 @@ private fun ReplyToModeView( .border(1.dp, ElementTheme.colors.separatorPrimary, RoundedCornerShape(6.dp)) .padding(4.dp) ) { + // Larger density DPI and font scale means less space to display the content, so we limit it to 1 line to avoid overflow issues + val currentDensity = LocalDensity.current + val hasLowResolution = currentDensity.density * currentDensity.fontScale >= MAX_SCALING_VALUE + val maxReplyContentLines = if (hasLowResolution) 1 else 2 InReplyToView( inReplyTo = replyToDetails, hideImage = hideImage, + maxLines = maxReplyContentLines, modifier = Modifier.weight(1f), ) Icon( 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 5a3ee1c8a0..4860a53ae7 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 @@ -29,6 +29,7 @@ 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.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -40,6 +41,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource @@ -50,6 +52,7 @@ import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -66,10 +69,14 @@ import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconColorButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId +import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent +import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetailsProvider +import io.element.android.libraries.matrix.ui.messages.reply.aProfileDetailsReady import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.textcomposer.components.SendButtonIcon @@ -181,7 +188,7 @@ fun TextComposer( placeholder = placeholder, registerStateUpdates = true, modifier = Modifier - .padding(top = 6.dp, bottom = 6.dp) + .padding(top = 4.dp, bottom = 6.dp) .fillMaxWidth(), style = ElementRichTextEditorStyle.composerStyle(hasFocus = state.richTextEditorState.hasFocus), resolveMentionDisplay = resolveMentionDisplay, @@ -651,10 +658,14 @@ private fun TextInputBox( composerMode = composerMode, onResetComposerMode = onResetComposerMode, ) + } else { + // Top padding for the message composer box + Spacer(Modifier.height(4.dp)) } + Box( modifier = Modifier - .padding(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp) + .padding(top = 1.dp, bottom = 4.dp, start = 12.dp, end = 12.dp) .then(Modifier.testTag(TestTags.textEditor)), contentAlignment = Alignment.CenterStart, ) { @@ -664,7 +675,7 @@ private fun TextInputBox( Icon( modifier = Modifier .clickable { showBottomSheet = true } - .padding(horizontal = 8.dp, vertical = 4.dp) + .padding(start = 8.dp, end = 8.dp, top = 4.dp, bottom = 4.dp) .align(Alignment.CenterEnd), imageVector = CompoundIcons.InfoSolid(), tint = ElementTheme.colors.iconCriticalPrimary, @@ -983,6 +994,40 @@ internal fun TextComposerVoiceNotEncryptedPreview() = ElementPreview { } } +@Preview +@Composable +internal fun TextComposerScaledDensityWithReplyPreview() { + ElementPreview { + CompositionLocalProvider( + LocalDensity provides Density( + density = 3f, + fontScale = 1.25f, + ), + ) { + val replyToDetails = InReplyToDetails.Ready( + eventId = EventId("\$1234"), + senderId = UserId("@alice:example.com"), + senderProfile = aProfileDetailsReady(), + eventContent = MessageContent( + body = "Message which are being replied, and which was long enough to be displayed on two lines (only!).", + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = TextMessageType("Message which are being replied, and which was long enough to be displayed on two lines (only!).", null) + ), + textContent = "Message which are being replied, and which was long enough to be displayed on two lines (only!).", + ) + Box(modifier = Modifier.width(480.dp).height(120.dp)) { + ATextComposer( + state = aTextEditorStateMarkdown(initialText = "", initialFocus = true), + voiceMessageState = VoiceMessageState.Idle, + composerMode = MessageComposerMode.Reply(replyToDetails, hideImage = false), + ) + } + } + } +} + @Composable private fun PreviewColumn( items: ImmutableList, diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt index b3c60b69d7..bd6944d603 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt @@ -82,7 +82,7 @@ fun MarkdownTextInput( AndroidView( modifier = Modifier - .padding(top = 6.dp, bottom = 6.dp) + .padding(top = 5.dp, bottom = 6.dp) .fillMaxWidth(), factory = { context -> MarkdownEditText(context).apply { diff --git a/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt b/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt index a611fa83cf..e9bd34d10e 100644 --- a/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt +++ b/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt @@ -22,6 +22,7 @@ import app.cash.paparazzi.DeviceConfig import app.cash.paparazzi.Paparazzi import app.cash.paparazzi.RenderExtension import app.cash.paparazzi.TestName +import com.android.resources.Density.DEFAULT_DENSITY import com.android.resources.NightMode import com.android.resources.ScreenOrientation import io.element.android.compound.theme.ElementTheme @@ -42,12 +43,13 @@ object ScreenshotTest { Locale.setDefault(locale) paparazzi.fixScreenshotName(preview, localeStr) + paparazzi.snapshot { CompositionLocalProvider( LocalInspectionMode provides true, LocalDensity provides Density( density = LocalDensity.current.density, - fontScale = 1.0f, + fontScale = preview.previewInfo.fontScale, ), LocalConfiguration provides Configuration().apply { setLocales(LocaleList(locale)) @@ -121,19 +123,22 @@ object PaparazziPreviewRule { deviceConfig: DeviceConfig = ScreenshotTest.defaultDeviceConfig, renderExtensions: Set = setOf(), ): Paparazzi { - val densityScale = deviceConfig.density.dpiValue / 160f + val densityScale = deviceConfig.density.dpiValue.toFloat() / DEFAULT_DENSITY + val customScreenWidth = preview.previewInfo.widthDp.takeIf { it >= 0 }?.let { it * densityScale }?.toInt() val customScreenHeight = preview.previewInfo.heightDp.takeIf { it >= 0 }?.let { it * densityScale }?.toInt() val isLandscape = preview.previewInfo.device.contains("landscape") return Paparazzi( deviceConfig = deviceConfig.copy( + screenWidth = customScreenWidth ?: deviceConfig.screenWidth, + screenHeight = customScreenHeight ?: deviceConfig.screenHeight, nightMode = when (preview.previewInfo.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) { true -> NightMode.NIGHT false -> NightMode.NOTNIGHT }, locale = locale, softButtons = false, - screenHeight = customScreenHeight ?: deviceConfig.screenHeight, orientation = if (isLandscape) ScreenOrientation.LANDSCAPE else ScreenOrientation.PORTRAIT, + fontScale = preview.previewInfo.fontScale, ), maxPercentDifference = 0.01, renderExtensions = renderExtensions, diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png index 9b77a1b471..586bf84274 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54298b08251d3bd32c451dbb2076a40f20254f78806c30c0647f1bf062f3df7a -size 399342 +oid sha256:22e3d682c4866bd5c519ab88d08290708929af805438a0bd093200cddcbd41b2 +size 399376 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png index 76e98b4314..f1cde998de 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e8aabdc6d15c46ee59ba0e9d2b3b3f19500801c96501b39732d7f9f95e9130f -size 59204 +oid sha256:947ccb947f4a961ff7d17b936f2c866d66fea0361879d51ad4c65d18465c1a9f +size 59226 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png index 9b77a1b471..586bf84274 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54298b08251d3bd32c451dbb2076a40f20254f78806c30c0647f1bf062f3df7a -size 399342 +oid sha256:22e3d682c4866bd5c519ab88d08290708929af805438a0bd093200cddcbd41b2 +size 399376 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png index 3204029c4a..dd5a1e333c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9eba0f1d35c5456b58a09ca8370c93f0d1959e8e9aa503501cc49ecfaf198522 -size 59075 +oid sha256:0d9e221ec2f4ee764967e94c32f52b1615b25dec8fc7697dd5bcd01fc4da8d69 +size 59098 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png index 394e42e69b..d695d41c94 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e078891f5a377bf42cb787f436dcb7471de959db0c4d3afa5d7cacee20b2bf15 -size 86126 +oid sha256:547bf4e3bec05c219f5a72cfd8d506eb7c39429970cced5c2b8f2999ae390265 +size 86149 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png index 50341180e4..4a6e1cd828 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a56951545b00dc74fd7780648bb2a508176c47df6a2ce6920f2b8a63d15f58a5 -size 72675 +oid sha256:6d326595038160376db620a07a180de7af37ebfc76d4927ed1176ef6f4370aab +size 72700 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png index 8f18c5dace..fa4beb6dfb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0008cd2827cf805678958567bbce2ca86640a5f27e95ebf1c9cdbc0b86edfd0 -size 405032 +oid sha256:a8e8bcb6fdffb2d8673e4ee4e16e21672ffe99e717c48fd35b8411a8aa0530e9 +size 405064 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png index 43c6183fdc..d789e92297 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b08c65638e961e2fa5f194e93c3a63ead0976b13c1b9821850c3ee865eac0a8 -size 82767 +oid sha256:3caecb171d3095ef5c3593c6289b2d99e6cd6a6c635d822ad24061e502bdeb2e +size 82790 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Day_0_en.png index 6a73efb364..1f93d989e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9fc58451a493906def731f8002457a7c88de57c4024d38aab0feb8bf9704491c -size 18847 +oid sha256:a3da06e8a768fb3d1987fd4dea324439f15149ab101ee7644b94d0bee98f4b4f +size 18891 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Night_0_en.png index 3a89d35440..71446fdc34 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_MessageComposerView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75a0673b17799b239c2ca2719b6ec08abe4c4fdfabe3cc0ccda5c51a7a1db880 -size 17712 +oid sha256:9a14656ec0cce306c1057f56df52122c5fd2ca2525c9803e47b5845cde361c2c +size 17705 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png index 51846a888b..59b336cb1a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba76e7df81874aa6549a5f8ca7987046a4b43a63852c83fece541dc319e839d6 -size 131727 +oid sha256:c64b270815016ecd157fe430538090afc8f94c4ec2402a6c6de01ff1d762db94 +size 131744 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png index 3501707206..9c5932834e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b92c8a8283be1efed5faf6fb5f8a091f225dee38fd95e1a1b1914fa06661dc21 -size 56261 +oid sha256:0dd30568e628750f922a87c2df1fd7751e9d899b9163253c9f2a0c7b03e4a869 +size 56247 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png index 58e652df1e..c19f70ee0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c89a2eeba5fa540b6ab6516da1d8dd7810ee0754149a8a7a07cbae2182d106f5 -size 55364 +oid sha256:bc8b338c1a56b1b663171e16815b3c8122dab3ec948f3db4b9e790833b3f89a6 +size 55378 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png index 11901f4244..3cd7dd274c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:094f9dc069bfaa0a5b168d2ec41e0b3d9e9dceb135815cb0f07ba4cab9dca669 -size 54108 +oid sha256:b2a89e79995050e8b24b459172a7c123cc08c64097d5d735cef8c47f913a3bf4 +size 54080 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png index 6e06afc836..ae8c29241d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:832b227fc82b946df042658d134f1c699c720d3e153576259fb145ec9d0c4c45 -size 58441 +oid sha256:616deb9421b09e2fa25d6953263fd70a9f687fdfbdf9503bbc35e7a0660ec440 +size 58459 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png index 461d173e97..767be1a188 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:407301c3ad51be44fcfcd804954a672e677ea1bc59af39e4269100acc4f720d7 -size 59368 +oid sha256:970396f75edf55841822286155e73e5f4981c347c7c2ff34e69ff9e4bf0aac9f +size 59343 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png index 284f92cb26..157e74f7f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:473a4f7d9623a7351399d3fcf98e30adbd31feabb23efacda83fb68460b75e48 -size 50912 +oid sha256:dc02a7c7b38753d9509b3cb0fb2eb0e29b6d6c79b8471ba4dc7dd5b81b13d15b +size 50892 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png index 33ed4fd667..b3c490ad32 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccf988123f7fcf7a2d6ad3914d3e1a30dcf99c49ada7fb7dbaaacb64d7f2250e -size 55562 +oid sha256:30e13e1b91d681088ceba71f21f668a5d8b8f376cb10832f0289b1b14c1103e4 +size 55569 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png index f926ca104f..250279e2f8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1612a4b0e0df958cf99295ab318ed8260d5c12b705f65f5db4ab2341930564b8 -size 50518 +oid sha256:4f9e76f5d50ce3e0fa259f0692184564a8a988c2e0ba047595c34a99c04fb8e2 +size 50510 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png index bc016b9861..6b4cb7360c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7078a6ac34df84c959f6e2c206d818822a58493673749a3b89500a1ef1c0acf8 -size 52949 +oid sha256:abf3863e6d5ddc747dfea06a006983345937cd85d0e89b60bc625f4ad16b2691 +size 52906 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png index eedb0c1ae8..4f903b55b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f69563c42d5315b9e4203719128340fab045ea3473c494e1a1376fe4cbb3f0d8 -size 53521 +oid sha256:2e99ae9731e9c75fd025db8f24649d6219941ff3aaf0bd4a67bc2c8d1f204cb3 +size 53516 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png index 1b03d639f8..5e28ba8938 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c623703f53cbf1ae42e1d05af88e3c94e5b438cb96a3dc5cd234026b29bf0e0a -size 58286 +oid sha256:f5c6ac53f33fb4338a11358a487c2042304691ecf50f61ca0e7cbb75bc227efc +size 58294 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png index dbe5409ce1..74826e1e9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba5ae56e80ca9f5d3e5e2e0d50a2cbda7870c6286f350764dac7817d533d6c18 -size 51735 +oid sha256:805245ffe7f4e99a0f5927b89bcaa6ab8eaf7cc603d352b14b8109e76eecbdf2 +size 51742 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en.png index 1cc489f067..264ff76564 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5bd87fa02dda072996cb8b1c927bceca0a7dac0c790e82681b4c1e411523365 -size 32310 +oid sha256:0672e8d71e04366d0fd7622b3758e7ca310b627b7424639fef58f91c324c3598 +size 46781 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en.png index 8808b06521..678b74ef59 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37903c21d648cbc2e761b32bc822bbe4099b8259e78e3a5b75f5677f2979c20e -size 6208 +oid sha256:22ffc77f78c6453a8719f8112fbf9bc97b41bbf9b738f701764599b4b8aa50e2 +size 6342 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en.png index 42b189e5be..7172c3fee2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17b8d1408828a857eda20d194c342bef45151a141d294ba8df756d9b860e6d98 -size 6008 +oid sha256:5a5b20dcdcda35f57296a96cf44ae67a0e9a7798a073eca0d49380d93e256606 +size 6133 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png index 1a6f5d660b..4caec79857 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30ae0b86a9834a90990a42f6bad0fc9010b4109bfbbe85072f00d61b0664e6e2 -size 10926 +oid sha256:5aa13d38c3c677dc552e1ad6ffdc19caa37c96287945b877804584e418e4acbc +size 10915 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png index 1c65fadbf4..6482d7322b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6c87eb2b2da4afdadd949bd39e88389c34053adb19d34f8958f97ae1faf90da -size 18557 +oid sha256:416b0ee79cd8c07fed42739309059895f8c36c20d3838be4a5a4afbfbd0b5394 +size 18548 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png index 42f4e1a941..6f42ac691e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c49dbe21e9c465adc1f12a57b87dcb06569936e80d047e0db77314cefce4691 -size 7756 +oid sha256:c82fdba61809fce17e2eb7e9a79857a260e5598a2a9db88f481db69e2c7f79fa +size 7745 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png index 41e20b4266..fddd092e48 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7523f982565c692f9986d11bba14ecc51a3401700de5a752fe5d2b667d0ea236 -size 10560 +oid sha256:36aad99f720579ad309c01591f2d4e765925aefd60bec2f66a28c14d5748b855 +size 10551 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png index be3a01d3d2..92b79113e1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73769f2c3ced2e20f6a3a91cd8cd040c14e93a19c923d5784e2081cf4baf2d44 -size 17790 +oid sha256:1d527056f8cc0ae149aed408898cfc47cfdaba91cc7367e4cbf10fa49df44f9b +size 17781 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png index 90d85686d7..f59422b33e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_ComposerModeView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef3e1d6d11520f6475059032d53c9c0a6e80c133318a0ae44dfc67d9b69c31c1 -size 7494 +oid sha256:c9042bb2175fb555c005faa1f69bffd1640c91a3c109a18d4759d802d1540350 +size 7485 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png index 37f723e839..5f54605f82 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0bcb9f9715c5ecf3007c2128f68e040512645c5db10db1adf6cd2bf118d50b5 -size 50279 +oid sha256:6a9022d63fa2d6f972b94856ceae281a918bddbdb935962bd21088baf126e03c +size 50165 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png index 02237c1549..996927c6c1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02bc44adb506a0a8b71ef96d8f3d5b9ce0ad2ec7dc9cba27eca8e0bfcaf804c0 -size 48113 +oid sha256:adf6cbfa0c5a85debf5f271e16c1cd6ea2d8bf092d8a5ff829e624212805e21e +size 48034 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png index c36a00cd27..40342f172c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b170b771205f42a4aaf6e23b1043cc2b7ca591cc940fc729f8c7ca62e1778ccc -size 51327 +oid sha256:6f8c5be5646019061349e6b3a7f358de7a0e2198f132be83cc44ddf5d82ac6da +size 51339 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png index ed3fbcb332..2156c25e2a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db1c5fb588286dd755213c2eadf23488ddaf9eac7e88585a339484511382cd4c -size 49522 +oid sha256:734df31d9ad63ff8ce0877daaa7c1036a0a322209d16ff9c9cf544d26676bdf9 +size 49482 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png index 4d6bf8bbf9..12323c479d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:008f560c95d92128a7978478563d47bbf57bc0ed1d165f69c60f3d088a8b1798 -size 41741 +oid sha256:1d52e9f943bbefe5bc763dcd2b460c2e701625d427efc344b53b1ca38854bd8b +size 41761 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png index 44fd390226..3b24860bec 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e8f94bfe6ac910599edd6d2a49ed0369e2304dc589cb574cbf095157e2ae507 -size 39148 +oid sha256:aa6e7dae4a224c2911536a5fc956cdee78fb02b0af2549054dc3705c53aff481 +size 39131 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png index ea61e45a32..d29752dfca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5de0b9b9e57b29ea1db60e136654359a05373788ed2ced2036fb536ca20d74f5 -size 50358 +oid sha256:d362911049fc57b2a321042c420e36a5685d29957e8da336babd9abac14d50c6 +size 50031 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png index fe3884483c..16b16d8f75 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc2fcfae3ff423b0c805a24f46e42a3321830a160f42e0d82026da1bef6cebcc -size 48490 +oid sha256:827d8beccea22589652fde2e1b83de48429775301f7d68c43950605b92940fb7 +size 47849 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png index e4cd320317..f7c45ecf1c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f26a02838efca6a91ab005822913eb770e9cf06799653532905814f97848567 -size 60599 +oid sha256:c62b0036ff3375f70003b21192a2e8e05871b54c960022bac57066eb390b47a3 +size 60597 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png index fb52919dd3..6135707a6d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:008f75cc5a2bceeba54406ff74c2e5541ebf7a39c00489afd941cfcc79e6ada9 -size 58085 +oid sha256:d393c37651e18449f5f0fdd44fdd9e91d1a2d4fbb6afbd3a92c91dba5c125135 +size 57722 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png index 37f723e839..728390d025 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0bcb9f9715c5ecf3007c2128f68e040512645c5db10db1adf6cd2bf118d50b5 -size 50279 +oid sha256:8c17f3c52a425eb77760c6c3d5f9e18c4dc4f14ca5fb6e4e386d9205df3b4fbb +size 49990 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png index 02237c1549..b793c0b42f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02bc44adb506a0a8b71ef96d8f3d5b9ce0ad2ec7dc9cba27eca8e0bfcaf804c0 -size 48113 +oid sha256:70700bd9b3b3157f75336c7d4b6f56deb462bd30bbcea6ac773c2da5f993df90 +size 47773 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png index cf5d4dec00..cfe22711ba 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6dbcd0f76ceb070d1a7b3f9a22292b37c5bd9fa005915233db7bcb8f45d4ccef -size 61775 +oid sha256:6af8b4ecc2845f6cc8ee6c15507852ead9bc76840e35deeeb0f0318ab9f7678e +size 61702 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png index d7cb6108b0..d96c551efa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:335853740399624113c6e83d2cbc411691eb74759bcdcc1575b7fa3d10ad4ef6 -size 58751 +oid sha256:44d1604be0007f4db8585fd40ae56d4a346801c98388c3b69582d32be34cdd7a +size 58533 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Day_0_en.png index d04df1d38c..1764036218 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8cf7ee8e457e03a2abad0419fb8466f3f43b85abeabf705dd7af412dc4e4d45 -size 51250 +oid sha256:24debf9cd1db19d5e6245e556d871b9a2a756d6c9e80fd5b45cb930e9a50a394 +size 51429 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Night_0_en.png index 9b53a68b10..f73f125a1a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerFormatting_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6db26883ef045ff984e8cbf6256a01b8221825efa29b82364187c6b4fcf9d2a -size 48653 +oid sha256:5e9ce65239d7f8cee5ace51d9559ad4433cba28d762bf535228d9c4fe6755eac +size 48818 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png index df3af23261..e35f1b24c8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2703da4167bd0198f9666c2160bf95e4c99ac718864ae67d277fbbb4fd50014f -size 71876 +oid sha256:08ea9ead35a143a4a14fa6b4185258417466d7d05659ac839c823d80a950a8f6 +size 71689 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png index 6d8f6e1a3e..892b7a03b0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86f6e18357569284c223afb87195be656e6e6c90794e64ef6a13346c8de6c496 -size 58367 +oid sha256:aa695595ef8f487bf0503648024f4337ac8b39035a79d8c5612c366dd2c8c570 +size 58177 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png index 2704eb3847..a2bb96eba8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05f9317281ed84751b9f168c4495e94d1f68a9f9e7946270402db59e259d1ac5 -size 71392 +oid sha256:6e6e9f5972f3119468855637eb0ff4e975ffe1a36162bd88485ff34598bed6d5 +size 71258 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png index 6cc38e5ad5..b1ef3a5c64 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be4cda10c2b416d70d020c46abb00e41a2802e5d71f2dc416c506cffae147af1 -size 80226 +oid sha256:36d9ffefb8b575dbdf308b4075511edb2716f1b5d5de7dcb96a0a13dd68d9052 +size 79811 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png index a74e2710c8..1e939c2803 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d29017d9dca92779074b963ba29681bb6cc83728a15ba2f55846c8fb2751d1d -size 61119 +oid sha256:27320b5230058ae90d35f681eb46a64fcdb0a83037b2e5ec2fce49a331e4f525 +size 61091 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png index f3472de5f0..f4afd108ed 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8d1701f1be6087e93d15bbeed97659e57e0d58b9d5087fad0253d5d3dd60194 -size 59972 +oid sha256:e159e59cc4fbcb7e33b4db5f0b04b486ab7d07426371e288c9bbc2b80c05097c +size 59854 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png index be14ebd9b2..fa92ec10e6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2d984f17ca414c523d6a2cdcf9fc4f82c0759b22b72b60e8f5bb28776350a72 -size 66958 +oid sha256:db7a7db0cd732c80d03b561ed3061843bdecd23c6f188a7117d3674a62fa15e7 +size 66757 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png index c0ee61b312..eb02cd57a7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eeb25a0b7738b0a8b12a2fbdcfc469dcfc2c893ebfa4a50a3047491f817ff981 -size 88665 +oid sha256:2f4d9572d105726c07387f037e65092adcbb8b631d0406eabad30dbc8382383d +size 88343 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png index 05cb3a4a89..d6a380f3a1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1f008fc8bc035bf9256e19e831691d3ac7c3347e83aaed2ae8d4b7a7f5b4213 -size 59285 +oid sha256:e9dd1cb61ef6b1a6f15d766882f6d748ff8b45c4cb45588ebf8e3787cfac269c +size 59158 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png index 63622b0027..3ccd6de45d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9294ee360463d72968ef89eeed7ff52c80da29e4a59f36f00422f1fe3cb7d9f -size 59350 +oid sha256:b5286b5cea91c0f474d86413a1808129cecbf4a5b5992dee2059ec0cbe6e74ee +size 59207 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png index 62268cf4f8..b4712967f6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5dd13cfda2b0f029a46477cbe9f8db1e3a191890072665adda02ec0750cddcd6 -size 66535 +oid sha256:5330b8699041f01a5874c92152f8b6524755d327612d976c7b731ac9def233e2 +size 66344 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png index da1080256f..b9cc103539 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b32f9442e9088eec377f74127c99002aaf2c5668b0550047dd7b1c9e73ad619 -size 58783 +oid sha256:65f9224c7c4556477c362fe81057d3fc89fe9043e447d225809dbb66d1895f74 +size 58644 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png index 9e1047504c..aed4467033 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24baa66c2fced922b328987b51c1045af7111fb3c7e4bafdc46046eae61d0f87 -size 68773 +oid sha256:0ec9a6e9914fcaece7a5fc79a94437a6798a9ef9fe29da301a9b6b199bc90ecc +size 68290 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png index 70a49794e7..9499864bec 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e343b71b9f170fa7879510544cfc95af1ba15ebc128bc5d78afd49d10c70dc66 -size 55802 +oid sha256:a765b2e132737bb0213be31344fea05e60dc46b30b032c0c53b1a7adae59359c +size 55167 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png index c04c1cae02..e65958a5d4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d76f37cc5bd2d6ee9b7c87bfe7b656b0095ce6ded4d07cdc48d255039aed3520 -size 68313 +oid sha256:c26f7171640584447f185263092281a44b25c2cb3cef9e470cd9d10474c1f241 +size 67857 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png index 98a5dfd03c..533989345d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d24998e960d2d4d36c1ef0f589e9094d972203016b0a923268c1894bd09f267f -size 76999 +oid sha256:9bf5ef7638d415bedef349848c03bdcc093e00f391d91c5d528b466ee8117a64 +size 76423 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png index ba691c8f65..c8636a07f9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62592587ff02f0d36cb40f0b59fa3e7c6925cd42622ac76c4d561f6df999eba9 -size 58404 +oid sha256:dc76afb5738bb1cc70ce048a990cb428dce012eebbf503df59439cbd8546dbe4 +size 58006 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png index 7ee8d6355c..838a92aeb7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc54d34649b067af6e0daa7d2e1c8661572fe0139ea9aed209b28c3a99f44f12 -size 57353 +oid sha256:30b9d933c5e1cf1a5f4bc721cf8328b87ea025fae703c239a81a6d68748775d5 +size 56888 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png index 80a0c981fb..e9afa6fd69 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10f02c7de0575dc30c65cafa4adeb265d6ea1e487db240f1d4052be138a8b0b0 -size 64014 +oid sha256:5308541d962b0835476e6443a4dd1af53bebd477ab2f382daefda9121483cff5 +size 63637 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png index 3c4f0dff27..fe9f9527af 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a196fe9e7c551fa7cc1145c9f8df12c5905678fae285884b71e7ea15cea1bf5b -size 85088 +oid sha256:c2325468ef6b2c89b2989d7ce80526cae29eaab3708da4bedcbde0b2c4c2f9dd +size 84835 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png index 616dacf9a0..139c44ba12 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60b3b04167249a6283dccae1450645853df5e05ac7a31f419c674be0594dd413 -size 56710 +oid sha256:451ef300ac8c65887a1caccf643772dd331f59dd1181c97f0b9c53a0ff457f89 +size 56207 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png index 256094a264..71a9acd0b1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d303c75fe252ee9d3fb0bd91131ed44b731ea6fbe120dc1379aeac4c4d43c467 -size 56693 +oid sha256:4bcfaa8bca539371c914e56ed1108282f0e4df826f99527ce982a720f22d2655 +size 56192 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png index 9aa831dde8..c4f985c80e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81d23de4f3afac7993f42ea8030f6a2392768b343761408d6737382492443267 -size 63586 +oid sha256:d65864db2aa76e16df454f6772c296ac4cb9efebe2a417560e2b0e8e65503a89 +size 63211 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png index 3c59d53b44..6c2e72c7ce 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c3a1636c58e8243f971f69ea3575e75a12526863f1304a32f65fc2991fd403f -size 56250 +oid sha256:483daeec8b5d0be508de8f979ace30bdda1ee1c7b3ccb33af0938deacb8f0f40 +size 55673 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png index 93c1f0a9ce..2114fe5594 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8eb6049cc99813238995f936022fd9fd5a43d1e917bfc69ab1069fe3da456cb5 -size 73316 +oid sha256:247d836caf3bed3b89c6a772861d8e302f0b9c5f9c299edd316ad83ce55c8d9e +size 73090 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png index fe7b50f2e8..bef915901c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:611527e8c0bce7a9fb48b5eff42170cb9da5f40cf020c78209dee84615d300ba -size 56514 +oid sha256:b3006fc80bef839cb8a2a1ad83f9572b157f0abfe8fd9f170de2c09f882e02d0 +size 56132 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png index dd8f8d2a66..72e28cbe9d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77b28be1b95709082e0302cca5b65c2d57ab48786e6a22facb8c86116f058b11 -size 71667 +oid sha256:f3c5de24b62819c74c8183ea8a934e3e463bd2da4d00641341ade7e58b644e61 +size 71496 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png index be45e720dd..5db52bc9c2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31875ed4c6d9443418899de47eeb5b61d2246d8321e83579681cfa152ff4a056 -size 83174 +oid sha256:b60c12e4345b74815300f992b5c95a54c9ceb4d91e511f13e98e2f2805bfa1f9 +size 82673 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png index e7efad21d5..f01e79ce79 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cc4f388f677bf04259344b5bfc9033ef6a4a76ad161012abcd0239ef520a8d8 -size 59670 +oid sha256:04dca8661539bd8c9a4afd97f1882415d7c27858b2b489de4f857205543be4fc +size 59397 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png index 638e2761d7..3146c25a3d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e57a614424396e36229d7877a0bb222a51e9e955a42e180acc1d43c048684da2 -size 58787 +oid sha256:8adec1a157ed614916988f563391dc817319bb27b10d5b4a3a41da531e9554a0 +size 58466 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png index 6c510542bb..c6fa978c91 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4546f32ff1eeae0a923d473491926a6037eddf59c0c88c516c504b9875874c8a -size 66402 +oid sha256:4bea8196d7650886772d346a013e85307005d9a3f24b5a681a14fc1f218b971e +size 66295 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png index d472874510..ae98e95d46 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acd25c00d9127c2c78f48b22296a5ab33f1e16ec5698c93dd29adc9172467aac -size 101706 +oid sha256:d3e535259e6d81f396970531e095453989908e91f4a8ecaf47325430eb86c955 +size 101506 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png index 48f0ad6881..ea8fccf53c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d066e82aba5742c7e84a260de0e4578bb3bc8faac097225271cfdb14cd52f5f0 -size 57816 +oid sha256:cc534ed58d1faf6fbf1f4fdace08e02958e60b54c457436eac2a9c1357b39517 +size 57490 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png index f8f0337792..171702f3db 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c037b4de113387ac7e28d256d28ce9308be184b4ebff988ed96760623acfafd -size 57776 +oid sha256:a56524de1c9f55eb3d6d88342d6d8576508d6145b3fecb8dddc38c598c82a67c +size 57356 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png index 6278391831..882819289b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81883325e2e450c33f38b3143c43a3fa3d659a210ff6e9ef40de71b1d0522f50 -size 66781 +oid sha256:0c7299aba8e5340b443223858d405f99ab1a4667721b0abbd895713111055116 +size 66570 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png index 07c20262cd..b27cfcbcf3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6b5808bdde620cac3fe980aee1f8162a854965113d99d074442a2baa818d712 -size 57198 +oid sha256:4294a5f0c9b943ccf3e9c5ac6f9ecbd574c34cd5334a044342c72cf72f0ef80a +size 56848 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png index c41f41d043..182b04ed36 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7174f340d6e16be525da9a06270f07abc7496fc6c41a5670a71bd1b23f4a72c2 -size 69957 +oid sha256:d2a3c8af39fa40b72e95cc4191f820ab2b2b173e37b99178ff7c06a5870ca2c7 +size 69971 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png index 5d3b894ebc..834036c242 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbb0c22089c063c18042c8778c1b69edb441af8071f7dfb9a3ffdaeab4ba4c71 -size 53340 +oid sha256:73a1a7607c6273081ef1b866be384fc40b65283cca4f72f701f174d913973c85 +size 52902 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png index 61a6581ec4..e35a7cd447 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9a561ca3aa61371cc1bd0c1b51508469a0343de3bd8f404055041591c60d42f -size 68231 +oid sha256:f5bbbd86cfe40fb6e861a9473f0a63bcbba808d915da99b14f085a27b9428e15 +size 68300 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png index 7c25276223..8ca87c0c40 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c739add59dd40303652319c0b789ec4d0d2224cc097598ef717e8fb101031ad7 -size 79471 +oid sha256:b9610ae365f1cc089b17cb068e66c5f90414364c6bf181c1c7ea2800353a9914 +size 79614 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png index a3fcdfc5f0..45d11dd4ac 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61d30aca9b213938462659c2dcb8bc8ef10b28821f8492715003262f4cae142c -size 56761 +oid sha256:072afde5059b3a90977929811f43402d396ac64debf2cbf17c1f6efd35394b46 +size 56298 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png index e10bdbdf26..06d1f5c9c3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a84be2101e96ab4e7566e4fe1af14243466c7dba7e540fb7502acbbf70d33aaa -size 55835 +oid sha256:563e94244304f75a1d64151fdc35e35a9eee2f0c88d4dd4e4872a580adfc434b +size 55392 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png index 29ac8cd6f3..b10f296866 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f168b3af0e3679a2d7a5f2baddc1523c1afe9dc433d25c267572097d9ab7d15 -size 63284 +oid sha256:529ee850c430ea3bd54aac5b0a768cf49dbce44c6629e41ca4a8293e60d993f9 +size 63140 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png index f405aa34cb..80fb5cec31 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41799e15fad757a976b278d5d722fc755dcfdda3ad0880a1f4058a337b96d470 -size 97907 +oid sha256:38ab31d94f2252fc5a6bfa720529eaa1d0f9459395e77383cf55b06547ca6117 +size 97622 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png index 9b72a8c4fd..a83053dfd8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3d27473a9375edc590aeedf8dcb188e1c23785a8f8c62900aa439c33f86ca13 -size 54772 +oid sha256:a2b367cb2f3d35dce7c038c3358906e32669245537df0e4d6ec33c21ce6c23ff +size 54362 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png index 7a87bb30d2..478b23ef50 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52a125268370bb369c53271f204b5f942da75f01639a39ae6b935d3f3ab4ef00 -size 54705 +oid sha256:57a1fbbce28ef24a5190758b2482622fafda8ec6206b68b8ed632e0e946dda87 +size 54131 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png index d0e908caff..93ddb25b2b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56d531df665ae3baa6400b0fc83b1fe756ec0f452ddd2423457ed26ea18aed98 -size 63628 +oid sha256:261747f96fbf93367dae4819a2d4ae8883573cc75af1d6f43cae77f0eaf55736 +size 63307 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png index 29df858167..d142023a66 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4e66a9e00b7aa05294522055cf6a89e68d409496c1a24ef0b6d841221f6883b -size 54122 +oid sha256:e5786c4a4e98207f229f41a32defb71e059ac3ea9380acacd8883e188c68e81c +size 53735 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerScaledDensityWithReply_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerScaledDensityWithReply_en.png new file mode 100644 index 0000000000..3806b4217c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerScaledDensityWithReply_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d35ab62460942f4f14edc87aab84f4d659b18763c4cf8a1c353f99085c1c164d +size 16727 From 289dfff50a07e7544e4cff8811e485ec308bcf30 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:52:21 +0100 Subject: [PATCH 0229/1083] Promote "history sharing on invite" out of developer options (#6647) * Enable history sharing by default, unconditionally * Remove feature-flag dep from history viz icons in room header * Remove feature-flag dep from warning on inviting new people * Remove feature-flag dep from warning on starting chat with new people * Remove `enableKeyShareOnInvite` feature flag * Update screenshots * Remove redundant `FakeFeatureFlagService()` invocation, per review comment --------- Co-authored-by: ElementBot --- .../impl/DefaultInvitePeoplePresenter.kt | 13 +------- .../impl/DefaultInvitePeoplePresenterTest.kt | 30 +++++++------------ .../messages/impl/MessagesPresenter.kt | 4 +-- .../messages/impl/MessagesPresenterTest.kt | 6 ---- .../roomdetails/impl/RoomDetailsPresenter.kt | 3 -- .../roomdetails/impl/RoomDetailsState.kt | 3 +- .../impl/RoomDetailsStateProvider.kt | 3 -- .../roomdetails/impl/RoomDetailsStateTest.kt | 25 ++++------------ .../startchat/impl/DefaultStartDMAction.kt | 5 +--- .../startchat/impl/root/StartChatPresenter.kt | 3 -- .../startchat/impl/root/StartChatState.kt | 1 - .../impl/root/StartChatStateProvider.kt | 1 - .../startchat/impl/root/StartChatView.kt | 1 - .../impl/DefaultStartDMActionTest.kt | 15 ++-------- .../userprofile/api/UserProfileState.kt | 1 - .../impl/root/UserProfilePresenter.kt | 7 ----- .../impl/UserProfilePresenterTest.kt | 2 -- .../shared/UserProfileStateProvider.kt | 1 - .../userprofile/shared/UserProfileView.kt | 1 - .../libraries/featureflag/api/FeatureFlags.kt | 11 ------- .../matrix/impl/RustMatrixClientFactory.kt | 2 +- .../CreateDmConfirmationBottomSheet.kt | 12 +++----- ...es.roomdetails.impl_RoomDetailsA11y_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_0_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_10_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_11_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_12_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_13_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_14_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_15_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_16_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_17_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_18_en.png | 4 +-- ...roomdetails.impl_RoomDetailsDark_19_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_1_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_2_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_4_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_5_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_7_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_8_en.png | 4 +-- ....roomdetails.impl_RoomDetailsDark_9_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_0_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_10_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_11_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_12_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_13_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_14_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_15_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_16_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_17_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_18_en.png | 4 +-- ...res.roomdetails.impl_RoomDetails_19_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_1_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_2_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_4_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_5_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_7_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_8_en.png | 4 +-- ...ures.roomdetails.impl_RoomDetails_9_en.png | 4 +-- ...eateDmConfirmationBottomSheet_Day_1_en.png | 4 +-- ...eateDmConfirmationBottomSheet_Day_2_en.png | 3 -- ...teDmConfirmationBottomSheet_Night_1_en.png | 4 +-- ...teDmConfirmationBottomSheet_Night_2_en.png | 3 -- 63 files changed, 106 insertions(+), 206 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt index 58b3fb67f6..b223d30617 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -37,8 +36,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.theme.components.SearchBarResultState 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.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.encryption.identity.IdentityState @@ -74,7 +71,6 @@ class DefaultInvitePeoplePresenter( private val coroutineDispatchers: CoroutineDispatchers, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val appErrorStateService: AppErrorStateService, - private val featureFlagService: FeatureFlagService, private val matrixClient: MatrixClient, ) : InvitePeoplePresenter { @AssistedFactory @@ -93,8 +89,6 @@ class DefaultInvitePeoplePresenter( val showSearchLoader = rememberSaveable { mutableStateOf(false) } val sendInvitesAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } - val enableKeyShareOnInvite by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false) - val recentDirectRooms by produceState(emptyList(), roomMembers.value) { if (roomMembers.value.isSuccess()) { val activeMemberIds = roomMembers.value.dataOrNull().orEmpty() @@ -137,12 +131,7 @@ class DefaultInvitePeoplePresenter( val selectedUserIdentities = produceState( emptyMap().toImmutableMap(), selectedUsers.value, - enableKeyShareOnInvite, ) { - if (!enableKeyShareOnInvite) { - return@produceState - } - val selected = selectedUsers.value val cached = value @@ -213,7 +202,7 @@ class DefaultInvitePeoplePresenter( } } is InvitePeopleEvents.SendInvites -> { - if (enableKeyShareOnInvite && unknownUsers.isNotEmpty() && sendInvitesAction.value !is ConfirmingUnknownUserInvitation) { + if (unknownUsers.isNotEmpty() && sendInvitesAction.value !is ConfirmingUnknownUserInvitation) { sendInvitesAction.value = ConfirmingUnknownUserInvitation( unknownUsers ) diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index a1d72010f6..e7fef11423 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -15,9 +15,6 @@ import io.element.android.features.invitepeople.api.InvitePeopleEvents import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.theme.components.SearchBarResultState -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -405,10 +402,14 @@ internal class DefaultInvitePeoplePresenterTest { val inviteUserResult = lambdaRecorder> { userId: UserId -> Result.success(Unit) } + val encryptionService = FakeEncryptionService( + getUserIdentityResult = { _ -> Result.success(null) }, + ) val presenter = createDefaultInvitePeoplePresenter( userRepository = repository, inviteUserResult = inviteUserResult, - coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) + coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), + matrixClient = FakeMatrixClient(encryptionService = encryptionService), ) presenter.test { val initialState = awaitItem() @@ -451,13 +452,18 @@ internal class DefaultInvitePeoplePresenterTest { Result.failure(AN_EXCEPTION) } val showErrorResResult = lambdaRecorder { _, _ -> } + + val encryptionService = FakeEncryptionService( + getUserIdentityResult = { _ -> Result.success(null) }, + ) val presenter = createDefaultInvitePeoplePresenter( userRepository = repository, inviteUserResult = inviteUserResult, coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), appErrorStateService = FakeAppErrorStateService( showErrorResResult = showErrorResResult, - ) + ), + matrixClient = FakeMatrixClient(encryptionService = encryptionService), ) presenter.test { val initialState = awaitItem() @@ -632,15 +638,11 @@ internal class DefaultInvitePeoplePresenterTest { val encryptionService = FakeEncryptionService( getUserIdentityResult = getUserIdentityResult ) - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) - } val presenter = createDefaultInvitePeoplePresenter( coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), inviteUserResult = inviteUserResult, matrixClient = FakeMatrixClient(encryptionService = encryptionService), - featureFlagService = featureFlagService ) presenter.test { val initialState = awaitItem() @@ -703,15 +705,11 @@ internal class DefaultInvitePeoplePresenterTest { val encryptionService = FakeEncryptionService( getUserIdentityResult = getUserIdentityResult ) - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) - } val presenter = createDefaultInvitePeoplePresenter( userRepository = repository, coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), matrixClient = FakeMatrixClient(encryptionService = encryptionService), - featureFlagService = featureFlagService ) presenter.test { val initialState = awaitItemAsDefault() @@ -790,14 +788,10 @@ internal class DefaultInvitePeoplePresenterTest { val encryptionService = FakeEncryptionService( getUserIdentityResult = getUserIdentityResult ) - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) - } val presenter = createDefaultInvitePeoplePresenter( coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), matrixClient = FakeMatrixClient(encryptionService = encryptionService), - featureFlagService = featureFlagService ) presenter.test { val initialState = awaitItem() @@ -878,7 +872,6 @@ fun TestScope.createDefaultInvitePeoplePresenter( userRepository: UserRepository = FakeUserRepository(), coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), appErrorStateService: AppErrorStateService = FakeAppErrorStateService(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), matrixClient: MatrixClient = FakeMatrixClient(), ): DefaultInvitePeoplePresenter { return DefaultInvitePeoplePresenter( @@ -888,7 +881,6 @@ fun TestScope.createDefaultInvitePeoplePresenter( coroutineDispatchers = coroutineDispatchers, sessionCoroutineScope = backgroundScope, appErrorStateService = appErrorStateService, - featureFlagService = featureFlagService, matrixClient = matrixClient, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index f115dd2799..b98bd764de 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -217,12 +217,10 @@ class MessagesPresenter( val dmRoomMember by room.getDirectRoomMember(membersState) val roomMemberIdentityStateChanges = identityChangeState.roomMemberIdentityStateChanges - val isKeyShareOnInviteEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false) // The top bar should show a "history" icon if: - // * History sharing is enabled, // * The room is encrypted, and: // * The room's history_visibility allows future users to see content. - val topBarSharedHistoryIcon = if (isKeyShareOnInviteEnabled) roomInfo.sharedHistoryIcon() else SharedHistoryIcon.NONE + val topBarSharedHistoryIcon = roomInfo.sharedHistoryIcon() LifecycleResumeEffect(dmRoomMember, roomInfo.isEncrypted) { if (roomInfo.isEncrypted == true) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 6e12c607d8..50bacb005f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -1228,9 +1228,6 @@ class MessagesPresenterTest { initialRoomInfo = aRoomInfo(isEncrypted = true, historyVisibility = RoomHistoryVisibility.Shared), ), ), - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true) - ) ) presenter.testWithLifecycleOwner { awaitItem() @@ -1249,9 +1246,6 @@ class MessagesPresenterTest { initialRoomInfo = aRoomInfo(isEncrypted = true, historyVisibility = RoomHistoryVisibility.WorldReadable), ), ), - featureFlagService = FakeFeatureFlagService( - initialState = mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true) - ) ) presenter.testWithLifecycleOwner { awaitItem() diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 853d76859b..5fd44076e6 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -168,8 +168,6 @@ class RoomDetailsPresenter( val canReportRoom by produceState(false) { value = client.canReportRoom() } - val enableKeyShareOnInvite by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false) - return RoomDetailsState( roomId = room.roomId, roomName = roomName, @@ -199,7 +197,6 @@ class RoomDetailsPresenter( isTombstoned = roomInfo.successorRoom != null, showDebugInfo = isDeveloperModeEnabled, roomVersion = roomInfo.roomVersion, - enableKeyShareOnInvite = enableKeyShareOnInvite, roomHistoryVisibility = roomInfo.historyVisibility, eventSink = ::handleEvent, ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index 20ec12fdb9..e74f71322d 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -51,7 +51,6 @@ data class RoomDetailsState( val isTombstoned: Boolean, val showDebugInfo: Boolean, val roomVersion: String?, - val enableKeyShareOnInvite: Boolean, val roomHistoryVisibility: RoomHistoryVisibility, val eventSink: (RoomDetailsEvent) -> Unit ) { @@ -64,7 +63,7 @@ data class RoomDetailsState( if (isPublic) { add(RoomBadge.PUBLIC) } - if (enableKeyShareOnInvite && isEncrypted) { + if (isEncrypted) { when (roomHistoryVisibility) { RoomHistoryVisibility.Invited, RoomHistoryVisibility.Joined -> add(RoomBadge.SHARED_HISTORY_HIDDEN) RoomHistoryVisibility.Shared -> add(RoomBadge.SHARED_HISTORY_SHARED) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index e40e6b03ef..7f3701a770 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -121,7 +121,6 @@ fun aRoomDetailsState( canReportRoom: Boolean = true, isTombstoned: Boolean = false, showDebugInfo: Boolean = false, - enableKeyShareOnInvite: Boolean = false, roomHistoryVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Shared, eventSink: (RoomDetailsEvent) -> Unit = {}, ) = RoomDetailsState( @@ -153,7 +152,6 @@ fun aRoomDetailsState( isTombstoned = isTombstoned, showDebugInfo = showDebugInfo, roomVersion = "12", - enableKeyShareOnInvite = enableKeyShareOnInvite, roomHistoryVisibility = roomHistoryVisibility, eventSink = eventSink, ) @@ -195,6 +193,5 @@ fun aSharedHistoryRoomDetailsState( roomHistoryVisibility: RoomHistoryVisibility ) = aRoomDetailsState( isEncrypted = true, - enableKeyShareOnInvite = true, roomHistoryVisibility = roomHistoryVisibility, ) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateTest.kt index 7bfd52d82d..54ad539bfb 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateTest.kt @@ -37,24 +37,24 @@ class RoomDetailsStateTest { } @Test - fun `room public encrypted should have encrypted and public badges`() { + fun `room public encrypted should have encrypted, public, and history sharing shared badges`() { val sut = aRoomDetailsState( isPublic = true, isEncrypted = true, ) assertThat(sut.roomBadges).isEqualTo( - persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC) + persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_SHARED) ) } @Test - fun `room not public encrypted should have encrypted badges`() { + fun `room not public encrypted should have encrypted and history sharing shared badges`() { val sut = aRoomDetailsState( isPublic = false, isEncrypted = true, ) assertThat(sut.roomBadges).isEqualTo( - persistentListOf(RoomBadge.ENCRYPTED) + persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.SHARED_HISTORY_SHARED) ) } @@ -62,7 +62,6 @@ class RoomDetailsStateTest { fun `room public not encrypted should not have history sharing badges`() { val sut = aRoomDetailsState( isEncrypted = false, - enableKeyShareOnInvite = true, roomHistoryVisibility = RoomHistoryVisibility.Shared ) assertThat(sut.roomBadges).isEqualTo( @@ -74,7 +73,6 @@ class RoomDetailsStateTest { fun `room public encrypted should have history sharing hidden badge`() { val sut = aRoomDetailsState( isEncrypted = true, - enableKeyShareOnInvite = true, roomHistoryVisibility = RoomHistoryVisibility.Joined ) assertThat(sut.roomBadges).isEqualTo( @@ -83,22 +81,9 @@ class RoomDetailsStateTest { } @Test - fun `room public encrypted should have history sharing shared badge`() { + fun `room public encrypted with world_readable visibility should have history sharing world_readable badge`() { val sut = aRoomDetailsState( isEncrypted = true, - enableKeyShareOnInvite = true, - roomHistoryVisibility = RoomHistoryVisibility.Shared - ) - assertThat(sut.roomBadges).isEqualTo( - persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_SHARED) - ) - } - - @Test - fun `room public encrypted should have history sharing world_readable badge`() { - val sut = aRoomDetailsState( - isEncrypted = true, - enableKeyShareOnInvite = true, roomHistoryVisibility = RoomHistoryVisibility.WorldReadable ) assertThat(sut.roomBadges).isEqualTo( diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt index 3bfbd1ca18..6821005c67 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt @@ -15,8 +15,6 @@ import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.features.startchat.api.StartDMAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.StartDMResult @@ -28,7 +26,6 @@ import io.element.android.services.analytics.api.AnalyticsService class DefaultStartDMAction( private val matrixClient: MatrixClient, private val analyticsService: AnalyticsService, - private val featureFlagService: FeatureFlagService, ) : StartDMAction { override suspend fun execute( matrixUser: MatrixUser, @@ -50,7 +47,7 @@ class DefaultStartDMAction( val identityState = matrixClient.encryptionService.getUserIdentity(matrixUser.userId, fallbackToServer = false).getOrNull() actionState.value = ConfirmingStartDmWithMatrixUser( matrixUser = matrixUser, - isUserIdentityUnknown = featureFlagService.isFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite) && identityState == null + isUserIdentityUnknown = identityState == null ) } } diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt index 7afbe19c3d..e176f202ad 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt @@ -58,8 +58,6 @@ class StartChatPresenter( featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch) }.collectAsState(initial = false) - val enableKeyShareOnInvite = featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(false) - fun handleEvent(event: StartChatEvents) { when (event) { is StartChatEvents.StartDM -> localCoroutineScope.launch { @@ -78,7 +76,6 @@ class StartChatPresenter( userListState = userListState, startDmAction = startDmActionState.value, isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled, - enableKeyShareOnInvite = enableKeyShareOnInvite.value, eventSink = ::handleEvent, ) } diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt index 989a5b8d20..65f977d3e3 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt @@ -17,6 +17,5 @@ data class StartChatState( val userListState: UserListState, val startDmAction: AsyncAction, val isRoomDirectorySearchEnabled: Boolean, - val enableKeyShareOnInvite: Boolean, val eventSink: (StartChatEvents) -> Unit, ) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt index 17d83a9e11..a1e8f9d4f0 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt @@ -82,6 +82,5 @@ fun aCreateRoomRootState( userListState = userListState, startDmAction = startDmAction, isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled, - enableKeyShareOnInvite = false, eventSink = eventSink, ) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt index 28bf52549e..e077cbe82e 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt @@ -130,7 +130,6 @@ fun StartChatView( if (data is ConfirmingStartDmWithMatrixUser) { CreateDmConfirmationBottomSheet( matrixUser = data.matrixUser, - enableKeyShareOnInvite = state.enableKeyShareOnInvite, isUserIdentityUnknown = data.isUserIdentityUnknown, onSendInvite = { state.eventSink(StartChatEvents.StartDM(data.matrixUser)) diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt index 88b935e47d..2c1fd1aa2b 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt @@ -13,9 +13,6 @@ import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.CreatedRoom import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -88,7 +85,7 @@ class DefaultStartDMActionTest { val state = mutableStateOf>(AsyncAction.Uninitialized) val matrixUser = aMatrixUser() action.execute(matrixUser, false, state) - assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = false)) + assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(matrixUser, isUserIdentityUnknown = true)) assertThat(analyticsService.capturedEvents).isEmpty() } @@ -107,37 +104,31 @@ class DefaultStartDMActionTest { } @Test - fun `when history sharing enabled, user identity fetched and identity unknown`() = runTest { + fun `when user identity fetched and identity unknown`() = runTest { val getUserIdentityResult = lambdaRecorder> { _ -> Result.success(null) } val encryptionService = FakeEncryptionService(getUserIdentityResult = getUserIdentityResult) val matrixClient = FakeMatrixClient(encryptionService = encryptionService).apply { givenFindDmResult(Result.success(null)) } - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite, true) - } val action = createStartDMAction( matrixClient = matrixClient, - featureFlagService = featureFlagService ) val state = mutableStateOf>(AsyncAction.Uninitialized) action.execute(aMatrixUser(), false, state) - assertThat(getUserIdentityResult.assertions().isCalledOnce()) + getUserIdentityResult.assertions().isCalledOnce() assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(aMatrixUser(), isUserIdentityUnknown = true)) } private fun createStartDMAction( matrixClient: MatrixClient = FakeMatrixClient(), analyticsService: AnalyticsService = FakeAnalyticsService(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService() ): DefaultStartDMAction { return DefaultStartDMAction( matrixClient = matrixClient, analyticsService = analyticsService, - featureFlagService = featureFlagService, ) } } diff --git a/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt b/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt index e2a309c17f..0e0016ee14 100644 --- a/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt +++ b/features/userprofile/api/src/main/kotlin/io/element/android/features/userprofile/api/UserProfileState.kt @@ -26,7 +26,6 @@ data class UserProfileState( val dmRoomId: RoomId?, val canCall: Boolean, val snackbarMessage: SnackbarMessage?, - val enableKeyShareOnInvite: Boolean, val eventSink: (UserProfileEvents) -> Unit ) { enum class ConfirmationDialog { diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt index a451d86b70..7e09a03ec3 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt @@ -12,7 +12,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState @@ -32,8 +31,6 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.bool.orFalse -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -53,7 +50,6 @@ class UserProfilePresenter( private val client: MatrixClient, private val startDMAction: StartDMAction, private val sessionEnterpriseService: SessionEnterpriseService, - private val featureFlagService: FeatureFlagService, ) : Presenter { @AssistedFactory interface Factory { @@ -105,8 +101,6 @@ class UserProfilePresenter( } val userProfile by produceState(null) { value = client.getProfile(userId).getOrNull() } - val enableKeyShareOnInvite = featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(false) - fun handleEvent(event: UserProfileEvents) { when (event) { is UserProfileEvents.BlockUser -> { @@ -159,7 +153,6 @@ class UserProfilePresenter( dmRoomId = dmRoomId, canCall = canCall, snackbarMessage = null, - enableKeyShareOnInvite = enableKeyShareOnInvite.value, eventSink = ::handleEvent, ) } diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt index 1325b46bc0..bbdc698f17 100644 --- a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt @@ -24,7 +24,6 @@ import io.element.android.features.userprofile.api.UserProfileVerificationState import io.element.android.features.userprofile.impl.root.UserProfilePresenter import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -415,7 +414,6 @@ class UserProfilePresenterTest { sessionEnterpriseService = FakeSessionEnterpriseService( isElementCallAvailableResult = { isElementCallAvailable }, ), - featureFlagService = FakeFeatureFlagService() ) } } diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt index a4bbcd6aa4..fe318a8670 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt @@ -61,6 +61,5 @@ fun aUserProfileState( dmRoomId = dmRoomId, canCall = canCall, snackbarMessage = snackbarMessage, - enableKeyShareOnInvite = false, eventSink = eventSink, ) diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt index 34f992f77d..5d541edf2b 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt @@ -114,7 +114,6 @@ fun UserProfileView( if (data is ConfirmingStartDmWithMatrixUser) { CreateDmConfirmationBottomSheet( matrixUser = data.matrixUser, - enableKeyShareOnInvite = state.enableKeyShareOnInvite, isUserIdentityUnknown = data.isUserIdentityUnknown, onSendInvite = { state.eventSink(UserProfileEvents.StartDM) 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 d4e52bdcf6..15e61f4260 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 @@ -52,17 +52,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - EnableKeyShareOnInvite( - key = "feature.enableKeyShareOnInvite", - title = "Share encrypted history with new members", - description = "When inviting a user to an encrypted room that has history visibility set to \"shared\"," + - " share encrypted history with that user, and accept encrypted history when you are invited to such a room." + - "\nRequires an app restart to take effect." + - "\n\nWARNING: this feature is EXPERIMENTAL and not all security precautions are implemented." + - " Do not enable on production accounts.", - defaultValue = { false }, - isFinished = false, - ), Knock( key = "feature.knock", title = "Ask to join", diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 6cbf122084..933298bc6c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -167,7 +167,7 @@ class RustMatrixClientFactory( } ) ) - .enableShareHistoryOnInvite(featureFlagService.isFeatureEnabled(FeatureFlags.EnableKeyShareOnInvite)) + .enableShareHistoryOnInvite(true) .threadsEnabled(featureFlagService.isFeatureEnabled(FeatureFlags.Threads), threadSubscriptions = false) .requestConfig( RequestConfig( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt index 7e0e51050a..f63bda378b 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt @@ -54,18 +54,17 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun CreateDmConfirmationBottomSheet( matrixUser: MatrixUser, - enableKeyShareOnInvite: Boolean, isUserIdentityUnknown: Boolean, onSendInvite: () -> Unit, onDismiss: () -> Unit, modifier: Modifier = Modifier, ) { - val titleContent = if (enableKeyShareOnInvite && isUserIdentityUnknown) { + val titleContent = if (isUserIdentityUnknown) { stringResource(R.string.screen_bottom_sheet_create_dm_unknown_user_title) } else { stringResource(R.string.screen_bottom_sheet_create_dm_title) } - val descriptionContent = if (enableKeyShareOnInvite && isUserIdentityUnknown) { + val descriptionContent = if (isUserIdentityUnknown) { stringResource(R.string.screen_bottom_sheet_create_dm_unknown_user_content) } else { stringResource(R.string.screen_bottom_sheet_create_dm_message, matrixUser.getFullName()) @@ -154,7 +153,6 @@ internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter( ) state: CreateDmConfirmationBottomSheetState) = ElementPreview { CreateDmConfirmationBottomSheet( matrixUser = state.matrixUser, - enableKeyShareOnInvite = state.enableKeyShareOnInvite, isUserIdentityUnknown = state.isUserIdentityUnknown, onSendInvite = {}, onDismiss = {}, @@ -163,14 +161,12 @@ internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter( data class CreateDmConfirmationBottomSheetState( val matrixUser: MatrixUser, - val enableKeyShareOnInvite: Boolean, val isUserIdentityUnknown: Boolean, ) class CreateDmConfirmationBottomSheetStateProvider : PreviewParameterProvider { override val values = sequenceOf( - CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = false, isUserIdentityUnknown = false), - CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = true, isUserIdentityUnknown = false), - CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), enableKeyShareOnInvite = true, isUserIdentityUnknown = true), + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = false), + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = true), ) } diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png index 3df4b3886c..8d8186f2d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbbd62622843fbd1d8d35b63c7308eaed46b488e6b189e987983144e5395bd09 -size 78972 +oid sha256:2119838c9649710465dc1b8610550ce101f3016a1a6511c3f6dadc715fb75862 +size 82975 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png index 44e3d87eb9..d674b1ad00 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31d18a5e250e531fd7b986690306366cf69eedcfdbaba28148e3edd1d36ae597 -size 42912 +oid sha256:7ad7b9331a5d504b8d2145c4428e6b64ed838b371f1aad5c288e5545f8a20f1f +size 45464 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png index 449dbd7465..2567512ca9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a04a5aa9e35df5eb82a0a708b2b743bb83a1a9408fee91beff60d5a1ce2c6d5d -size 41599 +oid sha256:8d74ede198f221b1138ed49bac7e02ee0fefbccd38735b09237fda95a78f6bd2 +size 44174 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png index 279035fea1..ee9fcd2088 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef69f889a28afe5704da86296ebf9916a7af1de751eb4c1ee4995ca3f70ea12d -size 40737 +oid sha256:b3f483a9e05278928f806f9534720c121efa77bd11b93ea6afc8b543f51a6d7c +size 43171 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png index 72f8640e83..724a99374d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d4312936ba67965a8b35e714bbc3014214320311c5d077d33382ebb5aca5738 -size 42172 +oid sha256:3045102b9695ce3c095ac81e3d3d26dbf182d433427903e280189613a74f2984 +size 44758 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png index 7c1059539b..c62a4e99b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b07f6c942ab083d94c22218010b4aa646cf03e87af41fbda89b16620f7b9752 -size 42079 +oid sha256:2bbbf23895558745ebe4fab7faee8ffb4acba07f48b652cc130c78ddf89bebef +size 44684 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png index d7691fa7e2..f23e6e5532 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b6db26bd05f206661a5707a972cb6f843eef82c76e5e0035775625b4a6268a4 -size 42640 +oid sha256:1f72fb044fb52f226600ad2eb3344e8122edcce15c75800fb483f3b93a1c6e26 +size 45092 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png index 9e68ee9859..47f40ccaab 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f77eba1f623f67eba427312523def9a45c41581dd4e047701b2c75f787fcffc -size 43178 +oid sha256:14261c716c286b17ee2afcb652378f9703b39f67b219256f6ac3cde61cd50947 +size 45589 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png index c42d3ebe59..fd5b8fce76 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a62965a57fea6665739d8e8b2fda9e15abf119ea59f6bbd5d7d8a269512064b9 -size 42421 +oid sha256:b1b1c3f8db4dc58dcaab91f254da2906138c09c65d4e57a77a5be9af371aaa5d +size 44944 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png index 45da7b512e..5491a33e2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39780082d7826422d70902ac2b7859013c30b41d31f20aefc25ada8aeae196c2 -size 41684 +oid sha256:a5d3a4bd5c340c0d439ccd7d7e24f372d89255a775a9497e5d9b8847354cafb6 +size 44236 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index 029a2c3639..e44f676f01 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5917028dda35add5ed6b32fa9017a9cdcdfb8d273d230aa6d529bebfbf0b95c8 -size 39646 +oid sha256:6d9a464a1bc24dc76d1a10ae835fb24839b521ba446a1adad3e70f4ae5f17857 +size 42076 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 55a953b2df..46bb9b0a89 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f65f298b3f14ecb0da53f03a20a5464a7f6ae138dfdf417ad936601a521fbb30 -size 39601 +oid sha256:29592dcede3af29136c857b03975c2697470682371ac5d606f2e6974f89ea268 +size 42030 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png index 7f4cd39731..d58516f709 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df3ceef42a59cc072e3aa21c89e9b90f0524ac422d1538804b6fcb8abf97752e -size 38090 +oid sha256:676908cf3eabc3417f228dabd2663bb0aa3d903d1b6f0e2fe770bdd6fbb48af2 +size 40407 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png index 23ccf2249a..2a765938ad 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bf5c596196e64554117addd1247aa1e5be6e8095d85a595b1c2a6232ed483eb -size 36591 +oid sha256:ae13e58b01e0e43591c0374474b33fea60574a5d8b22cb57092d15637dc58baa +size 37920 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png index 36de539c48..c8d3e8f6fa 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6900db132e6b79de1c5ac986666af46e3f7ef65a9c4cc7d847dde6962eadd129 -size 41352 +oid sha256:a5bb345d25a8b90a34708123fc6ba72dd6aca2c09ade4c26b29e9168d65e18be +size 42466 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index c5d81c75e3..cdb5f92f18 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7199817c8591ccf11241204af8a39d2ed1a60dfe238b06387749d57858cfa65 -size 39288 +oid sha256:c1d4af8779d9869938b17f26b155c584c10d119479c62918d5b819a0db30acac +size 41720 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png index 4b9b30b2ba..478f3dcb3c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed4073d3b427b2a314667f5118b571e5896f1439582b9209077ec9c62ee0e061 -size 43097 +oid sha256:6cb0953ce6c69ad2e49213bf0dbff76a87505f88a092660b71d97ad1e75a5344 +size 45766 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png index 60200cea9a..37a67e7aa0 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c68c895b189a41c7edf8fee58202560ef47e0a98082ddc3a346546f4f1346de7 -size 42100 +oid sha256:c0f655ed143e7b894e37d99fc64c75d44e6483e830055e04609a9da36830278c +size 44670 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png index f9287533ca..b41099055e 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1879c3d54dfed55e4bb46d967c9c8c5a4f95f4e31e884afde4c9c517f35402e -size 42093 +oid sha256:ac26ca718f2118d88315704ce4bc7960983ab2ac0c394199da2c5b3feeec4438 +size 44688 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png index bb868da01c..836386fc75 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2b5dc5cd20ccfdb7e6a1accabf6e139ff343c16378af19232168f835b1c97df -size 43650 +oid sha256:9a9c05a4ace7dc7013e4b02b5e652296399cb2f391ed4bacb2f74d06b68c4be4 +size 46436 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png index 72803025b8..f3ee29437c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9c7dce94908b2b0287c196f564c306a05306f058c71d75be3b298a45683bce4 -size 42321 +oid sha256:997444daf4024495291014f1cae1cee2ba389d160c0ccae706b120dcd908996e +size 45024 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png index 9d2b424654..5ccda85a79 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:743fcac827e8df7742127491722c3ce617a54c0b64fd3336f939994b45376966 -size 41470 +oid sha256:527d2c4574c8a5f6946ee94415e30152fdd9e153fd7651b5a40df789e8694d72 +size 43969 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png index dd489b5147..60753106e7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:671ae1ee2f065705b38063cb354c4bb4a63247e01e1101dd155515b46decb660 -size 42926 +oid sha256:7da6bfdf7bc9878e1850f8a443adae82a3a4b0aaa5574cec74081ba6f88b879e +size 45622 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png index d5f14e286e..5549792942 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f352ad92472cb8b152ef0660c7f66b55b956ec05bd11dbeb2c9aa543d0db2ca -size 42849 +oid sha256:2e253e47f998774da8443926990526105fd918b79040955a3d884558a110db8a +size 45538 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png index cc8b1c74e1..e5dac7dc72 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5742ffdefde6a9e3f01ba021a75eea20599cc520fa4976aa45cf1c10e394f62b -size 43367 +oid sha256:60a989450ffb8ed428d5dd021573b821d238a06f5515f21f9d50b855889ad985 +size 46022 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png index c9db5d9a07..d4143895a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f6be8e586f9692013ce38c483c42fb23f8c135593e17a72f3be19381719fe6c -size 43967 +oid sha256:37e6049854cd5aaeb50f38c4604e631fb561f0f309d4c58d41becf69a01ca036 +size 46596 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png index 6b9fc92803..03bcda4666 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b4b470aa3f3650c26c6e1cf2491ffb7c3ea58db28dd00c0755a7f5727dc60f1 -size 43192 +oid sha256:05a841f7590a33ffea5b09ffc0975bc9090b03cace9e22c330965ce773431211 +size 45849 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png index 12b5fd1b6d..19d509d513 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:656c300cea79355aa3b35cd59666f8e35aa4c09d69dd422e816f256cbe6d420d -size 42685 +oid sha256:8bc90cce90b0648a340e332276fe4395aec673408aaf938bd0d744d45c89dec2 +size 45396 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index 4c7d16ea22..8027c68a7b 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93fe116bc34f9cf8ee3da2317948a98405e36a6fb98a58b2046a049af435e913 -size 40373 +oid sha256:c3ab8eeb4123df1feb35b4d9d9c7fbf166be943edfeb9fa23ac6549463763b10 +size 42853 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index 33efb5e55e..64acd4e843 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09f89c67652965407ea147aef158d0b3281850b95cca35f7aec207693bb0af62 -size 40242 +oid sha256:a3eee4e61c8676a547c3ccbb1d6b9ea2ce0ae30286012de6b3a4f912b908d2e0 +size 42722 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png index 5e8f3baa0e..ef06cd3451 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04c7f8e85d58591c3dd6ade913b9fe0861ff7f774fdb4b46e63c9f86ef5a918a -size 38959 +oid sha256:02c734eb60efab5050988331527aae294fc6baf0b110e3395103429a79ba059c +size 41424 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png index cb6e8c1f80..25bcd31599 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27918a9baa05b2cb8dee7219b6e19cc10be1421be190d1e35724d237270761af -size 37382 +oid sha256:ced1cdb2e11bff01ffce233ddf6cf826d6db266739abcd022f83b58d8bec012f +size 38785 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png index a8894c7eab..92b2b86922 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ee0a79abd45fc9573e64b6f06491f33dfca34ddd96c0dbd3d8cf7a9052b47be -size 42072 +oid sha256:db67d40bae68ec1ece950a06f618606fedc78aa997743b1804db4b69848ba65b +size 43381 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index cc81464baa..8b143f6b5c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7146d365a105c86eecc34027d2b824e90ca1615fcf77ca0f49ed920dbffe22d -size 39903 +oid sha256:6cee9f291a3257f3960ea5d1490f3f219bb0d42b01109b9b398b941524b85971 +size 42383 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png index 55d8ab9869..a1071426b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:863c5db2d8fd863b057d0ddfe26bb3804d15126c2fdb58fc03c0087d79c6a3b3 -size 44056 +oid sha256:79ac979bcc0339ed30c68c4617f082a9398edf657cc3aea1c80df04bd4b8bab2 +size 46724 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png index 83b9c7131d..36a3defc1f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16b815f5ec48c101a7bde78cd5a4e30e825138f359e415699ef2b14e6ea23869 -size 42968 +oid sha256:0d71c5e3a8dd2defe2dd37fee1a22921f49bbc9a52a766e5ad082b6595c6ff75 +size 45577 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png index faf5081313..6c4e522988 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c47ff32beec1987fdb9f92ef6e5c9b7eca04ab20ebab576a2028225a595ba12 -size 42911 +oid sha256:ada1e17913092a5e33b5f422a41826dd711102cfb5ab396d5d323e8e0f0b6589 +size 45590 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png index c7e3599c58..d7ff4a1d2f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb4d6bfb9c412de00a2b4956032dd42906b5451eb99e6ebb1880dc01f6b55af5 -size 26077 +oid sha256:26bf76ccdb56d042422553f557d91d0f26d874a710f696ac106c5c2b5590d332 +size 38833 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png deleted file mode 100644 index d7ff4a1d2f..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:26bf76ccdb56d042422553f557d91d0f26d874a710f696ac106c5c2b5590d332 -size 38833 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png index fe44b8941c..f5ff7856b2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8c422787b67d477d3b7c8d5dee8879f33d47153dc93dd29bb3883e4ed863a41 -size 25232 +oid sha256:8413aed02383572cfe8c481c6ba8b0db4cfb3402334c37f2d8b54a73fe4bf594 +size 37343 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png deleted file mode 100644 index f5ff7856b2..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8413aed02383572cfe8c481c6ba8b0db4cfb3402334c37f2d8b54a73fe4bf594 -size 37343 From 3379c61ad1a59e68b099ac6a88d48725e17389de Mon Sep 17 00:00:00 2001 From: Kurban Sagitov <58472509+krbns@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:20:24 +0300 Subject: [PATCH 0230/1083] PR:Fix mention pill cut off (#6622) * Fix mention pill cut off * trigger CI after screenshots * trigger CI after screenshots --- .../android/libraries/textcomposer/mentions/MentionSpan.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpan.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpan.kt index b0f973b6b9..e2ae08c421 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpan.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpan.kt @@ -105,15 +105,12 @@ class MentionSpan( bottom: Int, paint: Paint ) { - // Extra vertical space to add below the baseline (y). This helps us center the span vertically - val extraVerticalSpace = y + paint.ascent() + paint.descent() - top - val availableWidth = (canvas.width - x).coerceAtLeast(0f) val measuredWidth = measuredTextWidth + startPadding + endPadding val pillWidth = minOf(availableWidth, measuredWidth.toFloat()) backgroundPaint.color = backgroundColor - val rect = RectF(x, top.toFloat(), x + pillWidth, y.toFloat() + extraVerticalSpace) + val rect = RectF(x, top.toFloat(), x + pillWidth, bottom.toFloat()) val radius = rect.height() / 2 canvas.drawRoundRect(rect, radius, radius, backgroundPaint) From 112dc93fff29f0cddaa8a2aba7deab8924e15304 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:23:26 +0200 Subject: [PATCH 0231/1083] Update dependency io.sentry:sentry-android to v8.39.1 (#6648) 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 f0078399c0..edbfdc2489 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -222,7 +222,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.39.0" -sentry = "io.sentry:sentry-android:8.38.0" +sentry = "io.sentry:sentry-android:8.39.1" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 1c229e7229b148fb7653dcbcf459d39d93d62dc5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 14:28:52 +0200 Subject: [PATCH 0232/1083] =?UTF-8?q?Replace=20"=20-=20"=20by=20"=20?= =?UTF-8?q?=E2=80=A2=20"=20as=20it=20renders=20better.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/ui/VerificationContentVerifying.kt | 3 ++- .../details/MediaDeleteConfirmationBottomSheet.kt | 3 ++- .../impl/details/MediaDetailsBottomSheet.kt | 3 ++- .../mediaviewer/impl/local/audio/MediaMetadata.kt | 5 +++-- .../element/android/libraries/ui/strings/Strings.kt | 12 ++++++++++++ 5 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 libraries/ui-strings/src/main/kotlin/io/element/android/libraries/ui/strings/Strings.kt diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt index 6fc593ffb2..891b2a108c 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationContentVerifying.kt @@ -35,6 +35,7 @@ import io.element.android.features.verifysession.impl.emoji.toEmojiResource import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.verification.SessionVerificationData import io.element.android.libraries.matrix.api.verification.VerificationEmoji +import io.element.android.libraries.ui.strings.Strings @Composable internal fun VerificationContentVerifying( @@ -49,7 +50,7 @@ internal fun VerificationContentVerifying( ) { when (data) { is SessionVerificationData.Decimals -> { - val text = data.decimals.joinToString(separator = " - ") + val text = data.decimals.joinToString(separator = Strings.NICE_SEPARATOR) Text( modifier = Modifier .fillMaxWidth() diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt index 84712eb10a..f13e2f1600 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt @@ -46,6 +46,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.ui.strings.Strings @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -149,7 +150,7 @@ private fun MediaRow( ) // Info Text( - text = state.mediaInfo.mimeType + " - " + state.mediaInfo.formattedFileSize, + text = state.mediaInfo.mimeType + Strings.NICE_SEPARATOR + state.mediaInfo.formattedFileSize, color = ElementTheme.colors.textSecondary, maxLines = 1, overflow = TextOverflow.Ellipsis, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index 5ace40a0d1..a433abbf39 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -49,6 +49,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.ui.strings.Strings /** * Ref: https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=2229-149220 @@ -93,7 +94,7 @@ fun MediaDetailsBottomSheet( ) SectionText( title = stringResource(R.string.screen_media_details_file_format), - text = state.mediaInfo.mimeType + " - " + state.mediaInfo.formattedFileSize, + text = state.mediaInfo.mimeType + Strings.NICE_SEPARATOR + state.mediaInfo.formattedFileSize, ) Spacer(modifier = Modifier.height(16.dp)) if (state.eventId != null) { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaMetadata.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaMetadata.kt index 4c267a54dc..dc0090298c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaMetadata.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaMetadata.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.mediaviewer.impl.local.audio import androidx.media3.common.MediaMetadata +import io.element.android.libraries.ui.strings.Strings fun MediaMetadata?.hasArtwork(): Boolean { return this?.artworkData != null || this?.artworkUri != null @@ -22,13 +23,13 @@ fun MediaMetadata?.buildInfo(): String { } if (title != null) { if (isNotEmpty()) { - append(" - ") + append(Strings.NICE_SEPARATOR) } append(title) } if (recordingYear != null) { if (isNotEmpty()) { - append(" - ") + append(Strings.NICE_SEPARATOR) } append(recordingYear) } diff --git a/libraries/ui-strings/src/main/kotlin/io/element/android/libraries/ui/strings/Strings.kt b/libraries/ui-strings/src/main/kotlin/io/element/android/libraries/ui/strings/Strings.kt new file mode 100644 index 0000000000..c4566a5db2 --- /dev/null +++ b/libraries/ui-strings/src/main/kotlin/io/element/android/libraries/ui/strings/Strings.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.ui.strings + +object Strings { + const val NICE_SEPARATOR = " • " +} From a276e67ce60b2b3a62de0aacb89033626d2efa9c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 24 Apr 2026 12:38:13 +0000 Subject: [PATCH 0233/1083] Update screenshots --- ...tcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png | 4 ++-- ...omposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png | 4 ++-- ...raries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png | 4 ++-- ...ries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png index 627828a287..3acdc88bea 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e171ced0a7f9994d1e9addb093959fb455727d81912aecb377742541181535a -size 35733 +oid sha256:c9e68f504334bf51de555c27936d2561f3def8c7920189512594b74ba9770105 +size 35720 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png index ee87ced6f5..ed7123fb14 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanThemeInTimeline_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba17ec26a4807e2cad64769b98140e2d77f133e39be72090a1f44ca143427833 -size 34106 +oid sha256:7523890541aefd0f65533247e0bb0b5c306946b19ab7d27cc8ff0d6e69e85478 +size 34166 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png index 140398dcaa..aaabcd8f67 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8366d3c9ea45d6b7e24184b5ba9756cfcfe8a592ec19b107be1168b307840192 -size 49433 +oid sha256:cc5c6f3dc41efa8c969c70ad36c1c4ada0feaf279767d0e2165a5837f568e2e7 +size 49441 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png index 0c0a38fbd5..508c21c942 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79cc95b3838f24e85a87d5f0116575ad74e2abc03b77a28464d7fa82fb357840 -size 47343 +oid sha256:d091d25da896e86e0851cd3d440f7b4b05dfaac6240d9639b06e9e362c20f5ca +size 47304 From de7b4002d8d5953a7304fc01237b1a666124f0c0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 15:16:26 +0200 Subject: [PATCH 0234/1083] MediaDetailsBottomSheet: update wording. --- libraries/mediaviewer/impl/src/main/res/values/localazy.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/res/values/localazy.xml b/libraries/mediaviewer/impl/src/main/res/values/localazy.xml index 760ba2e7dc..02a16a8736 100644 --- a/libraries/mediaviewer/impl/src/main/res/values/localazy.xml +++ b/libraries/mediaviewer/impl/src/main/res/values/localazy.xml @@ -12,8 +12,8 @@ "Images and videos uploaded to this room will be shown here." "No media uploaded yet" "Media and files" - "File format" - "File name" + "Format" + "Name" "No more files to show" "No more media to show" "File info" From 592980613793b82ac389c0b4061bbe6b09320013 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 24 Apr 2026 13:34:34 +0000 Subject: [PATCH 0235/1083] Update screenshots --- ...ession.impl.incoming_IncomingVerificationView_Day_9_en.png | 4 ++-- ...sion.impl.incoming_IncomingVerificationView_Night_9_en.png | 4 ++-- ...ession.impl.outgoing_OutgoingVerificationView_Day_9_en.png | 4 ++-- ...sion.impl.outgoing_OutgoingVerificationView_Night_9_en.png | 4 ++-- ...pl.details_MediaDeleteConfirmationBottomSheet_Day_0_en.png | 4 ++-- ...pl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png | 4 ++-- ....details_MediaDeleteConfirmationBottomSheet_Night_0_en.png | 4 ++-- ....details_MediaDeleteConfirmationBottomSheet_Night_1_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png | 4 ++-- ...ies.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png | 4 ++-- ...s.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png | 4 ++-- 22 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en.png index 59ce066fe9..3639cb1312 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e40914567317a9cbecd3638bf23cba6ffbaa9be24733909aa58cb8d84a64c463 -size 31169 +oid sha256:4c1298d7a7bef09a72be97f859448a877594088482de6e1fc2660e1a5dcb0869 +size 31354 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en.png index 8315edcfd1..841dd9f1bc 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19e65122fd39fbf25050c9e982285fea34c4fec06647d713c8ea78c2c813ea5a -size 30478 +oid sha256:621db291024ceaa9bba2bc3e71a68b6fc67dab8055ede0595f0519499324b483 +size 30644 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en.png index 59ce066fe9..3639cb1312 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e40914567317a9cbecd3638bf23cba6ffbaa9be24733909aa58cb8d84a64c463 -size 31169 +oid sha256:4c1298d7a7bef09a72be97f859448a877594088482de6e1fc2660e1a5dcb0869 +size 31354 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en.png index 8315edcfd1..841dd9f1bc 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19e65122fd39fbf25050c9e982285fea34c4fec06647d713c8ea78c2c813ea5a -size 30478 +oid sha256:621db291024ceaa9bba2bc3e71a68b6fc67dab8055ede0595f0519499324b483 +size 30644 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en.png index 9b60b2ece6..355afd8b64 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08a9c400585956485c4a18bafa78ba4fa8eee8b98fce657077777686871041b5 -size 31010 +oid sha256:2222b0d2d1589df67d73aad8eee9a1f30efb1392e0c5493f47f69cac01c8710b +size 31044 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png index 9738b22d77..851f4f8125 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18b494c43b9fa9535d7e3dd4a7b70f9b17bb630b1273495ce8318c397f4a8b5e -size 43556 +oid sha256:20fa72623728a8f1b8206af75dcba3b83384aeab2977fde952bc4d3000aa7d7b +size 43579 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en.png index d913afbcbd..e1cf8ac4eb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e7825e195725479409a23b626771fe207debec55953c0869e5dd9bcae210dc7 -size 29529 +oid sha256:ada067f89b469fccaaf4b9751c0469a9f776ef6206d5ebbb68b7b2128d77ce3c +size 29564 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png index 05c5ee2803..24793ec7c9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60e267a641d11da48b69caedddb3ee8827365ebd6bf252af12f59f5ddbaceece -size 42133 +oid sha256:f717f0e4ea67364e505e8c756931d11bdb696d7be5f11bb155f085c9f2a668cc +size 42149 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png index 6875fb8c82..8a527331d9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e630a264276ce61b6661bbd907c9c66d57471d5ae3a0194c4f452ad865410f21 -size 41161 +oid sha256:67be1e8e93d0c10366f4b37f14ca0f90c1f4ccd5da9024c9a396d3d46507e18c +size 40339 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png index 6875fb8c82..8a527331d9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e630a264276ce61b6661bbd907c9c66d57471d5ae3a0194c4f452ad865410f21 -size 41161 +oid sha256:67be1e8e93d0c10366f4b37f14ca0f90c1f4ccd5da9024c9a396d3d46507e18c +size 40339 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png index 9f41fd0cb9..31159650e7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d842fb5cacf27fcb2bb0a983d34b5955475f8c127f129e9e22f064e1716a2ff5 -size 40596 +oid sha256:6fd553034a694bcba932cfe2bf575b413a98b46f49bdcfd7426eff9571a89204 +size 39786 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png index d8e71e8e59..69da701004 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:865e66b2d88ad172deea40315da88e8d0bd4647ebeaa3327646ebaaf9101fa10 -size 31414 +oid sha256:6144f221b9d11c70d15b54321bfbff3d1de1454e6c73be34d7b2e82bd1625a94 +size 30701 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png index 6e1fabefb6..e16a2bc691 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b637a243fdbcb212a644b5250a3b7840150bc2de250184cfd8d503ca0fa0400 -size 39983 +oid sha256:a512016e96b933f6089e60b634fa77f140dfa7de50d3a8c1a62092ad552d7f2d +size 39216 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png index 6e1fabefb6..e16a2bc691 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b637a243fdbcb212a644b5250a3b7840150bc2de250184cfd8d503ca0fa0400 -size 39983 +oid sha256:a512016e96b933f6089e60b634fa77f140dfa7de50d3a8c1a62092ad552d7f2d +size 39216 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png index 68241c9cfe..94c9bdb789 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:273b69361a9190b0e6c0a5487f22c910e803afc5cde5bc91d2cbe920b0bcaa14 -size 39662 +oid sha256:e17cfdc4028958cafd87a82754c033290010223558ef2115253c9384a547a31e +size 38925 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png index e7db1044b7..2534bd5d0c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:821914e5a21df26cf8cec6f391f9560bef3392f8d1ffae2ec862f87686a02149 -size 29996 +oid sha256:2898f00a828a69ce9cdd56994d7878f6aae8c5b2ea5d1150df57aa2ebd7e537b +size 29233 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png index 2449b7450a..809459297c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a99991c09e28f2cb87dcecebc83fe62c77323cc1126e643a11cc66d198f0b2da -size 41079 +oid sha256:3ddbddbf5303bb86f901cdd880ca2fde15c7c4af22dd7cf1a7903dcab5df25b3 +size 40254 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png index 5c7c878b2e..1ceb7c6b68 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca9a11f1bce2572ad55e8763470f9498754613ac2b3cc2960cc6ee22ccb2a422 -size 39764 +oid sha256:89e17d0b8fdd749b6e97385e8369132d52b0e10adf7d23157c3bdbeb7721e694 +size 39007 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png index 09797bc372..41e45ad002 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36de9783112b421c13530eff9eda026b7ba4e6a721cfd75bb2bca7e2b32cb84a -size 26140 +oid sha256:e641d1d6604b6c5f489ab38438d9f3b8dcea9802113011200e9ea589c4e2dbee +size 25310 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png index 3dccb4c068..99f5bb1dae 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:010120cbcbfed1e7bfa3fb4c88df6e1098d0382cb1834f1a8046e312434f201d -size 26549 +oid sha256:89da32776c436ca00045afb76f42c5f0e5c59f6d682d59a3204461b10ea95474 +size 26617 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png index 5c7c878b2e..1ceb7c6b68 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca9a11f1bce2572ad55e8763470f9498754613ac2b3cc2960cc6ee22ccb2a422 -size 39764 +oid sha256:89e17d0b8fdd749b6e97385e8369132d52b0e10adf7d23157c3bdbeb7721e694 +size 39007 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png index 1259041506..c38069d18e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e15267ee448fae18a63022ab464769528b07585f13ccdb2e8c5589584759d69 -size 31485 +oid sha256:4c9c5240346788914d7ab6a825c38f6fc2d6dba8bdc2879c2657cdafe3718b34 +size 31511 From c283f0109be5321be8ca4755a4354c6da6cf0aec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 16:16:15 +0200 Subject: [PATCH 0236/1083] a11y: add heading to the title. --- .../mediaviewer/impl/details/MediaDetailsBottomSheet.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index a433abbf39..9ce2dc4a7f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -25,6 +25,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter @@ -222,7 +224,10 @@ private fun ColumnScope.Title() { Text( modifier = Modifier .align(Alignment.CenterHorizontally) - .padding(top = 16.dp, bottom = 8.dp, start = 16.dp, end = 16.dp), + .padding(top = 16.dp, bottom = 8.dp, start = 16.dp, end = 16.dp) + .semantics { + heading() + }, text = stringResource(R.string.screen_media_details_title), textAlign = TextAlign.Center, style = ElementTheme.typography.fontBodyLgMedium, From fb50fce64936f61834a8aa0ea30fba94fb05dc37 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 16:53:30 +0200 Subject: [PATCH 0237/1083] Ensure preview has a date --- .../impl/details/MediaBottomSheetStateDetailsProvider.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt index de21ff667d..e79bfa5e77 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt @@ -21,7 +21,9 @@ open class MediaBottomSheetStateDetailsProvider : PreviewParameterProvider Date: Fri, 24 Apr 2026 15:12:13 +0000 Subject: [PATCH 0238/1083] Update screenshots --- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png index 31159650e7..d53b0ecf7e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fd553034a694bcba932cfe2bf575b413a98b46f49bdcfd7426eff9571a89204 -size 39786 +oid sha256:3f89a1039bc2d101af319c0b6259d8eebc9d313ae34947aedee525945be23799 +size 44604 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png index 94c9bdb789..e36f282ba2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e17cfdc4028958cafd87a82754c033290010223558ef2115253c9384a547a31e -size 38925 +oid sha256:8608e63ef9ff79fd698c202d60a8c73f8874f8610601a0ff6dc85663ed82c7da +size 43537 From 9a2ad3928af8892a29e2c903fa652acb5554441e Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:17:54 +0200 Subject: [PATCH 0239/1083] Merge pull request #6658 from element-hq/sync-localazy Sync Strings --- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-ro/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 24 +- .../src/main/res/values-bg/translations.xml | 1 - .../src/main/res/values-da/translations.xml | 1 - .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-es/translations.xml | 1 - .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 1 - .../src/main/res/values-it/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 1 - .../main/res/values-pt-rBR/translations.xml | 1 - .../src/main/res/values-uk/translations.xml | 2 +- .../src/main/res/values-ur/translations.xml | 1 - .../src/main/res/values-uz/translations.xml | 1 - .../src/main/res/values-vi/translations.xml | 1 - .../src/main/res/values-zh/translations.xml | 16 +- .../src/main/res/values-ro/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 12 +- .../src/main/res/values-ro/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 54 +- .../src/main/res/values-zh/translations.xml | 14 +- .../src/main/res/values-cs/translations.xml | 4 + .../src/main/res/values-fr/translations.xml | 4 + .../src/main/res/values-ja/translations.xml | 4 + .../src/main/res/values-zh/translations.xml | 4 + .../src/main/res/values-zh/translations.xml | 36 +- .../src/main/res/values-zh/translations.xml | 40 +- .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-zh/translations.xml | 34 +- .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 5 + .../src/main/res/values-ro/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-cs/translations.xml | 8 + .../src/main/res/values-zh/translations.xml | 87 +- .../src/main/res/values-ro/translations.xml | 14 +- .../src/main/res/values-zh/translations.xml | 22 +- .../src/main/res/values-ro/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 44 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-cs/translations.xml | 9 + .../src/main/res/values-fr/translations.xml | 8 + .../src/main/res/values-ja/translations.xml | 7 + .../src/main/res/values-zh/translations.xml | 63 +- .../impl/src/main/res/values/localazy.xml | 8 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 34 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 94 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 18 +- .../src/main/res/values-ro/translations.xml | 18 +- .../src/main/res/values-zh/translations.xml | 69 +- .../src/main/res/values-zh/translations.xml | 28 +- .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-zh/translations.xml | 22 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-ro/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 46 +- .../src/main/res/values-zh/translations.xml | 92 +- .../src/main/res/values-cs/translations.xml | 2 + .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 3 +- .../src/main/res/values-zh/translations.xml | 3 +- .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 56 +- .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-cs/translations.xml | 13 + .../src/main/res/values-fr/translations.xml | 2 + .../src/main/res/values-ja/translations.xml | 2 + .../src/main/res/values-ro/translations.xml | 20 +- .../src/main/res/values-zh/translations.xml | 206 +- .../src/main/res/values/localazy.xml | 4 + ...en_FullscreenAnnouncementView_Day_1_de.png | 3 + ....spaces_SpaceAnnouncementView_Day_0_de.png | 3 - ...nfigureroom_ConfigureRoomViewDark_0_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_1_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_2_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_3_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_4_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_5_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_6_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_7_de.png | 4 +- ...nfigureroom_ConfigureRoomViewDark_8_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_0_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_1_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_2_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_3_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_4_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_5_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_6_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_7_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_8_de.png | 4 +- ...hooseSelfVerificationModeView_Day_0_de.png | 4 +- ...hooseSelfVerificationModeView_Day_1_de.png | 4 +- ...hooseSelfVerificationModeView_Day_2_de.png | 4 +- ...hooseSelfVerificationModeView_Day_3_de.png | 4 +- ...hooseSelfVerificationModeView_Day_4_de.png | 4 +- ...omponents_RoomListContentView_Day_4_de.png | 4 +- ...onents_SetUpRecoveryKeyBanner_Day_0_de.png | 4 +- ...me.impl.spaces_HomeSpacesView_Day_0_de.png | 4 +- ...me.impl.spaces_HomeSpacesView_Day_1_de.png | 4 +- .../features.home.impl_HomeView_Day_13_de.png | 4 +- .../features.home.impl_HomeView_Day_4_de.png | 4 +- ...people.impl_InvitePeopleView_Day_10_de.png | 3 + ...es.joinroom.impl_JoinRoomView_Day_9_de.png | 4 +- ...internal_StaticMapPlaceholder_Day_0_de.png | 4 +- ....impl.share_ShareLocationView_Day_6_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_0_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_1_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_2_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_3_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_4_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_5_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_6_de.png | 3 + ...on.impl.show_ShowLocationView_Day_7_de.png | 3 + ...mpl.unlock_PinUnlockViewInApp_Day_3_de.png | 4 +- ...mpl.unlock_PinUnlockViewInApp_Day_5_de.png | 4 +- ...mpl.unlock_PinUnlockViewInApp_Day_6_de.png | 4 +- ...een.impl.unlock_PinUnlockView_Day_3_de.png | 4 +- ...een.impl.unlock_PinUnlockView_Day_5_de.png | 4 +- ...een.impl.unlock_PinUnlockView_Day_6_de.png | 4 +- ...hclassic_LoginWithClassicView_Day_0_de.png | 3 + ...hclassic_LoginWithClassicView_Day_1_de.png | 3 + ...er_ConfirmAccountProviderView_Day_0_de.png | 4 +- ...er_ConfirmAccountProviderView_Day_1_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_8_de.png | 3 + ...irect_DefaultDirectLogoutView_Day_1_de.png | 4 +- ...irect_DefaultDirectLogoutView_Day_2_de.png | 4 +- ...irect_DefaultDirectLogoutView_Day_3_de.png | 4 +- ....impl_AccountDeactivationView_Day_0_de.png | 4 +- ....impl_AccountDeactivationView_Day_1_de.png | 4 +- ....impl_AccountDeactivationView_Day_2_de.png | 4 +- ....impl_AccountDeactivationView_Day_3_de.png | 4 +- ....impl_AccountDeactivationView_Day_4_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_0_de.png | 4 +- ...tures.logout.impl_LogoutView_Day_10_de.png | 4 +- ...tures.logout.impl_LogoutView_Day_11_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_1_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_2_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_3_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_4_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_5_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_6_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_7_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_8_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_9_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_0_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_2_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_3_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_4_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_5_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_6_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_7_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_8_de.png | 4 +- ...ntity_IdentityChangeStateView_Day_1_de.png | 4 +- ...ntity_IdentityChangeStateView_Day_2_de.png | 4 +- ...essagesViewWithIdentityChange_Day_1_de.png | 4 +- ...essagesViewWithIdentityChange_Day_2_de.png | 4 +- ...er_AttachmentSourcePickerMenu_Day_0_de.png | 4 +- ...ecomposer_MessageComposerView_Day_0_de.png | 4 +- ...ent_TimelineItemEncryptedView_Day_2_de.png | 4 +- ...vent_TimelineItemLocationView_Day_1_de.png | 3 + ...vent_TimelineItemLocationView_Day_2_de.png | 3 + ...vent_TimelineItemLocationView_Day_3_de.png | 3 + ...vent_TimelineItemLocationView_Day_4_de.png | 3 + ...ts_TimelineItemCallNotifyView_Day_0_de.png | 4 +- ...nents_TimelineItemEventRowUtd_Day_0_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_17_de.png | 3 + ...pl.topbars_MessagesViewTopBar_Day_0_de.png | 4 +- ...es.messages.impl_MessagesView_Day_0_de.png | 4 +- ...s.messages.impl_MessagesView_Day_10_de.png | 4 +- ...es.messages.impl_MessagesView_Day_1_de.png | 4 +- ...es.messages.impl_MessagesView_Day_3_de.png | 4 +- ...es.messages.impl_MessagesView_Day_4_de.png | 4 +- ...es.messages.impl_MessagesView_Day_5_de.png | 4 +- ...es.messages.impl_MessagesView_Day_7_de.png | 4 +- ...es.messages.impl_MessagesView_Day_9_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_0_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_1_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_2_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_3_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_4_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_5_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_6_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_7_de.png | 3 + ...dvanced_AdvancedSettingsViewBlack_8_de.png | 3 + ...ings_AppDeveloperSettingsPage_Day_0_de.png | 3 + ...ings_AppDeveloperSettingsView_Day_0_de.png | 3 + ...ings_AppDeveloperSettingsView_Day_1_de.png | 3 + ...veloper_DeveloperSettingsView_Day_0_de.png | 4 +- ...veloper_DeveloperSettingsView_Day_1_de.png | 4 +- ...veloper_DeveloperSettingsView_Day_2_de.png | 4 +- ...veloper_DeveloperSettingsView_Day_3_de.png | 3 - ...impl.root_PreferencesRootViewDark_0_de.png | 4 +- ...impl.root_PreferencesRootViewDark_1_de.png | 4 +- ...impl.root_PreferencesRootViewDark_2_de.png | 3 + ...impl.root_PreferencesRootViewDark_3_de.png | 3 + ...impl.root_PreferencesRootViewDark_4_de.png | 3 + ...impl.root_PreferencesRootViewDark_5_de.png | 3 + ...mpl.root_PreferencesRootViewLight_0_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_1_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_2_de.png | 3 + ...mpl.root_PreferencesRootViewLight_3_de.png | 3 + ...mpl.root_PreferencesRootViewLight_4_de.png | 3 + ...mpl.root_PreferencesRootViewLight_5_de.png | 3 + ...itprofile_EditUserProfileView_Day_3_de.png | 3 + ....roomdetails.impl_RoomDetailsDark_0_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_10_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_11_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_12_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_13_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_14_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_15_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_16_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_17_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_18_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_1_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_20_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_21_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_22_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_2_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_4_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_7_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_8_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_9_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_0_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_10_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_11_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_12_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_13_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_14_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_15_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_16_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_17_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_1_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_20_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_21_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_22_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_2_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_4_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_7_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_8_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_9_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_0_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_1_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_2_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_3_de.png | 4 +- ...et.root_ResetIdentityRootView_Day_0_de.png | 4 +- ...et.root_ResetIdentityRootView_Day_1_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_14_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_0_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_1_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_5_de.png | 4 +- ....root_SecurityAndPrivacyViewDark_14_de.png | 4 +- ....root_SecurityAndPrivacyViewDark_15_de.png | 4 +- ....root_SecurityAndPrivacyViewDark_16_de.png | 4 +- ...l.root_SecurityAndPrivacyViewDark_4_de.png | 4 +- ...l.root_SecurityAndPrivacyViewDark_5_de.png | 4 +- ...l.root_SecurityAndPrivacyViewDark_6_de.png | 4 +- ...root_SecurityAndPrivacyViewLight_14_de.png | 4 +- ...root_SecurityAndPrivacyViewLight_15_de.png | 4 +- ...root_SecurityAndPrivacyViewLight_16_de.png | 4 +- ....root_SecurityAndPrivacyViewLight_4_de.png | 4 +- ....root_SecurityAndPrivacyViewLight_5_de.png | 4 +- ....root_SecurityAndPrivacyViewLight_6_de.png | 4 +- ...ce.impl.leave_LeaveSpaceView_Day_10_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_0_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_1_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_2_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_3_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_4_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_5_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_6_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_7_de.png | 4 +- ...res.space.impl.root_SpaceView_Day_8_de.png | 4 +- ...tionWithVerificationViolation_Day_0_de.png | 4 +- ...rofile.shared_UserProfileView_Day_9_de.png | 4 +- ...ming_IncomingVerificationView_Day_9_de.png | 4 +- ...oing_OutgoingVerificationView_Day_9_de.png | 4 +- ...mePickerHorizontal_DateTime_pickers_de.png | 4 +- ...eateDmConfirmationBottomSheet_Day_1_de.png | 4 +- ...ui.components_SpaceHeaderView_Day_0_de.png | 3 + ...ix.ui.components_SpaceInfoRow_Day_0_de.png | 4 +- ....components_SpaceRoomItemView_Day_0_de.png | 4 +- ....components_SpaceRoomItemView_Day_1_de.png | 4 +- ....components_SpaceRoomItemView_Day_2_de.png | 4 +- ....components_SpaceRoomItemView_Day_3_de.png | 4 +- ....components_SpaceRoomItemView_Day_4_de.png | 4 +- ....components_SpaceRoomItemView_Day_5_de.png | 4 +- ....components_SpaceRoomItemView_Day_6_de.png | 4 +- ....components_SpaceRoomItemView_Day_7_de.png | 4 +- ....components_SpaceRoomItemView_Day_8_de.png | 4 +- ...DeleteConfirmationBottomSheet_Day_0_de.png | 4 +- ...DeleteConfirmationBottomSheet_Day_1_de.png | 3 + ...tails_MediaDetailsBottomSheet_Day_0_de.png | 4 +- ...tails_MediaDetailsBottomSheet_Day_1_de.png | 3 + ...tails_MediaDetailsBottomSheet_Day_2_de.png | 3 + ...tails_MediaDetailsBottomSheet_Day_3_de.png | 3 + ...impl.gallery_MediaGalleryView_Day_8_de.png | 4 +- ....viewer_MediaViewerViewLandscape_11_de.png | 3 + ....viewer_MediaViewerViewLandscape_12_de.png | 3 + ....viewer_MediaViewerViewLandscape_14_de.png | 3 + ...l.viewer_MediaViewerViewLandscape_2_de.png | 3 + ...ewer.impl.viewer_MediaViewerView_11_de.png | 4 +- ...ewer.impl.viewer_MediaViewerView_12_de.png | 4 +- ...iewer.impl.viewer_MediaViewerView_2_de.png | 4 +- ...oser_MarkdownTextComposerEdit_Day_0_de.png | 4 +- ...mposer_TextComposerAddCaption_Day_0_de.png | 4 +- ...tcomposer_TextComposerCaption_Day_0_de.png | 4 +- ...poser_TextComposerEditCaption_Day_0_de.png | 4 +- ..._TextComposerEditNotEncrypted_Day_0_de.png | 4 +- ...textcomposer_TextComposerEdit_Day_0_de.png | 4 +- ...omposerFormattingNotEncrypted_Day_0_de.png | 4 +- ...mposer_TextComposerFormatting_Day_0_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_0_de.png | 4 +- ...extComposerReplyNotEncrypted_Day_10_de.png | 4 +- ...extComposerReplyNotEncrypted_Day_11_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_1_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_2_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_3_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_4_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_5_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_6_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_7_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_8_de.png | 4 +- ...TextComposerReplyNotEncrypted_Day_9_de.png | 4 +- ...extcomposer_TextComposerReply_Day_0_de.png | 4 +- ...xtcomposer_TextComposerReply_Day_10_de.png | 4 +- ...xtcomposer_TextComposerReply_Day_11_de.png | 4 +- ...extcomposer_TextComposerReply_Day_1_de.png | 4 +- ...extcomposer_TextComposerReply_Day_2_de.png | 4 +- ...extcomposer_TextComposerReply_Day_3_de.png | 4 +- ...extcomposer_TextComposerReply_Day_4_de.png | 4 +- ...extcomposer_TextComposerReply_Day_5_de.png | 4 +- ...extcomposer_TextComposerReply_Day_6_de.png | 4 +- ...extcomposer_TextComposerReply_Day_7_de.png | 4 +- ...extcomposer_TextComposerReply_Day_8_de.png | 4 +- ...extcomposer_TextComposerReply_Day_9_de.png | 4 +- ..._TextComposerScaledDensityWithReply_de.png | 3 + screenshots/html/data.js | 2100 +++++++++-------- 358 files changed, 2386 insertions(+), 2154 deletions(-) create mode 100644 features/location/impl/src/main/res/values-zh/translations.xml create mode 100644 screenshots/de/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_de.png delete mode 100644 screenshots/de/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_de.png create mode 100644 screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_10_de.png create mode 100644 screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png create mode 100644 screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png create mode 100644 screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_de.png create mode 100644 screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_de.png create mode 100644 screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_8_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_de.png create mode 100644 screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png create mode 100644 screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png create mode 100644 screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_de.png create mode 100644 screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_de.png create mode 100644 screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_de.png delete mode 100644 screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_3_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png create mode 100644 screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_de.png create mode 100644 screenshots/de/libraries.matrix.ui.components_SpaceHeaderView_Day_0_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_de.png create mode 100644 screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png diff --git a/appnav/src/main/res/values-zh/translations.xml b/appnav/src/main/res/values-zh/translations.xml index 406471196e..f6eac30310 100644 --- a/appnav/src/main/res/values-zh/translations.xml +++ b/appnav/src/main/res/values-zh/translations.xml @@ -1,6 +1,6 @@ - "登出并升级" + "注销并升级" "%1$s 不再支持旧协议。请注销并重新登录以继续使用该应用程序。" - "您的服务器不再支持旧协议。请登出并重新登录以继续使用此应用。" + "你的主服务器不再支持旧协议。请注销并重新登录以继续使用此 app。" diff --git a/features/analytics/api/src/main/res/values-zh/translations.xml b/features/analytics/api/src/main/res/values-zh/translations.xml index e5f9fccd66..e8f0fcb434 100644 --- a/features/analytics/api/src/main/res/values-zh/translations.xml +++ b/features/analytics/api/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ "共享匿名使用数据以帮助我们排查问题。" - "您可以阅读我们的所有条款 %1$s。" + "你可以阅读我们的所有条款 %1$s。" "此处" "共享分析数据" diff --git a/features/analytics/impl/src/main/res/values-zh/translations.xml b/features/analytics/impl/src/main/res/values-zh/translations.xml index d18650654b..8393e45e81 100644 --- a/features/analytics/impl/src/main/res/values-zh/translations.xml +++ b/features/analytics/impl/src/main/res/values-zh/translations.xml @@ -2,9 +2,9 @@ "我们不会记录或分析任何个人数据" "共享匿名使用数据以帮助我们排查问题。" - "您可以阅读我们的所有条款 %1$s。" + "你可以阅读我们的所有条款 %1$s。" "此处" "可以随时关闭此功能" - "我们不会与第三方共享您的数据" + "我们不会与第三方共享你的数据" "帮助改进 %1$s" diff --git a/features/call/impl/src/main/res/values-zh/translations.xml b/features/call/impl/src/main/res/values-zh/translations.xml index 6192568a61..7a81fde819 100644 --- a/features/call/impl/src/main/res/values-zh/translations.xml +++ b/features/call/impl/src/main/res/values-zh/translations.xml @@ -1,8 +1,8 @@ "通话进行中" - "点按即可返回通话" + "点击以返回通话" "☎️ 通话中" - "Element Call 不支持在此 Android 版本中使用蓝牙音频设备。请选择其他音频设备。" - "Element 来电" + "Element Call 不支持在此 Android 版本中使用蓝牙音频设备。请选择其它音频设备。" + "Element Call 来电" diff --git a/features/createroom/impl/src/main/res/values-ro/translations.xml b/features/createroom/impl/src/main/res/values-ro/translations.xml index a46fd1a1c4..fd1854db40 100644 --- a/features/createroom/impl/src/main/res/values-ro/translations.xml +++ b/features/createroom/impl/src/main/res/values-ro/translations.xml @@ -3,14 +3,14 @@ "Cameră nouă" "Invitați prieteni" "A apărut o eroare la crearea camerei" - "Doar persoanele invitate pot accesa această cameră. Toate mesajele sunt criptate end-to-end." + "Doar persoanele invitate se pot alătura." "Oricine poate găsi această cameră. Puteți modifica acest lucru oricând în setări." "Oricine poate cere să se alăture camerei, dar un administrator sau un moderator va trebui să accepte cererea" - "Cereți să vă alăturați" + "Permite solicitarea de alăturare" "Oricine se poate alătura acestei camere" "Pentru ca această cameră să fie vizibilă în directorul de camere publice, veți avea nevoie de o adresă de cameră." - "Adresa camerei" + "Adresă" "Vizibilitatea camerei" "Subiect (opțional)" diff --git a/features/createroom/impl/src/main/res/values-zh/translations.xml b/features/createroom/impl/src/main/res/values-zh/translations.xml index 46d9654fbf..8d898fe5f0 100644 --- a/features/createroom/impl/src/main/res/values-zh/translations.xml +++ b/features/createroom/impl/src/main/res/values-zh/translations.xml @@ -1,21 +1,21 @@ - "新聊天室" + "新房间" "邀请朋友" - "创建聊天室时出错" + "创建房间时出错" "由于未知错误,空间创建失败。请稍后再试。" "添加名称…" - "新聊天室" + "新房间" "新空间" "仅限受邀者加入。" "私密" - "任何人都能找到此聊天室。 -你可以随时在聊天室设置中更改。" - "任何人都可以找到并加入" + "任何人都能找到此房间。 +你可以随时在房间设置中更改。" + "任何人都可以加入" "公共" - "任何人都可申请加入,但需由管理员或版主批准请求。" - "请求加入" - "%1$s 中的任何人都可加入,但其他人必须申请访问权限。" + "任何人都可申请加入,但需由管理员或协管员批准申请。" + "申请加入" + "%1$s 中的任何人都可以加入,但其他人必须申请访问。" "申请加入" "仅限受邀者加入。" "私密" @@ -24,13 +24,13 @@ "%1$s 中的任何人可加入。" "标准" "谁有权访问此房间" - "要使该聊天室在公共目录中可见,您需要一个聊天室地址。" + "要使该房间在公共目录中可见,你需要一个地址。" "地址" "房间可见性" "(无空间)" - "请勿添加至空间" + "不要添加到空间" "未选择空间" - "添加至空间" + "添加到空间" "主题(可选)" "添加描述…" diff --git a/features/deactivation/impl/src/main/res/values-bg/translations.xml b/features/deactivation/impl/src/main/res/values-bg/translations.xml index 34ad5b4772..936e4726a5 100644 --- a/features/deactivation/impl/src/main/res/values-bg/translations.xml +++ b/features/deactivation/impl/src/main/res/values-bg/translations.xml @@ -1,5 +1,4 @@ "Моля, потвърдете, че искате да деактивирате акаунта си. Това действие не може да бъде отменено." - "Деактивиране на акаунта" diff --git a/features/deactivation/impl/src/main/res/values-da/translations.xml b/features/deactivation/impl/src/main/res/values-da/translations.xml index c6dcb1710a..dfbf00a1c6 100644 --- a/features/deactivation/impl/src/main/res/values-da/translations.xml +++ b/features/deactivation/impl/src/main/res/values-da/translations.xml @@ -10,5 +10,4 @@ "Fjerne dig fra alle samtaler" "Slette dine kontooplysninger fra vores identitetsserver." "Dine beskeder vil stadig være synlige for registrerede brugere, men vil ikke være tilgængelige for nye eller uregistrerede brugere, hvis du vælger at slette dem." - "Deaktiver konto" diff --git a/features/deactivation/impl/src/main/res/values-de/translations.xml b/features/deactivation/impl/src/main/res/values-de/translations.xml index 1aec7495a1..e03d53bbce 100644 --- a/features/deactivation/impl/src/main/res/values-de/translations.xml +++ b/features/deactivation/impl/src/main/res/values-de/translations.xml @@ -10,5 +10,5 @@ "Du wirst aus allen Chats entfernt." "Lösche deine Kontoinformationen von unserem Identitätsserver." "Deine Nachrichten werden für bereits registrierte Nutzer weiterhin sichtbar sein. Für neue oder unregistrierte Nutzer sind sie nicht verfügbar, wenn du sie löschen solltest." - "Nutzerkonto deaktivieren" + "Benutzerkonto deaktivieren" diff --git a/features/deactivation/impl/src/main/res/values-es/translations.xml b/features/deactivation/impl/src/main/res/values-es/translations.xml index cd0757ba3e..17ae73d6c8 100644 --- a/features/deactivation/impl/src/main/res/values-es/translations.xml +++ b/features/deactivation/impl/src/main/res/values-es/translations.xml @@ -10,5 +10,4 @@ "Te eliminará de todas las salas de chat." "Eliminará la información de tu cuenta de nuestro servidor de identidad." "Tus mensajes seguirán siendo visibles para los usuarios registrados, pero no estarán disponibles para los usuarios nuevos o no registrados si decides eliminarlos." - "Desactivar cuenta" diff --git a/features/deactivation/impl/src/main/res/values-fr/translations.xml b/features/deactivation/impl/src/main/res/values-fr/translations.xml index 675ac1e1e0..875142bc01 100644 --- a/features/deactivation/impl/src/main/res/values-fr/translations.xml +++ b/features/deactivation/impl/src/main/res/values-fr/translations.xml @@ -10,5 +10,5 @@ "Vous retirer de tous les salons et toutes les discussions." "Supprimer les informations de votre compte du serveur d’identité." "Rendre vos messages invisibles aux futurs membres des salons si vous choisissez de les supprimer. Vos messages seront toujours visibles pour les utilisateurs qui les ont déjà récupérés." - "Désactiver le compte" + "Désactiver votre compte" diff --git a/features/deactivation/impl/src/main/res/values-hr/translations.xml b/features/deactivation/impl/src/main/res/values-hr/translations.xml index 04148fdc48..9273254886 100644 --- a/features/deactivation/impl/src/main/res/values-hr/translations.xml +++ b/features/deactivation/impl/src/main/res/values-hr/translations.xml @@ -10,5 +10,4 @@ "Ukloniti vas iz svih soba za razgovore." "Izbrisati podatke o vašem računu s našeg poslužitelja identiteta." "Vaše će poruke i dalje biti vidljive registriranim korisnicima, ali neće biti dostupne novim ili neregistriranim korisnicima ako ih odlučite izbrisati." - "Deaktiviraj račun" diff --git a/features/deactivation/impl/src/main/res/values-it/translations.xml b/features/deactivation/impl/src/main/res/values-it/translations.xml index 3fbc9d536b..7cd484d0e4 100644 --- a/features/deactivation/impl/src/main/res/values-it/translations.xml +++ b/features/deactivation/impl/src/main/res/values-it/translations.xml @@ -10,5 +10,5 @@ "Ti rimuove da tutte le stanze di chat." "Elimina le informazioni del tuo account dal nostro server di identità." "I tuoi messaggi saranno ancora visibili agli utenti registrati, ma non saranno disponibili per gli utenti nuovi o non registrati se decidi di eliminarli." - "Disattiva account" + "Disattivazione dell\'account" diff --git a/features/deactivation/impl/src/main/res/values-ja/translations.xml b/features/deactivation/impl/src/main/res/values-ja/translations.xml index 873b1308ec..f41dd1d282 100644 --- a/features/deactivation/impl/src/main/res/values-ja/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ja/translations.xml @@ -10,5 +10,5 @@ "すべてのチャットルームから退出します。" "アカウント提供元サーバーからアカウント情報を削除します。" "あなたの会話は、既存ユーザーには引き続き表示されますが、新規ユーザーには表示されなくなります。" - "アカウントを無効化" + "アカウントを削除" diff --git a/features/deactivation/impl/src/main/res/values-ko/translations.xml b/features/deactivation/impl/src/main/res/values-ko/translations.xml index 6b7953a4a5..42dd0aa0e2 100644 --- a/features/deactivation/impl/src/main/res/values-ko/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ko/translations.xml @@ -10,5 +10,4 @@ "모든 채팅방에서 자신을 제거하세요." "당사의 신원 서버에서 귀하의 계정 정보를 삭제하세요." "메시지는 등록된 사용자에게는 계속 표시되지만, 삭제하면 신규 또는 미등록 사용자는 볼 수 없게 됩니다." - "계정 비활성화" diff --git a/features/deactivation/impl/src/main/res/values-pt-rBR/translations.xml b/features/deactivation/impl/src/main/res/values-pt-rBR/translations.xml index 7000a65d47..a986b18a7c 100644 --- a/features/deactivation/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/deactivation/impl/src/main/res/values-pt-rBR/translations.xml @@ -10,5 +10,4 @@ "Te remover de todas as salas de conversa." "Apague as informações da sua conta do nosso servidor de identidade." "Suas mensagens ainda estarão visíveis para os usuários registrados, mas não estarão disponíveis para usuários novos ou não registrados se você optar por apagá-las." - "Desativar conta" diff --git a/features/deactivation/impl/src/main/res/values-uk/translations.xml b/features/deactivation/impl/src/main/res/values-uk/translations.xml index 04b32df8b2..62cf66cec1 100644 --- a/features/deactivation/impl/src/main/res/values-uk/translations.xml +++ b/features/deactivation/impl/src/main/res/values-uk/translations.xml @@ -10,5 +10,5 @@ "Видалити вас з усіх чатів." "Видаліть інформацію свого облікового запису з нашого сервера ідентифікації." "Ваші повідомлення залишатимуться видимими для зареєстрованих користувачів, але недоступними для нових або незареєстрованих користувачів, якщо ви вирішите їх видалити." - "Деактивувати обліковий запис" + "Відключити обліковий запис" diff --git a/features/deactivation/impl/src/main/res/values-ur/translations.xml b/features/deactivation/impl/src/main/res/values-ur/translations.xml index 297b29c519..3cad49aeb3 100644 --- a/features/deactivation/impl/src/main/res/values-ur/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ur/translations.xml @@ -10,5 +10,4 @@ "آپ کو تمام چیت رومز سے ہٹا دے گا۔" "ہمارے شناختی سرور سے اپنے اکاؤنٹ کی معلومات کو حذف کریں۔" "آپ کے پیغامات اب بھی رجسٹرڈ صارفین کو نظر آئیں گے لیکن اگر آپ انہیں حذف کرنے کا انتخاب کرتے ہیں تو نئے یا غیر رجسٹرڈ صارفین کے لیے دستیاب نہیں ہوں گے۔" - "اکاؤنٹ کو غیر فعال کریں" diff --git a/features/deactivation/impl/src/main/res/values-uz/translations.xml b/features/deactivation/impl/src/main/res/values-uz/translations.xml index 19a70bb149..d357f38186 100644 --- a/features/deactivation/impl/src/main/res/values-uz/translations.xml +++ b/features/deactivation/impl/src/main/res/values-uz/translations.xml @@ -10,5 +10,4 @@ "Sizni barcha chat xonalaridan olib tashlash." "Hisobingiz haqidagi axborotni identifikatsiya serverimizdan o‘chirib tashlang." "Xabarlaringiz ro‘yxatdan o‘tgan foydalanuvchilarga ko‘rinadi, lekin ularni o‘chirishni tanlasangiz, yangi yoki ro‘yxatdan o‘tmagan foydalanuvchilarga ko‘rinmaydi." - "Hisobni faolsizlantirish" 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 b61167ff80..f3b48163ed 100644 --- a/features/deactivation/impl/src/main/res/values-vi/translations.xml +++ b/features/deactivation/impl/src/main/res/values-vi/translations.xml @@ -10,5 +10,4 @@ "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/deactivation/impl/src/main/res/values-zh/translations.xml b/features/deactivation/impl/src/main/res/values-zh/translations.xml index ca24375d66..3916921652 100644 --- a/features/deactivation/impl/src/main/res/values-zh/translations.xml +++ b/features/deactivation/impl/src/main/res/values-zh/translations.xml @@ -1,14 +1,14 @@ - "请确认您要停用您的账户。此操作无法撤消。" + "请确认要删除的账户。此操作无法撤消。" "删除我的所有消息" "警告:未来的用户可能会看到不完整的对话。" - "停用您的帐户是%1$s,它将:" - "不可逆转的" - "%1$s您的账户(您无法登录回来,并且您的ID无法重复使用)。" + "正在删除的账户为 %1$s,它将:" + "不可逆" + "你的账户 %1$s(将无法再登录,并且 ID 无法重复使用)。" "永久禁用" - "将您从所有聊天房间中移除。" - "从我们的身份服务器中删除您的账户信息。" - "注册用户仍可看到您的消息,但如果您选择删除它们,新用户或未注册用户将无法看到您的消息。" - "停用账户" + "将你从所有聊天房间中移除。" + "从我们的身份服务器中删除你的账户信息。" + "注册用户仍可看到你的消息,但如果选择删除它们,新用户或未注册用户将无法看到你的消息。" + "删除账户" diff --git a/features/ftue/impl/src/main/res/values-ro/translations.xml b/features/ftue/impl/src/main/res/values-ro/translations.xml index abf72140e8..85b151faa8 100644 --- a/features/ftue/impl/src/main/res/values-ro/translations.xml +++ b/features/ftue/impl/src/main/res/values-ro/translations.xml @@ -2,8 +2,8 @@ "Nu puteți confirma?" "Creați o nouă cheie de recuperare" - "Verificați acest dispozitiv pentru a configura mesagerie securizată." - "Confirmați că sunteți dumneavoastră" + "Alegeți cum doriți să vă verificați pentru a configura mesageria securizată." + "Confirmați-vă identitatea digitală" "Utilizați un alt dispozitiv" "Utilizați cheia de recuperare" "Acum puteți citi sau trimite mesaje în siguranță, iar oricine cu care conversați poate avea încredere în acest dispozitiv." diff --git a/features/ftue/impl/src/main/res/values-zh/translations.xml b/features/ftue/impl/src/main/res/values-zh/translations.xml index 68a48831e0..c111aecaa9 100644 --- a/features/ftue/impl/src/main/res/values-zh/translations.xml +++ b/features/ftue/impl/src/main/res/values-zh/translations.xml @@ -3,13 +3,13 @@ "无法确认?" "创建新的恢复密钥" "选择验证方式以设置安全的消息传输。" - "确认您的数字身份" - "使用其他设备" + "确认你的数字身份" + "使用其它设备" "使用恢复密钥" - "现在,您可以安全地阅读或发送消息,与您聊天的人也会信任此设备。" + "现在你可以安全地读取或发送消息,并且与你聊天的任何人也可以信任此设备。" "设备已验证" - "使用其他设备" - "正在等待其他设备……" - "您可以稍后更改设置。" + "使用其它设备" + "正在等待其它设备……" + "你可以稍后更改设置。" "允许通知,绝不错过任何消息" diff --git a/features/home/impl/src/main/res/values-ro/translations.xml b/features/home/impl/src/main/res/values-ro/translations.xml index e4a80b4fb7..be1933e160 100644 --- a/features/home/impl/src/main/res/values-ro/translations.xml +++ b/features/home/impl/src/main/res/values-ro/translations.xml @@ -5,9 +5,9 @@ "Nu primiți notificări?" "Sunetul pentru notificări a fost actualizat — mai clar, mai rapid și mai puțin perturbatoar." "Am reîmprospătat sunetele" - "Recuperați-vă identitatea criptografică și mesajele anterioare cu o cheie de recuperare dacă ați pierdut toate dispozitivele existente." - "Configurați recuperarea" - "Configurați recuperarea pentru a vă proteja contul" + "Chaturile dumneavoastră sunt salvate automat cu criptare end-to-end. Pentru a restaura această copie de rezervă și a vă păstra identitatea digitală atunci când pierzdeți accesul la toate dispozitivele dumneavoastră, veți avea nevoie de cheia de recuperare." + "Obțineți cheia de recuperare" + "Faceți un backup al mesajelor" "Backup-ul pentru chat nu este sincronizat. Trebuie să confirmați cheia de recuperare pentru a menține accesul la backup." "Introduceți cheia de recuperare" "Ați uitat cheia de recuperare?" 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 e0704c52a6..4bc15b08cf 100644 --- a/features/home/impl/src/main/res/values-zh/translations.xml +++ b/features/home/impl/src/main/res/values-zh/translations.xml @@ -1,56 +1,56 @@ - "请关闭本应用的电池优化设置,确保不错过任何消息通知。" + "对此 app 禁用电池优化以确保不错过任何通知。" "禁用优化" "通知未送达?" - "您的通知提示音已升级 - 更清晰、更快速、干扰更少。" - "我们已更新您的声音" - "生成新的恢复密钥,该密钥可用于在您无法访问设备时恢复加密的消息历史记录。" + "通知提示音已升级:更清晰、更快速、干扰更少。" + "我们已更新你的声音" + "你的聊天已被端到端加密自动备份。如果你无法访问所有设备,则需要使用恢复密钥并保留数字身份。" "获取恢复密钥" "备份聊天" "确认恢复密钥,以保持对密钥存储和消息历史的访问。" "输入恢复密钥" "忘记了恢复密钥?" "你的密钥存储已不同步" - "为确保您不会错过重要来电,请更改设置以允许锁屏时的全屏通知。" + "为确保你不会错过重要来电,请更改设置以允许锁屏时的全屏通知。" "提升通话体验" - "全部聊天" + "聊天" "空间" - "您确定要拒绝加入 %1$s 的邀请吗?" + "你确定要拒绝加入 %1$s 的邀请?" "拒绝邀请" - "您确定要拒绝与 %1$s 开始私聊吗?" + "你确定要拒绝与 %1$s 私聊?" "拒绝聊天" "没有邀请" "%1$s (%2$s)邀请了你" - "这是一个一次性的过程,感谢您的等待。" - "设置您的账户。" - "创建新的对话或聊天室" + "此为一次性流程,感谢等待。" + "设置账户。" + "创建新的对话或房间" "清除筛选条件" "通过向某人发送消息来开始。" - "还没有聊天。" + "暂无聊天。" "收藏夹" - "可以在聊天设置里将聊天添加到收藏夹中。 -现在,可以取消选择过滤器以查看其他对话。" - "您未收藏任何聊天" + "可以在聊天设置里将聊天添加到收藏夹。 +现在可以取消选择筛选器以查看其它对话。" + "你尚未收藏任何聊天" "邀请" "没有待处理的邀请。" "低优先级" - "您还没有任何低优先级聊天" - "您可以取消选择过滤器以查看其他对话" - "您没有关于此选项的聊天" + "你暂无任何低优先级聊天" + "你可以取消选择筛选器以查看其它对话" + "你暂无适用于此选项的聊天" "用户" - "目前您还没有私信" - "聊天室" - "您尚未进入任何聊天室" + "你暂无任何私聊" + "房间" + "你尚未进入任何房间" "未读" "恭喜! 没有任何未读消息!" - "加入请求已发送" - "全部聊天" - "标记为已读" - "标记为未读" + "加入申请已发送" + "聊天" + "设为已读" + "设为未读" "此房间已升级" - "您的空间" - "您似乎正在使用新设备。使用另一台设备进行验证以访问您的加密消息。" + "你的空间" + "你似乎正在使用新设备。使用另一台设备进行验证以访问加密消息。" "验证是你本人" diff --git a/features/invite/impl/src/main/res/values-zh/translations.xml b/features/invite/impl/src/main/res/values-zh/translations.xml index 8c27397225..61e7f15f59 100644 --- a/features/invite/impl/src/main/res/values-zh/translations.xml +++ b/features/invite/impl/src/main/res/values-zh/translations.xml @@ -1,18 +1,18 @@ - "您将不会看到来自该用户的任何信息或房间邀请" + "你将不会看到来自该用户的任何消息或房间邀请" "屏蔽用户" - "向您的帐户提供商举报此房间。" - "描述举报的原因…" + "向账户提供者举报此房间。" + "描述举报的理由…" "拒绝并屏蔽" - "您确定要拒绝加入 %1$s 的邀请吗?" + "你确定要拒绝加入 %1$s 的邀请?" "拒绝邀请" - "您确定要拒绝与 %1$s 开始私聊吗?" + "你确定要拒绝与 %1$s 私聊?" "拒绝聊天" "没有邀请" "%1$s (%2$s)邀请了你" - "是的,拒绝并屏蔽" - "您确定要拒绝加入此房间的邀请吗?这也将阻止 %1$s 与您联系或邀请您加入房间。" + "是,拒绝并屏蔽" + "你确定要拒绝此房间的加入邀请?这也将阻止 %1$s 与你联系或邀请你加入房间。" "拒绝邀请并屏蔽" "拒绝并屏蔽" diff --git a/features/invitepeople/impl/src/main/res/values-cs/translations.xml b/features/invitepeople/impl/src/main/res/values-cs/translations.xml index fa5b3aa9a9..c041433267 100644 --- a/features/invitepeople/impl/src/main/res/values-cs/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-cs/translations.xml @@ -2,4 +2,8 @@ "Již členem" "Již pozván(a)" + "Momentálně s těmito kontakty nemáte žádné chaty. Před pokračováním potvrďte jejich pozvání do této místnosti." + "Momentálně s tímto kontaktem nemáte žádné chaty. Před pokračováním potvrďte pozvání do této místnosti." + "Pozvat nové kontakty do této místnosti?" + "Pozvat nový kontakt do této místnosti?" diff --git a/features/invitepeople/impl/src/main/res/values-fr/translations.xml b/features/invitepeople/impl/src/main/res/values-fr/translations.xml index dcc16f58cf..b5df870002 100644 --- a/features/invitepeople/impl/src/main/res/values-fr/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-fr/translations.xml @@ -2,4 +2,8 @@ "Déjà membre" "Déjà invité(e)" + "Vous n’avez actuellement aucune conversation avec ces contacts. Veuillez confirmer leur invitation à rejoindre ce salon avant de continuer." + "Vous n’avez actuellement aucune conversation avec ce contact. Veuillez confirmer son invitation à rejoindre ce salon avant de continuer." + "Inviter de nouveaux contacts dans ce salon ?" + "Inviter un nouveau contact dans ce salon ?" 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 eefa446d79..db5b91ca2b 100644 --- a/features/invitepeople/impl/src/main/res/values-ja/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-ja/translations.xml @@ -2,4 +2,8 @@ "既に参加しています" "既に招待しています" + "これらの人物とのチャットがありません。はじめに、招待の状況を確認してください。" + "この連絡先とのチャットがありません。はじめに、招待の状況を確認してください。" + "このルームに新しい連絡先を招待しますか?" + "このルームに新しい連絡先を招待しますか?" diff --git a/features/invitepeople/impl/src/main/res/values-zh/translations.xml b/features/invitepeople/impl/src/main/res/values-zh/translations.xml index b1e0e953f8..7b1bb29288 100644 --- a/features/invitepeople/impl/src/main/res/values-zh/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-zh/translations.xml @@ -2,4 +2,8 @@ "已经是成员" "已邀请" + "你与这些联系人暂无任何聊天。请确认对方被邀请到此房间后再继续。" + "你与此人暂无任何聊天。请确认对方被邀请到此房间后再继续。" + "邀请新联系人到此房间?" + "邀请新联系人到此房间?" diff --git a/features/joinroom/impl/src/main/res/values-zh/translations.xml b/features/joinroom/impl/src/main/res/values-zh/translations.xml index d38f9d3427..e4de8dfec4 100644 --- a/features/joinroom/impl/src/main/res/values-zh/translations.xml +++ b/features/joinroom/impl/src/main/res/values-zh/translations.xml @@ -1,34 +1,34 @@ - "您已被 %1$s 封禁。" + "你已被 %1$s 封禁。" "你已被此房间封禁" "理由:%1$s。" - "取消请求" - "是的,取消" - "您确定要取消加入此房间的请求吗?" + "取消申请" + "是,取消" + "你确定要取消加入此房间的申请?" "取消加入申请" - "是的,拒绝并屏蔽" - "您确定要拒绝加入此房间的邀请吗?这也将阻止 %1$s 与您联系或邀请您加入房间。" + "是,拒绝并屏蔽" + "你确定要拒绝此房间的加入邀请?这也将阻止 %1$s 与你联系或邀请你加入房间。" "拒绝邀请并屏蔽" "拒绝并屏蔽" "加入失败" - "您需要被邀请加入,否则可能会受到访问限制。" + "你需要被邀请才能加入,否则可能会遭遇访问限制。" "忘记" - "您需要邀请才能加入" + "你需要被邀请才能加入" "受邀于" "加入" - "您可能需要受到邀请或成为某个空间的成员才能加入。" - "加入聊天室" - "允许的字符数量 %2$d中的%1$d" + "你可能需要被邀请或成为某个空间的成员才能加入。" + "加入房间" + "允许的字符数量共 %2$d 个,当前为 %1$d 个" "消息(可选)" - "如果您的请求被接受,您将收到加入房间的邀请。" - "加入请求已发送" + "如果你的申请被批准,你将收到加入房间的邀请。" + "加入申请已发送" "无法显示房间预览。这可能是由于网络或服务器问题造成的。" "无法显示此房间预览" - "%1$s 尚不支持空间。您可以通过 Web 端访问空间" - "空间尚不支持" - "点击下面的按钮,系统将通知聊天室管理员。获得批准后将能够加入对话。" - "只有聊天室成员才能查看消息历史记录。" - "想加入此聊天室吗?" + "%1$s 暂不支持空间。你可以通过 Web 客户端访问空间。" + "空间尚未受到支持" + "点击以下按钮以通知房间管理员。获得批准后你将能加入对话。" + "只有房间成员才能查看消息历史。" + "想加入此房间吗?" "预览不可用" diff --git a/features/knockrequests/impl/src/main/res/values-zh/translations.xml b/features/knockrequests/impl/src/main/res/values-zh/translations.xml index 08718dfc5a..d70632861c 100644 --- a/features/knockrequests/impl/src/main/res/values-zh/translations.xml +++ b/features/knockrequests/impl/src/main/res/values-zh/translations.xml @@ -1,32 +1,32 @@ - "是的,全部接受" - "您确定要接受所有加入请求吗?" - "接受所有请求" + "是,全部接受" + "你确定要接受所有加入申请?" + "接受所有申请" "全部接受" - "我们无法接受所有请求。是否要再试一次?" - "无法接受所有请求" - "接受所有加入请求" - "我们无法接受此请求。是否要再试一次?" - "无法接受请求" - "接受加入请求" - "是的,拒绝并禁止" - "您确定要拒绝并禁止吗%1$s?该用户将无法再次请求加入该房间。" + "我们无法接受所有申请。是否重试?" + "无法接受所有申请" + "接受所有加入申请" + "我们无法接受此申请。是否重试?" + "无法接受申请" + "接受加入申请" + "是,拒绝并禁止" + "你确定要拒绝并封禁 %1$s?该用户将无法再次申请加入该房间。" "拒绝并禁止访问" "拒绝并禁止访问" - "是的,拒绝" - "您确定要拒绝 %1$s 加入此房间的请求吗?" + "是,拒绝" + "你确定要拒绝 %1$s 加入此房间的申请?" "拒绝访问" "拒绝和禁止" - "我们无法拒绝此请求。是否要再试一次?" - "拒绝请求失败" - "拒绝加入请求" - "当有人请求加入房间时,您将能够在这里看到他们的请求。" - "没有待处理的加入请求" - "正在加载加入请求…" + "我们无法拒绝此申请。是否重试?" + "拒绝申请失败" + "拒绝加入申请" + "当有人申请加入房间时,你将能够在这里看到其申请。" + "暂无待处理的加入申请" + "正在加载加入申请…" "申请加入" - "%1$s+ %2$d 其他人想加入这个房间" + "%1$s、%2$d 及其他人想加入此房间" "查看全部" "接受" diff --git a/features/leaveroom/api/src/main/res/values-zh/translations.xml b/features/leaveroom/api/src/main/res/values-zh/translations.xml index 6b7f17558b..a4c920a221 100644 --- a/features/leaveroom/api/src/main/res/values-zh/translations.xml +++ b/features/leaveroom/api/src/main/res/values-zh/translations.xml @@ -1,10 +1,10 @@ - "您确定要离开此对话吗?此对话不公开,未经邀请您将无法重新加入。" - "确定要离开此聊天室吗?此处只有你一个人。如果离开此聊天室,包括你在内的所有人都将无法进入。" - "确定要离开此聊天室吗?此聊天室不公开,没有邀请你将无法重新加入。" + "你确定要离开此对话?此对话不公开,你将无法在未经邀请的情况下重新加入。" + "确定要离开此房间?此处只有你一个人。如果离开,包括你在内的所有人都将无法加入。" + "确定要离开此房间吗?此房间不公开,没有邀请你将无法重新加入。" "选择所有者" - "您是本房间的唯一所有者。离开房间前,您需要将所有权转移给他人。" + "你是此房间的唯一所有者。离开前需要转让所有权给他人。" "转让所有权" - "确定要离开聊天室吗?" + "确定要离开房间?" diff --git a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml index 10ae1ae7a7..1bd74d5104 100644 --- a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml @@ -1,18 +1,18 @@ "扫描二维码" - "在笔记本电脑或台式机上打开%1$s " + "在笔记本电脑或台式机上打开 %1$s" "使用此设备扫描二维码" "准备进行扫描" - "在电脑上打开%1$s 获取二维码" + "在台式电脑上打开 %1$s 以获取二维码" "数字不匹配" - "输入两位数的验证码" - "这将验证您与其他设备的连接是否安全。" + "输入两位数字的代码" + "这将验证你与其它设备的连接是否安全。" "请输入另一台设备上显示的数字" "账户提供方不支持 %1$s." "不支持 %1$s." - "您的账户提供商不支持使用二维码登录新设备。" - "不支持二维码" + "你的账户提供者不支持使用二维码登录到新设备。" + "二维码不受支持" "登录被另一台设备取消" "登录请求已取消" "登录已过期. 请重试." @@ -25,10 +25,10 @@ "台式计算机" "正在加载二维码…" "移动设备" - "您想连接哪种类型的设备?" - "请重试,并确保您已正确输入两位验证码。如果验证码仍然不匹配,请联系您的账户提供商。" + "你想连接哪种类型的设备?" + "请重试,并确保已正确输入两位数字的代码。如果数字仍然不匹配,请联系账户提供者。" "数字不匹配" - "无法与新设备建立安全连接。您现有的设备仍然安全,无需担心。" + "无法与新设备建立安全连接。你的现有设备仍然安全,无需担心。" "现在怎么办?" "如果这是网络问题,请尝试使用二维码再次登录" "如果遇到同样的问题,请尝试使用不同的 WiFi 网络或使用移动数据代替 WiFi" @@ -36,22 +36,22 @@ "连接不安全" "登录被另一台设备取消" "登录请求已取消" - "其它设备未接受请求" + "另一设备上的登录请求已被拒绝。" "登录被拒绝" - "您无需额外操作。" - "您已在另一台设备登录。" + "无需额外操作。" + "你已在另一设备上登录。" "登录已过期. 请重试." "登录未及时完成" "另一个设备不支持使用二维码登录 %s. 尝试手动或使用另一个设备扫描二维码." - "不支持二维码" + "二维码不受支持" "账户提供方不支持 %1$s." "不支持 %1$s." - "使用其他设备上显示的二维码。" - "再试一次" + "使用其它设备上显示的二维码。" + "重试" "二维码错误" - "您需要授予 %1$s 使用设备摄像头的权限才能继续。" - "允许摄像头权限以扫描 QR 码" + "你需要授予 %1$s 使用设备摄像头的权限才能继续。" + "允许访问摄像头以扫描二维码" "发生了意外错误。请再试一次。" diff --git a/features/location/impl/src/main/res/values-cs/translations.xml b/features/location/impl/src/main/res/values-cs/translations.xml index 99deeba029..6bb5b1db8c 100644 --- a/features/location/impl/src/main/res/values-cs/translations.xml +++ b/features/location/impl/src/main/res/values-cs/translations.xml @@ -1,4 +1,5 @@ + "Vaše historie aktuální polohy bude uložena v místnosti a bude viditelná pro členy i po skončení relace." "Zvolte, jak dlouho chcete sdílet svou aktuální polohu." diff --git a/features/location/impl/src/main/res/values-zh/translations.xml b/features/location/impl/src/main/res/values-zh/translations.xml new file mode 100644 index 0000000000..6837d3a1eb --- /dev/null +++ b/features/location/impl/src/main/res/values-zh/translations.xml @@ -0,0 +1,5 @@ + + + "你实时位置历史将存储在房间中,并于会话结束后对其他成员可见。" + "选择共享实时位置的时长。" + diff --git a/features/lockscreen/impl/src/main/res/values-ro/translations.xml b/features/lockscreen/impl/src/main/res/values-ro/translations.xml index d40bfbaece..7555d7eb58 100644 --- a/features/lockscreen/impl/src/main/res/values-ro/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-ro/translations.xml @@ -23,7 +23,7 @@ Alegeți ceva memorabil. Dacă uitați acest PIN, veți fi deconectat din aplica "Vă rugăm să introduceți același cod PIN de două ori" "Codurile PIN nu corespund" "Va trebui să vă reconectați și să creați un cod PIN nou pentru a continua" - "Sunteți deconectat" + "Acest device este în curs de eliminare" "Aveți %1$d încercare de deblocare" "Aveți %1$d încercări de deblocare" 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 b83c7d4e85..62da77cbb5 100644 --- a/features/lockscreen/impl/src/main/res/values-zh/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-zh/translations.xml @@ -8,21 +8,21 @@ "更改 PIN 码" "允许生物识别解锁" "移除 PIN 码" - "您确定要删除 PIN 码吗?" + "你确定要删除 PIN 码?" "移除 PIN 码?" "允许 %1$s" "我宁愿使用 PIN 码" "节省时间,用 %1$s 来解锁应用程序" "选择 PIN 码" "确认 PIN 码" - "锁定 %1$s 以为聊天增加安全性。 + "锁定 %1$s 以增加聊天的安全性。 -选择好记的 PIN 码。如果忘掉了这个 PIN 码,就不得不登出应用。" - "出于安全原因,您不能选择这个 PIN 码" +选择好记的 PIN 码。如果忘掉了此 PIN 码,你将被迫从 app 注销。" + "出于安全考虑,你不能使用此 PIN 码" "选择不同的 PIN 码" "请输入两次相同的 PIN 码" "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 6146f1776d..fa31796c3b 100644 --- a/features/login/impl/src/main/res/values-cs/translations.xml +++ b/features/login/impl/src/main/res/values-cs/translations.xml @@ -37,7 +37,15 @@ "Matrix je otevřená síť pro bezpečnou a decentralizovanou komunikaci." "Vítejte zpět!" "Přihlaste se k %1$s" + "Otevřít Element Classic" + "Otevřete Element Classic na svém zařízení" + "Přejděte do Nastavení > Zabezpečení a soukromí" + "V části Správa kryptografických klíčů vyberte Obnova šifrovaných zpráv" + "Postupujte podle pokynů k povolení úložiště klíčů" + "Vraťte se do %1$s" + "Povolte úložiště klíčů, než budete pokračovat na %1$s" "Verze %1$s" + "Kontrola účtu" "Ruční přihlášení" "Přihlaste se k %1$s" "Přihlásit se pomocí QR kódu" 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 f9c9141ff2..ac125ba945 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -1,46 +1,51 @@ "更改账户提供方" - "服务器地址" + "主服务器地址" "输入搜索词或域名地址。" "搜索公司、社区或私人服务器。" "寻找账户提供方" - "这是您的对话将存在的地方,就像您使用电子邮件提供方来保存电子邮件一样。" - "您即将登录 %s" - "这是您的对话将存在的地方,就像您使用电子邮件提供方来保存电子邮件一样。" - "您即将在 %s 上创建一个帐户" + "这是你的对话将存在的地方,就像你使用邮件提供者来存储电子邮件那样。" + "你即将登录到 %s" + "这是你的对话将存在的地方,就像你使用邮件提供者来存储电子邮件那样。" + "你即将在 %s 上创建账户" "Matrix.org 由 Matrix.org 基金会运营,是用于安全、去中心化的通信的公共 Matrix 网络上的大型免费服务器。" - "其他" - "使用其他账户提供商,例如您自己的私人服务器或工作账户。" + "其它" + "使用其它账户提供者,例如你自己的私有服务器或工作账户。" "更改账户提供方" "Google Play" - "%1$s 需要 Element Pro 应用。请从应用商店下载。" - "需要 Element Pro 版" - "我们无法访问此服务器。请检查您输入的服务器网址是否正确。如果 URL 正确,请联系您的服务器管理员寻求进一步帮助。" - "由于 .well-known 文件中存在问题,服务器不可用: + "%1$s 要求 Element Pro。请从应用商店下载。" + "需要 Element Pro" + "我们无法访问此服务器。请检查输入的服务器 URL 是否正确。如果 URL 正确,请联系服务器管理员寻求进一步帮助。" + "由于 .well-known 文件存在问题,服务器不可用: %1$s" - "所选账户提供商不支持跨屏同步。需要升级服务器才能使用%1$s。" - "%1$s不允许连接到%2$s。" + "所选账户提供者不支持滑动同步。需要升级服务器才能使用 %1$s。" + "%1$s 不允许连接到 %2$s。" "本应用已配置为允许访问:%1$s 。" - "账户提供商%1$s 不被允许。" - "服务器网址" + "账户提供者 %1$s 不被允许。" + "主服务器 URL" "输入域名地址。" - "您的服务器地址是什么?" + "你的服务器地址是什么?" "选择服务器" "创建账户" "该账户已被停用。" - "错误的用户名和/或密码" - "这不是合法的用户 ID。期望格式:‘@user:homeserver.org’。" + "用户名与(或)密码不正确" + "这不是合法的用户 ID。预期格式:“@user:homeserver.org”。" "此服务器使用刷新令牌。使用密码登录时不支持这些功能。" - "该服务器不支持密码登录和 OIDC 第三方账户登录。请联系服务器管理员,或选择别的服务器。" - "输入您的详细信息" + "该服务器不支持密码登录与 OIDC 登录。请联系服务器管理员或选择另一服务器。" + "输入详细信息" "Matrix 是一个用于安全、去中心化通信的开放网络。" "欢迎回来!" "登录到 %1$s" "打开 Element Classic" "在你的设备上打开 Element Classic" "前往“设置” > “安全与隐私”" + "在加密密钥管理中选择“恢复加密消息”。" + "按指示启用密钥存储" + "返回到 %1$s" + "请先启用密钥存储再继续处理 %1$s" "版本%1$s" + "正在检查账户" "手动登录" "登录到 %1$s" "使用二维码登录" @@ -48,57 +53,57 @@ "欢迎回来" "欢迎使用 %1$s,快而简约的消息应用。" "欢迎使用 %1$s,速度与简洁的极致。" - "融入您的 Element" + "融入 Element" "建立安全连接" - "无法与新设备建立安全连接。您现有的设备仍然安全,无需担心。" + "无法与新设备建立安全连接。你的现有设备仍然安全,无需担心。" "现在怎么办?" "如果这是网络问题,请尝试使用二维码再次登录" "如果遇到同样的问题,请尝试使用不同的 WiFi 网络或使用移动数据代替 WiFi" "如果不起作用,请手动登录" "连接不安全" - "您会被要求输入此设备上显示的两位数。" - "在您的其他设备上输入下面的数字" - "在其他设备登录后重试,或使用另一个已登录的设备。" - "其他设备未登录" + "你将被要求输入此设备上显示的两位数字。" + "在你的其它设备上输入以下数字" + "在其它设备登录后重试,或使用另一个已登录的设备。" + "尚未登录的其它设备" "登录被另一台设备取消" "登录请求已取消" - "其它设备未接受请求" + "另一设备上的登录请求已被拒绝。" "登录被拒绝" - "您无需额外操作。" - "您已在另一台设备登录。" + "无需额外操作。" + "你已在另一设备上登录。" "登录已过期. 请重试." "登录未及时完成" "另一个设备不支持使用二维码登录 %s. 尝试手动或使用另一个设备扫描二维码." - "不支持二维码" + "二维码不受支持" "账户提供方不支持 %1$s." "不支持 %1$s." "准备进行扫描" "在桌面设备上打开 %1$s" "点击你的头像" "选择 %1$s" - "「连接新设备」" + "“关联新设备”" "使用此设备扫描二维码" - "仅在您的账户提供方支持时才可用。" + "仅在账户提供者支持时可用。" "在另一台设备上打开 %1$s 以获取二维码" - "使用其他设备上显示的二维码。" - "再试一次" + "使用其它设备上显示的二维码。" + "重试" "二维码错误" "转到摄像头设置" - "您需要授予 %1$s 使用设备摄像头的权限才能继续。" - "允许摄像头权限以扫描 QR 码" + "你需要授予 %1$s 使用设备摄像头的权限才能继续。" + "允许访问摄像头以扫描二维码" "扫描二维码" "重新开始" "发生了意外错误。请再试一次。" - "等着您的其他设备" - "您的账户提供方可能会要求您提供以下代码来验证登录。" - "您的验证码" + "正在等待其它设备" + "你的账户提供者可能会要求你提供以下代码以验证登录。" + "你的验证码" "更改账户提供方" "专为 Element 员工提供的私人服务器。" "Matrix 是一个用于安全、去中心化通信的开放网络。" - "这是您的对话将存在的地方,就像您使用电子邮件提供方来保存电子邮件一样。" + "这是你的对话将存在的地方,就像你使用邮件提供者来存储电子邮件那样。" "即将登录 %1$s" - "选择账户提供商" + "选择账户提供者" "即将在 %1$s 上创建一个账户" diff --git a/features/logout/impl/src/main/res/values-ro/translations.xml b/features/logout/impl/src/main/res/values-ro/translations.xml index 7124188269..1f1ff9e07a 100644 --- a/features/logout/impl/src/main/res/values-ro/translations.xml +++ b/features/logout/impl/src/main/res/values-ro/translations.xml @@ -4,15 +4,15 @@ "Deconectați-vă" "Deconectați-vă" "Deconectare în curs…" - "Sunteți pe cale să vă deconectați de la ultima sesiune. Dacă vă deconectați acum, veți pierde accesul la mesajele criptate." - "Ați dezactivat backup-ul" - "Cheile dumneavoastră erau încă în curs de backup atunci când ați fost deconectat. Reconectați-vă pentru ca cheile dumneavoastră să poată fi salvate înainte de a vă deconecta." + "Acesta este singurul dumneavoastră dispozitiv. Dacă îl eliminați, veți avea nevoie de o cheie de recuperare pentru a vă confirma identitatea digitală și a restaura mesajele criptate data viitoare când vă conectați." + "Sunteți pe cale să vă pierdeți accesul la mesajele dumneavoastră criptate." + "Cheile dumneavoastră erau încă în curs de backup atunci când ați fost deconectat. Reconectați-vă pentru ca cheile dumneavoastră să poată fi salvate înainte de a elimina acest dispozitiv." "Cheile dumneavoastră sunt încă în curs de backup" "Vă rugăm să așteptați până la finalizarea acestui proces înainte de a vă deconecta." "Cheile dumneavoastră sunt încă în curs de backup" "Deconectați-vă" - "Sunteți pe cale să vă deconectați de la ultima sesiune. Dacă vă deconectați acum, veți pierde accesul la mesajele criptate." - "Recuperarea nu este configurată" - "Sunteți pe cale să vă deconectați de la ultima sesiune. Dacă vă deconectați acum, este posibil să pierdeți accesul la mesajele criptate." - "Ați salvat cheia de recuperare?" + "Acesta este singurul dumneavoastră dispozitiv. Dacă îl eliminați, veți avea nevoie de o cheie de recuperare pentru a vă confirma identitatea digitală și a restaura chat-urile criptate data viitoare când vă conectați." + "Sunteți pe cale să pierdeți accesul la mesajele dumneavoastră criptate" + "Acesta este singurul dumneavoastră dispozitiv. Dacă îl eliminați, veți avea nevoie de o cheie de recuperare pentru a vă confirma identitatea digitală și a restaura mesajele criptate data viitoare când vă conectați." + "Asigurați-vă că aveți acces la cheia de recuperare înainte de a elimina acest dispozitiv." diff --git a/features/logout/impl/src/main/res/values-zh/translations.xml b/features/logout/impl/src/main/res/values-zh/translations.xml index d438c64ff3..3370b40f3c 100644 --- a/features/logout/impl/src/main/res/values-zh/translations.xml +++ b/features/logout/impl/src/main/res/values-zh/translations.xml @@ -1,18 +1,18 @@ - "您确定要删除此设备吗?" + "你确定要移除此设备?" "删除此设备" "删除此设备" "正在删除设备……" - "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" - "您已关闭备份" - "当你离线时,密钥仍在备份中。重新连接以便在登出之前备份密钥。" - "您的密钥仍在备份中" - "请等待此操作完成后再登出。" - "您的密钥仍在备份中" + "这是你的唯一设备。一旦移除,下次登录时你需要使用恢复密钥验证数字身份并恢复加密聊天。" + "你即将失去加密聊天的访问权" + "当你离线时,密钥仍在备份。重新连接以便在移除设备之前备份密钥。" + "你的密钥仍在备份中" + "请等待此操作完成再移除此设备。" + "你的密钥仍在备份中" "删除此设备" - "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" - "未设置恢复" - "即将登出最后一个会话。如果现在登出,将无法访问加密的消息。" - "您保存了恢复密钥吗?" + "这是你的唯一设备。一旦移除,下次登录时你需要使用恢复密钥验证数字身份并恢复加密聊天。" + "你即将失去加密聊天的访问权" + "这是你的唯一设备。一旦移除,下次登录时你需要使用恢复密钥验证数字身份并恢复加密聊天。" + "确保你移除此设备前拥有恢复密钥" diff --git a/features/messages/impl/src/main/res/values-ro/translations.xml b/features/messages/impl/src/main/res/values-ro/translations.xml index ff380874ea..67b72dc2a8 100644 --- a/features/messages/impl/src/main/res/values-ro/translations.xml +++ b/features/messages/impl/src/main/res/values-ro/translations.xml @@ -35,7 +35,7 @@ "Înregistrați un videoclip" "Atașament" "Bibliotecă foto și video" - "Locație" + "Partajați locația" "Sondaj" "Formatarea textului" "Mesajele anterioare nu sunt momentan disponibile în această cameră" diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index 2a6b9bf78d..26518d656c 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -7,13 +7,13 @@ "由未知或已删除的设备加密。" "由未经其所有者验证的设备加密。" "由未经验证的用户加密。" - "活动" + "节假日" "旗帜" - "食物和饮料" + "饮食" "动物和自然" - "物品" + "日常物品" "表情和人物" - "旅行和地点" + "文旅景点" "最近的 Emoji" "符号" "使用旧版应用程序的用户可能无法看到字幕。" @@ -23,13 +23,13 @@ "上传媒体失败,请重试。" "允许的最大文件大小为%1$s 。" "文件太大,无法上传" - "第%1$d/%2$d项" + "第 %1$d 个项目,共 %2$d 个" "优化图像质量" "处理中…" "屏蔽用户" "请确认是否要隐藏该用户当前和未来的所有信息" - "此消息将举报给您的服务器管理员。他们无法读取任何加密消息。" - "举报此内容的原因" + "此消息将举报给服务器管理员。他们无法读取任何加密消息。" + "举报此内容的理由" "相机" "拍摄照片" "录制视频" @@ -39,40 +39,40 @@ "投票" "文本格式化" "消息历史记录当前不可用。" - "此聊天室无法查看消息历史记录。请验证此设备以查看之。" - "您想邀请他们回来吗?" - "此聊天室中只有您一个人" - "通知整个聊天室" + "消息历史在此房间不可用。请验证此设备以查看。" + "你想邀请他们回来吗?" + "此聊天中只有你一人" + "通知整个房间" "所有人" "再次发送" "消息发送失败" - "添加表情符号" - "这是 %1$s 聊天室的开始。" + "添加反应" + "这是房间 %1$s 的开头。" "这是本对话的开始。" - "不支持的呼叫。询问呼叫者是否可以使用新的 Element X 应用程序。" + "不受支持的通话。询问呼叫方是否可以使用新的 Element X app。" "折叠" "消息已复制" - "您无权在此聊天室发言" + "你无权在此房间发言" - "%1$d 个成员添加表情符号 %2$s" + "%1$d 个成员使用 %2$s 反应" - "您与 %1$d 个成员添加表情符号 %2$s" + "你与其他 %1$d 个成员使用 %2$s 反应" - "您添加了表情符号%1$s" + "你使用 %1$s 反应" "折叠" "展开" "显示反应摘要" "新消息" - "%1$d 个聊天室变化" + "%1$d 个房间变化" - "跳转至新房间" + "跳转到新房间" "本房间已被替换,现已失效" "查看历史消息" - "该聊天室是其他聊天室的延续" + "此房间是另一房间的延续" - "%1$s,%2$s 和其他 %3$d 个人" + "%1$s,%2$s 及其他 %3$d 人" "%1$s 正在输入" diff --git a/features/poll/api/src/main/res/values-zh/translations.xml b/features/poll/api/src/main/res/values-zh/translations.xml index 773d2b03fc..037d6d7c85 100644 --- a/features/poll/api/src/main/res/values-zh/translations.xml +++ b/features/poll/api/src/main/res/values-zh/translations.xml @@ -4,5 +4,5 @@ "%1$d 总投票百分比" "将移除之前的选择" - "这是获胜的答案" + "此为胜出的答案" diff --git a/features/poll/impl/src/main/res/values-zh/translations.xml b/features/poll/impl/src/main/res/values-zh/translations.xml index f231e99d76..ee40168ea7 100644 --- a/features/poll/impl/src/main/res/values-zh/translations.xml +++ b/features/poll/impl/src/main/res/values-zh/translations.xml @@ -5,11 +5,11 @@ "隐藏投票" "选项 %1$d" "更改尚未保存,确定要返回吗?" - "删除选项%1$s" + "删除选项 %1$s" "问题或话题" "投票的内容是什么?" "创建投票" - "您确定要删除此投票吗?" + "你确定要删除此投票?" "删除投票" "编辑投票" "无法找到正在进行的投票。" diff --git a/features/preferences/impl/src/main/res/values-cs/translations.xml b/features/preferences/impl/src/main/res/values-cs/translations.xml index 0127a98b41..12014e7104 100644 --- a/features/preferences/impl/src/main/res/values-cs/translations.xml +++ b/features/preferences/impl/src/main/res/values-cs/translations.xml @@ -11,6 +11,15 @@ "Skrýt avatary v žádostech o pozvání do místnosti" "Skrýt náhledy médií na časové ose" "Experimentální funkce" + "Vzdálenost, kterou musíte urazit, aby se spustila aktualizace." + "Ujistěte se, že je pro tuto aplikaci povolena možnost \"Přesná poloha\". Chcete-li změnit oprávnění, přejděte do %1$s." + "Nastavení aplikace" + "Aktuální informace o poloze" + + "Každý %1$d metr" + "Každé %1$d metry" + "Každých %1$d metrů" + "Rychlejší nahrávání fotografií a videí a snížení spotřeby dat" "Optimalizace kvality médií" "Moderování a bezpečnost" diff --git a/features/preferences/impl/src/main/res/values-fr/translations.xml b/features/preferences/impl/src/main/res/values-fr/translations.xml index 5ee91388bd..292b5bf9a5 100644 --- a/features/preferences/impl/src/main/res/values-fr/translations.xml +++ b/features/preferences/impl/src/main/res/values-fr/translations.xml @@ -11,6 +11,14 @@ "Masquer les avatars des salons dans les invitations" "Masquer les aperçus des médias dans les discussions" "Expérimental" + "Distance à effectuer pour envoyer une mise à jour." + "Assurez-vous que la « Localisation précise » est activée pour cette application. Pour modifier l’autorisation, aller à: %1$s." + "Paramètres de l’application" + "Mises à jour en direct de la localisation" + + "%1$d mètre" + "%1$d mètres" + "Téléchargez des photos et des vidéos plus rapidement et réduisez la consommation de données" "Optimisez la qualité des médias" "Modération et sécurité" diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml index 9cd0dfea96..10cbca0ada 100644 --- a/features/preferences/impl/src/main/res/values-ja/translations.xml +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -11,6 +11,13 @@ "ルームへの招待リクエストにアバターを表示しない" "タイムラインにメディアのプレビューを表示しない" "ラボ" + "更新するのに必要な移動距離です。" + "「正確な位置情報」がこのアプリで使用可能なことを確認してください。権限を変更するには %1$s を開いてください。" + "アプリ設定" + "ライブ位置情報の更新" + + "%1$dm ごと" + "写真や動画を高速で送信してデータ使用量を減らす" "メディアの品質を最適化" "制限と安全" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 0dac7ab6d8..d57fb3b740 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -1,25 +1,32 @@ - "为确保您不会错过重要来电,请更改设置以允许锁屏时的全屏通知。" + "为确保你不会错过重要来电,请更改设置以允许锁屏时的全屏通知。" "提升通话体验" "选择如何接收通知" "开发者模式" - "允许开发人员访问特性和功能。" - "自定义 Element Call URL" - "为 Element 通话设置基本 URL。" + "启用以访问适用于开发者的功能与特性。" + "自定义 Element Call 基础 URL" + "为 Element Call 设置基础 URL。" "URL 无效,请确保包含协议(http/https)和正确的地址。" "在房间邀请请求中隐藏头像" - "在时间轴中隐藏媒体预览" + "在时间线上隐藏媒体预览" "实验室" + "触发一次更新所需的移动距离。" + "确保已为 app 启用“精确位置”。如需更改该权限请转到 %1$s 。" + "App 设置" + "实时位置更新" + + "每 %1$d 米" + "针对上传进行优化" - "媒体" - "内容审核与安全" + "优化媒体质量" + "尺度与安全" "自动优化图像以实现更快的上传速度和更小的文件大小。" "优化图片上传质量" "%1$s。点击此处更改。" - "高 (1080p)" - "低画质 (480p)" - "标准 (720p)" + "高(1080p)" + "低(480p)" + "标准(720p)" "视频上传质量" "通知推送提供者" "禁用富文本编辑器,手动输入 Markdown。" @@ -30,53 +37,53 @@ "始终隐藏" "始终显示" "在私人房间" - "随时可以通过点击隐藏的媒体来显示它" - "在时间轴中显示媒体" - "启用在时间轴中查看消息源码的选项。" - "您没有屏蔽用户" + "点击隐藏的媒体即可将其恢复显示" + "在时间线上显示媒体" + "启用在时间线上查看消息源码的选项。" + "暂无已屏蔽的用户" "解除屏蔽" "可以重新接收他们的消息。" "解除屏蔽用户" "正在解除屏蔽……" "显示名称" - "您的显示名称" + "你的显示名称" "遇到未知错误,无法更改信息。" "无法更新个人资料" "编辑个人资料" "更新个人资料……" - "启用主题回复" - "应用将重启以应用此更改。" + "启用消息列中的回复" + "App 将重启以应用此更改。" "尝试我们最新的开发理念。这些功能尚未最终确定,可能不稳定,也可能会发生变化。" "想尝试新功能?" "实验室" "更多设置" "音视频通话" "配置不匹配" - "我们简化了通知设置,使选项更易于查找。您过去选择的某些自定义设置未在此处显示,但它们仍然有效。 + "我们简化了通知设置,使选项更易于查找。你曾经选择的某些自定义设置未在此处显示,但它们仍然有效。 -如果继续,您的某些设置可能会更改。" +如果继续,你的某些设置可能会被更改。" "私聊" - "各聊天室的独立设置" + "各房间单独的设置" "更新通知设置时出错。" - "全部消息" + "所有消息" "仅限提及和关键词" - "在私聊中,请通知我:" - "在群聊中,请通知我:" + "在私聊中通知我以下类型" + "在群聊中通知我以下类型" "在此设备上启用通知" "配置尚未更正,请重试。" "群聊" "邀请" - "服务器在加密聊天室中不支持此选项,因此在某些聊天室可能无法收到通知。" + "主服务器不支持在加密房间中的此选项,因此在某些房间你可能无法收到通知。" "提及" "全部" "提及" - "请通知我:" - @room 时通知我 - "要接收通知,请更改您的 %1$s。" + "通知我以下类型" + "我在房间中被提及时通知我" + "要接收通知,请更改 %1$s。" "系统设置" "系统通知已关闭" "通知" - "推送历史记录" + "推送历史" "排查问题" "排查通知问题" diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index 31ee676226..d5abe1df6a 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -11,6 +11,14 @@ "Hide avatars in room invite requests" "Hide media previews in timeline" "Labs" + "The distance you have to move to trigger an update." + "Make sure \"Precise Location” is enabled for this app. To change the permission go to %1$s." + "App Settings" + "Live location updates" + + "Every %1$d meter" + "Every %1$d meters" + "Upload photos and videos faster and reduce data usage" "Optimise media quality" "Moderation and Safety" diff --git a/features/rageshake/api/src/main/res/values-zh/translations.xml b/features/rageshake/api/src/main/res/values-zh/translations.xml index 34a643ceab..ca81dd2d2c 100644 --- a/features/rageshake/api/src/main/res/values-zh/translations.xml +++ b/features/rageshake/api/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ "%1$s 上次使用时崩溃了。想和我们分享崩溃报告吗?" - "你似乎愤怒地摇晃了手机。想要打开 Bug 报告页面吗?" + "你似乎愤怒地摇晃了手机。是否打开 Bug 报告页面?" "摇一摇" "检测阈值" diff --git a/features/rageshake/impl/src/main/res/values-zh/translations.xml b/features/rageshake/impl/src/main/res/values-zh/translations.xml index 527a35cdcc..b34badea08 100644 --- a/features/rageshake/impl/src/main/res/values-zh/translations.xml +++ b/features/rageshake/impl/src/main/res/values-zh/translations.xml @@ -1,20 +1,20 @@ "附上截图" - "如果您有任何后续问题,可以与我联系。" + "如果有任何后续问题可以联系我。" "联系我" "编辑截图" - "请尽可能详细地描述问题。您做了什么?您预期会发生什么?实际发生了什么?" + "请尽可能详细地描述问题。你做了什么?预期会发生什么?实际上发生了什么?" "描述问题…" "请尽可能用英文描述。" "描述太短,请提供详细情况。谢谢!" "发送崩溃日志" "允许日志" - "日志文件过大,无法包含在本报告中,请通过其他方式发送给我们。" + "日志文件过大,无法包含在本次报告中,请通过其它方式发送给我们。" "发送屏幕截图" - "为确认一切正常运行,您的消息中将包含日志。如要发送不带日志的消息,请关闭此设置。" + "为确认一切正常运行,日志中将包含你的消息。如要发送不含消息的日志,请关闭此设置。" "%1$s 上次使用时崩溃了。想和我们分享崩溃报告吗?" - "如果您遇到通知问题,上传通知设置可以帮助我们查明根本原因。" + "如果你遭遇通知相关问题,上传通知设置可以帮助我们调查根本原因。请注意:这些规则可能包含私人信息,例如你的显示名称或用于接收通知的关键词。" "发送通知设置" "查看日志" diff --git a/features/reportroom/impl/src/main/res/values-zh/translations.xml b/features/reportroom/impl/src/main/res/values-zh/translations.xml index 40a0b5f1b0..e79148a45d 100644 --- a/features/reportroom/impl/src/main/res/values-zh/translations.xml +++ b/features/reportroom/impl/src/main/res/values-zh/translations.xml @@ -1,8 +1,8 @@ - "您的报告已成功提交,但在尝试离开房间时遇到了问题。请重试。" + "你的举报已成功提交,但在尝试退出房间时遇到问题。请重试。" "无法离开房间" "向管理员举报此房间。如果信息已加密,管理员将无法读取。" - "描述举报的原因…" + "描述举报的理由…" "举报房间" diff --git a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml index d3c4cada77..9d792fcc74 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml @@ -7,24 +7,24 @@ "成员" "邀请人员" "管理空间" - "管理聊天室" + "管理房间" "管理成员" "消息和内容" "协管员" "移除人员" - "更改聊天室头像" + "更改房间头像" "编辑详情" - "更改聊天室名称" - "更改聊天室主题" + "更改房间名称" + "更改房间主题" "发送消息" "权限" "编辑管理员" - "您将无法撤消此操作。您正在提升用户的权限到与您相同的级别。" + "此操作无法撤消。你正在提升用户的权限到与你相同的权力值。" "添加管理员?" - "此操作无法撤销。您正在将所有权转移给所选用户。一旦离开此界面,该操作将永久生效。" + "此操作无法撤消。你正在将所有权转移给所选用户。一旦离开此处,该操作将永久生效。" "转让所有权" "降级" - "您正在降级,此更改将无法撤消。如果您是聊天室中的最后一个特权用户,则无法重新获得权限。" + "你正在降级自身,此更改无法撤消。如果你是房间中的最后一个拥有特权的用户,则无法重新获得权限。" "降级自己?" "%1$s(待处理)" "(待处理)" @@ -35,9 +35,9 @@ "管理员" "协管员" "成员" - "您有未保存的更改。" + "你有未保存的更改。" "保存更改?" - "没有被封禁的用户。" + "暂无被封禁的用户。" "%1$d 被禁用" @@ -46,10 +46,10 @@ "%1$d 个人" - "移除并封禁成员" + "封禁用户" "仅移除成员" - "取消封禁" - "如果受到邀请,他们可以重新加入聊天室。" + "解封" + "如果他们受到邀请,则可以重新加入房间。" "解封用户" "已封禁用户" "成员" @@ -60,10 +60,10 @@ "管理员" "协管员" "所有者" - "聊天室成员" + "房间成员" "正在解除封禁 %1$s" "管理员" - "管理员和所有者" + "管理员与所有者" "更改我的角色" "降级为成员" "降级为协管员" @@ -73,10 +73,10 @@ "所有者" "权限" "重置权限" - "重置权限后,您将丢失当前设置。" + "重置权限后你将丢失当前设置。" "重置权限?" "角色" - "聊天室详情" - "空间详情" + "房间详细信息" + "空间详细信息" "角色与权限" diff --git a/features/roomaliasresolver/impl/src/main/res/values-zh/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-zh/translations.xml index 52934b6a08..6b44301045 100644 --- a/features/roomaliasresolver/impl/src/main/res/values-zh/translations.xml +++ b/features/roomaliasresolver/impl/src/main/res/values-zh/translations.xml @@ -1,5 +1,5 @@ "无法显示此房间预览" - "无法解析聊天室别名。" + "无法解析房间别名。" diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index d803f01fb7..d2cc6773fb 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -1,12 +1,12 @@ - "新成员无法查看历史记录" - "新成员可见历史记录" + "新成员不能看到历史" + "新成员可以看到历史" "任何人都能查看历史记录" - "您需要一个地址才能在公共目录中显示。" + "你需要一个地址才能使其在公共目录中可见。" "编辑地址" "更新通知设置时出错。" - "服务器在加密聊天室中不支持此选项,因此在某些聊天室可能无法收到通知。" + "主服务器不支持在加密房间中的此选项,因此在某些房间你可能无法收到通知。" "投票" "管理员" "封禁成员" @@ -17,18 +17,18 @@ "消息和内容" "协管员" "移除人员" - "更改聊天室头像" + "更改房间头像" "编辑详情" - "更改聊天室名称" - "更改聊天室主题" + "更改房间名称" + "更改房间主题" "发送消息" "编辑管理员" - "您将无法撤消此操作。您正在提升用户的权限到与您相同的级别。" + "此操作无法撤消。你正在提升用户的权限到与你相同的权力值。" "添加管理员?" - "此操作无法撤销。您正在将所有权转移给所选用户。一旦离开此界面,该操作将永久生效。" + "此操作无法撤消。你正在将所有权转移给所选用户。一旦离开此处,该操作将永久生效。" "转让所有权" "降级" - "您正在降级,此更改将无法撤消。如果您是聊天室中的最后一个特权用户,则无法重新获得权限。" + "你正在降级自身,此更改无法撤消。如果你是房间中的最后一个拥有特权的用户,则无法重新获得权限。" "降级自己?" "%1$s(待处理)" "(待处理)" @@ -39,41 +39,41 @@ "管理员" "协管员" "成员" - "您有未保存的更改。" + "你有未保存的更改。" "保存更改?" "添加主题" "已加密" "未加密" - "公共聊天室" + "公共房间" "编辑详情" "出现未知错误,无法更改信息。" - "无法更新聊天室" + "无法更新房间" "消息已加密,只有你和消息接收者拥有唯一解密密钥。" "消息加密已启用" "加载通知设置时出错。" - "无法将此聊天室静音,请重试。" - "无法取消此聊天室的静音,请重试。" - "完成之前请勿关闭应用程序。" - "准备邀请…" + "无法静音此房间,请重试。" + "无法取消静音此房间,请重试。" + "完成之前请勿关闭 app。" + "正在准备邀请…" "邀请朋友" "离开聊天" - "离开聊天室" - "媒体和文件" + "离开房间" + "媒体与文件" "自定义" "默认" "通知" - "置顶消息" + "已置顶的消息" "个人资料" "申请加入" "角色与权限" "名称" "安全与隐私" "安全" - "分享聊天室" - "聊天室信息" + "分享房间" + "房间信息" "主题" - "正在更新聊天室……" - "没有被封禁的用户。" + "正在更新房间…" + "暂无被封禁的用户。" "%1$d 被禁用" @@ -82,10 +82,10 @@ "%1$d 个人" - "移除并封禁成员" + "封禁用户" "仅移除成员" - "取消封禁" - "如果受到邀请,他们可以重新加入聊天室。" + "解封" + "如果他们受到邀请,则可以重新加入房间。" "解封用户" "已封禁用户" "成员" @@ -96,24 +96,24 @@ "管理员" "协管员" "所有者" - "聊天室成员" + "房间成员" "正在解除封禁 %1$s" "允许自定义设置" - "开启此功能将覆盖您的默认设置" + "启用此功能将覆盖默认设置" "在此聊天中通知我以下内容" - "你可以在你的 %1$s 中更改这一项。" + "你可以在 %1$s 中更改此项。" "全局设置" "默认设置" "撤销独立设置" "加载通知设置时出错。" "恢复默认模式失败,请重试。" "设置模式失败,请重试。" - "服务器在加密聊天室中不支持此选项,无法在此聊天室收到通知。" - "全部消息" + "主服务器不支持在加密房间中的此选项,因此在此房间你可能无法收到通知。" + "所有消息" "仅限提及和关键词" - "在这个聊天室,通知我:" + "在此房间通知我以下类型" "管理员" - "管理员和所有者" + "管理员与所有者" "更改我的角色" "降级为成员" "降级为协管员" @@ -123,19 +123,19 @@ "所有者" "权限" "重置权限" - "重置权限后,您将丢失当前设置。" + "重置权限后你将丢失当前设置。" "重置权限?" "角色" - "聊天室详情" + "房间详细信息" "角色与权限" "添加地址" - "授权空间内任何成员均可加入,其他人员需申请访问权限。" + "已授权空间内的任何成员都可以加入,其他人必须申请访问。" "所有用户均需申请访问权限。" - "请求加入" - "%1$s 成员可自由加入,其他人员需申请访问权限。" - "是的,启用加密" - "一旦启用,就不能再禁用房间的加密功能。消息历史记录只能在房间成员被邀请或加入房间后才可见。 -除房间成员外,任何人都无法阅读信息。这可能会妨碍机器人和网桥正常工作。 + "申请加入" + "%1$s 成员可以加入,但其他人员必须申请访问。" + "是,启用加密" + "一旦启用,就不能再禁用房间的加密功能。消息历史只能在房间成员被邀请或加入房间后才可见。 +除房间成员外,任何人都无法阅读消息。这可能会阻止机器人和桥接器正常工作。 我们不建议对任何人都能找到并加入的房间启用加密。" "启用加密?" "加密一旦启用,就无法禁用。" @@ -143,7 +143,7 @@ "启用端到端加密" "任何人都可以加入。" "任何人" - "选择哪些空间的成员无需邀请即可加入本聊天室。%1$s" + "选择哪些无需邀请即可加入此房间的空间成员。%1$s" "管理空间" "仅限受邀者加入。" "仅限受邀者" @@ -151,8 +151,8 @@ "任何位于已授权空间的成员均可加入。" "%1$s 中的任何人都可加入。" "空间成员" - "目前不支持空间" - "您需要一个地址才能在公共目录中显示。" + "“空间”功能当前不受支持" + "你需要一个地址才能使其在公共目录中可见。" "地址" "允许通过搜索 %1$s 的公共房间目录来发现此房间" "通过公共目录搜索功能实现可被发现性。" @@ -160,12 +160,12 @@ "任何人(历史记录公开)" "更改不会影响之前的消息,只会影响新消息。%1$s" "谁可以读取历史记录" - "自受邀以来的成员" + "自成员被邀请时起" "成员(完整历史记录)" "房间地址是查找和访问房间的方式。这也确保你可以轻松地向他人分享房间。 你可以选择在你服务器的公共房间目录中发布你的房间。" "房间发布" - "地址是查找和访问聊天室及空间的途径,同时确保您能轻松与他人共享。" + "地址是查找和访问房间及空间的途径,同时确保你能轻松与他人共享。" "可见性" "安全与隐私" diff --git a/features/roomdetailsedit/impl/src/main/res/values-zh/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-zh/translations.xml index cf7abd7cc8..ae6d0167c3 100644 --- a/features/roomdetailsedit/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetailsedit/impl/src/main/res/values-zh/translations.xml @@ -2,6 +2,6 @@ "编辑详情" "出现未知错误,无法更改信息。" - "无法更新聊天室" - "正在更新聊天室……" + "无法更新房间" + "正在更新房间…" diff --git a/features/roomdirectory/impl/src/main/res/values-zh/translations.xml b/features/roomdirectory/impl/src/main/res/values-zh/translations.xml index 742a762858..705b8e353f 100644 --- a/features/roomdirectory/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdirectory/impl/src/main/res/values-zh/translations.xml @@ -1,5 +1,5 @@ "加载失败" - "聊天室目录" + "房间目录" diff --git a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml index 2c18ee4216..2c7e6584b8 100644 --- a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml @@ -1,22 +1,22 @@ - "移除并封禁成员" + "封禁用户" "封禁" - "即使受到邀请,他们也无法再次加入聊天室。" - "您确定要封禁该成员吗?" - "即使再次受邀,他们也无法加入这个空间,但他们仍将保留其在任何房间或子空间的成员资格。" + "他们即使受到邀请也无法再次加入房间。" + "你确定要封禁该成员?" + "即使再次被邀请,他们也无法加入此空间,但其在任何房间或子空间的成员资格仍然保留。" "正在封禁 %1$s" "移除" - "如果受到邀请,他们可以重新加入聊天室。" - "您确定要移除此成员吗?" - "如果受到邀请,他们将能够再次加入这个空间,并且他们仍将保留其在任何房间或子空间的成员资格。" + "如果他们受到邀请,则可以重新加入房间。" + "你确定要移除此成员?" + "如果被邀请,他们将能够再次加入此空间,并且其在任何房间或子空间的成员资格仍然保留。" "查看个人资料" "移除用户" "删除成员并禁止重新加入?" "正在移除 %1$s……" "解封用户" - "取消封禁" - "如果再次收到邀请,他们可以重新加入该聊天室" + "解封" + "如果他们受到邀请,则可以重新加入" "确定要解除该成员的封禁吗?" "正在解除封禁 %1$s" diff --git a/features/securebackup/impl/src/main/res/values-ro/translations.xml b/features/securebackup/impl/src/main/res/values-ro/translations.xml index f8adf79229..452a0543c8 100644 --- a/features/securebackup/impl/src/main/res/values-ro/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ro/translations.xml @@ -2,16 +2,16 @@ "Dezactivați backupul" "Activați backupul" - "Stocați identitatea criptografică și cheile de mesaje în siguranță pe server. Acest lucru vă va permite să vizualizați mesajele anterioare pe orice dispozitiv nou. %1$s." + "Acest lucru vă va permite să vizualizați istoricul camerelor pe orice dispozitiv nou și este necesar pentru backupul mesajelor și al identității digitale. %1$s." "Backup" - "Stocarea cheilor trebuie activată pentru a configura recuperarea." + "Stocarea cheilor trebuie activată pentru a face un backup al mesajelor." "Încărcați cheile de pe acest dispozitiv" "Permiteți stocarea cheilor" "Schimbați cheia de recuperare" - "Recuperați-vă identitatea criptografică și mesajele anterioare cu o cheie de recuperare dacă ați pierdut toate dispozitivele existente." + "Mesajele dumneavoastră sunt copiate automat cu criptare end-to-end. Pentru a restaura această copie de rezervă și a vă păstra identitatea digitală atunci când pierdeți accesul la toate dispozitivele dumneavoastră, veți avea nevoie de cheia de recuperare." "Introduceți cheia de recuperare" "Backup-ul pentru chat nu este sincronizat în prezent." - "Configurați recuperarea" + "Obțineți cheia de recuperare" "Deschideți %1$s pe un dispozitiv desktop" "Conectați-vă din nou la contul dumneavoastră" "Când vi se cere să vă verificați dispozitivul, selectați%1$s" @@ -23,8 +23,8 @@ "Detaliile contului, contactele, preferințele și lista de chat vor fi păstrate" "Veți pierde mesajele anterioare care au fost stocate doar pe server" "Va trebui să verificați din nou toate dispozitivele și contactele existente" - "Resetați-vă identitatea numai dacă nu aveți acces la un alt dispozitiv conectat și ați pierdut cheia de recuperare." - "Nu puteți confirma? Va trebui să vă resetați identitatea." + "Resetați-vă identitatea digitală numai dacă nu aveți acces la un alt dispozitiv conectat și ați pierdut cheia de recuperare." + "Nu puteți confirma? Va trebui să vă resetați identitatea digitală." "Dezactivare" "Veți pierde mesajele criptate dacă sunteți deconectat de pe toate dispozitivele." "Sunteți sigur că doriți să dezactivați backup-ul?" @@ -58,12 +58,12 @@ "Generați cheia de recuperare" "Nu împărtășiți cheia cu nimeni!" "Configurarea recuperării a reușit" - "Configurați recuperarea" + "Obțineți cheia de recuperare" "Da, resetați acum" "Acest proces este ireversibil." - "Sunteți sigur că doriți să vă resetați identitatea?" + "Sunteți sigur că doriți să vă resetați identitatea digitală?" "S-a produs o eroare necunoscută. Vă rugăm să verificați dacă parola contului dvs. este corectă și să încercați din nou." "Introduceți…" - "Confirmați că doriți să vă resetați identitatea." + "Confirmați că doriți să vă resetați identitatea digitală." "Introduceți parola contului pentru a continua" diff --git a/features/securebackup/impl/src/main/res/values-zh/translations.xml b/features/securebackup/impl/src/main/res/values-zh/translations.xml index 8d86e496cb..c2e7d5c2cb 100644 --- a/features/securebackup/impl/src/main/res/values-zh/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh/translations.xml @@ -2,47 +2,48 @@ "关闭备份" "开启备份" - "将您的密码学身份和消息密钥安全地存储在服务器上。这样您就可以在任何新设备上查看您的消息历史记录。%1$s。" + "这将允许你在新设备上查看聊天历史, 这是备份聊天与数字身份所必需的。%1$s。" "密钥存储" - "必须打开密钥存储才能设置恢复。" + "必须启用密钥存储才能备份聊天。" "从此设备上传密钥" "允许密钥存储" "更改恢复密钥" - "如果您丢失了所有现有设备,使用恢复密钥恢复您的密码学身份和消息历史记录。" + "你的聊天已被端到端加密自动备份。如果你无法访问所有设备,则需要使用恢复密钥并保留数字身份。" "输入恢复密钥" - "您的密钥存储当前不同步。" + "当前密钥存储已脱离同步。" "获取恢复密钥" + "你的聊天已被端到端加密自动备份。如果你无法访问所有设备,则需要使用恢复密钥恢复备份并保留数字身份。" "在桌面设备中打开 %1$s" - "再次登录您的账户" - "当要求验证您的设备时,选择 %1$s" - "「全部重置」" + "再次登录你的账户" + "当要求验证你的设备时,选择 %1$s" + "“重置全部”" "按照说明创建新的恢复密钥" "将新的恢复密钥保存在密码管理器或加密备忘录中" - "使用其他设备重置账户的加密" + "使用其它设备重置账户的加密" "继续重置" - "您的账户信息、联系人、偏好设置和聊天列表将被保留" - "您将丢失现有的消息历史记录" - "您将需要再次验证所有您的现有设备和联系人" - "仅当您无法访问其他已登录设备并且丢失了恢复密钥时才重置您的数字身份。" - "无法确认?那么你需要重置您的数字身份。" - "关闭" - "如果您登出所有设备,您的加密消息将丢失。" - "您确定要关闭备份吗?" - "关闭备份将删除您当前的加密密钥备份并关闭其他安全功能。在这种情况下,你将:" + "你的账户信息、联系人、偏好和聊天列表将被保留" + "你将丢失所有仅存储在服务器上的消息历史" + "你将需要再次验证所有现有设备与联系人" + "仅当你无法访问其它已登录的设备并且丢失了恢复密钥时才重置数字身份。" + "无法确认?你需要重置数字身份。" + "删除" + "如果移除所有设备,你将丢失加密聊天历史,并且需要重置数字身份。" + "你确定要关闭密钥存储?" + "删除密钥存储将移除你的数字身份并关闭以下安全功能:" "新设备上没有加密消息的历史记录" - "如果您在所有设备上登出了 %1$s,那将无法访问加密消息" - "您确定要关闭备份吗?" - "如果您丢失了现有的恢复密钥,请获取新的恢复密钥。更改恢复密钥后,您的旧密钥将不再起作用。" + "如果你在所有位置注销 %1$s,将无法访问加密消息" + "你确定要关闭并删除密钥存储?" + "如果你丢失了现有恢复密钥,请重新获取。旧密钥将随恢复密钥更改后失效。" "生成新的恢复密钥" "请勿与任何人分享!" "恢复密钥已更改" "更改恢复密钥?" "创建新的恢复密钥" - "确保没有人能看到这个界面!" - "请重试以确认访问您的密钥存储。" + "确保没人能看到此界面!" + "请重试以确认访问密钥存储。" "恢复密钥不正确" - "如果您有安全密钥或安全短语,也可以用。" - "输入……" + "如果你有安全密钥或安全口令也同样可用。" + "输入…" "丢失了恢复密钥?" "恢复密钥已确认" "输入恢复密钥" @@ -51,19 +52,19 @@ "保存恢复密钥" "将此恢复密钥保存在安全的地方,例如密码管理器、加密笔记或物理保险箱。" "点击复制恢复密钥" - "保存您的恢复密钥" - "完成此步骤后,您将无法访问新的恢复密钥。" - "您保存了恢复密钥吗?" - "您的聊天备份受恢复密钥保护。如果您在安装后需要新的恢复密钥,则可以通过选择「更改恢复密钥」来重新创建。" + "保存恢复密钥到安全的地方。" + "此步骤之后将无法访问新的恢复密钥。" + "你是否已保存恢复密钥?" + "密钥存储受恢复密钥保护。如果在设置后需要新的恢复密钥,则可以通过选择“更改恢复密钥”重新创建。" "生成恢复密钥" "请勿与任何人分享!" "恢复设置成功" "获取恢复密钥" - "是的,立即重置" + "是,立即重置" "此过程不可逆。" - "您确定要重置您的数字身份吗?" - "发生未知错误。请检查您的帐户密码是否正确,然后重试。" - "输入……" - "确认您要重置您的数字身份。" - "输入您的账户密码以继续" + "你确定要重置数字身份?" + "发生未知错误。请检查你的账户密码是否正确并重试。" + "输入…" + "请确认你要重置数字身份。" + "输入账户的密码以继续" diff --git a/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml b/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml index 8b10638e25..dda5834ba7 100644 --- a/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml @@ -1,20 +1,20 @@ - "您需要一个地址才能在公共目录中显示。" + "你需要一个地址才能使其在公共目录中可见。" "编辑地址" "无需邀请即可加入的公共空间。" "管理空间" "(未知空间)" - "您尚未加入的其他空间" - "您的空间" + "你尚不是其成员的其它空间" + "你的空间" "添加地址" - "授权空间内任何成员均可加入,其他人员需申请访问权限。" + "已授权空间内的任何成员都可以加入,其他人必须申请访问。" "所有用户均需申请访问权限。" - "请求加入" - "%1$s 成员可自由加入,其他人员需申请访问权限。" - "是的,启用加密" - "一旦启用,就不能再禁用房间的加密功能。消息历史记录只能在房间成员被邀请或加入房间后才可见。 -除房间成员外,任何人都无法阅读信息。这可能会妨碍机器人和网桥正常工作。 + "申请加入" + "%1$s 成员可以加入,但其他人员必须申请访问。" + "是,启用加密" + "一旦启用,就不能再禁用房间的加密功能。消息历史只能在房间成员被邀请或加入房间后才可见。 +除房间成员外,任何人都无法阅读消息。这可能会阻止机器人和桥接器正常工作。 我们不建议对任何人都能找到并加入的房间启用加密。" "启用加密?" "加密一旦启用,就无法禁用。" @@ -22,7 +22,7 @@ "启用端到端加密" "任何人都可以加入。" "任何人" - "选择哪些空间的成员无需邀请即可加入本聊天室。%1$s" + "选择哪些无需邀请即可加入此房间的空间成员。%1$s" "管理空间" "仅限受邀者加入。" "仅限受邀者" @@ -30,8 +30,8 @@ "任何位于已授权空间的成员均可加入。" "%1$s 中的任何人都可加入。" "空间成员" - "目前不支持空间" - "您需要一个地址才能在公共目录中显示。" + "“空间”功能当前不受支持" + "你需要一个地址才能使其在公共目录中可见。" "地址" "允许通过搜索 %1$s 的公共房间目录来发现此房间" "通过公共目录搜索功能实现可被发现性。" @@ -39,12 +39,12 @@ "任何人(历史记录公开)" "更改不会影响之前的消息,只会影响新消息。%1$s" "谁可以读取历史记录" - "自受邀以来的成员" + "自成员被邀请时起" "成员(完整历史记录)" "房间地址是查找和访问房间的方式。这也确保你可以轻松地向他人分享房间。 你可以选择在你服务器的公共房间目录中发布你的房间。" "房间发布" - "地址是查找和访问聊天室及空间的途径,同时确保您能轻松与他人共享。" + "地址是查找和访问房间及空间的途径,同时确保你能轻松与他人共享。" "可见性" "安全与隐私" diff --git a/features/signedout/impl/src/main/res/values-zh/translations.xml b/features/signedout/impl/src/main/res/values-zh/translations.xml index 87c7620d98..6768608294 100644 --- a/features/signedout/impl/src/main/res/values-zh/translations.xml +++ b/features/signedout/impl/src/main/res/values-zh/translations.xml @@ -1,8 +1,8 @@ "你在另一个会话中更改了密码" - "你已从其他会话中删除本会话" - "您的服务器管理员已禁止您访问" - "您可能因下列原因而被登出。请重新登录以继续使用 %s。" - "你已登出" + "你已从其它会话中删除此会话" + "服务器管理员已禁止你的访问" + "你可能因以下原因而被注销。请重新登录以继续使用 %s。" + "你已注销" diff --git a/features/space/impl/src/main/res/values-zh/translations.xml b/features/space/impl/src/main/res/values-zh/translations.xml index cdac25a8ae..784ab4bff4 100644 --- a/features/space/impl/src/main/res/values-zh/translations.xml +++ b/features/space/impl/src/main/res/values-zh/translations.xml @@ -5,20 +5,20 @@ "离开 %1$d 个房间和空间" - "选择您想要离开且您不是其唯一管理员的房间:" - "您需要为该空间指定另一位管理员才能离开。" - "您是%1$s 的唯一所有者。在您离开前,需要将所有权转移给他人。" - "您不会从以下房间中被移除,因为您是唯一的管理员:" - "离开%1$s?" - "您是 %1$s 的唯一管理员" + "选择想要退出并且你不是其唯一管理员的房间:" + "你需要为该空间指定另一位管理员才能离开。" + "你是 %1$s 的唯一所有者。在离开前需要将所有权转移给他人。" + "由于因为你是唯一的管理员,你不会从以下房间被移除:" + "离开 %1$s?" + "你是 %1$s 中唯一的管理员" "转让所有权" - "聊天室" - "添加聊天室不会影响其访问权限。如需更改访问权限,请前往“聊天室设置” > “安全与隐私”。" - "添加您的第一个聊天室" + "房间" + "添加房间不会影响其访问权限。如需更改访问权限,请前往“房间设置” > “安全与隐私”。" + "添加第一个房间" "查看成员" - "移除聊天室不会影响其访问权限。要更改访问权限,请转到“聊天室信息”>“隐私和安全”。" + "移除房间不会影响其访问权限。要更改访问权限,请转到“房间信息” > “隐私和安全”。" - "移除 %1$d 个 %2$s 中的聊天室" + "移除 %2$s 个房间,共 %1$d 个" "离开空间" "角色与权限" diff --git a/features/startchat/impl/src/main/res/values-zh/translations.xml b/features/startchat/impl/src/main/res/values-zh/translations.xml index fcbb6afd45..0467ab9c0e 100644 --- a/features/startchat/impl/src/main/res/values-zh/translations.xml +++ b/features/startchat/impl/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ - "新聊天室" - "聊天室目录" + "新房间" + "房间目录" "在开始聊天时发生了错误" "输入地址加入房间" "地址无效" diff --git a/features/userprofile/shared/src/main/res/values-zh/translations.xml b/features/userprofile/shared/src/main/res/values-zh/translations.xml index 38c4e3e8eb..fd1906725d 100644 --- a/features/userprofile/shared/src/main/res/values-zh/translations.xml +++ b/features/userprofile/shared/src/main/res/values-zh/translations.xml @@ -13,7 +13,7 @@ "解除屏蔽" "可以重新接收他们的消息。" "解除屏蔽用户" - "使用 Web 应用程序验证此用户。" + "使用 Web 客户端验证此用户。" "验证 %1$s" "在开始聊天时发生了错误" diff --git a/features/verifysession/impl/src/main/res/values-ro/translations.xml b/features/verifysession/impl/src/main/res/values-ro/translations.xml index 0d1ddd0530..cb22fd02d9 100644 --- a/features/verifysession/impl/src/main/res/values-ro/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ro/translations.xml @@ -2,8 +2,8 @@ "Nu puteți confirma?" "Creați o nouă cheie de recuperare" - "Verificați acest dispozitiv pentru a configura mesagerie securizată." - "Confirmați că sunteți dumneavoastră" + "Alegeți cum doriți să vă verificați pentru a configura mesageria securizată." + "Confirmați-vă identitatea digitală" "Utilizați un alt dispozitiv" "Utilizați cheia de recuperare" "Acum puteți citi sau trimite mesaje în siguranță, iar oricine cu care conversați poate avea încredere în acest dispozitiv." diff --git a/features/verifysession/impl/src/main/res/values-zh/translations.xml b/features/verifysession/impl/src/main/res/values-zh/translations.xml index b48bfe3f87..63cb67330b 100644 --- a/features/verifysession/impl/src/main/res/values-zh/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh/translations.xml @@ -3,52 +3,52 @@ "无法确认?" "创建新的恢复密钥" "选择验证方式以设置安全的消息传输。" - "确认您的数字身份" - "使用其他设备" + "确认你的数字身份" + "使用其它设备" "使用恢复密钥" - "现在,您可以安全地阅读或发送消息,与您聊天的人也会信任此设备。" + "现在你可以安全地读取或发送消息,并且与你聊天的任何人也可以信任此设备。" "设备已验证" - "使用其他设备" - "正在等待其他设备……" + "使用其它设备" + "正在等待其它设备……" "发生了一些错误。网络请求超时,或者被服务器拒绝。" - "确认下面的表情符号与您其他设备上显示的表情符号相匹配。" - "比较表情符号" - "请验证下方表情是否与对方设备显示一致" - "确认以下数字与其他会话中显示的一致。" + "确认以下 Emoji 与你的其它设备上显示的相匹配。" + "比较 Emoji" + "请验证以下 Emoji 是否与对方设备显示的一致" + "确认以下数字与其它会话中显示的一致。" "比较数字" - "现在您可以在其他设备上安全地阅读或发送消息。" - "现在您可以在发送或接收消息时信任该用户的数字身份。" + "现在可以在其它设备上安全地阅读或发送消息。" + "现在可以在发送或接收消息时信任该用户的数字身份。" "设备已验证" "输入恢复密钥" "要么请求超时,要么请求被拒绝,要么验证不匹配。" - "证明自己的身份以访问加密历史消息。" + "证明身份以访问加密消息历史。" "打开已有会话" "重试验证" "准备就绪" "等待比对……" - "比较一组表情符号。" - "比较表情符号,确保它们以相同顺序排列。" + "比较一组唯一的 Emoji。" + "比较唯一的 Emoji,确保它们以相同顺序排列。" "已登录" "要么请求超时,要么请求被拒绝,要么验证不匹配。" "验证失败" "仅在你发起此验证后才继续。" - "验证另一台设备以确保您的消息历史记录保密。" - "现在您可以在其他设备上安全地阅读或发送消息。" + "验证另一台设备以确保消息历史的安全。" + "现在可以在其它设备上安全地阅读或发送消息。" "设备已验证" "已请求验证" "不匹配" "匹配" - "从此处开始验证之前,请确保您已在其他设备上打开了该应用程序。" + "从此处开始验证之前请确保你已在其它设备上打开了 app。" "在另一台验证的设备上打开应用" - "为了提高安全性,请通过比较设备上的一组表情符号来验证此用户。通过使用安全方式来做到这一点,如面对面。" + "为提高安全性,请通过比较设备上的一组 Emoji 以验证此用户。通过使用安全的方式比如面对面来实施此步骤。" "验证此用户?" - "为了额外的安全性,另一位用户想要验证您的数字身份。您将看到一组表情符号供您比较。" - "您应该会在另一台设备上看到一个弹出窗口。现在从那里开始验证。" + "为提高安全性,另一用户想要验证你的数字身份。你将看到一组 Emoij 供你比较。" + "你应该会在另一台设备上看到一个弹出窗口。现在从该处开始验证。" "在另一台设备上开始验证" "在另一台设备上开始验证" - "等待其他用户" - "一旦被接受,您将能够继续进行验证。" - "请在其他会话中接受验证请求。" + "正在等待其他用户" + "一旦被接受,你将能够继续进行验证。" + "接受此请求以在另一会话中开始验证流程以继续操作。" "等待接受请求" "正在删除设备……" diff --git a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml index cd22ebed38..35a501c7a2 100644 --- a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml @@ -1,6 +1,6 @@ - "(头像也更改了)" + "(头像也已更换)" "%1$s 更换了头像" "你更换了头像" "%1$s 降级为成员" @@ -13,61 +13,61 @@ "你将显示名称设置为 %1$s" "%1$s 晋升为管理员" "%1$s 晋升为协管员" - "%1$s 更换了聊天室头像" - "你更换了聊天室头像" - "%1$s 移除了聊天室头像" - "你移除了聊天室头像" - "%1$s 封禁了 %2$s" - "你封禁了 %1$s" - "你封禁了%1$s:%2$s" - "%1$s封禁了%2$s:%3$s" - "%1$s 创建了聊天室" - "你创建了聊天室" + "%1$s 更换了房间头像" + "你更换了房间头像" + "%1$s 移除了房间头像" + "你移除了房间头像" + "%1$s 已封禁 %2$s" + "你已封禁 %1$s" + "你已封禁 %1$s:%2$s" + "%1$s 已封禁 %2$s:%3$s" + "%1$s 创建了房间" + "你创建了房间" "%1$s 邀请了 %2$s" "%1$s 接受了邀请" "你接受了邀请" "你邀请了 %1$s" "%1$s 邀请了你" - "%1$s 加入了聊天室" - "你加入了聊天室" - "%1$s 请求加入" - "%1$s 允许 %2$s 加入" - "您已允许 %1$s 加入" - "你已请求加入" - "%1$s 拒绝了 %2$s 的加入请求" - "你拒绝了 %1$s 的加入请求" - "%1$s 拒绝了你的加入请求" + "%1$s 加入了房间" + "你加入了房间" + "%1$s 申请加入" + "%1$s 已允许 %2$s 加入" + "你已允许 %1$s 加入" + "你已申请加入" + "%1$s 拒绝了 %2$s 的加入申请" + "你拒绝了 %1$s 的加入申请" + "%1$s 拒绝了你的加入申请" "%1$s 已不再想加入" "你取消了加入申请" - "%1$s 离开了聊天室" - "你离开了聊天室" - "%1$s 将聊天室名称改为 %2$s" - "你把聊天室名称改为 %1$s" - "%1$s 移除了聊天室名称" - "你移除了聊天室名称" + "%1$s 离开了房间" + "你离开了房间" + "%1$s 将房间名称更改为 %2$s" + "你将房间名称更改为 %1$s" + "%1$s 移除了房间名称" + "你移除了房间名称" "%1$s 没有任何更改" - "您未进行任何更改" - "%1$s 更改了置顶消息" - "您更改了置顶消息" - "%1$s 置顶了一条消息" - "您置顶了一条消息" - "%1$s 取消置顶了一条消息" - "您取消置顶了一条消息" + "你未做任何更改" + "%1$s 更改了已置顶的消息" + "你更改了已置顶的消息" + "%1$s 置顶了 1 个消息" + "你已置顶了 1 个消息" + "%1$s 取消置顶了 1 个消息" + "你取消置顶了 1 个消息" "%1$s 拒绝了邀请" - "您拒绝了邀请" + "你拒绝了邀请" "%1$s 已移除 %2$s" - "您移除了 %1$s" - "您移除了 %1$s:%2$s" + "你移除了 %1$s" + "你移除了 %1$s:%2$s" "%1$s 移除了 %2$s:%3$s" - "%1$s 向 %2$s 发送了加入聊天室的邀请" - "你邀请 %1$s 加入聊天室" - "%1$s 撤销了 %2$s 加入聊天室的邀请" - "你撤销了 %1$s 加入聊天室的邀请" - "%1$s 将主题改为:%2$s" - "你将主题改为:%1$s" - "%1$s 移除了聊天室主题" - "你移除了聊天室主题" - "%1$s 解禁了 %2$s" - "你解禁了 %1$s" + "%1$s 向 %2$s 发送了加入房间的邀请" + "你邀请 %1$s 加入房间" + "%1$s 撤消了 %2$s 加入房间的邀请" + "你撤消了 %1$s 加入房间的邀请" + "%1$s 将主题更改为:%2$s" + "你将主题更改为:%1$s" + "%1$s 移除了房间主题" + "你移除了房间主题" + "%1$s 已解封 %2$s" + "你已解封 %1$s" "%1$s 对其成员资格进行了未知更改" diff --git a/libraries/matrixui/src/main/res/values-cs/translations.xml b/libraries/matrixui/src/main/res/values-cs/translations.xml index a8e82b288c..cdfb34c032 100644 --- a/libraries/matrixui/src/main/res/values-cs/translations.xml +++ b/libraries/matrixui/src/main/res/values-cs/translations.xml @@ -3,5 +3,7 @@ "Poslat pozvánku" "Chcete začít chatovat s %1$s?" "Poslat pozvánku?" + "Momentálně s touto osobou nemáte žádné chaty. Před pokračováním potvrďte pozvání." + "Chcete zahájit chat s tímto novým kontaktem?" "%1$s (%2$s) vás pozval(a)" diff --git a/libraries/matrixui/src/main/res/values-ja/translations.xml b/libraries/matrixui/src/main/res/values-ja/translations.xml index ce2b24041c..8834c0c18c 100644 --- a/libraries/matrixui/src/main/res/values-ja/translations.xml +++ b/libraries/matrixui/src/main/res/values-ja/translations.xml @@ -3,7 +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 0a2effc4cf..b466f13226 100644 --- a/libraries/matrixui/src/main/res/values-zh/translations.xml +++ b/libraries/matrixui/src/main/res/values-zh/translations.xml @@ -1,8 +1,9 @@ "发送邀请" - "您想与%1$s 开始聊天吗?" + "你是否要与 %1$s 开始聊天?" "发送邀请?" + "你与此人暂无任何聊天。请确认对方被邀请后再继续。" "是否与新联系人开始聊天?" "%1$s (%2$s)邀请了你" diff --git a/libraries/mediaviewer/impl/src/main/res/values-zh/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-zh/translations.xml index 08b33993dc..5bdec732a2 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-zh/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-zh/translations.xml @@ -11,11 +11,12 @@ "媒体" "上传到此房间的图像和视频将在此处显示。" "尚未上传任何媒体" - "媒体和文件" + "媒体与文件" "文件格式" "文件名" "没有更多文件可显示了" "没有更多媒体可显示了" + "文件信息" "上传者:" "上传于" diff --git a/libraries/permissions/api/src/main/res/values-zh/translations.xml b/libraries/permissions/api/src/main/res/values-zh/translations.xml index eb093046a3..a071113a1f 100644 --- a/libraries/permissions/api/src/main/res/values-zh/translations.xml +++ b/libraries/permissions/api/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ - "为了让应用程序使用相机,请在系统设置中授予权限。" + "为了让 app 使用相机,请在系统设置中授予权限。" "请在系统设置中授予权限。" - "为了让应用程序使用麦克风,请在系统设置中授予权限。" - "为了让应用程序显示通知,请在系统设置中授予权限。" + "为了让 app 使用麦克风,请在系统设置中授予权限。" + "为了让 app 显示通知,请在系统设置中授予权限。" diff --git a/libraries/push/impl/src/main/res/values-zh/translations.xml b/libraries/push/impl/src/main/res/values-zh/translations.xml index 7e59c317c3..21988770c0 100644 --- a/libraries/push/impl/src/main/res/values-zh/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh/translations.xml @@ -1,74 +1,74 @@ "通话" - "监听事件" + "正在监听事件" "嘈杂通知" - "来电振铃" + "响铃通话" "静默通知" - "%1$s:%2$d 条消息" + "%1$s:%2$d 个消息" - "%d 条通知" + "%d 个通知" - "统一推送通知分发器注册失败,您将无法再接收通知。请检查应用的通知设置及推送分发器的状态。" - "您有新消息。" + "UnifiedPush 分发器注册失败,你将无法再接收通知。请检查 app 的通知设置及推送分发器的状态。" + "你有新消息。" - "您有 %d 条新消息。" + "你有 %d 条新消息。" "📞 来电" "📹 来电" - "** 无法发送——请打开聊天室" + "** 无法发送——请打开房间" "加入" "拒绝" "%d 个邀请" - "邀请您聊天" - "%1$s 邀您聊天" + "已邀请你聊天" + "%1$s 已邀请你聊天" "提到了你:%1$s" "新消息" - "%d 条新消息" + "%d 个新消息" - "使用 %1$s 回应" - "标记为已读" + "已使用 %1$s 反应" + "设为已读" "快速回复" - "邀请你加入聊天室" - "%1$s 邀请您加入房间" + "邀请你加入房间" + "%1$s 已邀请你加入房间" "我" - "%1$s提及或回复" - "已邀请您加入该空间" - "%1$s 邀请您加入该空间" - "您正在查看通知!点击我!" - "线程 %1$s" + "%1$s 个提及或回复" + "已邀请你加入空间" + "%1$s 邀请你加入空间" + "你正在查看通知!点击我!" + "位于 %1$s 中的消息列" "%1$s:%2$s" "%1$s: %2$s %3$s" - "%d 条未读消息" + "%d 个未读消息" "%1$s 和 %2$s" "%2$s 中的 %1$s" "在 %2$s 和 %3$s 中的 %1$s" - "%d 个聊天室" + "%d 个房间" "后台同步" - "谷歌服务" + "Google 服务" "找不到有效的 Google Play 服务。通知可能无法正常工作。" - "检查被阻止的用户" + "检查被屏蔽的用户" "查看被屏蔽的用户" "未屏蔽任何用户。" - "您已屏蔽 %1$d 位用户。您将不再收到这些用户的推送通知。" + "你已屏蔽 %1$d 位用户。将不再收到这些用户的通知。" "已屏蔽用户" "获取当前推送提供者的名称。" "未选择任何推送提供者。" - "当前推送提供商:%1$s和当前分销商:%2$s . 但经销商%3$s未找到。应用程序可能已被卸载?" - "当前推送提供商:%1$s ,但尚未配置分销商。" + "当前推送提供这:%1$s 及当前分发器:%2$s . 但未找到分发器 %3$s。该 app 可能已被卸载?" + "当前推送提供者:%1$s ,但尚未配置分发器。" "当前推送提供者:%1$s。" - "当前推送提供商:%1$s (%2$s )" + "当前推送提供者:%1$s(%2$s)" "当前推送提供者" "确保应用程序至少有一个推送提供者。" "未找到推送提供者。" diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-zh/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-zh/translations.xml index 2fac432ca8..3b9048a37f 100644 --- a/libraries/pushproviders/unifiedpush/src/main/res/values-zh/translations.xml +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-zh/translations.xml @@ -1,9 +1,9 @@ - "确保 UnifiedPush distributor 可用。" - "未找到推送 distributor。" + "确保 UnifiedPush 分发器可用。" + "未找到推送分发器。" - "找到 %1$d 个 distributors:%2$s" + "找到 %1$d 个分发器:%2$s" "检查 UnifiedPush" diff --git a/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml b/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml index 8db2b9c767..fdde227bef 100644 --- a/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml +++ b/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml @@ -20,7 +20,7 @@ "应用下划线格式" "切换全屏模式" "缩进" - "应用行内代码格式" + "应用内联代码格式" "设置链接" "切换编号列表" "打开撰写选项" diff --git a/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml index 2375580f2c..e451d82a9b 100644 --- a/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml +++ b/libraries/troubleshoot/impl/src/main/res/values-zh/translations.xml @@ -1,10 +1,10 @@ - "推送历史记录" + "推送历史" "运行测试" "再次运行测试" "一些测试失败了。请查看详情。" - "运行测试以检测您的配置中可能导致通知无法按预期运行的问题。" + "运行测试以检测配置中可能导致通知行为异常的问题。" "尝试修复" "所有测试均成功通过。" "排查通知问题" 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 57bb2427fc..4343f2980b 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -52,6 +52,7 @@ "Vyžaduje se časově omezená akce, na ověření máte jednu minutu" "Zobrazit heslo" "Zahájit hovor" + "Zahájit videohovor" "Zahájit hlasový hovor" "Místnost s náhrobkem" "Avatar uživatele" @@ -89,12 +90,15 @@ "Deaktivovat účet" "Odmítnout" "Odmítnout a zablokovat" + "Smazat" + "Smazat účet" "Odstranit hlasování" "Odznačit vše" "Zakázat" "Vyřadit" "Zavřít" "Hotovo" + "Stáhnout" "Upravit" "Upravit titulek" "Upravit hlasování" @@ -473,6 +477,14 @@ Opravdu chcete pokračovat?" "Možnosti" "Odstranit %1$s" "Nastavení" + "Nikdo nesdílí svou polohu" + "Sdílení aktuální polohy" + + "%1$d osoba" + "%1$d osoby" + "%1$d lidí" + + "Na mapě" "Výběr média se nezdařil, zkuste to prosím znovu." "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" @@ -498,6 +510,7 @@ Opravdu chcete pokračovat?" "Zpráva v %1$s" "Rozbalit" "Zmenšit" + "Sdílení aktuální polohy" "Již si prohlížíte tuto místnost!" "%1$s z %2$s" "%1$s Připnuté zprávy" 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 bc109f5ff7..08791b1b38 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -88,6 +88,8 @@ "Désactiver le compte" "Refuser" "Refuser et bloquer" + "Supprimer" + "Supprimer le compte" "Supprimer le sondage" "Tout désélectionner" "Désactiver" 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 8d0345e0e0..ae5592d3f6 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -86,6 +86,8 @@ "アカウントを無効化" "拒否" "拒否してブロック" + "削除" + "アカウントを削除" "投票を削除" "全ての選択を解除" "無効化" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index 652a285961..f47d43b47e 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -306,7 +306,7 @@ Motiv:%1$s." "Editor text avansat" "Cameră" "Numele camerei" - "de exemplu, numele proiectului dvs." + "de exemplu, numele proiectului dumneavoastră" "%1$d Camera" "%1$d Camere" @@ -332,7 +332,7 @@ Motiv:%1$s." "Partajați spațiul" "Locație partajată" "Spațiu comun" - "Deconectare în curs" + "Eliminare în curs" "Ceva nu a mers bine" "Am întâmpinat o problemă. Vă rugăm să încercați din nou." "Spațiu" @@ -356,7 +356,7 @@ Motiv:%1$s." "Nu s-a putut decripta" "Trimis de pe un dispozitiv nesigur" "Nu aveți acces la acest mesaj" - "Identitatea verificată a expeditorului a fost resetată" + "Identitatea digitala verificată a expeditorului a fost resetată" "Nu am putut trimite invitații unuia sau mai multor utilizatori." "Nu s-a putut trimite invitația (invitațiile)" "Deblocare" @@ -383,8 +383,8 @@ Motiv:%1$s." "Mesaj în așteptare" "Dumneavoastră" "Această cameră a fost configurată astfel încât noii membri să poată citi istoricul. %1$s" - "Identitatea lui %1$s a fost resetată. %2$s" - "Identitatea %2$s a lui %1$s a fost resetată. %3$s" + "Identitatea digitala lui %1$s a fost resetată. %2$s" + "Identitatea digitala %2$s a lui %1$s a fost resetată. %3$s" "(%1$s)" "Identitatea lui %1$s a fost resetată." "Identitatea %2$s a lui %1$s a fost resetată. %3$s" @@ -445,11 +445,11 @@ Sunteți sigur că doriți să continuați?" "%1$d Mesaje fixate" "Mesaje fixate" - "Urmează să accesați contul dvs. %1$s pentru a vă reseta identitatea. După aceea, veți fi redirecționat către aplicație." - "Nu puteți confirma? Accesați contul dvs. pentru a vă reseta identitatea." + "Urmează să accesați contul dvs. %1$s pentru a vă reseta identitatea digitală. După aceea, veți fi redirecționat către aplicație." + "Nu puteți confirma? Accesați contul dumneavoastră pentru a vă reseta identitatea digitală." "Retrageți verificarea și trimiteți" "Puteți să vă retrageți verificarea și să trimiteți acest mesaj oricum, sau puteți anula pentru moment și să încercați din nou mai târziu după reverificarea lui %1$s." - "Mesajul dumneavoastră nu a fost trimis deoarece identitatea verificată a lui %1$s s-a schimbat" + "Mesajul dumneavoastră nu a fost trimis deoarece identitatea digitala verificată a lui %1$s s-a schimbat" "Trimiteți mesajul oricum" "%1$s utilizează unul sau mai multe dispozitive neverificate. Puteți trimite mesajul oricum sau puteți anula pentru moment și puteți încerca din nou mai târziu, după ce %2$s își va verifica toate dispozitivele." "Mesajul dvs. nu a fost trimis deoarece %1$s nu si-a verificat toate dispozitivele" @@ -472,12 +472,12 @@ Sunteți sigur că doriți să continuați?" "Deschideți în Apple Maps" "Deschideți în Google Maps" "Deschideți în OpenStreetMap" - "Distribuiți această locație" + "Partajați locația selectată" "Spații pe care le-ați creat sau la care v-ați alăturat." "%1$s • %2$s" "Spațiu %1$s" "Spații" - "Mesajul nu a fost trimis deoarece identitatea verificată a lui %1$s s-a schimbat." + "Mesajul nu a fost trimis deoarece identitatea digitala verificată a lui %1$s s-a schimbat." "Mesajul nu a fost trimis deoarece %1$s nu a verificat toate dispozitivele." "Mesajul nu a fost trimis deoarece nu ați verificat unul sau mai multe dispozitive." "Locație" 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 15e9fd6bea..7bd218ca54 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -1,6 +1,6 @@ - "添加表情符号:%1$s" + "添加反应:%1$s" "地址" "头像" "最小化消息文本框" @@ -32,8 +32,8 @@ "投票" "投票已结束" "二维码" - "使用 %1$s 回应" - "使用其他表情符号回应" + "使用 %1$s 反应" + "使用其它 Emoji 做出反应" "%1$s 和 %2$s 已读" "%1$s 及其他 %2$d 人已读" @@ -41,16 +41,16 @@ "%1$s 已读" "点击以显示全部" "撤回反应 %1$s" - "移除表情符号%1$s" + "移除反应:%1$s" "房间头像" "发送文件" "发送方位置" - "限时操作,您有一分钟的时间来验证" + "请求的操作有时间限制,你有 1 分钟的时间来验证" "显示密码" "开始通话" "开始视频通话" - "发起语音通话" - "已封存的聊天室" + "开始语音通话" + "已封存的房间" "用户头像" "用户菜单" "查看头像" @@ -58,13 +58,13 @@ "语音消息,时长:%1$s" "录制语音消息" "停止录制" - "您的头像" + "你的头像" "接受" "添加标题" - "添加现有聊天室" + "添加现有房间" "添加到时间线" "返回" - "呼叫" + "通话" "取消" "暂时取消" "选择照片" @@ -80,18 +80,21 @@ "复制消息链接" "复制文本" "创建" - "创建聊天室" + "创建房间" "创建空间" "停用" "停用账户" "拒绝" "拒绝并屏蔽" + "删除" + "删除账户" "删除投票" "取消全选" "禁用" "丢弃" "关闭" "完成" + "下载" "编辑" "编辑标题" "编辑投票" @@ -115,26 +118,26 @@ "了解更多" "离开" "离开聊天" - "离开聊天室" + "离开房间" "离开空间" "载入更多" "管理账户" "管理账户与设备" "管理设备" - "管理聊天室" + "管理房间" "发送消息给" "最小化" "下一步" "否" - "以后再说" + "暂不" "确定" "打开上下文菜单" - "打开设置" - "用其他方式打开" + "设置" + "使用其它方式打开" "置顶" "快速回复" "引用" - "回应" + "反应" "拒绝" "移除" "删除标题" @@ -174,39 +177,41 @@ "拍摄照片" "点按查看选项" "翻译" - "再试一次" + "重试" "取消置顶" "查看" - "在时间轴中查看" + "在时间线上查看" "查看源码" "是" - "是的,再试一次" - "您的服务器现在支持更快的新协议。现在登出并重新登录以进行升级。现在这样做可以帮助您避免在以后删除旧协议时被强制登出。" + "是,重试" + "你的服务器现在支持更快的新协议。现在注销并重新登录以升级。立即这样做可以避免你在以后删除旧协议时被强制注销。" "有可用升级" "关于" "可接受的使用政策" "添加账户" - "添加另一个账户" + "添加账户" "添加标题" "高级设置" "一张图片" "分析" "正在同步通知…" - "你离开了聊天室" - "您已退出会话" + "你离开了房间" + "你已注销会话" "外观" "音频" - "测试版" + "Beta" "已屏蔽用户" "气泡" + "来电被拒接" "通话已开始" + "你已拒接来电" "聊天记录备份" "已复制到剪贴板" "版权" - "正在创建聊天室…" - "正在创建空间……" + "正在创建房间…" + "正在创建空间…" "请求已取消" - "离开聊天室" + "离开房间" "离开空间" "邀请已拒绝" "深色" @@ -219,12 +224,13 @@ "下载失败" "正在下载" "(已编辑)" - "编辑中" + "正在编辑" "编辑标题" "* %1$s %2$s" "空文件" "加密" "已启用加密" + "于 %1$s 结束" "输入 PIN 码" "错误" "发生错误,可能无法收到新消息通知。请在设置中对通知进行故障排除。 @@ -232,7 +238,7 @@ 原因:%1$s。" "所有人" "失败" - "收藏" + "收藏夹" "已收藏" "文件" "文件已删除" @@ -245,7 +251,7 @@ "回复 %1$s" "安装 APK" "找不到此 Matrix ID,因此可能无法收到邀请。" - "正在离开聊天室" + "正在离开房间" "正在离开空间" "浅色" "链接已复制到剪贴板" @@ -254,12 +260,12 @@ "实时位置" "实时位置已结束" "正在加载…" - "正在加载更多……" + "正在加载更多…" "其他 %d 人" - "%1$d个成员" + "%1$d 个成员" "消息" "消息操作" @@ -271,20 +277,20 @@ "名称" "%1$s (%2$s)" "没有结果" - "无聊天室名" + "无房间名称" "未命名空间" "未加密" "离线" "开源许可证" "或" - "其他选项" + "其它选项" "密码" "用户" - "固定链接" + "永久链接" "权限" "已置顶" "请检查 Internet 连接" - "请稍候……" + "请稍候…" "确定要结束这个投票吗?" "投票:%1$s" "总票数:%1$s" @@ -295,13 +301,13 @@ "正在准备…" "隐私政策" "私密" - "私有聊天室" + "私有房间" "私有空间" "公共" - "公共聊天室" - "公开空间" - "回应" - "回应" + "公共房间" + "公共空间" + "反应" + "反应" "理由" "恢复密钥" "正在刷新…" @@ -310,16 +316,16 @@ "%1$d 个回复" "正在回复 %1$s" - "报告错误" + "报告 bug" "报告问题" "报告已提交" "富文本编辑器" "角色" - "聊天室" - "聊天室名称" - "例如:您的项目名称" + "房间" + "房间名称" + "例如:你的项目名称" - "%1$d 房间" + "%1$d 个房间" "保存的更改" "正在保存" @@ -330,7 +336,7 @@ "已读" "选择账户" - "%1$d 已选中" + "已选中 %1$d 个" "发送至" "正在发送…" @@ -342,10 +348,10 @@ "服务器 URL" "设置" "共享空间" - "新成员可见历史记录" + "新成员可以看到历史" "共享实时位置" "共享位置" - "共享空间" + "已共享的空间" "正在移除设备" "发生了一些错误" "我们遇到了一个问题。请重试。" @@ -353,12 +359,12 @@ "空间成员" "该空间的主题是什么?" - "%1$d 空间" + "%1$d 个空间" "开始聊天…" "贴纸" "成功" - "推荐" + "建议" "建议" "正在同步" "系统" @@ -367,7 +373,7 @@ "消息列" "消息列" "主题" - "该聊天室的主题是什么?" + "该房间的主题是什么?" "无法解密" "从不安全的设备发送" "无权访问此消息" @@ -376,7 +382,7 @@ "无法发送邀请" "解锁" "解除静音" - "不支持的呼叫" + "不受支持的通话" "不支持的事件" "用户名" "验证已取消" @@ -394,14 +400,14 @@ "标准质量" "质量与上传速度的平衡" "语音消息" - "等待…" - "正在等待解密密钥" + "正在等待…" + "正在等待此消息" "正在等待实时位置…" - "任何人都可查看历史记录" - "您" - "%1$s (%2$s) 由于您当时不在聊天室内,系统已将消息共享给您。" - "%1$s 由于您当时不在聊天室内,系统已将此消息共享给您。" - "本聊天室已配置为允许新成员阅读历史记录。%1$s" + "任何人都可以看到历史" + "你" + "由于你当时不在房间内,%1$s(%2$s)已将消息向你共享。" + "由于你当时不在房间内,%1$s 已将消息向你共享。" + "此房间已配置为允许新成员阅读历史。%1$s" "%1$s的数字身份已重置。%2$s" "%1$s %2$s 的数字身份已重置。%3$s" "(%1$s)" @@ -413,7 +419,7 @@ 确定要继续吗?" "请再次确认链接" - "选择您上传的视频的默认质量。" + "选择你上传的视频的默认质量。" "视频上传质量" "允许的最大文件大小为:%1$s" "文件太大,无法上传" @@ -423,95 +429,99 @@ "错误" "成功" "警告" - "您有未保存的更改。" + "你有未保存的更改。" "更改尚未保存,确定要返回吗?" "保存更改?" "允许的最大文件大小为:%1$s" - "选择您要上传的视频的质量。" + "选择你要上传的视频的质量。" "选择视频上传质量" - "搜索表情符号" - "您已在此设备以%1$s 身份登录。" - "您的服务器需要升级,以支持 Matrix 鉴权服务和账户创建。" - "创建固定链接失败" + "搜索 Emoji" + "你已在此设备以 %1$s 的身份登录。" + "你的主服务器需要升级,以支持 Matrix 认证服务和账户创建。" + "永久链接创建失败" "%1$s 无法加载地图,请稍后再试。" "加载消息失败" - "%1$s 无法访问您的位置,请稍后再试。" + "%1$s 无法访问你的位置,请稍后再试。" "无法上传语音消息。" "该房间已不存在或邀请已失效。" "请开启 GPS 以使用基于位置的功能。" - "找不到消息" - "%1$s 没有权限访问您的位置。您可以在设置中启用位置权限。" - "%1$s 没有权限访问您的位置。在下方启用位置权限。" - "%1$s 没有权限访问您的麦克风。启用录制语音消息的权限。" + "未找到消息" + "%1$s 无权访问你的位置。你可以在“设置”中启用位置权限。" + "%1$s 无权访问你的位置。在下方启用访问权限。" + "%1$s 无权访问你的麦克风。启用访问权以录制语音消息。" "这可能是由于网络或服务器问题导致" "此房间地址已存在。请尝试编辑房间地址字段或更改房间名称" "不允许使用某些字符。仅支持字母、数字和以下符号 $ & ‘ ( ) * + / ; = ? @ [ ] - . _" - "某些信息尚未发送" + "某些消息尚未发送" "抱歉,发生了错误" - "🔐️ 加入我 %1$s" + "🔐️ 在 %1$s 中与我一起" "嗨!请通过 %1$s 与我联系:%2$s" "%1$s Android" - "摇一摇以报错" + "摇一摇以报告 bug" "屏幕截图" "%1$s:%2$s" "选项" - "移除%1$s" + "移除 %1$s" "设置" "目前无人分享其位置" "共享实时位置" + + "%1$d 个人" + "在地图上" "选择媒体失败,请重试。" "按下消息并选择 “%1$s” 将其包含在此处。" - "固定重要消息,以便轻松发现它们" + "置顶重要的消息以便于发现" - "%1$d 置顶消息" + "%1$d 个已置顶的消息" - "置顶消息" - "您将要转到您的%1$s帐户来重置您的数字身份。之后,您将被带回该应用。" - "无法确认?请前往您的帐户重置您的数字身份。" + "已置顶的消息" + "你即将被重定向到你在 %1$s 上的账户以重置数字身份。之后将被带回 app。" + "无法确认?请转到你的账户重置数字身份。" "撤回验证并发送" - "您可以撤回验证并仍然发送此消息;也可以暂时取消验证,在重新验证 %1$s 后重试。" - "您的消息未发送,因为%1$s的已验证数字身份已被重置" + "你可以撤回验证并照常发送此消息,也可以暂时取消验证,并于重新验证 %1$s 后重试。" + "你的消息未能发送,因为 %1$s 的已验证数字身份已被重置" "仍然发送消息" - "%1$s 正在使用一个或多个未经验证的设备。您还是可以继续发送信息;也可以暂时取消,等 %2$s 验证了所有设备后重试。" - "您的消息未发送,因为%1$s尚未验证所有设备" - "您有未验证的设备。您仍然可以发送消息;也可以暂时取消,并在验证所有设备后稍后重试。" - "您的消息未发送,因为您有尚未验证的设备。" + "%1$s 正在使用至少 1 个未经验证的设备。你可以照常发送消息,也可以暂时取消,直到 %2$s 验证所有设备后重试。" + "你的消息未能发送,因为 %1$s 尚未验证所有设备" + "你有至少 1 个未经验证的设备。你可以照常发送消息,也可以暂时取消,并在验证所有设备后重试。" + "你的消息未能发送,因为你有尚未验证的设备。" "编辑管理员或所有者" "处理要上传的媒体失败,请重试。" "无法获取用户信息" "%1$s 中的消息" "展开" "折叠" - "已经在此房间了!" + "共享实时位置" + "已经位于此房间!" "%1$s / %2$s" "置顶消息 %1$s" "正在加载消息…" "查看全部" "聊天" - "分享位置" - "分享我的位置" + "共享位置" + "共享我的位置" "在 Apple Maps 中打开" "在 Google Maps 中打开" "在 OpenStreetMap 中打开" "分享选定的位置" "共享选项" - "您创建或加入的空间。" + "你创建或加入的空间。" "%1$s • %2$s" - "创建空间以组织聊天室" - "%1$s空间" + "创建空间以组织房间" + "空间 %1$s" "空间" "共享于%1$s" "在地图上" "消息未发送,因为%1$s的已验证数字身份已被重置。" - "消息未发送,因为%1$s尚未验证所有设备。" - "消息未发送,因为您有尚未验证的设备。" + "消息未能发送,因为 %1$s 尚未验证所有设备。" + "消息未能发送,因为你有尚未验证的设备。" "位置" "版本:%1$s (%2$s)" "zh-Hans" "历史消息在此设备上不可用" - "您需要验证此设备才能访问历史消息" + "你需要验证此设备才能访问历史消息" "无权访问此消息" "无法解密消息" - "此消息已被阻止,因为您未验证您的设备,或者发件人需要验证您的身份。" + "此消息已被阻止,因为你未验证你的设备,或发送者需要验证你的数字身份。" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 28b28e814a..9db9bb4751 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -14,6 +14,7 @@ "Encryption details" "Expand message text field" "Hide password" + "Info" "Join call" "Jump to bottom" "Move the map to my location" @@ -48,6 +49,7 @@ "Send files" "Sender location" "Time limited action required, you have one minute to verify" + "Settings, action required" "Show password" "Start a call" "Start a video call" @@ -204,7 +206,9 @@ "Beta" "Blocked users" "Bubbles" + "Call declined" "Call started" + "You declined a call" "Chat backup" "Copied to clipboard" "Copyright" diff --git a/screenshots/de/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_de.png b/screenshots/de/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_de.png new file mode 100644 index 0000000000..08a29ff28c --- /dev/null +++ b/screenshots/de/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae20cc867db5b7163b12ed8afd841a704673d6539ea543b573dd0f7c560988c7 +size 59775 diff --git a/screenshots/de/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_de.png b/screenshots/de/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_de.png deleted file mode 100644 index 4bedce8ba9..0000000000 --- a/screenshots/de/features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:869749d64cb3836b99a132685a2411b56c3d93c6db1e2adddf669cf75ab90187 -size 68410 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png index f2b02ca79e..c975946b3d 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03d7fd58010b5eb1bdefef76648e08431728f51527815db9df58ee0010f871da -size 34304 +oid sha256:ad7189cbb855280fd2e12a5dc43d0062918f76ddcc4b5cc7677748cf08a4afa9 +size 34478 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png index cf7fd18f5d..adfa2c9666 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bce8b45b24c38b3a991dffd06d1b2f79da728820ab93f649138ae071883aff60 -size 36269 +oid sha256:17acafce434f31f50b3232c2bebcd3bb828c70031cb892d7f5a78704f5d58661 +size 36455 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png index 38a62af758..ae6d2b8bd1 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:241dd64dd76b17b3a024622963c809f8788e0c5ef5f841b9be500942e4618076 -size 45660 +oid sha256:f063ef08eaf607de6d7d7361046ac96f8932d232b1f5cc48125cc2ac04d30531 +size 45836 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png index 5b6e58f735..777af38fbf 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24ce85ea23acfd4d062785c013f5b1faa96d6ab75c1bab242bf03b6e6e330b78 -size 46572 +oid sha256:5f30f5d0f8e410f3addc64cd5fa7fbed8505bcd562a75de06cbf3a1e7a40ceb0 +size 46745 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png index 100e2139d3..16cf139fa9 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e36b034ca57ca657072a089fcb7f7cccd2a5ec9897f80077bba29f85f2dcc96c -size 48069 +oid sha256:3ce82d48e8b0b0c78a978277886a9916775cc12fc28edeb2807f63afb879c6a5 +size 48236 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png index 38a62af758..ae6d2b8bd1 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:241dd64dd76b17b3a024622963c809f8788e0c5ef5f841b9be500942e4618076 -size 45660 +oid sha256:f063ef08eaf607de6d7d7361046ac96f8932d232b1f5cc48125cc2ac04d30531 +size 45836 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png index 2e87baac06..0fb00157c3 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b1b8c43a078f16dd5424960c63bc42524ce73d5198834b5291f9bd874ee7b0a -size 46711 +oid sha256:6c844dd51824db5a123a2b7e564a001b3609245259ec25c601a181eb69362098 +size 46863 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png index 5f28babc08..8843434a9f 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d25872cb05d6d9b0cca7c579f67e531a059251ed033b3fa10a8969d161c9b050 -size 39859 +oid sha256:e31bebf55244a497eaf3442701b0db8b5ee6c061944c1b4e72da487660104643 +size 40044 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png index 81083ef1a9..371a8aca55 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2659371297c436c5aea18011221c081ec94299ba6a5643f5fda0214372b3096 -size 41515 +oid sha256:e3b6ee300dc038fbea819d19286d10bdf023872abda1bbe6d81b4fef97a2d934 +size 41341 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png index 9ba16e11d1..62ffd0f03e 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1845ce37a3c2cc763b745caeb6cfbc094b6bd65a3c8234dc8173a13c5377e038 -size 35299 +oid sha256:d550d37eb3a14779dd33171843339729cf3457f9a2a6e9d41d89b6c9f52f2f0f +size 35489 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png index 7538d489f0..9a45949a2f 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abcd7267209f3ca0881cfbe3c9457f024d4368a1c8fc6bba8a00ab89e95ffac0 -size 37563 +oid sha256:68ab96769960de6cc00a06b2ca59cbf4ad20e9788c9fcf09b4ddb126104359f7 +size 37773 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png index 0608a5a46e..fe057074c4 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:099f4b603ee07216e66a75d5d08b8f17084648526ac14e4e611c7c090260b8fc -size 47304 +oid sha256:e8583c1a707b3784dc2daf279628d86d813046743f77568aa1acb0361ce7cb4e +size 47505 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png index 62300fdbf1..fc4b29fedf 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc0b352e7c81e7e6389985c4c29d1a7074bd733e56789f3f675bbecd6ff17be7 -size 48289 +oid sha256:9016458c07e6c5e8fd962fe1ef08d0da82572c867304fb3ff4f694f83c40f36c +size 48497 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png index fc8a1452d4..62222688ca 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:800381effd5dcdd3f41d28defd29cb21c99d254de86a91c1e7f60f476a4e393c -size 49863 +oid sha256:0ba0af2f22cd932c626df190f2139f11906934b4d5de16cc1fde9d35488552ab +size 50028 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png index 0608a5a46e..fe057074c4 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:099f4b603ee07216e66a75d5d08b8f17084648526ac14e4e611c7c090260b8fc -size 47304 +oid sha256:e8583c1a707b3784dc2daf279628d86d813046743f77568aa1acb0361ce7cb4e +size 47505 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png index b47aaf7358..5a68c04ad0 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79db769c4c524aa2831ddf2e714102c0f1a5de1a7855025e67598c8f261e65da -size 48388 +oid sha256:ab9a5bc72358625c7623b3156365c299eaec576e96d11ecc3946e92511815509 +size 48578 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png index 84c90cefef..4e4cdee57b 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:631556267b57adf739438e7a9c094c411273de3d74113216064268926499d292 -size 41188 +oid sha256:9ce67e2cd809b3ba7f32c57cf87208e71a92df71b545bea2554ed7f6d28e78e7 +size 41381 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png index 13ddf126ee..11f94e5f15 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8c0999d16e140465ab18fff34650ac850cf650316f52b4a3dd9145e6f928d04 -size 43107 +oid sha256:d35a6a56027b453b845400ec2b5b5912eb5eff551b2c370a26110b584ed3d3a3 +size 42939 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png index 062623eb08..fdbc13a1ee 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c629821f33feb647b508b7f6bea584f807bd0e46162784d1ac764f97b050e9c5 -size 36461 +oid sha256:b62cf320453eb36be6e486e3100c3be1420fcdfd068f2276d27a824fb84e3f05 +size 42064 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png index afc83cfdd2..ddbdfb051f 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:003c99b1a807edd7a143bb5329d544a1519bfea1efbcd29c275d9b1bd0031a6f -size 29954 +oid sha256:88633b6deed6e44e354cf3c8ac9e8553f0dd41743198cf5d8ff57de51ecd45e4 +size 35217 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png index dae5be9d78..0dafa02950 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04a3913f1c1e74f6a78706dac9e1aa33e2520bd9c37857bf58a7e5a58f12ec17 -size 42559 +oid sha256:0887222f914448055346fd314b3a8bfdaeda5262b76f509749ec01877728a821 +size 48344 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png index 2da29be9b1..8051720f82 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06df3ed8524a4ff0d1ea12c43b624dd4f977ac591632d6062dc116aab53111fd -size 36195 +oid sha256:3c355fb7f9e899e9cc7fe9a4a0aefacb7f57e669b60927b9c77f29630a6168b0 +size 41774 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png index 61fb494655..40197c311f 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2e33198cfde05a0f48bded09ad60108993678ce6a84da6394cb0cca4df66edd -size 26295 +oid sha256:6085e75ee0b5669b078b7ff40c6f9e91f04263967a46076dda95802992224318 +size 31603 diff --git a/screenshots/de/features.home.impl.components_RoomListContentView_Day_4_de.png b/screenshots/de/features.home.impl.components_RoomListContentView_Day_4_de.png index 114c133d28..eecc5692c4 100644 --- a/screenshots/de/features.home.impl.components_RoomListContentView_Day_4_de.png +++ b/screenshots/de/features.home.impl.components_RoomListContentView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2574ac92d1424f5224beab9ac060d731a763cdc95a4550f07fb22bd4bd393105 -size 55716 +oid sha256:3d80e64f2206d9d21b3467ea4a7d5b06a33391cd56b5d899f944e7bd501b1743 +size 64430 diff --git a/screenshots/de/features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png b/screenshots/de/features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png index 5e1b3d5040..34f49e1141 100644 --- a/screenshots/de/features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png +++ b/screenshots/de/features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea704578dfaea8ab3a4dd6eb42e45b40e4037819fe83586947136252a39855f2 -size 38819 +oid sha256:a8bb68b889c934425bb53b0b923ddd86c5a6e9309dfb7d06505b986521ab75e7 +size 52580 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png index e7b089068f..e37cdbea74 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e46c26ec7af7c4d1c1bafc0fb8bda6ef4afe7dcc6ceb8a5a38f2872ccafbc6d0 -size 86687 +oid sha256:8d2644ac4e57a29d145c34f7752496e5985430760ef2f519f78588afcc2fbc70 +size 85745 diff --git a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png index 0d394678ce..5bfa67b2fd 100644 --- a/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png +++ b/screenshots/de/features.home.impl.spaces_HomeSpacesView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c50c374b59c957f4e007d9548c2e03ffb622fcba3de9bb0adb2e36336114263b -size 39053 +oid sha256:27e1b519904b26e0164f1bebd1dc1c28abe2f4352d107f07d66db7ed9dd59e52 +size 38165 diff --git a/screenshots/de/features.home.impl_HomeView_Day_13_de.png b/screenshots/de/features.home.impl_HomeView_Day_13_de.png index 1f5c8972bc..ae22fbde6b 100644 --- a/screenshots/de/features.home.impl_HomeView_Day_13_de.png +++ b/screenshots/de/features.home.impl_HomeView_Day_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3f9c61cbe5f80b7574765bfcc6a1bef06b434d35666ee4fa2b0ba6f09078352 -size 97503 +oid sha256:ba73b9e725eed082239a57c1233bb05e69a0a44dddaa64a4cc2b4a8e83130dfc +size 99560 diff --git a/screenshots/de/features.home.impl_HomeView_Day_4_de.png b/screenshots/de/features.home.impl_HomeView_Day_4_de.png index 40500e7b72..f5b92f61d9 100644 --- a/screenshots/de/features.home.impl_HomeView_Day_4_de.png +++ b/screenshots/de/features.home.impl_HomeView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55944dde4104ac2de65a11ab041d813416a21aae25e4cc21b9f624a2d33a80c0 -size 58447 +oid sha256:c54f63ff4b9621dc8e34179f15033a4ff6d61dd7cb22b47e56b5e2b9fda113d4 +size 57802 diff --git a/screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_10_de.png b/screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_10_de.png new file mode 100644 index 0000000000..821bf59326 --- /dev/null +++ b/screenshots/de/features.invitepeople.impl_InvitePeopleView_Day_10_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:569ac37ef5a1a15b294d70e0aba93dd2c4a8f8e2c23cc043e82759ab06ce14a6 +size 54965 diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png index 950394d6ef..cab79d8a48 100644 --- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png +++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9b94629caba74d3fa8f9d939edc441b687c6496001b185c6b7dc4ba13a197d4 -size 41978 +oid sha256:57454100c496cbf21eeb0dd858678a4e8c793d6d3ea8de908dd0878821046efa +size 41785 diff --git a/screenshots/de/features.location.api.internal_StaticMapPlaceholder_Day_0_de.png b/screenshots/de/features.location.api.internal_StaticMapPlaceholder_Day_0_de.png index f122f99f74..a9ddf2b614 100644 --- a/screenshots/de/features.location.api.internal_StaticMapPlaceholder_Day_0_de.png +++ b/screenshots/de/features.location.api.internal_StaticMapPlaceholder_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:212f8d1b300b7c1a4e4c3087018e81261b562fea9cf1fc1f2ef4a5443e3fc91d -size 440154 +oid sha256:5ac712ad4762c520a1e10cd11f65e112ce0d09d6cdaffbe99ef00a03748991dc +size 295885 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png index 7967b79a1c..bf8a621fe1 100644 --- a/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f148e3b2e061cc9cc1e3a6568f4452175b51341a2c317aed2c52a355351cdff -size 42513 +oid sha256:6a5606179cc7dacc1d0bc86ff0f38a7654cebeb7c428575e2da51d4af0ba12b9 +size 43384 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png index d4d8b13367..d52980f113 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c27b436e8284ef32e2d4fe1285587f1580b4139b6e098d9e37e976c98f595057 -size 19318 +oid sha256:1e8cb1edecba35913251d57d6eaa9d48149f7b2a26c180978c0ae34d3d354d97 +size 19693 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png index 61d38bcadf..7793479410 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0e8730caeac7c344ae3d7c605aa944a6b8d021b5f3b8cfd387cf9cc2814c6c9 -size 40339 +oid sha256:5f66385d2afa0a3a4c68418c58b65bb9f073512842d6b601ac9ba7170a70f3d7 +size 20266 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png index f3502aceac..cf15f3c0ff 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b70b5cc45b554c282a435f59d5311483569ad6be9875f25a1b88e1c9119b264 -size 36812 +oid sha256:a93c8f459e118b5e97802055c076a31c260a8d1b9b863dec4464d79b5ece62db +size 16650 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png index d1aa86b7c6..03f56a96b1 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:016809a14091abf8554648ea4cd45945541395772c540d8aa8b04a24c0190050 -size 32120 +oid sha256:534b3512dd38f27f313bbd8655667f3ecc104c5095e140f63b2e124277886d07 +size 40599 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png index d4d8b13367..3b8f513f0b 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c27b436e8284ef32e2d4fe1285587f1580b4139b6e098d9e37e976c98f595057 -size 19318 +oid sha256:af69b59202b1e21069e13e444017d8e25ec467d8cbe5899448d74700dc1a765d +size 37091 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png index a0d42acd55..8cf129ffae 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10244806518a4f64985be17fa5814d1523ef8796398a02632d48bcdf2d9daf53 -size 19451 +oid sha256:2ad009477e6df04362db43d17c2a43599ae19812ef4244b0ffdd436e18662969 +size 32383 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png new file mode 100644 index 0000000000..d52980f113 --- /dev/null +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e8cb1edecba35913251d57d6eaa9d48149f7b2a26c180978c0ae34d3d354d97 +size 19693 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png new file mode 100644 index 0000000000..0c68797fef --- /dev/null +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fe56f20ce5792f9dd60bf0ae08fa5c5c78fbb7a5f1a80eb2fe973716be69c00 +size 19831 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_de.png index d9b37fcbb6..1378a04aa5 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e9040a7720257db29bcc71a9466bfe081c832878f88baf52bdbbed390505a1b -size 37170 +oid sha256:8ace865ac209e2dee5944ea526d1fd8337236ae81c43f90635dbd9b2db905780 +size 38535 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_de.png index 48c92bc715..5294d06956 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1adfeeb7e91aae96124e3062f20c029df73cef9e68bee2149155e1aa0fb7dfa7 -size 33956 +oid sha256:dc388c605c1c09710b6e979aa2ec6110964c9ef3020b7e8c3e7bfaf839a48133 +size 35383 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_de.png index b33b0c2150..36c7aca115 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d9f3c98a0e112c49b365f20fb5c4403b6c2073f62072c457f5e7df9e4c979c3 -size 23555 +oid sha256:e3cf2430c703ec8c38d0fa11bd486f8aa960822246338ada3e0bc4fa2c846b7d +size 24074 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_3_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_3_de.png index 13ba4da40c..d78926b966 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_3_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:059452488e08fcb9f35afe0db8805665417108ed0593561251f648b91eb7c3ff -size 43688 +oid sha256:cb3267c007e01c5e691841911e4aa7bcfe319077a6b4f49d945e9bacc5474087 +size 45041 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_5_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_5_de.png index 6297eded9b..4502875e08 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_5_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b3ed6ddd42ca136fdb7ad0f18d03e112594c0d9de93264bc2659e1b3a4e1e75 -size 40614 +oid sha256:71f8a9d484a4056507b129f7fb390b2c67c99ec46a928da15caac4f95ffbd6fd +size 42006 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_6_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_6_de.png index ded859b551..014fdcd4b7 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_6_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b6828f3878d95a0357b399072acce35b073767fdbbfea90fe9eca73f60af802 -size 31600 +oid sha256:2c2e7d3a0b31388c8f373920e71ca23228fd5961a1705b3032b1407f35dc2e28 +size 31051 diff --git a/screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_de.png b/screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_de.png new file mode 100644 index 0000000000..6c4b3efc05 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54dd4604f24579447336a906c9cad8b7f0d27f2b30770a136709d2ea964a8ecb +size 78928 diff --git a/screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_de.png b/screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_de.png new file mode 100644 index 0000000000..68e2995e17 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7209ac29981ac25c206497fee6acacdf6fb8cbb1d0592b57ad343aa2bc8e4bbe +size 75196 diff --git a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_de.png b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_de.png index fc2a26b90e..7cd0b44e91 100644 --- a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_de.png +++ b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88d4448dbf7fad8cf6ec5075babdf09b5f46401a259a6ef3f9b380a4a3de0240 -size 38712 +oid sha256:ac1d614f172213fb336f22ae114bbadc0560824276ecc6fb97904eaee2b1f0c3 +size 38783 diff --git a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png index 77a79c8e8f..3fdbf2fe1c 100644 --- a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png +++ b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06d30166f29f5335460e6cbaabc81d7cdf38b7043b1767f51976386fe2e35347 -size 39568 +oid sha256:f96859710af78fb5578821e553eae9c1b5111c35535d6ea2920b59ff63b573eb +size 39638 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_8_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_8_de.png new file mode 100644 index 0000000000..0157c6d961 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d508cdc9742a8a2ff545599b106c0a57c84987d11940a03d416a69ff957aea4a +size 315614 diff --git a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_1_de.png b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_1_de.png index cce900f9c8..f284b228db 100644 --- a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_1_de.png +++ b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea70291958f6daa69da86f4479eb3c1c5398a6dc23ee8eb935ee2bf29e938861 -size 19022 +oid sha256:a89135e74bc17ed75126152bc1430e46c066549b42022995e19eb2e834ec2702 +size 27232 diff --git a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_2_de.png b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_2_de.png index 7ff2a4608d..3d3ad6e858 100644 --- a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_2_de.png +++ b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d8127471c3c6f14883bec221a6ce637ccdf733582caef4497689a59462299cf -size 9489 +oid sha256:3cd4d7561202538ac0cea1953f038c397e355bd478b5a2eb2d59a3670c135938 +size 10949 diff --git a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png index de80fa70ba..51d3b483b4 100644 --- a/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png +++ b/screenshots/de/features.logout.impl.direct_DefaultDirectLogoutView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cabdd1c4ad7e6256c232e10950f0d7c23410af2a5e91cf729265da0af6af8672 -size 20656 +oid sha256:67e1b58ec1118afb4dc8985f22df74e103313db8239d4b3650cd9052a258645b +size 22445 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png index a6428f063d..38bcc092a9 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f7c52ed254e4c25516714274000fe41f00820cd2df2b8232628ce43cf5e95c4 -size 90825 +oid sha256:21e1cce3efb6c835a83b1a0c29dc1aadbcf6d5a4c2e839343f71fa30ea6dd0c4 +size 91151 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png index 55443656e3..4fe8b578bd 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea581062b4d0e6bf40089463632c4ed6dc3e5d1fa81667148f50e39a7763d76d -size 90544 +oid sha256:be7af996c56f6c75636688d88c70814dd7c93e3963255d6dc2e89fc8032a51c5 +size 90886 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png index d95fa85ab0..e22e792f54 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e49596da984aafededd2ffe2c850ca3bea516e56f55e4e72cd5cedfcf6b4c4ef -size 79081 +oid sha256:7901b1eb373bfac3fa7a9549c66c157b0d70cd885364646fa37e014056d0bcd8 +size 78805 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png index 64e7962bbb..c872795d91 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09fb626761ab736d5ea66e3883e215d0a1ec1a89155036eeed1775e9cdaf5ff1 -size 69761 +oid sha256:40745997037a4b3856628bc8d485c8131f4586e0f855513fdfe97b2470507bc4 +size 70087 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png index ecb40a0d36..198287f424 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45f01d0a582bdf3ecbf34bc6c6c32f29d1cf83a182e12e3df1b80da6574ff836 -size 61047 +oid sha256:3471dcaa2c715b6c3fb8c6b5223f1cb398af8d9b7ff013af11f4c6feef7d4615 +size 61333 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_0_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_0_de.png index 8da7ace03d..6483c00de2 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_0_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0acf2aa6b64219b503f168f51c61d89781ade323346a70df5fc55937f8573d25 -size 11407 +oid sha256:e9d61733ee67c899170d1aa57fec8e9b7b24c3f3b629cbcd48e2a16199f2bab3 +size 16988 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_10_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_10_de.png index a2fc5098f0..e689072a9b 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_10_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:398ba71b5da9adf840da5fede416b5faaa712809dffebcb4e878929ceb634256 -size 30936 +oid sha256:72d2376c919a9d0fabe5324ac08659d23968e35a28636b76ba06cb5a45b713c4 +size 33299 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_11_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_11_de.png index 70b7056d37..91e1a4ebbe 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_11_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f4f342e83f6d444c17c7c24b9371820c0e08352f649aa0b13a431fa70d8d8d4 -size 36160 +oid sha256:60070d82ca0753ca6d98e6ed84715a3dce70c7ccd8cb317e7504035e15c7347b +size 38499 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png index 894daf596a..ba6edcd46e 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f731b09dcfd8f2eff8958f2a294c9f8f969301c290d118fcb9446a7414652b9 -size 47022 +oid sha256:f86f77e8055c5d568e4f1e3bf1757a140fef5839eadd8f17731fc079a0c08bbf +size 58945 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_2_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_2_de.png index a4346a5c07..2d49c3747a 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_2_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:467e3b44603d9f9e62af61c2247224aa9fcb27ed0074da1884b94e7666a93bec -size 32548 +oid sha256:5691fc1410a02d9526f73ab0e619056761909d9b65284decc089f4477e0b2acc +size 34918 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png index 894daf596a..ba6edcd46e 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f731b09dcfd8f2eff8958f2a294c9f8f969301c290d118fcb9446a7414652b9 -size 47022 +oid sha256:f86f77e8055c5d568e4f1e3bf1757a140fef5839eadd8f17731fc079a0c08bbf +size 58945 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_4_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_4_de.png index 02b28888b1..57162dc8af 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_4_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eae66522bc3d44a9b54e5dc8c6abb9b2f18eded3f1ddccbb6cc3a167c4b4e53c -size 25861 +oid sha256:390cb6ad3a2918bf8a52641d6084829d8dc9ee518058765e04fa863e6a955b0b +size 38436 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_5_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_5_de.png index 2511e03e32..b9b5c516aa 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_5_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ab576bdeb5aa0dd38c748de53c1d7cc406d2ac857506483f04cd93acd51ba3a -size 17087 +oid sha256:e34bac390005bfaab9f3c173c693c05390725f1b59033515ca3558dd1b551566 +size 22457 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png index 650d435f5c..d80e6d6b42 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7fea817934002a4e7343199a281c2ce08e3b299e23efed82e4f1f68ab94f977 -size 27206 +oid sha256:366028bdd1b02cf2f83977e01b4c8b0344950b5943874a193238ca180773b534 +size 33522 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png index 49d605924a..7704df7d91 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a2b1dc530bc95a778be29a331fe765b80b79ecd3690afd58e296aa27f398279 -size 40887 +oid sha256:3a56b1ee1bde9ad25090371050081ce13c900d6d085c21b63abd858229fe482d +size 42706 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png index 958d6e6583..71073f21cd 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92f34785ad838bbadaa40c4ab3a602fc2644673f7df4ce320227558b57042ec1 -size 41545 +oid sha256:ed9b2497d9c154f8bad06b5f0405d193f21549d9a0b4a661becce745d7203002 +size 50459 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png index aa8d8cc60d..dccb62e40c 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d8075c75345069f27546f566c039bc4d5632dacdf220a63b38a64fe88507340 -size 39385 +oid sha256:50089edf349ad41016816bf861fb35237c2e4e4ba588846607ecdb100fa624dd +size 41703 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png index dff61b2c88..3d408f0ee2 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec1b6c85754dd2f0ba4b67a86ab8688df6c6471a53e508198b1d3af630d179ca -size 400952 +oid sha256:c110f007c954fd01fad8d4e9810abae47bb89c330141c7c1d6412d3995943f4b +size 400985 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png index 77d7c16046..d466ee2bc4 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e82d2a12ee66397f1c114ae4836a8e513db4f1d87c1fc4501bc85efbb1e63f83 -size 62736 +oid sha256:8fae17aad6ac7dfb2fd2fac83c2c1b6d9e0743fa9d3d1a874fe269284149ce29 +size 62760 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png index dff61b2c88..3d408f0ee2 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec1b6c85754dd2f0ba4b67a86ab8688df6c6471a53e508198b1d3af630d179ca -size 400952 +oid sha256:c110f007c954fd01fad8d4e9810abae47bb89c330141c7c1d6412d3995943f4b +size 400985 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png index 0c7eeacfb6..c45996cc7b 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65925352e2e25b708f04c1adbdf5ec70a515a980776887a35351a8cd94ec94a8 -size 62591 +oid sha256:dbcda50596ea08167fda422fae89758bc46c719cd320103def3c90cea0a152ff +size 62616 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png index 041a34fe20..a1ae4a1c9b 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9392073a8a6600cae209985e789fa081496a2c5cedb772f835a73b05c49570aa -size 67711 +oid sha256:7b1172f37d89f97ec0360402c013328ad65bfb62422d5b81a8d06e9d8dc3cbba +size 67739 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png index 8313f647f2..3baea3a223 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb34a1ace20c04dd99090ef68d17924f3a24a475d1ce5d376969d18df95d315c -size 71910 +oid sha256:29d6a3980b5928907e5d5203ba4a5010feed5ca67107ef464933717664d72fb1 +size 71937 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png index f9b27b26a9..be72870cdf 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3c995ea0668250953302992ddf3e535247dc5e972fd737313b5d352349839e6 -size 407904 +oid sha256:df744636336e3b7dcf4b8c20a3a9dcf70247ea0a5602c11665bb020925c94dd1 +size 407934 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png index d2e6e0ccb9..48b54318d5 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:957d2be646cba8c187cf6583e4598b72b6449ac745eceb88b8cbe647e71ae236 -size 88554 +oid sha256:ea59b97a710eab6b10192373c7058b301e0d2b4bfe07d16f952d69593b8b78d7 +size 88581 diff --git a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png index 59a1f9a9cc..9b2462e1d3 100644 --- a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f66fe5b25e3de0a28bfdeb0d45de675407af34e2767b59a8bf75cfc225e9dd5a -size 25446 +oid sha256:c40eb122d941ba96cdccf2c97659fce4f5599c88f7aff0ef3e5d084abd0fb241 +size 27341 diff --git a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png index b957f75c10..56e8ed31c9 100644 --- a/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1930f51ff9b9d39cd9ea9a0addfcea9c5114b4f9e2449a57040deac0576f0498 -size 29491 +oid sha256:8b3f371d99fff430a018e02a3d64ff0e88fa615db43a3c48a66975fb00145970 +size 29875 diff --git a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png index aca8462ace..70f452b628 100644 --- a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png +++ b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3da0fcc021270fe7cfde72e03f44f9c95428f18673aa86bbfb11a6acc0b344f -size 65207 +oid sha256:f199bc84eb10342e677b22e60c1b74bd9c1fe0b9842c474961e601c23c9d67ad +size 66719 diff --git a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png index 6d95e18da8..80ad7b4e48 100644 --- a/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png +++ b/screenshots/de/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92c919777810db1c4d31897b44b3b35cf70ba6f244061f1539eb5efd4f20ede3 -size 66922 +oid sha256:743455d5509d5e81ee5eb4012a03c5ae8c2002750d57f5d379435e590adb2990 +size 67544 diff --git a/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png index 0ef8f31754..14abdc0caf 100644 --- a/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png +++ b/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38522e07ec0c1e856ed94599090255f7ab3b032ac8edd824553b21da3eb50192 -size 26139 +oid sha256:e4f823bf8a422775693ba64ca10e087286967d11c8ed94a3198f108abd3a9367 +size 27026 diff --git a/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png index e7fbb21056..ea8e6ae90c 100644 --- a/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.messagecomposer_MessageComposerView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab856d0a2de029924cccaf9f2285f3178315d83fb12e02f7f71d9c69fdddc5d1 -size 17989 +oid sha256:1e07d15bb95f7385596d7f454620a282277f8ca42e258728d6dbc17b5da84f59 +size 18045 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png index 0fa4f15cf4..cae13d102e 100644 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73ba15459015c981b063966fecfabb28af7b2bbf25d16412439f0f35e6d6694c -size 12924 +oid sha256:0b5196548e23ad3308c3517c2764dafe73b620115d1721cd4eaa1967e795a174 +size 14262 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png new file mode 100644 index 0000000000..642cb48d0f --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebee62aecbbc7e65168799cdeb940d112095d7e38059bf91e4192dea242eb884 +size 113883 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png new file mode 100644 index 0000000000..0b33acb4dc --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7bc6e29e43c98d47257304e38b5d6f3c0aeb55fc671adc02ea0234ba6ff31be +size 120123 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png new file mode 100644 index 0000000000..400c371f56 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aec9126323f766fa0caf0bf1aba5ebd2110bfe6076c91197f4613088eb3b8a62 +size 120233 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_de.png new file mode 100644 index 0000000000..9fc7fac5f8 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62abb24d710f2bbcd5965887318ac1c1ed7af2aa7ead64fa8557781e3c03ba9d +size 21189 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png index c9a5dda40a..610bc5d0a0 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f89baf13d98c9060d9346883cc72b23308442604eb589bbfe1d6ba5e180db5 -size 57070 +oid sha256:e2b86e1326023be378c0c03b12305810f36e4fed11886ffd3bfa46ef9e5802ab +size 18767 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png index ac8ba29d96..7a936dbc60 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe8e088ca91657f0d834b77169905afb29f610c8abc04ccedad4ce408216c032 -size 37992 +oid sha256:b5646e1e203737e229787944dd524377f51fe1478507c9a6dd19916716526404 +size 38381 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png new file mode 100644 index 0000000000..75eb3ccc78 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68cef5541309a99a95f5004cbdcb4d091a70f68c142de2ff78deb710c521ea30 +size 69820 diff --git a/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png b/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png index 6d76726db9..99f0c161e8 100644 --- a/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png +++ b/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d61417b446f42bf388970c65e8df1f8ceaf87d457c55cc1cdbdc60d2ebe0b5a5 -size 54834 +oid sha256:d23534a940951085437a3c739b58d515a968869227db794a149b5066abe21800 +size 58473 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png index b355228561..9dcacf8924 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da02621bac48d9f9d7349dfc02244dcbc698442f1a8975d2c9b9d8e2d9c64fab -size 56650 +oid sha256:bb6ca0ade3d54ffc371ea734a0aba16d27b192b8a602e79355cdc45d1a3fb33b +size 56639 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png index 6a6d9271cc..98dd645229 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5c26f5383e1d079f5fa8a62baff668032181568a52bbbbc90bc2ee5d70d78a7 -size 67208 +oid sha256:9b13eb680dca1d551d843b92dff0062a58781c6c9c1fe713e35c26412b6addf6 +size 68596 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png index 80bd625605..8e73293bb2 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26faad6c5e6bb011b3df1eb723558c22383eab2b2ac53e906349807afe1ac7a5 -size 41131 +oid sha256:b1afe6a244e864befb72decf8d2518b9588b3f59b5382c8e5c6130a2ea33e23b +size 41952 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png index 47d2038cb4..9cfff702c3 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b7c1a47a6a122af432404385fe938f3da344c1c1aeeca3a6d4faae95c377470 -size 55932 +oid sha256:4d4c8687f4067cb9de6cdecffe70d9a91471ab6298a601b64336211459fd03da +size 55948 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png index e451952b98..7cbc28b7a1 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0db0d106c3ebdafc7242ae1f0ebbe9211b035fa6d75b6b092a926052420aa920 -size 54067 +oid sha256:9b254226cc6b00d4871855a5c566d2f35cbbabe2048a58f12e86cd07372a2d91 +size 54071 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png index 2997d59585..88897e9150 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba00ca1bb5a5abe1f58944b3d73d85d78b797126aa76873efa03bfff3df0b8ca -size 60458 +oid sha256:10845895f042e2fabfdf9ab573ceaac779ee30ecede1c76e5bc68d78b51bf985 +size 60476 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png index fcb59350b1..7c18c364e1 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0ba9fbfdf7e5c21c9461a103c5e552d8585ccfc152507ca701c5a8ff28fee49 -size 59958 +oid sha256:4bf1fd981150ed276bafe5b2e4f710c47ad423c085267ba65070b1a2806ca078 +size 59937 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png index 76cb8f4e26..63497b4081 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f263db2048cf39ed38c4895b5f76e6bc9c9d0fb8de09a745a324c47e695b1c1 -size 51533 +oid sha256:a7cf06d5921dae7bbdd3b774e38ac6fcbad724261c1adef9ad93ff992fcc7669 +size 51515 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png new file mode 100644 index 0000000000..20df66736f --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2c1dc2c23f6b8dafab3eec3bd703c9ffeacf8e3de6f0da8b182ded7dea27244 +size 53656 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png new file mode 100644 index 0000000000..e9d7ece4cc --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2215fecf0a0cd2e708d7b2aba1879528d3a1ea07cc2dfa255d74986fec933ca +size 53531 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png new file mode 100644 index 0000000000..5ed68bb027 --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca1bff9d9c6f5b68823a43eebc8196ae9705f743e7b59897a69cc4016ee155ea +size 53523 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png new file mode 100644 index 0000000000..7e71476836 --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c208bdd8a985ab7108020659f0c6dec3413fdd54a529f86d7f2bcb44448fe0d9 +size 53520 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png new file mode 100644 index 0000000000..46d1ca20e2 --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abe747567a372eb4b674a1e7976b24d498ad2a4d7e20d425c9291ddb05922a14 +size 53339 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png new file mode 100644 index 0000000000..567949e6e5 --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90068ee2e83b713cd11d9879bbcc3c389dd0f79778d8999df6bfc9f2b1b1bb55 +size 53662 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png new file mode 100644 index 0000000000..04837d0ca6 --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3387219f505ee6168eb44879b4f943b75459f4c5b6c311cce874eba5e49ba628 +size 53108 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png new file mode 100644 index 0000000000..304befe3c3 --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7333bd76d2de37bd13fe507d89c000984d73141a3dec81f71eaa13d6658871e +size 52600 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png new file mode 100644 index 0000000000..025b3d596f --- /dev/null +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97f271f0ba965c1b40edaad388e111bf624c01e5caceb73dfae1e09c28b3856a +size 61504 diff --git a/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_de.png b/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_de.png new file mode 100644 index 0000000000..7fe20b1ba2 --- /dev/null +++ b/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:acd9db5acab1221cd8e78ba1fa3679da5e84c6c3e648e87c7143753bb636e498 +size 59053 diff --git a/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_de.png b/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_de.png new file mode 100644 index 0000000000..74819b40b1 --- /dev/null +++ b/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c3a9be1c0c98f2735fd882bf6ccee1efb4b2ba3f14ef161b8b4401cb01ad19d +size 56242 diff --git a/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_de.png b/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_de.png new file mode 100644 index 0000000000..61c5d7bad5 --- /dev/null +++ b/screenshots/de/features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfd699dea1779a7a04f8c27b7e1034ed366f21b4248791786ebd521cf942f38f +size 53865 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png index ee2c10a62c..c90222ce97 100644 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png +++ b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf136b30186c020c761496b14baa482a01a786eacd1e335e59bfe991fbe4d6b2 -size 49391 +oid sha256:99f92671020a73a3350a84e30fbe8915e0d8704f846a15bc01a56ac17b223e87 +size 56493 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png index fc82156d3e..20639717fc 100644 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png +++ b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c2553146562f2e8a6ee5144cb06d482a4928fd3e155aef90ca25cda9a99267d -size 44282 +oid sha256:5ab82b153feaaa1b8f43f9a3586387e87fd598b9055ebb6d3a6ecb81c7f071f2 +size 47418 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png index 063b8ba357..c90222ce97 100644 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png +++ b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30c484fe8b370b96c3515bc1232ebb24495763b7b47c53d08d24fcebac62770e -size 46996 +oid sha256:99f92671020a73a3350a84e30fbe8915e0d8704f846a15bc01a56ac17b223e87 +size 56493 diff --git a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_3_de.png b/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_3_de.png deleted file mode 100644 index ee2c10a62c..0000000000 --- a/screenshots/de/features.preferences.impl.developer_DeveloperSettingsView_Day_3_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cf136b30186c020c761496b14baa482a01a786eacd1e335e59bfe991fbe4d6b2 -size 49391 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png index ecad978eea..99f738df12 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d57b5854a0156811f11b23a51f347387183507d95da7b68a94f9ac211ec7f36 -size 42003 +oid sha256:fe130f936313191f602331d5b1a08dd025da47a66ce23dd71cee0665e951a3ac +size 44506 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png index 78e516e447..47113e66d0 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ef5f886b293e35592e5c41b8e84a21995982ed56ade44f0e4dadd83767202df -size 41800 +oid sha256:1228309dd9c2dbaa340f1b941ca9da17067c619a8645e870f20bf39db7c9ba25 +size 27560 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png new file mode 100644 index 0000000000..12791633f9 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b095c101503364437c57050c56fbcc56e8187a697921364eee4ae0807ad684e +size 38449 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png new file mode 100644 index 0000000000..edfa967da9 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:128e6931b4ac3fbc02138fba8a67e22f60e722acddd8db26b1b031102bcbb198 +size 28060 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png new file mode 100644 index 0000000000..efb26f07c5 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc9e3439b97efbd490030a7fdae43bccd60193b18c658f4ced99959550fc77bd +size 29481 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png new file mode 100644 index 0000000000..01f0712a7a --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ca99f565a56588d126e357df4417469e39ff196d21d41cdbff05166b8356da1 +size 21419 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png index 247fa79f85..2b260ff9f6 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc5c25affd9692e0c48c8160a444d98771ba5d725554024ffa0bcdbf00e49b9c -size 43020 +oid sha256:a3b21d14f077ebcaa11ac2dca31fb08f9dc21f26a4847c6d1c623f0ec953cdc2 +size 45806 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png index 2346a013bb..a584834ca9 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7edf11d971f30998917d1ff9b3fcce43aef543a96289eea074be8d3a9eb37fab -size 43077 +oid sha256:bff3f28233c7b1be7c3524f06258dfcf27dffa4251279beb2bacb883c3c86c41 +size 28576 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png new file mode 100644 index 0000000000..bd510c21a9 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f3ff8d40a465f3d73143de0d66566c0129a794cdba9556bb54423b2110375c8 +size 39033 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png new file mode 100644 index 0000000000..bc7f862d77 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a7aab1f7cc5a26672666fab13a36fd7bb47d524b9ffa172bac322c1ad1c3b40 +size 28583 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png new file mode 100644 index 0000000000..7cd952fef4 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4743cbd8f565d114a74024455bddd999df95fba4c0ca346b32203cf6fb6f7550 +size 30203 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png new file mode 100644 index 0000000000..9cbde40654 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a7e61a79e28968dfe2f57b75b88125471fecccdf4af670c7f2ca238019fc31c +size 21527 diff --git a/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_de.png b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_de.png new file mode 100644 index 0000000000..717c042d39 --- /dev/null +++ b/screenshots/de/features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d14d6b601dc1b0e75cfb8a981d50be84038a544a83837cc5ea5ce2b415ff6226 +size 20879 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index e38435bab5..759f942a33 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17ad93c86555868ac098ce3beadb8dbde57c89af9bc2caec61df1f3596325ae4 -size 46178 +oid sha256:088e737cec6fb5fbd624a16dbbcca45a8815441b93ef4d949acbaea9d9c52c3c +size 49472 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 23fc5ecd1f..10ad61fad0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d16ff2356729e9d5aea99f00b110efff09d6c0beaa33e100846f3c56cb0fb0a9 -size 44757 +oid sha256:f2f53b1fbc09307314ad92c688ef26490520de7380d27cab1ca67aca6e34a655 +size 47718 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index fa145bb3cd..e95dd4de1d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8c48700213f1ac24b20c08d8585bea693ae08cf4a3dc91e6ac6aa08c1a02cb4 -size 43518 +oid sha256:7bab8c4a37f2d9fbd4b29cdd729db9a84216fcfae3023facbfb979ecdf4645b6 +size 46428 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 564d0ae6bc..32193ce5f1 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f97df43c4f6e479e7ccdaa94d0e817f2ab3f02cf21986df1af09805eed8bd59 -size 45340 +oid sha256:b6a11d9f2402b756b61a5ab3bb766bf19404fb24b306f86634650b070554268b +size 48264 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index 90d69eb98c..a29bbd09cb 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75b4afed84d26d914eb82cdef4d9b7757d7cb27b0ee938c2bcca48d10553ced9 -size 45253 +oid sha256:b37442dd675bf8ce133b57484ec8dc11c695df69907ead762fa4b79c7c978663 +size 48172 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index 85c3b70cf2..0fd4f66fcc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7d85799138c9367a1229f36d90481577f08e027c4e946789f48e098b3927a0e -size 45832 +oid sha256:fa879e0d1483b07c3127ed07da87b8aabcc38c51db6e158ff29039e3b1886745 +size 49071 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 133d94e153..6100b21322 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ffbe5ab44b8cd51b94d766ff8bf0cfe05b56152d94a75d2858aca6b25db0bb8 -size 46364 +oid sha256:05db3b3e42f59515ffad1c522496ebff6092bd458297ca92eba25b321d8be0ca +size 49564 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index 95a9128cc5..63eb0980b8 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18f4ef21e7a652f29dc88206e514ad600c05cc9dd2a6a3532e4aa3e68894d7ba -size 45621 +oid sha256:5662df69d4f1c66bb47019096df83031b190d7bc8e0b354c06f09d7c25d3773f +size 48454 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index eee91513e2..44c943a262 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d04a9c799ef61bf131131e527c8734dd8ca67880d92a9ad121b576bc11d4a992 -size 44835 +oid sha256:81ac09d41d5f08d8f4714f070c3661e0628a0d28f32d58eb0a1460eacb1be8d0 +size 47752 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index d99db83de0..cf0d675e49 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd41d6b3943d4c5e74090acb90a712b930be74c49c6a39fbe2f3b60e90855fd0 -size 42886 +oid sha256:2dadbbe0ad65da59d7599f782e3893375867821ba0b8309c61a94f530cd58965 +size 44846 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index d02979f393..3b5b87ac98 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17e33f973d9e33f6e06e7b2b66d448d66183a353ed76c1d7712a13e2af9cbbc4 -size 42839 +oid sha256:1d8648c9c6297f2e8ec87b334e1e885555e921faa7d98dda70fffb902ebe2688 +size 44828 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index e0520466b7..c418b7d0b4 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccc14ef7b66c52afcb6d806b4d8d170ffb83b7817a5ecfaffd706853bbc35cf3 -size 41743 +oid sha256:bc469282e83bb5e88a173fc8a4500f8260f37ffc8afb20449e1126aa50631693 +size 43177 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index d8814411f0..8360619979 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33521284c24815367a302bde9c49b2795ecb5d803ac322220f720c5269605ea8 -size 47818 +oid sha256:3a0a8cafff67aa2fd2991ce4320ed412cfebed0208b2d1c4e8bc0f45e7977e6b +size 48534 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index e89ffa97bd..d0a134673b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f16ad28caae15b4bd13fa61dd5b95450a559b00dc005b157fecf44c9b7df625 -size 47553 +oid sha256:3e1625ee06b9ae0025bf798705c8919b405f9cd917d85056623618fe0223e736 +size 48450 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index 3ab82edebb..720c2eeae6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c493224b3437d144e064f91a9dcc97779953cddd81aa5884631ca0046d72dad -size 47264 +oid sha256:0aaf88dcf5e06d6c409318447e154b9d0b33775ad3e3aa8d8e3fe2b85aedd816 +size 48017 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index 15c3785853..e95f8da31b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ab93cdb57a580a52ed48dde779355440d6a67412f9699927a8d4214388fc4a0 -size 39451 +oid sha256:ae9087dda9b2c6e160aa14dbb45e8ab614f2c315158c5bfc48d5c67058ebb63c +size 42639 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index 85b757fb86..aeb6c18836 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:647eaeb0c9ddce71bf99e382fa45bfc560affe38e8581e12016a1e5a37e270ba -size 44587 +oid sha256:ff3ddf54027d1f77d8e1e1f5cc063f1c13fc2725447d7cb6475c2ebb6c84b529 +size 47002 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index ddac91c4b5..a600833dc2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b129c0c7e62d3874d1b7e466dbbca271873b20d3155981eafdbd9c33202eb04 -size 42527 +oid sha256:c99f882e777e43d1689ffa80a5396583426d987725424c779eff019f96d1c1bb +size 44444 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index a85951f6d6..9d4d6b35bf 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb393ca334e520249176e392cbf9f495c8651904f2e03680bd740f4d9b1c1ade -size 46076 +oid sha256:6d637a9ab06a5eb79bbee7d141be92563d1c6d4acbb301b61a8c02db53e89132 +size 49078 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index d8ac60f111..0884641063 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d420ac1d49b4f2a47d00e6fc273e2f2768b14a05f0d10c8c655cb492abfe142 -size 45474 +oid sha256:5f45315776c2e841043aabdef8b72a8cd4e485270ada198b28f92de8f55bc7ca +size 48392 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index 3ec8b090c2..82093102db 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8435264c98cefccc80e7a4bd32d903708e878f4c4ad2686aa35df8fdb9324882 -size 44159 +oid sha256:401e526ee8c3e27e90d34a9cb86561789172a9b91b5b5a6f5955aa4b001dfb1a +size 47658 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index 8d470aa1eb..d7778998b9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0cdc554f6e3ce1725e2459ca0c6133f7f14a15d730f190bbbb795eb11c0404e -size 47224 +oid sha256:0f7fd6001307e447476310fc91cfe2eab0bddd8d0bc137a9a35698320f30f706 +size 50559 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index dc8f2611d0..777eaaf717 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d408175ca51c0b36ec01cd950b079467e29bdfdec9b18a1b81f1480ffff51e6b -size 45740 +oid sha256:17c582d1666c5c7b6040b007a13f0c6367eccd07d2a35847e4751bf8e5de7ed6 +size 48691 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index 5e1712b9a9..c59448b50d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bc00b126e3820666bad9a4904b3956ab391a6af0f74ce30794373af1c654ea8 -size 44592 +oid sha256:673f1524b9a0e8284600cdcc5536bdf98574424c31a8a35552a75cbdd404424d +size 47490 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index 6f725c591f..f0c70fc293 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:438edecdc96de067dfef71395ca0dbde45b5127f5a8d507dd4148f43da12f1c2 -size 46370 +oid sha256:a7aff67290ac05d786c65cdc2dabc4bc6dbf60a802d0b77ae8c8404fd05e1bb7 +size 49256 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index db3edbd7ed..4c43697ac5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2272a4633116a8f58a24273fe348e4cf979eb31fa78a641ea6da28345e358846 -size 46265 +oid sha256:ec0e7d344810f5fa43b9bc05c41116501350e3daedabd33c97782082264369ab +size 49157 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index 8d78460895..f0d89fc365 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a45ea374ed7827a1aaddcb6b5d0eb344b4c0d79ae328099bdff79a8a3ef84b5d -size 46769 +oid sha256:a012a170cbd17e1fe588c27e41e531baa12097830ed205ac5c9c51c5bd62e003 +size 50108 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index f7d40446e8..865602ac62 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4ba031a35b259142083b6fd508b7ab15cf169f7f5b1535bd81ef7e4fbdc0a6d -size 47370 +oid sha256:4f734bad723be9fada8b38763321ea63778f0ebfd65567472432ac32634d7b67 +size 50695 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index fe75d48f6a..1a59d9ec17 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e87581df1ada41c9b7b85f576da8c32f856203a6c48e7f40128fbf30c7a33a0 -size 46646 +oid sha256:7a3c70bad40927fcd45902da33a3fe12fa50057e278c6009b1ed5befe4512182 +size 49470 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index 56080a7551..1c01af3450 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d87b127824291e0343f53cf50a22f0e1e8b89e00be55ea5f625aac59f9109a4d -size 46142 +oid sha256:a9e7f2edac607fcd372a991078a4d9d92e01e148ddebce2785174dbf877e14bf +size 49045 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index e9d5014602..aa64291503 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:827747ea2eae177d460d615b9da37db515f635ed433567945e1d88cb39337594 -size 43944 +oid sha256:755919c37c18cac3fe595975847620ce4a0b836b01546fbbfd3cdd1693ad5435 +size 45945 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 8bf44cdefc..1cb9dd897b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1765877cdc96b174cb7a2e087165c74d1ceca02137d0daa510ec247cc4f481b6 -size 43823 +oid sha256:735d92a8a39f4ec22ab51830cc0a5877697d028a12ba4cec2c2cce0475cddea5 +size 45888 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 52c52e8769..1d527ce0e6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f3c5533e239f54302eb7867bda7571fd966b4c298be9ec48abad6a5025c22d7 -size 42890 +oid sha256:7c9e86d87f93e3e96ee25b6090b0f989baf173a189a3c2274dc2cdd06dd566e1 +size 44223 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index c510c5f777..c6e83dd003 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abb0b25a08a6507a9b3c0f3ed79ca11b26dcc54a9350a0711f9385ccb0ffa29a -size 48855 +oid sha256:1ed0a0e971a25574d13b6bbc5e0137f8a3f2bb1909d6149d16e09199dce3c25a +size 49535 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index aadf561762..dd2ebef37e 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f615089fb33bf68a1f24bc1d7f78ba899ea80c5dd5e046b05df04055e7d15ed3 -size 48571 +oid sha256:fd5dcb36fc1e9cb675d461850e88f80402d30e43c6f8709ab3274326ad4a42b5 +size 49454 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index 2c22f9b92c..9c0a4282b1 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9f1b2f0372b538dfc219ac8ac699347a199f0df903813ad1a97b7e158f50f9f -size 48241 +oid sha256:b24f32d9a8640b7d1ef5a2b77d6198d3dbfabcab7a9cf46af8a0b24e23655eeb +size 48999 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index 22634ff9dc..24966de76f 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab5386c966f4b5981bee9d39cd6a315bdc86dd286ff2c5e08aca4c5bb3304b23 -size 40457 +oid sha256:e92a8647bc6be119cb6dd401267f3369ad0ffa61372efc21d8e1752350c37a54 +size 43617 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index 7574b9b61d..5c5bc77cb2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49009a3a070a668b7487ce69b3bf1377ce113cf003e1571db3f90d8319ec084c -size 45597 +oid sha256:2ce073c24e1d2b0cfcc6fc64cc62042c5bb9260e7636441827fdc746964aefbe +size 48017 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index 00e31d8cd9..0a07cb8799 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e268c85951e089414695eed071ec5c98a80030d130f92d8a934f815dcc75334 -size 43480 +oid sha256:19fa23046e80df108a9d9cabe2b34d713e12d74127b3c4a320b5770e286429ea +size 45506 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index ed016c1eea..a9ebd612f5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a0b75e17e467d1a8abcb59f0e490c57e1bc538f10a6900cbff2e2c14994f0f8 -size 47246 +oid sha256:6d764589c800027ef6f34660324d980c6525475b0a65d7f1e7b4afa4f4f19aaa +size 50155 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index d4eb3afff0..9a167dc9b8 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd5c0dbd3621d8936b4e7eaac29524fb837007daef330802d71a12c1978d973c -size 46623 +oid sha256:a3784f50878f750bc04b45ca657ccb89d74343164ef7b0aa06fb43260f46ef72 +size 49429 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index 3466e4571a..b2f44c24d5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:706e54694211c141ad5cd505379f695504b2fa4b793a9aae5242d52f72b9aea8 -size 45157 +oid sha256:91302b37b756a39cae34160110d2f7bb3fd67129343cde63ae22b109861299c7 +size 48671 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png index 510ef4cff5..3841e9a8c1 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f8be955697c172685ed1abacf1466e6d16be50a127d60fcdd07ffe863a2b280 -size 30422 +oid sha256:f8a25adefb463d3415cf792c55c2357d0654c9837d9d8c85473337e4da57df30 +size 31673 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png index c14394e142..44731d0b48 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00bd106c1e653a8a9e2c25766c7c7fc3aff62ad7cab95f1c64e7f8a943ccf76b -size 29594 +oid sha256:ad35b8e920b273ea94cdcd4e0e3ea4bac5e5d9fda31148c06fe32655b9946b8b +size 30437 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png index c14394e142..44731d0b48 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00bd106c1e653a8a9e2c25766c7c7fc3aff62ad7cab95f1c64e7f8a943ccf76b -size 29594 +oid sha256:ad35b8e920b273ea94cdcd4e0e3ea4bac5e5d9fda31148c06fe32655b9946b8b +size 30437 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png index 9fc30c087b..1031c440de 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:486e225305ef358a4209a7702e80be03d76a6da4cca3f99106d8b0c652e5f9d0 -size 44032 +oid sha256:6df694b16f3474dee2429f9ccf5279bdfbbe23d102911e633937e7f7ef12538c +size 45374 diff --git a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png index d3fc6cd00f..6c25e2f248 100644 --- a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:828cac2a145d0a4c9f4a585abce862c07ec8f5a96413210c0d3f347b0bc63f8c -size 69449 +oid sha256:3af95d96750feab55d52e066e2201c38224b1b280c9b995fcbfa1a92b2d2472a +size 69083 diff --git a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png index b686bc6fa0..829944fbc8 100644 --- a/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:711929ee9ee4f29008113163b4eac4646bd73ae0e32ec614caa6dd72827aefa6 -size 49781 +oid sha256:da0280b7c12febde1947781a235d844063bfbf0c7402ceb7585627484135ae86 +size 51293 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png index 2e8f128b7c..53994b7029 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ff016cdc3ea47662f224c49fd182cc16ca3bb1e09191ccaf2c418ab93a358a6 -size 74302 +oid sha256:1293917283d4db5644f4cdbb00a76b0071dbbde7574b8ec3376f19a0fcf6dbb9 +size 75856 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png index cdf64c352d..d6f33a24d0 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73542eae97679631df08f0e505ada9a12325ca5544eae4d37dc5c0a0ea4c4939 -size 62398 +oid sha256:b9212912117ff8653d8cc2c15eb360e2da0ef68e5ef79846f3e2f00f1fab9c8a +size 62526 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png index 55345f0018..4e2a7b2671 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12537f5ebb752dd40f9ed048bc30669f78e8fdffd3bba3c4c4c7f34e8aee1f6c -size 59311 +oid sha256:d61ffb76ac311f35f3b3b5e83810e62524efbca9721f35812d1ae2386482b1ee +size 59008 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png index 217548fbb0..b723e43390 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cfdcaac6e0f1eaa0bd95e26fbdebc698dd90cd0570bc757755ea8bc8d66f82e -size 42170 +oid sha256:aa77b425148e59b5d230f835baacc1ca3ac184a09e538057bf5d6438f20f83a4 +size 41503 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png index b9e27d64de..58d6c1f136 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f91b5e9e379a6053f2dc204edf67dcdbc3aaea7b0ef055360cb8e1c749a862d -size 28994 +oid sha256:9ba6580e7b5cf07c6dbd067ec863dcb485a3fbc7d03d93dbffd8a6c2d337b058 +size 29129 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png index 2ee8c1d373..2dd817a0d9 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:beaf80641fe9918dc76626709feaf7e4f20445fde61ca26dd867eb77960d39e6 -size 61646 +oid sha256:054a9b89b6c4007b839e53190b10938a7dc5947badad88876be243e1386628a3 +size 61787 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png index 2ee8c1d373..2dd817a0d9 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:beaf80641fe9918dc76626709feaf7e4f20445fde61ca26dd867eb77960d39e6 -size 61646 +oid sha256:054a9b89b6c4007b839e53190b10938a7dc5947badad88876be243e1386628a3 +size 61787 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png index 08a5405021..cc0df3adc9 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81a6bbb9b125f32ddf968b39589a50f5c86f57e0ce74f64c4bfdeeb0a15d1044 -size 56320 +oid sha256:4ffea6362670777720ad844d424ca9fa8ca9a3a79f26adbdaad1b28adbfe18d6 +size 56453 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png index a4810cfa49..84155f40e1 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:732945a494e17c01ba15eb2d125c451dd24fe0d372e4f8c326870c00cd5919a9 -size 63468 +oid sha256:323f616c91310b48da0170fddb7c7ad68edff7ffda48e933cf20e9728b8057b1 +size 63607 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png index a4810cfa49..84155f40e1 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:732945a494e17c01ba15eb2d125c451dd24fe0d372e4f8c326870c00cd5919a9 -size 63468 +oid sha256:323f616c91310b48da0170fddb7c7ad68edff7ffda48e933cf20e9728b8057b1 +size 63607 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png index 6052cc869e..fbd2710432 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f50dff310fa256e245c367ff86925b5836a01c15c291693fc63cbd252218e98 -size 30303 +oid sha256:b6e6da70984ea50474cf4f12c78ca8a4df196e92bdb77bb9ccebb4e00ff986cc +size 30460 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png index d1472d9bce..d016666d26 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1b686819cafac3ef2b162303af90ee7a3235d9710bbfbd32b55eb32795344ed -size 63939 +oid sha256:b3c2270c8ff1643956b0ab4fcd066dd4509b0fa175ae8652e83bde5c1c3aaa33 +size 64089 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png index d1472d9bce..d016666d26 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1b686819cafac3ef2b162303af90ee7a3235d9710bbfbd32b55eb32795344ed -size 63939 +oid sha256:b3c2270c8ff1643956b0ab4fcd066dd4509b0fa175ae8652e83bde5c1c3aaa33 +size 64089 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png index e478d3dfd5..f434d2afca 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cb8223671b7e668dd25586e72d06eda531b8f73e25f2a0c8f58c8a20e2bed69 -size 58885 +oid sha256:16423874fda81c259bc18949f550ccd0cd2f56aff89304fda784d51d02e175b4 +size 59036 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png index ca3ca6fb08..eab0ec0568 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ecec81c744dea2ba5adcf8154ef01a817066e7efeeb815e97db0b387078d3ab -size 65933 +oid sha256:f7fb8ec382a876de47b2c1fb89de638bd1b6fd44e088e7fed4eef09c59f8eade +size 66082 diff --git a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png index ca3ca6fb08..eab0ec0568 100644 --- a/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png +++ b/screenshots/de/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ecec81c744dea2ba5adcf8154ef01a817066e7efeeb815e97db0b387078d3ab -size 65933 +oid sha256:f7fb8ec382a876de47b2c1fb89de638bd1b6fd44e088e7fed4eef09c59f8eade +size 66082 diff --git a/screenshots/de/features.space.impl.leave_LeaveSpaceView_Day_10_de.png b/screenshots/de/features.space.impl.leave_LeaveSpaceView_Day_10_de.png index 379896cbeb..94df28a991 100644 --- a/screenshots/de/features.space.impl.leave_LeaveSpaceView_Day_10_de.png +++ b/screenshots/de/features.space.impl.leave_LeaveSpaceView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:860a35adb3a3ed607050890e3a7c246a952162ab06de7a64c7d19dad27cbe94f -size 31909 +oid sha256:a35bd47b1c72dc9bd8df40ae31737fa86826f29fa895b8516d156261bd678fec +size 37731 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png index 9ac2444e4f..df387ee482 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8804204dff0d36762b0c02e9503f2e06b6be257b9e1c0c2af6df0c0fe2855b9 -size 50289 +oid sha256:d8ec051c3ff5258f937b80e879d5120cff573558418e022df0604c85ea0d20af +size 50027 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png index 36817c5f75..c3ddaacb75 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a69c330592d208be768c7f607bede843483a92140155c974ad4a84116ebd142d -size 50380 +oid sha256:e253dbf67edbe2047726be540ca8dd96a92623fe786f4c642ce369779b2a20ea +size 51127 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png index 40e51c9537..03e3a3e58e 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:428725b17dde8ae30898299043e2d5e03ce63f516c93e440e660823fabd43e4a -size 52036 +oid sha256:a11958a3fb1af0e4ab037fc47aca888d9d14fc6fa692a8409766071629e55631 +size 52246 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png index 806bb43ddc..aa75305737 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccd76b6702435a24f67ab28adc60b462acb2fb430daf87b6ddc53237940bb29a -size 61987 +oid sha256:70972a7bcb6546370e820cd8e6dd56f27d8ebc42974d041fa4d028520ee1407d +size 61119 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png index 75087f2a67..1fe2580582 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:524f0d29e59175ceb996b81b98625e168033077b12541f8747fa6c6082097cdd -size 62629 +oid sha256:e59fa963aa02f2b621c9dacb4dfab56dcca4fde294d1cfecb31c83496dc6448e +size 61761 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png index 8a71650321..50e51d4b3b 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e338d699f2cb5d4645742e9dff3dc7cd3dec20d2ad75821bd3fdb3fb8e917a96 -size 57250 +oid sha256:bc94524eb19fe2878558d3cef5da93247f83373b62175115f7d6ede815b2a404 +size 57045 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_6_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_6_de.png index bb7279e63f..bbc9cdc6eb 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_6_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:559df2e03be1e673f1bd3d8232d173fba53cd2f90f5db3dbfaa7198bac9c1f9c -size 33506 +oid sha256:16b7d04c97f37253169364cb66712c70cab46548833b9a4249cfa8e3c56747a3 +size 32833 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_7_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_7_de.png index f41021a302..6f1d20b710 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_7_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63d47784152edf52001321e94d57a9724647c33c1b3cb960b3ad7bf399963a39 -size 34019 +oid sha256:980dbcdfea227a2209e7738d846505f3b08ec3ca1e553f44e1a94cafec1127c5 +size 33461 diff --git a/screenshots/de/features.space.impl.root_SpaceView_Day_8_de.png b/screenshots/de/features.space.impl.root_SpaceView_Day_8_de.png index 624b13fff5..744202fb4e 100644 --- a/screenshots/de/features.space.impl.root_SpaceView_Day_8_de.png +++ b/screenshots/de/features.space.impl.root_SpaceView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f71d4b804cada9b0a6ca00a91a423095f8c1f2b15908b6a63e9250a079268407 -size 52373 +oid sha256:a4bd5b6d993849919a38fbe546673441e455def888463e9bcc3377404fc9adda +size 52228 diff --git a/screenshots/de/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_de.png b/screenshots/de/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_de.png index f7f4fe51a0..b3ca4cd447 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9d20be83c90e8e0a54f59bd7b16cc914b080cb15cfc31b682d43724c3e3ad33 -size 25315 +oid sha256:234efe683bd6bc802f2a9502faaf6969cb5ad373a1128af8dacc99969d9c10bb +size 25692 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_9_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_9_de.png index dfa9eaa2f2..952de3033f 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_9_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:540458fc3c97157112560ac44278c57989fd7db20f2cd1779f2a99b1f666f7d2 -size 33938 +oid sha256:8f5a232c60af123ef006af7ca44bf43acd21dbc8b1f4568640eb7ec78e2378e8 +size 34580 diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_de.png index 673bb92edb..d617ad8f81 100644 --- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_de.png +++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3966e491e38c1c3a81faee839282b66260a1444c8878f03e6ce121941ffacb72 -size 36710 +oid sha256:37b686d30cc5cd2bf73ee82736cdcb0dfa5cac04401a7ad9d271b191296d8094 +size 36911 diff --git a/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_de.png b/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_de.png index 673bb92edb..d617ad8f81 100644 --- a/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_de.png +++ b/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3966e491e38c1c3a81faee839282b66260a1444c8878f03e6ce121941ffacb72 -size 36710 +oid sha256:37b686d30cc5cd2bf73ee82736cdcb0dfa5cac04401a7ad9d271b191296d8094 +size 36911 diff --git a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png index 6463867d7d..6a392c8059 100644 --- a/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png +++ b/screenshots/de/libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f85a57b51f5ac9d7165be8d83c414b8a1fce87f2bbbf4a345f145f01ba80e3f2 -size 34420 +oid sha256:48ae8baa9ed17971852d6d6c0022196ca076d6df67ebcf16046929ae11d91e0d +size 50565 diff --git a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png index a1c8e06dda..6e9497454b 100644 --- a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc315b17a2234172e3701606c1409b6ab1d551cc58e42ac7db80b2e76a852c69 -size 26784 +oid sha256:9d365fb5ebb274cdf830763e8354e5fb532929f590f9ae93259c823fa66a64a5 +size 39239 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceHeaderView_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceHeaderView_Day_0_de.png new file mode 100644 index 0000000000..7e57514e60 --- /dev/null +++ b/screenshots/de/libraries.matrix.ui.components_SpaceHeaderView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ef090ea6ebf5245e8542ab2f5419b0b16656bb19080246558022ad10c201871 +size 63969 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png index 47ae5e64e6..8063fd08e9 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceInfoRow_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f245cfa43b2310ab533005012debe347d196b4c177e696ff4399c8431397113 -size 18057 +oid sha256:6c54bdbee226f0b32754e7bc8822dd6a722d096b8b0bea671b7b3f7e63e13cb2 +size 18810 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_0_de.png index d8a2dd91e3..f18a0304a6 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c68172fc235ff99b618910a4312d650da867b4fe6cd91d5a650e4b9ed2360948 -size 14914 +oid sha256:6918b0eb0b7aebabf8017ea3f4d6facd7ee40ed10e4ef5def22209df9d722296 +size 14681 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_de.png index befe1594c0..f8cbcfc1a9 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b736f4d8865b2607f549ede17418fe9ea86e523608ce7c98b97dd846d7cb9c3 -size 14543 +oid sha256:d05166fbb55144719d8f304a2055b4d586e31768e0a840539b6584a01c8a9df4 +size 14310 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png index f7488f52f5..169e0d2b10 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7d0c9d5ec4e405c9abe3f708359a1d0305d06643e7862b69a44111b91adee29 -size 10236 +oid sha256:622e92307a1aae1a9feb420709f74d9cef063cdfd8e9f562e65655cb54ee804f +size 9991 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_3_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_3_de.png index 11578a4a99..db8c3a14ee 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_3_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f448d9d670a8120f3ffbc11a8fbedbcfcaf2ac7ae9487d27222ed949654e2029 -size 20577 +oid sha256:c7d114b3db4b9c915b07000f679b99b96a3dc823e8a000da40445ffb91b9a001 +size 20341 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_4_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_4_de.png index f48b52f0f0..dcd39d5329 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_4_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1daf71801da8ef47d3ee5184391e896f574486b4512d3700552fa4dbb4fb475 -size 20267 +oid sha256:a77b495523c1a7cf42f0a12ace13a897e080368317d76e40a2997d5b8d3b7fa6 +size 20033 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_5_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_5_de.png index 130ecb8da2..060ad3df9d 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_5_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:069b8f17330883e7161292ea46765d2c81c56fe8e3cef4a8a1a89968640f7c8e -size 14176 +oid sha256:ab8ef2ba28427bcd185c6055edf92b4fa187df547c52cf392d8b37c2375e47b7 +size 13943 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_de.png index 7cba4e51b9..327ea308a7 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec2674db1e325e8009a9dbce9e012462a0508cadce19ca56e4b73cb295b0bc33 -size 33581 +oid sha256:d7dbf9bb99bd112618baff601ce3304518baf0cc8401d6b984d268264cf15007 +size 33349 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_7_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_7_de.png index 9951601678..8a727c7381 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_7_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6dccd98617c8fb11df558e4d2c152e9e012f471a102edf1774f2c5f5a0e32c5 -size 38513 +oid sha256:90703a90d1914820f1ebe396b80c57a87c85298fb66c092536b16e9b209ae291 +size 38296 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png index 4dff07dca5..e2acbcc89c 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90cd3c57526f2da48edcbbdcf354453e19bad5310052b46150f3ac55953a1f67 -size 10743 +oid sha256:9ad1db5f211ed3df04d31e973297a82685168834ee6b629ce10c3b9e82c226c9 +size 10512 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_de.png index b14856438a..efb7231b4f 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c50e2f2892deb269aab50da2ac188df46cf00a4d1c242ea748cff4fed06058a -size 35461 +oid sha256:c39fc1f4b149531f599f5ea69087685f63750f584f53fd98f9457f6e8e1a026d +size 35492 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_de.png new file mode 100644 index 0000000000..4ecdcd8c5e --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a5bfe153d49c2cf8cfb0305034bd062c3196f11e89e745a3da9965d1148870a +size 47632 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png index b62f148452..5fa5394165 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3ab3bf722f90727b238a6d6a51c75ce40b1074343e30dd714c3dc86977e9c6c -size 45120 +oid sha256:5e2325778fc5bdaa5ffd421f77cb83d1927ad4ad6731337b4878a99d3fbfe8aa +size 46053 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png new file mode 100644 index 0000000000..5fa5394165 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e2325778fc5bdaa5ffd421f77cb83d1927ad4ad6731337b4878a99d3fbfe8aa +size 46053 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png new file mode 100644 index 0000000000..1e6c6d88eb --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f845e0783b6f09ef7b0472f22465e8e5b086102d711e468f1466df45ff928ed +size 50410 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png new file mode 100644 index 0000000000..79f832dcc3 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2917a353e78569a92d5d276e99ebfce334ad8848d488f58312abb9d7bcf654b +size 33327 diff --git a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png index 9ac592fc55..1ec5f1ed66 100644 --- a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fced21fbe2a7c8d0fcdaea9c06c063dd747080fcf7cc35f42257cba68bd0cedc -size 45022 +oid sha256:0321ed8731d4867c59c482a8e631291537556f6003659b9e0c2aa77d61883a69 +size 45973 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png new file mode 100644 index 0000000000..c4822fa433 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2c35cf93948bbc2c344bc678db1159e77769577054bee9ed168cd07ccea5de2 +size 28202 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_de.png new file mode 100644 index 0000000000..189dc5c26e --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:762de4ead1258ac712f31b91586597f78487653c5ab3fbf14c7f92835e38a544 +size 30733 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_de.png new file mode 100644 index 0000000000..8ffa83e0e9 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6e4532edfb990b61d5fc6c30e5e054ef9de9c417ab39ed9b8a87d7936e0536e +size 8242 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_de.png new file mode 100644 index 0000000000..bf7e3395f8 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cb73f72e0e28fd731dceeabf2a1f2b03e194f59445e7b7b0757ef1674d3849f +size 199972 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png index 0f7abca2b0..16575bf2f5 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:013e99fac97e20013d15d780a9f9b39663fe9979378c923c2ccb29443f087212 -size 43323 +oid sha256:5300a530f5afb27d55369a9fec9af46e4ceccfe3ae6926d7bff90a7b8cbaa02d +size 44430 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_12_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_12_de.png index 8c73c6097e..6c364f2a44 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_12_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:732355669f5a2e1382aca0c4c39eff4416259551f7f5e6da9a43c07f6420e9ab -size 35037 +oid sha256:91045491d147d4543f3918f7862426fe5eac5f5012d581d9dc03648f48298120 +size 35572 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png index b83d3f8641..24779ec32a 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acdf6d5164b6af3932a9ea1ff8c7a1fb8a97e3829ef1cf8e27cd691fb4b0b7ea -size 46192 +oid sha256:f18aabd71856df14464096c7679850ef59a501ccb72c451606e8929abe8e8493 +size 46656 diff --git a/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png b/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png index 92f956925d..13aaccf97d 100644 --- a/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40f902114622ce212797bd9c0a7cf8fa9d465cacf1f32af99422558b35907d02 -size 52217 +oid sha256:9690aaa942b7314d5c0342eb2f50112b3eb27393c47fdff451ff3f7501e96c57 +size 52058 diff --git a/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png index c36a2ce217..6b9a41d3f7 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerAddCaption_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7326fadd145ca624810e858cc3413fb56a25f875854b7d2e75cd7e1d1b4134f -size 58018 +oid sha256:4bed208bbf05ccce0169888e2c0ea44c2cfaafd56fe31af1ed6d0f61ac24dcae +size 57954 diff --git a/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png index 8efd9aae7f..4b54cbd8f1 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerCaption_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cafd41a70160f81c647bb908e030609bd50003a54a89e1c7a58e5a7c6b20feda -size 43321 +oid sha256:cd33857c5c2c12ff5682c23fc10c351f7cab15631c67a915574c97834f6a4c98 +size 43353 diff --git a/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png index f9cbe155c1..b2657abb78 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerEditCaption_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbb50973fb9da0bb43708e3e608de3a22a301a2dc0d8c699bd9e0f59d5b44f20 -size 55991 +oid sha256:2cfa7073fce357505cb0aff9a44fa93d3c1ed36801c866d8c282743dade3bebb +size 55042 diff --git a/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png index c6d05fe805..7aa4a3b10b 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:987e6f677fe5412dcd5c94a883bf5966b18d048b31f189614ae2763823e319e9 -size 65017 +oid sha256:08e8c143ca1006a997b90d2b91a54c56d7e6d4f75fee8fbab5435772c94c75f2 +size 65057 diff --git a/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png index 92f956925d..7124c2da84 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerEdit_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40f902114622ce212797bd9c0a7cf8fa9d465cacf1f32af99422558b35907d02 -size 52217 +oid sha256:9a92d298fe4665f641db42908bfdd884f6439e6ba49fecb58e3b0d4ffd365f65 +size 51880 diff --git a/screenshots/de/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_de.png index 42a444fa21..2b6c35435f 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0616572000748e8483c377e64439159e00d5a836459d4208122b08b261346d29 -size 63305 +oid sha256:311b767a0e3406c6f6e46045b573ccf8033421008c39bc5a95f25d55f92c26d6 +size 63391 diff --git a/screenshots/de/libraries.textcomposer_TextComposerFormatting_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerFormatting_Day_0_de.png index ee39ef7d5c..a883181de0 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerFormatting_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerFormatting_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52b4ac22573e9ce47198277607cab5a5b9deec09e2adc88b92fac9a46ce22b7f -size 50963 +oid sha256:e20f3e52edb21bc7ce9ea63724604d59b749b841855a0b1b3a124e262d9fcd50 +size 51125 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png index 77f972cdd8..b473ee22c8 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49de6907472a673c5b79ae0f20a9939f9f6786fc757b9e1ac96077be34557d06 -size 73249 +oid sha256:221bcb0d8c23c286d330fe945d90cf864a17b8b6b3728e5fad98781353aa6ab4 +size 72954 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png index ac61252e96..b48cc48692 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29a442ba2414d64a550f4bded4835e11daeff0bd55031689af7072fba0fadcfd -size 59788 +oid sha256:17ff7c0207c49e50e950f276d63a58c1837b98048e5300278962fab0dd8d4184 +size 59481 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png index e9b333dc05..7d95518cfd 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5493a95039dae9babedde3214acbbff01c7b53a3b454251f234c6cdb09bbd35 -size 72797 +oid sha256:66f5fc6ad92fd7fea6d2c306cc666a4587cc1cdbc3aa98b45142cdf0c41e897f +size 72530 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png index 03a3fc0a40..8f5381f932 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e817846aa9983e8e38ba6c8ff29ec205636e7b9a72b461215c16eb06e22ceb0e -size 81614 +oid sha256:0f447bb8d44aa37b72de057afd9990f084efd60a11a2eb780c421a079e443903 +size 81106 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png index bef0dfd03d..e38e38a198 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddf5dbaf0ad4247513d38a34e89897d099daa8e3f6c0bf9495ac65dad0771f34 -size 62532 +oid sha256:0581ab71b5d91f4308fce842d2374168cbfeeb92e60658e4cdbf2e62d54e0eaa +size 62378 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png index 9267d1cb6c..c670eff478 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35b64678b72a2e2433d278f717d859dc6f53414db565ed325604e0911e8a7e4b -size 61375 +oid sha256:5e181b89dd2bf6ed1872e6a0fca74f7e335fc630015e4073b055da7a51426fd0 +size 61139 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png index a43cafd104..58301a23b1 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59b8beb90fbe005555a4de1d67230362623ab9b715796abb3a223f028bf89d5a -size 66981 +oid sha256:6cb0396eb3ffc95f88272f788542a7a1c6e3f7e63c76beb6bd7eddf46f7dc41e +size 66635 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png index 1f186b58be..6c68e65089 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ad07ef8db1754dadbca19207273bbbffc83a591b615c22a6d38fcb8322af072 -size 90155 +oid sha256:e975a70bcdf6e57b0df77d9e301252a934ed70bd48f0469433434246a668a023 +size 89801 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png index 558f92c29b..8588939a09 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e130d13f832caaa3b4016c2a915610bde46f0d34e7b394d52ccfb96f367afa74 -size 60683 +oid sha256:bec919f02167d8c094f84e0fba555000b1fc8ab69fcee16bd8e2a6ccf3fe8af4 +size 60444 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png index 0db525b4a1..824938172d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72db00abddd84b586596e1dc61fe89b27096fbc08ba82d23eaf703c5c83173fd -size 60746 +oid sha256:b42a72b8a0c47c86f86c71ba6153e4fb96e6f7fe4e4c43d4dabd6f3c5bb0ea1d +size 60510 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png index b14578a682..23cf3ec660 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:926284ff1d11c483707b568100fbdc8382a1a61ba146a0ef23594089bb3038c8 -size 69406 +oid sha256:a7a065b41b1d91d778b802bc9ba58a9491efc339fc08365ee93a2ce546ff630d +size 69115 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png index 340cea1e36..a421bc4928 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cf0dd833df3ace9700622b31f64513a3c76908d6651dbb0ffcc3b5a6a4dce9e -size 60201 +oid sha256:ecc34684316796fbc9ca8ef51c51dffdd208cdba1fa3094bf9cc78032ff69c5b +size 59948 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png index ef613cf899..995c0bdbef 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:164558c7d8cdd701a1d11e4f3df0448818a47eecb06024904e14c29651800f56 -size 72929 +oid sha256:2c2c8b262ad96121c40ada406ff69eccae562dde53e6c443e998a1e9298af176 +size 72670 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png index a16f0aaf45..664c684c76 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b801d74b3feee574ba81d9d2e270090c86e3c007daa9b96674c752e6428a5d9e -size 56175 +oid sha256:fea796dd9d77e3fdd8299c466ea7e288416139820e3d63160e14b602f8357fad +size 55744 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png index 39c6f3f77f..d0f110d40f 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e088310a4666c06e55fa88ef9d209e24ff681f9caaf148b1f1cbf4e0a8954206 -size 71274 +oid sha256:e0144461bd7e0076ef528a469ac99c7c8ca1d3473dbc18ebd635d430c3a2f13c +size 71061 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png index a906ed4d88..cdbe3c1024 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ffff1b75987e4b692fbec95fdc6bac243fdfb741e24d56f2e0f3b05c1b9a9a2 -size 82793 +oid sha256:c91ce0f1fc215deeca1e07c92a25ea1ce3c67c7e22c2ec3c8a611b5ee8e2bec6 +size 82226 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png index 6ffea11e25..c0c96ebe50 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17b44b1796d438eb804fec2aa1935c9ef0fbac16b90c55ee57ae0393862391c8 -size 59342 +oid sha256:7537431b942cf13953936fc7be06a0e269e03ac601426e60e0de3646b4848250 +size 59027 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png index 0bcdff0b59..908b4f2e78 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:467e422cef79f2be11df55814794472113b434822434301e52bdfd12c094deae -size 58453 +oid sha256:0490cb7ba961da251b82da2d4e248eb5e930e5cd853a0c0e4c184863483c1be3 +size 58094 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png index d28b54f3cc..f34df6b6a6 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e15f573b4d081b17f91ad2e19cc4920063dad46755217145fb8b13288eb2ad3b -size 65754 +oid sha256:f7bbd1bd20c2f1198e8e9681ce20a162586d4240ff8e6408675abad364f1e544 +size 65417 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png index 1e87d303a9..9c1c251e28 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d80a1a50b289631c432e1247af2ec1a41a9cb233f4ef9c5f6c964784113ff401 -size 101387 +oid sha256:a05a648bffe46f29a377bbf4ad548df153e3c17a0e8014a594d8314d4b85cf4b +size 101198 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png index 7903b1ba42..80150353ae 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:157c70292051f5dd737f309b2bdadddbe6cbf7ec3b322a3c47b937edc4df72e0 -size 57461 +oid sha256:4cc0e4d504ebda2d86e0c7ae557a89587d68957bacfcec9f918f740ab9ddcbe8 +size 57121 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png index a997076a87..51f4051085 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44df9e6774110798c72042f560bcc344a5b292f11cba5893190ad78513a8d07e -size 57468 +oid sha256:b657f75efe8e75f2e8f0ca45ed0d9ecb62400e3b214764edc2e1915812742c3d +size 56980 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png index b198b87ff5..abfdbcf57e 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8323ee0e5869c5408cc17476fb603af972fa570d1e6896bc063ce401f4d1582f -size 67617 +oid sha256:bb0220077eb2469994f899d9819baa3b4422525c306159f651f502cbebd24150 +size 67414 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png index 5515d78ee1..96f810d9ab 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31e974364b144d6270b890bf7293ca84a8680105d3914d5d6d2c1fa766b463a1 -size 56853 +oid sha256:6e9c42a7caed334e3da02c82d234b61ba95216d65e593ac8461c0649a0b032ab +size 56467 diff --git a/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png b/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png new file mode 100644 index 0000000000..eaa36d2c24 --- /dev/null +++ b/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:181ce0a2bf5e6eb95a7726bdf26540f2320e5fb6bc4d86b17f9e027314d79f0c +size 16262 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 47f9890ad3..0bf3fbcf3b 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,99 +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",20563,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20567,], ["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",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.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20567,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20567,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20567,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20567,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20567,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20567,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20567,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20567,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20567,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20567,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20567,], ["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",20563,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20563,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20567,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20567,], ["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",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_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20567,], ["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",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,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20567,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20567,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20567,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20567,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20567,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20570,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20567,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20567,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20567,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20567,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["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,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20567,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20567,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20567,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20567,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20567,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",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,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20570,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20570,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20570,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20567,], ["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",20563,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20567,], ["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",20563,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20567,], ["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",20563,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20567,], ["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",20563,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20567,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_0_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_0_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_1_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_1_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_2_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_2_en",0,], @@ -103,19 +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","",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,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20567,], ["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",20563,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20567,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.matrix.ui.components_AvatarPickerSizes_Day_0_en","libraries.matrix.ui.components_AvatarPickerSizes_Night_0_en",0,], ["libraries.matrix.ui.components_AvatarPickerViewRtl_Day_0_en","libraries.matrix.ui.components_AvatarPickerViewRtl_Night_0_en",0,], @@ -145,22 +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",20563,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20567,], ["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",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,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20567,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["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_BugReportViewDay_0_en","",20567,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20567,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20567,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20567,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20567,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -171,141 +171,140 @@ 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",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_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20567,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20567,], ["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",20563,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20567,], ["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",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.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20567,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20567,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20567,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20567,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20567,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20567,], ["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",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.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20567,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20567,], ["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",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,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20567,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20567,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20567,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20567,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20567,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20563,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20567,], ["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",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,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20567,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20567,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20567,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20567,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20567,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20567,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20567,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20567,], ["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",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.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20567,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20567,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20567,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20567,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20567,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20567,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20567,], ["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","",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,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20567,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20567,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20567,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20567,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20567,], ["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",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,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20567,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20567,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20567,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20567,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20567,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20567,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20567,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20567,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20567,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20567,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20567,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20567,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20567,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20567,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20567,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20567,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20567,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20567,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20567,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20567,], ["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","",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,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20567,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20567,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20567,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20567,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20567,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20567,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20567,], ["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",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_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20567,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20567,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20567,], ["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",20563,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20567,], ["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",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,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20567,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20567,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20567,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20567,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20567,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20567,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20567,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20567,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20567,], ["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,], @@ -320,20 +319,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",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,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20567,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20567,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20567,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20567,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20567,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20567,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20567,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20567,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20567,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20567,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20567,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20567,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20567,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20570,], ["libraries.matrix.ui.components_EditableOrgAvatarRtl_Day_0_en","libraries.matrix.ui.components_EditableOrgAvatarRtl_Night_0_en",0,], ["libraries.matrix.ui.components_EditableOrgAvatar_Day_0_en","libraries.matrix.ui.components_EditableOrgAvatar_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_Night_0_en",0,], @@ -341,28 +340,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",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_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20567,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20567,], ["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",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.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20567,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20567,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20567,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20567,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20567,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20567,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20567,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20567,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20567,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20567,], ["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,], @@ -382,49 +381,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",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.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20567,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20567,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20567,], ["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",20563,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20563,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20567,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20567,], ["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,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20570,], ["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",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.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20567,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20567,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20567,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20567,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20567,], ["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",20563,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20563,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20567,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20567,], ["features.home.impl_HomeViewA11y_en","",0,], -["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_0_en","features.home.impl_HomeView_Night_0_en",20567,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20567,], ["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",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,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20567,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20567,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20567,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20567,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20567,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20567,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20567,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20567,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20567,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20567,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20567,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20567,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20567,], ["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,], @@ -439,8 +438,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",20563,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20563,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20567,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20567,], ["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,], @@ -448,119 +447,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",20563,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20567,], ["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",20563,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20567,], ["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",20563,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20563,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20567,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20567,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["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,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20567,], ["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",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.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20570,], ["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_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20567,], ["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",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_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20567,], ["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",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.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20567,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20567,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20567,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20567,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20567,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20567,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20567,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20567,], ["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",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,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20567,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20567,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20567,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["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.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20567,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20567,], ["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",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,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20567,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20567,], ["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",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.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20567,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20567,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20567,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20567,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20567,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20567,], ["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",20563,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20567,], ["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,], @@ -615,45 +614,45 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20563,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20567,], ["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",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,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20567,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20567,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20567,], ["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",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,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20567,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20567,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20567,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20567,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20567,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20567,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20567,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20567,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20567,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20567,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20567,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20567,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20567,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20570,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20570,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20567,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20567,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20567,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20567,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20567,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20567,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20567,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20567,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20567,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20567,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20567,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20567,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["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,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20567,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20567,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20567,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20567,], ["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,], @@ -666,22 +665,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20563,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20563,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20567,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20570,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20567,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20570,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20570,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20570,], ["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",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.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20567,], ["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,], @@ -689,15 +692,15 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20570,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20570,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20570,], ["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_2_en","",20570,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -707,15 +710,15 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20563,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20563,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20567,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20567,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20563,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20567,], ["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","",20563,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20567,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -729,7 +732,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",20563,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20567,], ["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,], @@ -738,7 +741,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",20563,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20567,], ["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,], @@ -747,23 +750,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",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.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20567,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20567,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20567,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20567,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20567,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20567,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20567,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20567,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20567,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20567,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20567,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20567,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20567,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20567,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20567,], ["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",20563,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20567,], ["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,], @@ -774,113 +777,113 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",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.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20567,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20567,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20567,], ["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",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,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20567,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20570,], ["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",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,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20567,], ["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",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,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20567,], ["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",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,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20567,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20567,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20567,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20567,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20567,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20567,], ["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",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.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20567,], ["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",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,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20567,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20567,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20567,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20567,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20567,], ["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",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_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20567,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20567,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20567,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20567,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20567,], ["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",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_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20567,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20567,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20567,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20567,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20567,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20567,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20567,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20567,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20567,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20567,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20567,], ["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,], @@ -894,223 +897,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","",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.preferences.impl.root_PreferencesRootViewDark_0_en","",20567,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20567,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20567,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20567,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20570,], ["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","",20563,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20563,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20567,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20567,], ["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",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.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20567,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20567,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20567,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20567,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20567,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20567,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20567,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20567,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20567,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20567,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20567,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20567,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20567,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20567,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20567,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20567,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20567,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20567,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20567,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20567,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20567,], ["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",20563,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20563,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20567,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20567,], ["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",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,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20567,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20567,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20567,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20567,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20567,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20567,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20567,], ["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",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.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20567,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20567,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20567,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20567,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20567,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20567,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20567,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20567,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20567,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20567,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20567,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20567,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20567,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20567,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20567,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20567,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20567,], ["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",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,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20567,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20567,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20567,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20567,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20567,], ["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",20563,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20563,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20567,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20567,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["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.roomdetails.impl_RoomDetailsDark_0_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20567,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20567,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20567,], +["features.roomdetails.impl_RoomDetails_0_en","",20567,], +["features.roomdetails.impl_RoomDetails_10_en","",20567,], +["features.roomdetails.impl_RoomDetails_11_en","",20567,], +["features.roomdetails.impl_RoomDetails_12_en","",20567,], +["features.roomdetails.impl_RoomDetails_13_en","",20567,], +["features.roomdetails.impl_RoomDetails_14_en","",20567,], +["features.roomdetails.impl_RoomDetails_15_en","",20567,], +["features.roomdetails.impl_RoomDetails_16_en","",20567,], +["features.roomdetails.impl_RoomDetails_17_en","",20567,], +["features.roomdetails.impl_RoomDetails_18_en","",20567,], +["features.roomdetails.impl_RoomDetails_19_en","",20567,], +["features.roomdetails.impl_RoomDetails_1_en","",20567,], +["features.roomdetails.impl_RoomDetails_20_en","",20567,], +["features.roomdetails.impl_RoomDetails_21_en","",20567,], +["features.roomdetails.impl_RoomDetails_22_en","",20567,], +["features.roomdetails.impl_RoomDetails_2_en","",20567,], +["features.roomdetails.impl_RoomDetails_3_en","",20567,], +["features.roomdetails.impl_RoomDetails_4_en","",20567,], +["features.roomdetails.impl_RoomDetails_5_en","",20567,], +["features.roomdetails.impl_RoomDetails_6_en","",20567,], +["features.roomdetails.impl_RoomDetails_7_en","",20567,], +["features.roomdetails.impl_RoomDetails_8_en","",20567,], +["features.roomdetails.impl_RoomDetails_9_en","",20567,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20567,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20567,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20567,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20567,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20567,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20567,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20567,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20567,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20567,], ["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",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.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20567,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20567,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20567,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20567,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20567,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20567,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20567,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20567,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20567,], ["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",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.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20567,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20567,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20567,], ["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",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,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20567,], ["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",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,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20567,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20567,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20567,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20567,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20567,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20567,], ["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,], @@ -1133,16 +1136,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",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_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20567,], ["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",20563,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20567,], ["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,], @@ -1151,119 +1154,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",20563,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20567,], ["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,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20567,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20567,], ["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",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,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20567,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20567,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20567,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20567,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20567,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20567,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20567,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20567,], ["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","",20563,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20567,], ["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","",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,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20567,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20567,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20567,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20567,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20567,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20567,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20567,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20567,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20567,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20567,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20567,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20567,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20567,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20567,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20567,], ["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,], @@ -1286,33 +1289,35 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",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.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20567,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20567,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20567,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20567,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20567,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20567,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20567,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20567,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20567,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20567,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20567,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20567,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20567,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20567,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20567,], ["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",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,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20567,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20567,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20567,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20567,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20567,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20567,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20567,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20570,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20570,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20567,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20567,], ["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,], @@ -1322,106 +1327,107 @@ 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",20563,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20567,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",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",20563,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20567,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20567,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20567,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20570,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20567,], ["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",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.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20567,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20567,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20567,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20567,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20567,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20567,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20567,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20567,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20567,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20567,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20567,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20567,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20567,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20567,], ["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",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.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20567,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20567,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20567,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20567,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20567,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20567,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20567,], ["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",20563,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20567,], ["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",20563,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20567,], ["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",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_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20567,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20567,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20567,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20567,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20567,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20567,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20567,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20567,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20567,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20567,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20567,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20567,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20570,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20567,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20567,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20567,], ["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",20563,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20563,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20567,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20567,], ["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,], @@ -1434,17 +1440,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20563,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20563,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20567,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20567,], ["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,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20567,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20567,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20567,], ["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",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_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20567,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20567,], ["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,], @@ -1454,18 +1460,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",20563,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20567,], ["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",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.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20567,], ["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,], @@ -1473,18 +1479,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",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_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20567,], ["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",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_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20567,], ["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",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_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20567,], ["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,], @@ -1493,42 +1499,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20567,], ["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",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20567,], ["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",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20567,], ["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","",20563,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20567,], ["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",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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20567,], ["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",20563,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20567,], ["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",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.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20570,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20570,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20570,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20570,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20567,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20567,], ["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",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_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20567,], ["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",20563,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20567,], ["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,], @@ -1537,8 +1545,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",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.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20567,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20567,], ["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,], @@ -1553,8 +1561,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",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_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20567,], ["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,], @@ -1577,84 +1585,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",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",20563,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20567,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20570,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20567,], ["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",20563,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20567,], ["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",20563,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20567,], ["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",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,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20567,], ["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",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_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20567,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20567,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20567,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20567,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20567,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20567,], ["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","",20563,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20567,], ["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",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.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20567,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20567,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20567,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20567,], ["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",20563,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20567,], ["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",20563,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20567,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",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.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20567,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20567,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20567,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20567,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20567,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20567,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20567,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20567,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20567,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20567,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20567,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20567,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20567,], ["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",20563,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20563,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20567,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20567,], ["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",20563,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20567,], ["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,], From 14054344f4789b49f557d48d64fe2b763cc94d51 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 07:20:07 +0000 Subject: [PATCH 0240/1083] Update dependency org.jsoup:jsoup to v1.22.2 --- 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 edbfdc2489..3a1afc3373 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -191,7 +191,7 @@ serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-jso kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.4.0" showkase = { module = "com.airbnb.android:showkase", version.ref = "showkase" } showkase_processor = { module = "com.airbnb.android:showkase-processor", version.ref = "showkase" } -jsoup = "org.jsoup:jsoup:1.21.2" +jsoup = "org.jsoup:jsoup:1.22.2" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.2.0" timber = "com.jakewharton.timber:timber:5.0.1" From bf57223d0561d8e349a9d5cb57cd4e1d95f30ece Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 09:48:38 +0200 Subject: [PATCH 0241/1083] RoomListDeclineInviteMenu: limit room name Improve preview. Closes #6659 --- .../android/appconfig/ProtectionConfig.kt | 15 ++++++++ .../roomlist/RoomListDeclineInviteMenu.kt | 24 ++++++++----- ...ListStateDeclineInviteMenuShownProvider.kt | 36 +++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 appconfig/src/main/kotlin/io/element/android/appconfig/ProtectionConfig.kt create mode 100644 features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateDeclineInviteMenuShownProvider.kt diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/ProtectionConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/ProtectionConfig.kt new file mode 100644 index 0000000000..f6ad71eeb1 --- /dev/null +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/ProtectionConfig.kt @@ -0,0 +1,15 @@ +/* + * 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.appconfig + +object ProtectionConfig { + /** + * The maximum length of a room name, to limit attack vectors in room invite. + */ + const val MAX_ROOM_NAME_LENGTH = 128 +} diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt index 523e677a57..d641a06063 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt @@ -19,10 +19,13 @@ 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.appconfig.ProtectionConfig import io.element.android.compound.theme.ElementTheme import io.element.android.features.home.impl.R import io.element.android.features.home.impl.model.RoomListRoomSummary +import io.element.android.libraries.core.extensions.toSafeLength import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button @@ -44,7 +47,11 @@ fun RoomListDeclineInviteMenu( onDismissRequest = { eventSink(RoomListEvent.HideDeclineInviteMenu) }, ) { RoomListDeclineInviteMenuContent( - roomName = menu.roomSummary.name ?: menu.roomSummary.roomId.value, + roomName = menu.roomSummary.name?.toSafeLength( + maxLength = ProtectionConfig.MAX_ROOM_NAME_LENGTH, + ellipsize = true, + ) + ?: menu.roomSummary.roomId.value, onDeclineClick = { eventSink(RoomListEvent.HideDeclineInviteMenu) eventSink(RoomListEvent.DeclineInvite(menu.roomSummary, false)) @@ -112,16 +119,15 @@ private fun RoomListDeclineInviteMenuContent( } } -// TODO This component should be seen in [RoomListView] @Preview but it doesn't show up. -// see: https://issuetracker.google.com/issues/283843380 -// Remove this preview when the issue is fixed. @PreviewsDayNight @Composable -internal fun RoomListDeclineInviteMenuContentPreview() = ElementPreview { - RoomListDeclineInviteMenuContent( - roomName = "Room name", - onCancelClick = {}, - onDeclineClick = {}, +internal fun RoomListDeclineInviteMenuContentPreview( + @PreviewParameter(RoomListStateDeclineInviteMenuShownProvider::class) menu: RoomListState.DeclineInviteMenu.Shown, +) = ElementPreview { + RoomListDeclineInviteMenu( + menu = menu, + canReportRoom = false, onDeclineAndBlockClick = {}, + eventSink = {}, ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateDeclineInviteMenuShownProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateDeclineInviteMenuShownProvider.kt new file mode 100644 index 0000000000..73d4785e96 --- /dev/null +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListStateDeclineInviteMenuShownProvider.kt @@ -0,0 +1,36 @@ +/* + * 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.home.impl.roomlist + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.tooling.preview.datasource.LoremIpsum +import io.element.android.features.home.impl.model.RoomListRoomSummary +import io.element.android.features.home.impl.model.aRoomListRoomSummary + +open class RoomListStateDeclineInviteMenuShownProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aDeclineInviteMenuShown(), + aDeclineInviteMenuShown( + aRoomListRoomSummary( + name = LoremIpsum(500).values.first(), + ) + ), + aDeclineInviteMenuShown( + aRoomListRoomSummary( + name = null, + ) + ), + ) +} + +internal fun aDeclineInviteMenuShown( + roomSummary: RoomListRoomSummary = aRoomListRoomSummary(), +) = RoomListState.DeclineInviteMenu.Shown( + roomSummary = roomSummary, +) From 09ff3294d5e22e0db34f5924fec5639f775811b4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 10:23:56 +0200 Subject: [PATCH 0242/1083] Ensure that all the ModalBottomSheet can scroll. --- .../configureroom/SelectParentSpaceOptions.kt | 3 ++- .../home/impl/roomlist/RoomListContextMenu.kt | 7 +++++- .../roomlist/RoomListDeclineInviteMenu.kt | 6 ++++- .../impl/spacefilters/SpaceFiltersView.kt | 3 ++- .../invitepeople/impl/InvitePeopleView.kt | 1 + .../impl/actionlist/ActionListView.kt | 1 + .../ResolveVerifiedUserSendFailureView.kt | 1 + .../messagecomposer/AttachmentsBottomSheet.kt | 6 ++++- .../CustomReactionBottomSheet.kt | 3 ++- .../reactionsummary/ReactionSummaryView.kt | 3 ++- .../bottomsheet/ReadReceiptBottomSheet.kt | 3 ++- .../impl/root/RolesAndPermissionsView.kt | 1 + .../impl/RoomMemberModerationView.kt | 7 +++++- .../joinbyaddress/JoinRoomByAddressView.kt | 6 ++++- .../components/SimpleModalBottomSheet.kt | 6 ++++- .../theme/components/ModalBottomSheet.kt | 22 +++++++++++++++++-- .../ui/components/AvatarActionBottomSheet.kt | 1 + .../CreateDmConfirmationBottomSheet.kt | 20 +++++++++++------ .../MediaDeleteConfirmationBottomSheet.kt | 3 ++- .../impl/details/MediaDetailsBottomSheet.kt | 1 + .../textcomposer/CaptionWarningBottomSheet.kt | 6 ++++- 21 files changed, 88 insertions(+), 22 deletions(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/SelectParentSpaceOptions.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/SelectParentSpaceOptions.kt index 6b7b66b897..1480e57334 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/SelectParentSpaceOptions.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/SelectParentSpaceOptions.kt @@ -95,7 +95,8 @@ internal fun SelectParentSpaceOptions( sheetState.hide(coroutineScope) { displaySelectSpaceBottomSheet = false } - } + }, + scrollable = false, ) { SelectParentSpaceBottomSheet( spaces = spaces, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt index 30e3aaf0b7..569787c383 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt @@ -11,6 +11,8 @@ package io.element.android.features.home.impl.roomlist import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -43,6 +45,7 @@ fun RoomListContextMenu( ) { ModalBottomSheet( onDismissRequest = { eventSink(RoomListEvent.HideContextMenu) }, + scrollable = false, ) { RoomListModalBottomSheetContent( contextMenu = contextMenu, @@ -91,7 +94,9 @@ private fun RoomListModalBottomSheetContent( onReportRoomClick: () -> Unit, ) { Column( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()) ) { ListItem( headlineContent = { diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt index d641a06063..74462ec10c 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt @@ -13,6 +13,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.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -45,6 +47,7 @@ fun RoomListDeclineInviteMenu( ) { ModalBottomSheet( onDismissRequest = { eventSink(RoomListEvent.HideDeclineInviteMenu) }, + scrollable = false, ) { RoomListDeclineInviteMenuContent( roomName = menu.roomSummary.name?.toSafeLength( @@ -81,7 +84,8 @@ private fun RoomListDeclineInviteMenuContent( Column( modifier = Modifier .fillMaxWidth() - .padding(all = 16.dp), + .padding(all = 16.dp) + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, ) { Text( diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt index fb77c74203..1f0d6ff7d9 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt @@ -81,7 +81,8 @@ fun SpaceFiltersView( if (state is SpaceFiltersState.Selecting) { state.eventSink(SpaceFiltersEvent.Selecting.Cancel) } - } + }, + scrollable = false, ) { Box( modifier = Modifier 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 289ac193d4..b1f139f43c 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 @@ -262,6 +262,7 @@ private fun InvitePeopleConfirmModal( ModalBottomSheet( onDismissRequest = onDismiss, dragHandle = null, + scrollable = false, ) { IconTitleSubtitleMolecule( title = simplePluralStringResource( 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 ef446e36cf..e10dd2e1bc 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 @@ -156,6 +156,7 @@ fun ActionListView( sheetState = sheetState, onDismissRequest = ::onDismiss, modifier = modifier, + scrollable = false, ) { ActionListViewContent( state = state, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index 98e2bba3be..c14dd03f1e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -75,6 +75,7 @@ fun ResolveVerifiedUserSendFailureView( .navigationBarsPadding(), sheetState = sheetState, onDismissRequest = ::dismiss, + scrollable = true, ) { IconTitleSubtitleMolecule( modifier = Modifier.padding(24.dp), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt index 1fdb61f484..405e2b0be9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt @@ -13,6 +13,8 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -74,7 +76,8 @@ internal fun AttachmentsBottomSheet( sheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true ), - onDismissRequest = { isVisible = false } + onDismissRequest = { isVisible = false }, + scrollable = false, ) { AttachmentSourcePickerMenu( state = state, @@ -97,6 +100,7 @@ private fun AttachmentSourcePickerMenu( modifier = Modifier .navigationBarsPadding() .imePadding() + .verticalScroll(rememberScrollState()) ) { ListItem( modifier = Modifier.clickable { state.eventSink(MessageComposerEvent.PickAttachmentSource.PhotoFromCamera) }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt index f42a26cf65..4ac83c520b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt @@ -50,7 +50,8 @@ fun CustomReactionBottomSheet( ModalBottomSheet( onDismissRequest = ::onDismiss, sheetState = sheetState, - modifier = modifier + modifier = modifier, + scrollable = false, ) { val presenter = remember { EmojiPickerPresenter( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt index 03ce564eff..2a902fd692 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt @@ -90,7 +90,8 @@ fun ReactionSummaryView( if (state.target != null) { ModalBottomSheet( onDismissRequest = ::onDismiss, - modifier = modifier + modifier = modifier, + scrollable = false, ) { ReactionSummaryViewContent(summary = state.target) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt index b65e326045..9637298d58 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt @@ -57,7 +57,8 @@ internal fun ReadReceiptBottomSheet( sheetState.hide() state.eventSink(ReadReceiptBottomSheetEvent.Dismiss) } - } + }, + scrollable = false, ) { ReadReceiptBottomSheetContent( state = state, diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt index 269fdee664..2f8dab8029 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt @@ -153,6 +153,7 @@ private fun ChangeOwnRoleBottomSheet( .navigationBarsPadding(), sheetState = sheetState, onDismissRequest = ::dismiss, + scrollable = true, ) { Text( modifier = Modifier.padding(14.dp), diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt index ac6c5bc4cb..884e421e1f 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt @@ -17,6 +17,8 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -224,9 +226,12 @@ private fun RoomMemberActionsBottomSheet( onDismiss() } }, + scrollable = false, ) { Column( - modifier = Modifier.padding(vertical = 16.dp) + modifier = Modifier + .padding(vertical = 16.dp) + .verticalScroll(rememberScrollState()) ) { Avatar( avatarData = user.getAvatarData(size = AvatarSize.RoomListManageUser), diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt index e4f8a4faf2..360c59881c 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt @@ -13,8 +13,10 @@ 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.rememberScrollState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -52,11 +54,13 @@ fun JoinRoomByAddressView( onDismissRequest = { state.eventSink(JoinRoomByAddressEvent.Dismiss) }, + scrollable = false, ) { Column( modifier = Modifier .fillMaxWidth() - .padding(all = 16.dp), + .padding(all = 16.dp) + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, ) { RoomAddressField( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/SimpleModalBottomSheet.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/SimpleModalBottomSheet.kt index 34d119508a..9c3930ac64 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/SimpleModalBottomSheet.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/SimpleModalBottomSheet.kt @@ -14,6 +14,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.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -38,11 +40,13 @@ fun SimpleModalBottomSheet( onDismissRequest = onDismiss, modifier = modifier, sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + scrollable = false, ) { Column( modifier = Modifier .fillMaxWidth() - .padding(16.dp), + .padding(16.dp) + .verticalScroll(rememberScrollState()), ) { Text( title, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt index 2c577ec6b7..a7e9672a3a 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt @@ -10,10 +10,13 @@ package io.element.android.libraries.designsystem.theme.components import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -42,10 +45,15 @@ import io.element.android.libraries.designsystem.preview.sheetStateForPreview import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +/** + * For parameter [scrollable], set it to true if the content of the sheet does not already contain a scrollable component, such as a LazyColumn, + * to avoid nested scroll issues. In this case, the content will be wrapped in a Column with verticalScroll. + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun ModalBottomSheet( onDismissRequest: () -> Unit, + scrollable: Boolean, modifier: Modifier = Modifier, sheetState: SheetState = rememberModalBottomSheetState(), shape: Shape = BottomSheetDefaults.ExpandedShape, @@ -79,8 +87,17 @@ fun ModalBottomSheet( scrimColor = scrimColor, dragHandle = dragHandle, contentWindowInsets = contentWindowInsets, - content = content, - ) + ) { + if (scrollable) { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()), + ) { + content() + } + } else { + content() + } + } } @OptIn(ExperimentalMaterial3Api::class) @@ -112,6 +129,7 @@ private fun ContentToPreview() { ) { ModalBottomSheet( onDismissRequest = {}, + scrollable = false, ) { Text( text = "Sheet Content", diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt index 4628833bb4..880a7a9df6 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt @@ -67,6 +67,7 @@ fun AvatarActionBottomSheet( }, modifier = modifier, sheetState = sheetState, + scrollable = false, ) { AvatarActionBottomSheetContent( actions = actions, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt index f63bda378b..d663177ee6 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CreateDmConfirmationBottomSheet.kt @@ -14,6 +14,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.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState @@ -74,11 +76,13 @@ fun CreateDmConfirmationBottomSheet( modifier = modifier, onDismissRequest = onDismiss, sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + scrollable = false, ) { Column( modifier = Modifier .fillMaxWidth() - .padding(top = 24.dp, bottom = 16.dp, start = 16.dp, end = 16.dp), + .padding(top = 24.dp, bottom = 16.dp, start = 16.dp, end = 16.dp) + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, ) { if (isUserIdentityUnknown) { @@ -148,9 +152,11 @@ fun CreateDmConfirmationBottomSheet( @PreviewsDayNight @Composable -internal fun CreateDmConfirmationBottomSheetPreview(@PreviewParameter( - CreateDmConfirmationBottomSheetStateProvider::class -) state: CreateDmConfirmationBottomSheetState) = ElementPreview { +internal fun CreateDmConfirmationBottomSheetPreview( + @PreviewParameter( + CreateDmConfirmationBottomSheetStateProvider::class + ) state: CreateDmConfirmationBottomSheetState +) = ElementPreview { CreateDmConfirmationBottomSheet( matrixUser = state.matrixUser, isUserIdentityUnknown = state.isUserIdentityUnknown, @@ -166,7 +172,7 @@ data class CreateDmConfirmationBottomSheetState( class CreateDmConfirmationBottomSheetStateProvider : PreviewParameterProvider { override val values = sequenceOf( - CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = false), - CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = true), - ) + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = false), + CreateDmConfirmationBottomSheetState(matrixUser = aMatrixUser(), isUserIdentityUnknown = true), + ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt index f13e2f1600..0cae7f0262 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheet.kt @@ -59,7 +59,8 @@ fun MediaDeleteConfirmationBottomSheet( ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, - sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + scrollable = false, ) { Column( modifier = Modifier diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index 9ce2dc4a7f..0c73bfd17c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -72,6 +72,7 @@ fun MediaDetailsBottomSheet( ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, + scrollable = false, ) { Column( modifier = Modifier diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt index 23b4fae3a9..bec837664f 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/CaptionWarningBottomSheet.kt @@ -12,6 +12,8 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -37,11 +39,13 @@ fun CaptionWarningBottomSheet( ModalBottomSheet( modifier = modifier, onDismissRequest = onDismiss, + scrollable = false, ) { Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .padding(horizontal = 16.dp) + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(16.dp), ) { From 0d078a41ca74a3c1e5d23428523c4a0e1ee9eeb5 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 27 Apr 2026 08:40:35 +0000 Subject: [PATCH 0243/1083] Update screenshots --- ...mpl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png | 4 ++-- ...mpl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png | 3 +++ ...mpl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png | 3 +++ ...l.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png | 4 ++-- ...l.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png | 3 +++ ...l.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png | 3 +++ 6 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png index 70e3f6ae06..686013e622 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22e3dce5359ba6dd21bd1c17e4421b8341c51809843394c95a3d80db7a235309 -size 25774 +oid sha256:2a58c642983f209f2c4bb01ee0239c11edab299f48129800cbd41fe7a9032ad4 +size 26854 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png new file mode 100644 index 0000000000..278dfc4ae5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43837ff4703be9631370b56097bd36006bce98d23f17db629742c957ce945e5a +size 42390 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png new file mode 100644 index 0000000000..63a523b4ae --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b3025b589185d8d276bd3a809d8d94700268be1aec951fd02ff37072cef4998 +size 27431 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png index ddea584902..d6392b8c0f 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:671a0a0ce5571cb460fba789b58ec1e38b63b26ba61c1daeb5cccb986eb424b4 -size 24768 +oid sha256:2d7acb04225299d448edf35ad1f420ceafcabc7759a8f7d94ce11eca70781f79 +size 25339 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png new file mode 100644 index 0000000000..bf799e5042 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56b210d5d8dc06de139735ca34f2b5a4e5e7d0db395dc2dbe7b1c9d479d8858d +size 40405 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png new file mode 100644 index 0000000000..27a4cd57b0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ff47c937641549f63948d114510644aad02723a55e752587a1037752a2b3972 +size 25966 From a35236b8b0815dfc9115f6bbf504ad087ae8de29 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 15:12:23 +0200 Subject: [PATCH 0244/1083] Rename Preview. --- .../features/home/impl/roomlist/RoomListDeclineInviteMenu.kt | 2 +- ...s.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en.png} | 0 ...s.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en.png} | 0 ...s.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en.png} | 0 ...home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en.png} | 0 ...home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en.png} | 0 ...home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en.png} | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename tests/uitests/src/test/snapshots/images/{features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png => features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png => features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png => features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png => features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png => features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png => features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en.png} (100%) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt index 74462ec10c..0a7a29ebc2 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenu.kt @@ -125,7 +125,7 @@ private fun RoomListDeclineInviteMenuContent( @PreviewsDayNight @Composable -internal fun RoomListDeclineInviteMenuContentPreview( +internal fun RoomListDeclineInviteMenuPreview( @PreviewParameter(RoomListStateDeclineInviteMenuShownProvider::class) menu: RoomListState.DeclineInviteMenu.Shown, ) = ElementPreview { RoomListDeclineInviteMenu( diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en.png rename to tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_1_en.png rename to tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_2_en.png rename to tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en.png rename to tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_1_en.png rename to tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_2_en.png rename to tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en.png From e289ec2af7cb106b0c9b58c0b54b5098e3da97e3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 15:15:23 +0200 Subject: [PATCH 0245/1083] Preview the whole bottom sheet. --- .../home/impl/roomlist/RoomListContextMenu.kt | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt index 569787c383..66982961fd 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt @@ -217,23 +217,16 @@ private fun RoomListModalBottomSheetContent( } } -// TODO This component should be seen in [RoomListView] @Preview but it doesn't show up. -// see: https://issuetracker.google.com/issues/283843380 -// Remove this preview when the issue is fixed. @PreviewsDayNight @Composable -internal fun RoomListModalBottomSheetContentPreview( +internal fun RoomListContextMenuPreview( @PreviewParameter(RoomListStateContextMenuShownProvider::class) contextMenu: RoomListState.ContextMenu.Shown ) = ElementPreview { - RoomListModalBottomSheetContent( + RoomListContextMenu( contextMenu = contextMenu, canReportRoom = true, - onRoomMarkReadClick = {}, - onRoomMarkUnreadClick = {}, onRoomSettingsClick = {}, - onLeaveRoomClick = {}, - onFavoriteChange = {}, - onClearCacheRoomClick = {}, onReportRoomClick = {}, + eventSink = {}, ) } From dca2dba938f9fe451702d487a35afb644af0ac60 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 15:16:42 +0200 Subject: [PATCH 0246/1083] Remove obsolete comment. --- .../libraries/designsystem/theme/components/ModalBottomSheet.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt index a7e9672a3a..689cba727f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt @@ -108,13 +108,11 @@ fun SheetState.hide(coroutineScope: CoroutineScope, then: suspend () -> Unit) { } } -// This preview and its screenshots are blank, see: https://issuetracker.google.com/issues/283843380 @Preview(group = PreviewGroup.BottomSheets) @Composable internal fun ModalBottomSheetLightPreview() = ElementPreviewLight { ContentToPreview() } -// This preview and its screenshots are blank, see: https://issuetracker.google.com/issues/283843380 @Preview(group = PreviewGroup.BottomSheets) @Composable internal fun ModalBottomSheetDarkPreview() = From e4ccec1cdd8c8de6b59964206119a4ee51148024 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 20 Apr 2026 14:53:05 +0200 Subject: [PATCH 0247/1083] call: Remove deprecated web<->EX api calls, use the new ones --- .../features/call/impl/utils/WebViewAudioManager.kt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index 2d674d21af..a72acb0594 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -268,10 +268,9 @@ class WebViewAudioManager( private fun setWebViewAndroidNativeBridge() { Timber.d("Adding callback in controls.onAudioPlaybackStarted") webView.evaluateJavascript("controls.onAudioPlaybackStarted = () => { androidNativeBridge.onTrackReady(); };", null) - Timber.d("Adding callback in controls.onOutputDeviceSelect") - webView.evaluateJavascript("controls.onOutputDeviceSelect = (id) => { androidNativeBridge.setOutputDevice(id); };", null) + Timber.d("Adding callback in controls.onAudioDeviceSelect") + webView.evaluateJavascript("controls.onAudioDeviceSelect = (id) => { androidNativeBridge.setAudioDevice(id); };", null) } - /** * Returns the list of available audio devices, sorted by likelihood of it being used for communication. * @@ -296,8 +295,8 @@ class WebViewAudioManager( ) { Timber.d("Updating available audio devices") val deviceList = json.encodeToString(devices) - webView.evaluateJavascript("controls.setAvailableOutputDevices($deviceList);", { - Timber.d("Audio: setAvailableOutputDevices result: $it") + webView.evaluateJavascript("controls.setAvailableAudioDevices($deviceList);", { + Timber.d("Audio: setAvailableAudioDevices result: $it") }) } @@ -402,7 +401,7 @@ private class AndroidWebViewAudioBridge( private val onAudioPlaybackStarted: () -> Unit, ) { @JavascriptInterface - fun setOutputDevice(id: String) { + fun setAudioDevice(id: String) { Timber.d("Audio device selected in webview, id: $id") onAudioDeviceSelected(id) } From aff53c2bc211f77ef354e5fc3ebbe2388e1386a2 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 27 Apr 2026 15:27:27 +0200 Subject: [PATCH 0248/1083] ktlint format --- .../android/features/call/impl/utils/WebViewAudioManager.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index a72acb0594..88c1d95572 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -271,6 +271,7 @@ class WebViewAudioManager( Timber.d("Adding callback in controls.onAudioDeviceSelect") webView.evaluateJavascript("controls.onAudioDeviceSelect = (id) => { androidNativeBridge.setAudioDevice(id); };", null) } + /** * Returns the list of available audio devices, sorted by likelihood of it being used for communication. * From 21cae089ae21992be18fb37aa98152edf20c6d2f Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 27 Apr 2026 13:39:42 +0000 Subject: [PATCH 0249/1083] Update screenshots --- ...eatures.home.impl.roomlist_RoomListContextMenu_Day_0_en.png | 3 +++ ...eatures.home.impl.roomlist_RoomListContextMenu_Day_1_en.png | 3 +++ ...eatures.home.impl.roomlist_RoomListContextMenu_Day_2_en.png | 3 +++ ...tures.home.impl.roomlist_RoomListContextMenu_Night_0_en.png | 3 +++ ...tures.home.impl.roomlist_RoomListContextMenu_Night_1_en.png | 3 +++ ...tures.home.impl.roomlist_RoomListContextMenu_Night_2_en.png | 3 +++ ....impl.roomlist_RoomListModalBottomSheetContent_Day_0_en.png | 3 --- ....impl.roomlist_RoomListModalBottomSheetContent_Day_1_en.png | 3 --- ....impl.roomlist_RoomListModalBottomSheetContent_Day_2_en.png | 3 --- ...mpl.roomlist_RoomListModalBottomSheetContent_Night_0_en.png | 3 --- ...mpl.roomlist_RoomListModalBottomSheetContent_Night_1_en.png | 3 --- ...mpl.roomlist_RoomListModalBottomSheetContent_Night_2_en.png | 3 --- 12 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png new file mode 100644 index 0000000000..6b4037b3eb --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c755a7dcfc2c9f48d449e570a3f1af1cde299fd90ddd4478e9a4c315cf03128 +size 23810 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png new file mode 100644 index 0000000000..e64ae4c3cf --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efa5408c3af0fcd39659b8d30b21ace43be46d2876815ad592f802a7887b5eb9 +size 23678 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png new file mode 100644 index 0000000000..82b04fc045 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fc512e71e168473e0e976be3e3e6cd24b455273257ad0adf970fc2641da43bb +size 25679 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png new file mode 100644 index 0000000000..f52d785548 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de71af50bba66a285b5ef44e1a4fe76ce6dc2e094c4c09ddf701deb9a5db898d +size 22025 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png new file mode 100644 index 0000000000..eef2177c3b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88b3583d55c6855027f13a152a6fc414f6b9e11d65e5b5403463b84fafe38c3f +size 21891 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png new file mode 100644 index 0000000000..87d3f56720 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e64367832735139b68269a8c679b9c6f2b929b906124a0ee93735cbdd9202d6d +size 23826 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en.png deleted file mode 100644 index 9b17990dbe..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a81e2f9d2c3834004b49b925025478b886c065a12dc850f1c42733e457630b97 -size 22442 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en.png deleted file mode 100644 index 5b45fb30de..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d3348885402696e4b8005740a452384223f60a64c524c32713cfbd9b3041e494 -size 22297 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en.png deleted file mode 100644 index 1ec1abe309..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a1a54d3171418082d8bdf442bb34c6b149e2707963f88dd7ea7cbff401534fc0 -size 23856 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en.png deleted file mode 100644 index e5a42fb07f..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ea756319eeb2d9ab6ad2425498a7a9902acada24c3ab359f880b5934f2511e5 -size 21384 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en.png deleted file mode 100644 index 2388eb323d..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c75bbb8425fa4b01f9d0d9398d93785f2a149f4abb820dadbfadf17bf4a6673e -size 21077 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en.png deleted file mode 100644 index 356ee32526..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:99defb3eb8530142a74c083d4f4ec2e592d465b3d2cf869e1710031ad6a805c9 -size 23136 From 88606474770e988cfdcb573cef474cabf824d3b2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 17:01:08 +0200 Subject: [PATCH 0250/1083] Element Call: remove support for SPA call links. Closes #6578 --- .../call/api/{CallType.kt => CallData.kt} | 25 +- .../call/api/ElementCallEntryPoint.kt | 8 +- .../call/impl/src/main/AndroidManifest.xml | 36 +-- .../call/impl/DefaultElementCallEntryPoint.kt | 14 +- .../RingingCallNotificationCreator.kt | 11 +- .../receivers/DeclineCallBroadcastReceiver.kt | 4 +- .../call/impl/ui/CallScreenPresenter.kt | 82 +++---- .../features/call/impl/ui/CallScreenState.kt | 1 - .../call/impl/ui/CallScreenStateProvider.kt | 2 - .../call/impl/ui/CallTypeExtension.kt | 19 -- .../call/impl/ui/ElementCallActivity.kt | 43 ++-- .../call/impl/ui/IncomingCallActivity.kt | 12 +- .../call/impl/utils/ActiveCallManager.kt | 51 ++-- .../call/impl/utils/CallIntentDataParser.kt | 98 -------- .../call/impl/utils/IntentProvider.kt | 10 +- .../call/DefaultElementCallEntryPointTest.kt | 6 +- .../android/features/call/ui/CallDataTest.kt | 23 ++ .../call/ui/CallScreenPresenterTest.kt | 95 +------- .../android/features/call/ui/CallTypeTest.kt | 45 ---- .../call/utils/CallIntentDataParserTest.kt | 226 ------------------ .../utils/DefaultActiveCallManagerTest.kt | 32 ++- .../call/utils/FakeActiveCallManager.kt | 14 +- .../call/test/FakeElementCallEntryPoint.kt | 14 +- .../messages/impl/MessagesFlowNode.kt | 12 +- .../roomdetails/impl/RoomDetailsFlowNode.kt | 8 +- .../userprofile/impl/UserProfileFlowNode.kt | 4 +- .../NotificationResultProcessor.kt | 8 +- .../DefaultNotificationResultProcessorTest.kt | 8 +- tools/adb/callLinkCustomScheme.sh | 14 -- tools/adb/callLinkCustomScheme2.sh | 14 -- 30 files changed, 203 insertions(+), 736 deletions(-) rename features/call/api/src/main/kotlin/io/element/android/features/call/api/{CallType.kt => CallData.kt} (50%) delete mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallTypeExtension.kt delete mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallIntentDataParser.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallDataTest.kt delete mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallTypeTest.kt delete mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/utils/CallIntentDataParserTest.kt delete mode 100755 tools/adb/callLinkCustomScheme.sh delete mode 100755 tools/adb/callLinkCustomScheme2.sh diff --git a/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt b/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallData.kt similarity index 50% rename from features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt rename to features/call/api/src/main/kotlin/io/element/android/features/call/api/CallData.kt index 4b09813418..c1dcf573c6 100644 --- a/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt +++ b/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallData.kt @@ -14,22 +14,9 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import kotlinx.parcelize.Parcelize -sealed interface CallType : NodeInputs, Parcelable { - @Parcelize - data class ExternalUrl(val url: String) : CallType { - override fun toString(): String { - return "ExternalUrl" - } - } - - @Parcelize - data class RoomCall( - val sessionId: SessionId, - val roomId: RoomId, - val isAudioCall: Boolean - ) : CallType { - override fun toString(): String { - return "RoomCall(sessionId=$sessionId, roomId=$roomId, isAudioCall=$isAudioCall)" - } - } -} +@Parcelize +data class CallData( + val sessionId: SessionId, + val roomId: RoomId, + val isAudioCall: Boolean +) : NodeInputs, Parcelable diff --git a/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt b/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt index caa557f4de..2976635ee2 100644 --- a/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt +++ b/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt @@ -17,13 +17,13 @@ import io.element.android.libraries.matrix.api.core.UserId interface ElementCallEntryPoint { /** * Start a call of the given type. - * @param callType The type of call to start. + * @param callData The data of call to start. */ - fun startCall(callType: CallType) + fun startCall(callData: CallData) /** * Handle an incoming call. - * @param callType The type of call. + * @param callData The data of call. * @param eventId The event id of the event that started the call. * @param senderId The user id of the sender of the event that started the call. * @param roomName The name of the room the call is in. @@ -35,7 +35,7 @@ interface ElementCallEntryPoint { * @param textContent The text content of the notification. If null the default content from the system will be used. */ suspend fun handleIncomingCall( - callType: CallType.RoomCall, + callData: CallData, eventId: EventId, senderId: UserId, roomName: String?, diff --git a/features/call/impl/src/main/AndroidManifest.xml b/features/call/impl/src/main/AndroidManifest.xml index daf1a910c9..c35c6843ff 100644 --- a/features/call/impl/src/main/AndroidManifest.xml +++ b/features/call/impl/src/main/AndroidManifest.xml @@ -30,44 +30,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:taskAffinity="io.element.android.features.call" /> ().inject(this) appCoroutineScope.launch { activeCallManager.hangUpCall( - callType = CallType.RoomCall( + callData = CallData( sessionId = notificationData.sessionId, roomId = notificationData.roomId, isAudioCall = notificationData.audioOnly diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt index da2c57c0ac..b9bd6640b4 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt @@ -23,7 +23,7 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.compound.theme.ElementTheme -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.data.WidgetMessage import io.element.android.features.call.impl.utils.ActiveCallManager import io.element.android.features.call.impl.utils.CallWidgetProvider @@ -52,7 +52,7 @@ import kotlin.time.Duration.Companion.seconds @AssistedInject class CallScreenPresenter( - @Assisted private val callType: CallType, + @Assisted private val callData: CallData, @Assisted private val navigator: CallScreenNavigator, private val callWidgetProvider: CallWidgetProvider, userAgentProvider: UserAgentProvider, @@ -69,10 +69,9 @@ class CallScreenPresenter( ) : Presenter { @AssistedFactory interface Factory { - fun create(callType: CallType, navigator: CallScreenNavigator): CallScreenPresenter + fun create(callData: CallData, navigator: CallScreenNavigator): CallScreenPresenter } - private val isInWidgetMode = callType is CallType.RoomCall private val userAgent = userAgentProvider.provide() @Composable @@ -90,9 +89,9 @@ class CallScreenPresenter( DisposableEffect(Unit) { coroutineScope.launch { // Sets the call as joined - activeCallManager.joinedCall(callType) + activeCallManager.joinedCall(callData) fetchRoomCallUrl( - inputs = callType, + callData = callData, urlState = urlState, callWidgetDriver = callWidgetDriver, languageTag = languageTag, @@ -100,19 +99,10 @@ class CallScreenPresenter( ) } onDispose { - appCoroutineScope.launch { activeCallManager.hangUpCall(callType) } + appCoroutineScope.launch { activeCallManager.hangUpCall(callData) } } } - - when (callType) { - is CallType.ExternalUrl -> { - // No analytics yet for external calls - } - is CallType.RoomCall -> { - screenTracker.TrackScreen(screen = MobileScreen.ScreenName.RoomCall) - } - } - + screenTracker.TrackScreen(screen = MobileScreen.ScreenName.RoomCall) HandleMatrixClientSyncState() callWidgetDriver.value?.let { driver -> @@ -149,18 +139,15 @@ class CallScreenPresenter( .launchIn(this) } - if (callType is CallType.RoomCall) { - // Note: For external calls isWidgetLoaded will always be false - LaunchedEffect(Unit) { - // Wait for the call to be joined, if it takes too long, we display an error - delay(10.seconds) + LaunchedEffect(Unit) { + // Wait for the call to be joined, if it takes too long, we display an error + delay(10.seconds) - if (!isWidgetLoaded) { - Timber.w("The call took too long to load. Displaying an error before exiting.") + if (!isWidgetLoaded) { + Timber.w("The call took too long to load. Displaying an error before exiting.") - // This will display a simple 'Sorry, an error occurred' dialog and force the user to exit the call - webViewError = "" - } + // This will display a simple 'Sorry, an error occurred' dialog and force the user to exit the call + webViewError = "" } } } @@ -204,37 +191,29 @@ class CallScreenPresenter( webViewError = webViewError, userAgent = userAgent, isCallActive = isWidgetLoaded, - isInWidgetMode = isInWidgetMode, eventSink = ::handleEvent, ) } private suspend fun fetchRoomCallUrl( - inputs: CallType, + callData: CallData, urlState: MutableState>, callWidgetDriver: MutableState, languageTag: String?, theme: String?, ) { urlState.runCatchingUpdatingState { - when (inputs) { - is CallType.ExternalUrl -> { - inputs.url - } - is CallType.RoomCall -> { - val result = callWidgetProvider.getWidget( - sessionId = inputs.sessionId, - roomId = inputs.roomId, - clientId = UUID.randomUUID().toString(), - isAudioCall = inputs.isAudioCall, - languageTag = languageTag, - theme = theme, - ).getOrThrow() - callWidgetDriver.value = result.driver - Timber.d("Call widget driver initialized for sessionId: ${inputs.sessionId}, roomId: ${inputs.roomId}") - result.url - } - } + val result = callWidgetProvider.getWidget( + sessionId = callData.sessionId, + roomId = callData.roomId, + clientId = UUID.randomUUID().toString(), + isAudioCall = callData.isAudioCall, + languageTag = languageTag, + theme = theme, + ).getOrThrow() + callWidgetDriver.value = result.driver + Timber.d("Call widget driver initialized for sessionId: ${callData.sessionId}, roomId: ${callData.roomId}") + result.url } } @@ -242,12 +221,11 @@ class CallScreenPresenter( private fun HandleMatrixClientSyncState() { val coroutineScope = rememberCoroutineScope() DisposableEffect(Unit) { - val roomCallType = callType as? CallType.RoomCall ?: return@DisposableEffect onDispose {} - val client = matrixClientsProvider.getOrNull(roomCallType.sessionId) ?: return@DisposableEffect onDispose { - Timber.w("No MatrixClient found for sessionId, can't send call notification: ${roomCallType.sessionId}") + val client = matrixClientsProvider.getOrNull(callData.sessionId) ?: return@DisposableEffect onDispose { + Timber.w("No MatrixClient found for sessionId, can't send call notification: ${callData.sessionId}") } coroutineScope.launch { - Timber.d("Observing sync state in-call for sessionId: ${roomCallType.sessionId}") + Timber.d("Observing sync state in-call for sessionId: ${callData.sessionId}") client.syncService.syncState .collect { state -> if (state != SyncState.Running) { @@ -256,7 +234,7 @@ class CallScreenPresenter( } } onDispose { - Timber.d("Stopped observing sync state in-call for sessionId: ${roomCallType.sessionId}") + Timber.d("Stopped observing sync state in-call for sessionId: ${callData.sessionId}") // Make sure we mark the call as ended in the app state appForegroundStateService.updateIsInCallState(false) } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt index c07594aebb..3608a2b620 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt @@ -15,6 +15,5 @@ data class CallScreenState( val webViewError: String?, val userAgent: String, val isCallActive: Boolean, - val isInWidgetMode: Boolean, val eventSink: (CallScreenEvents) -> Unit, ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt index 3e72f96f87..036bb6103a 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt @@ -26,7 +26,6 @@ internal fun aCallScreenState( webViewError: String? = null, userAgent: String = "", isCallActive: Boolean = true, - isInWidgetMode: Boolean = false, eventSink: (CallScreenEvents) -> Unit = {}, ): CallScreenState { return CallScreenState( @@ -34,7 +33,6 @@ internal fun aCallScreenState( webViewError = webViewError, userAgent = userAgent, isCallActive = isCallActive, - isInWidgetMode = isInWidgetMode, eventSink = eventSink, ) } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallTypeExtension.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallTypeExtension.kt deleted file mode 100644 index 0c18c3e1a4..0000000000 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallTypeExtension.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.call.impl.ui - -import io.element.android.features.call.api.CallType -import io.element.android.libraries.matrix.api.core.SessionId - -fun CallType.getSessionId(): SessionId? { - return when (this) { - is CallType.ExternalUrl -> null - is CallType.RoomCall -> sessionId - } -} 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 5fa3beb36a..dddcfceb50 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 @@ -35,8 +35,7 @@ import androidx.core.util.Consumer import androidx.lifecycle.Lifecycle import dev.zacsweers.metro.Inject import io.element.android.compound.colors.SemanticColorsLightDark -import io.element.android.features.call.api.CallType -import io.element.android.features.call.api.CallType.ExternalUrl +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.DefaultElementCallEntryPoint import io.element.android.features.call.impl.di.CallBindings import io.element.android.features.call.impl.pip.PictureInPictureEvents @@ -44,7 +43,6 @@ import io.element.android.features.call.impl.pip.PictureInPicturePresenter import io.element.android.features.call.impl.pip.PictureInPictureState import io.element.android.features.call.impl.pip.PipView import io.element.android.features.call.impl.services.CallForegroundService -import io.element.android.features.call.impl.utils.CallIntentDataParser import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.androidutils.browser.ConsoleMessageLogger import io.element.android.libraries.architecture.Presenter @@ -64,7 +62,6 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator, PipView { - @Inject lateinit var callIntentDataParser: CallIntentDataParser @Inject lateinit var presenterFactory: CallScreenPresenter.Factory @Inject lateinit var appPreferencesStore: AppPreferencesStore @Inject lateinit var featureFlagService: FeatureFlagService @@ -80,7 +77,7 @@ class ElementCallActivity : private val requestPermissionsLauncher = registerPermissionResultLauncher() - private val webViewTarget = mutableStateOf(null) + private val webViewTarget = mutableStateOf(null) private var eventSink: ((CallScreenEvents) -> Unit)? = null @@ -98,7 +95,7 @@ class ElementCallActivity : window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) } - setCallType(intent) + setCallData(intent) // If presenter is not created at this point, it means we have no call to display, the Activity is finishing, so return early if (!::presenter.isInitialized) { return @@ -111,8 +108,8 @@ class ElementCallActivity : setContent { val pipState = pictureInPicturePresenter.present() ListenToAndroidEvents(pipState) - val colors by remember(webViewTarget.value?.getSessionId()) { - enterpriseService.semanticColorsFlow(sessionId = webViewTarget.value?.getSessionId()) + val colors by remember(webViewTarget.value?.sessionId) { + enterpriseService.semanticColorsFlow(sessionId = webViewTarget.value?.sessionId) }.collectAsState(SemanticColorsLightDark.default) ElementThemeApp( appPreferencesStore = appPreferencesStore, @@ -123,9 +120,8 @@ class ElementCallActivity : ) { val state = presenter.present() eventSink = state.eventSink - LaunchedEffect(state.isCallActive, state.isInWidgetMode) { - // Note when not in WidgetMode, isCallActive will never be true, so consider the call is active - if (state.isCallActive || !state.isInWidgetMode) { + LaunchedEffect(state.isCallActive) { + if (state.isCallActive) { setCallIsActive() } } @@ -188,7 +184,7 @@ class ElementCallActivity : override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - setCallType(intent) + setCallData(intent) } override fun onDestroy() { @@ -207,25 +203,24 @@ class ElementCallActivity : finish() } - private fun setCallType(intent: Intent?) { - val callType = intent?.let { - IntentCompat.getParcelableExtra(intent, DefaultElementCallEntryPoint.EXTRA_CALL_TYPE, CallType::class.java) - ?: intent.dataString?.let(::parseUrl)?.let(::ExternalUrl) + private fun setCallData(intent: Intent?) { + val callData = intent?.let { + IntentCompat.getParcelableExtra(intent, DefaultElementCallEntryPoint.EXTRA_CALL_TYPE, CallData::class.java) } - val currentCallType = webViewTarget.value - if (currentCallType == null) { - if (callType == null) { + val currentCallData = webViewTarget.value + if (currentCallData == null) { + if (callData == null) { Timber.tag(loggerTag.value).d("Re-opened the activity but we have no url to load or a cached one, finish the activity") finish() } else { Timber.tag(loggerTag.value).d("Set the call type and create the presenter") - webViewTarget.value = callType - presenter = presenterFactory.create(callType, this) + webViewTarget.value = callData + presenter = presenterFactory.create(callData, this) } } else { - if (callType == null) { + if (callData == null) { Timber.tag(loggerTag.value).d("Coming back from notification, do nothing") - } else if (callType != currentCallType) { + } else if (callData != currentCallData) { Timber.tag(loggerTag.value).d("User starts another call, restart the Activity") setIntent(intent) recreate() @@ -236,8 +231,6 @@ class ElementCallActivity : } } - private fun parseUrl(url: String?): String? = callIntentDataParser.parse(url) - private fun registerPermissionResultLauncher(): ActivityResultLauncher> { return registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() 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 2c4deab65e..1d6989fb3c 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 @@ -19,7 +19,7 @@ import androidx.core.content.IntentCompat import androidx.lifecycle.lifecycleScope import dev.zacsweers.metro.Inject import io.element.android.compound.colors.SemanticColorsLightDark -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.call.impl.di.CallBindings import io.element.android.features.call.impl.notifications.CallNotificationData @@ -118,10 +118,10 @@ class IncomingCallActivity : AppCompatActivity() { private fun onAnswer(notificationData: CallNotificationData) { elementCallEntryPoint.startCall( - CallType.RoomCall( - notificationData.sessionId, - notificationData.roomId, - isAudioCall = notificationData.audioOnly + CallData( + sessionId = notificationData.sessionId, + roomId = notificationData.roomId, + isAudioCall = notificationData.audioOnly, ) ) } @@ -129,7 +129,7 @@ class IncomingCallActivity : AppCompatActivity() { private fun onCancel() { val activeCall = activeCallManager.activeCall.value ?: return appCoroutineScope.launch { - activeCallManager.hangUpCall(callType = activeCall.callType) + activeCallManager.hangUpCall(callData = activeCall.callData) } } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 99679a8afb..685fc932fe 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -20,7 +20,7 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn import io.element.android.appconfig.ElementCallConfig -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.CurrentCall import io.element.android.features.call.impl.notifications.CallNotificationData import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator @@ -73,20 +73,20 @@ interface ActiveCallManager { /** * Called to hang up the active call. It will hang up the call and remove any existing UI and the active call. - * @param callType The type of call that the user hangs up, either an external url one or a room one. + * @param callData The data about the call. * @param notificationData The data for the incoming call notification. */ suspend fun hangUpCall( - callType: CallType, + callData: CallData, notificationData: CallNotificationData? = null, ) /** * Called after the user joined a call. It will remove any existing UI and set the call state as [CallState.InCall]. * - * @param callType The type of call that the user joined, either an external url one or a room one. + * @param callData The data about the call. */ - suspend fun joinedCall(callType: CallType) + suspend fun joinedCall(callData: CallData) } @SingleIn(AppScope::class) @@ -143,7 +143,7 @@ class DefaultActiveCallManager( return } activeCall.value = ActiveCall( - callType = CallType.RoomCall( + callData = CallData( sessionId = notificationData.sessionId, roomId = notificationData.roomId, isAudioCall = notificationData.audioOnly, @@ -198,17 +198,17 @@ class DefaultActiveCallManager( } override suspend fun hangUpCall( - callType: CallType, + callData: CallData, notificationData: CallNotificationData?, ) = mutex.withLock { - Timber.tag(tag).d("Hang up call: $callType") + Timber.tag(tag).d("Hang up call: $callData") cancelIncomingCallNotification() val currentActiveCall = activeCall.value ?: run { // activeCall.value can be null if the application has been killed while the call was ringing // Build a currentActiveCall with the provided parameters. notificationData?.let { ActiveCall( - callType = callType, + callData = callData, callState = CallState.Ringing( notificationData = notificationData, ) @@ -219,8 +219,8 @@ class DefaultActiveCallManager( return@withLock } - if (currentActiveCall.callType != callType) { - Timber.tag(tag).w("Call type $callType does not match the active call type, ignoring") + if (currentActiveCall.callData != callData) { + Timber.tag(tag).w("Call type $callData does not match the active call type, ignoring") return@withLock } if (currentActiveCall.callState is CallState.Ringing) { @@ -244,8 +244,8 @@ class DefaultActiveCallManager( activeCall.value = null } - override suspend fun joinedCall(callType: CallType) = mutex.withLock { - Timber.tag(tag).d("Joined call: $callType") + override suspend fun joinedCall(callData: CallData) = mutex.withLock { + Timber.tag(tag).d("Joined call: $callData") cancelIncomingCallNotification() if (activeWakeLock?.isHeld == true) { Timber.tag(tag).d("Releasing partial wakelock after joining call") @@ -254,7 +254,7 @@ class DefaultActiveCallManager( timedOutCallJob?.cancel() activeCall.value = ActiveCall( - callType = callType, + callData = callData, callState = CallState.InCall, ) } @@ -307,15 +307,15 @@ class DefaultActiveCallManager( private fun observeRingingCall() { activeCall .filterNotNull() - .filter { it.callState is CallState.Ringing && it.callType is CallType.RoomCall } + .filter { it.callState is CallState.Ringing } .flatMapLatest { activeCall -> - val callType = activeCall.callType as CallType.RoomCall + val callData = activeCall.callData val ringingInfo = activeCall.callState as CallState.Ringing - val client = matrixClientProvider.getOrRestore(callType.sessionId).getOrNull() ?: run { + val client = matrixClientProvider.getOrRestore(callData.sessionId).getOrNull() ?: run { Timber.tag(tag).d("Couldn't find session for incoming call: $activeCall") return@flatMapLatest flowOf() } - val room = client.getRoom(callType.roomId) ?: run { + val room = client.getRoom(callData.roomId) ?: run { Timber.tag(tag).d("Couldn't find room for incoming call: $activeCall") return@flatMapLatest flowOf() } @@ -346,17 +346,17 @@ class DefaultActiveCallManager( // has joined the call from another session. activeCall .filterNotNull() - .filter { it.callState is CallState.Ringing && it.callType is CallType.RoomCall } + .filter { it.callState is CallState.Ringing } .flatMapLatest { activeCall -> - val callType = activeCall.callType as CallType.RoomCall + val callData = activeCall.callData // Get a flow of updated `hasRoomCall` and `activeRoomCallParticipants` values for the room - val room = matrixClientProvider.getOrRestore(callType.sessionId).getOrNull()?.getRoom(callType.roomId) ?: run { + val room = matrixClientProvider.getOrRestore(callData.sessionId).getOrNull()?.getRoom(callData.roomId) ?: run { Timber.tag(tag).d("Couldn't find room for incoming call: $activeCall") return@flatMapLatest flowOf() } room.roomInfoFlow.map { Timber.tag(tag).d("Has room call status changed for ringing call: ${it.hasRoomCall}") - it.hasRoomCall to (callType.sessionId in it.activeRoomCallParticipants) + it.hasRoomCall to (callData.sessionId in it.activeRoomCallParticipants) } } // We only want to check if the room active call status changes @@ -388,10 +388,7 @@ class DefaultActiveCallManager( // Nothing to do } is CallState.InCall -> { - when (val callType = value.callType) { - is CallType.ExternalUrl -> defaultCurrentCallService.onCallStarted(CurrentCall.ExternalUrl(callType.url)) - is CallType.RoomCall -> defaultCurrentCallService.onCallStarted(CurrentCall.RoomCall(callType.roomId)) - } + defaultCurrentCallService.onCallStarted(CurrentCall.RoomCall(value.callData.roomId)) } } } @@ -404,7 +401,7 @@ class DefaultActiveCallManager( * Represents an active call. */ data class ActiveCall( - val callType: CallType, + val callData: CallData, val callState: CallState, ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallIntentDataParser.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallIntentDataParser.kt deleted file mode 100644 index f5433c15a0..0000000000 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallIntentDataParser.kt +++ /dev/null @@ -1,98 +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.features.call.impl.utils - -import android.net.Uri -import androidx.core.net.toUri -import dev.zacsweers.metro.Inject - -@Inject -class CallIntentDataParser { - private val validHttpSchemes = sequenceOf("https") - private val knownHosts = sequenceOf( - "call.element.io", - ) - - fun parse(data: String?): String? { - val parsedUrl = data?.toUri() ?: return null - val scheme = parsedUrl.scheme - return when { - scheme in validHttpSchemes -> parsedUrl - scheme == "element" && parsedUrl.host == "call" -> { - parsedUrl.getUrlParameter() - } - scheme == "io.element.call" && parsedUrl.host == null -> { - parsedUrl.getUrlParameter() - } - // This should never be possible, but we still need to take into account the possibility - else -> null - } - ?.takeIf { it.host in knownHosts } - ?.withCustomParameters() - } - - private fun Uri.getUrlParameter(): Uri? { - return getQueryParameter("url") - ?.let { urlParameter -> - urlParameter.toUri().takeIf { uri -> - uri.scheme in validHttpSchemes && !uri.host.isNullOrBlank() - } - } - } -} - -/** - * Ensure the uri has the following parameters and value in the fragment: - * - appPrompt=false - * - confineToRoom=true - * to ensure that the rendering will bo correct on the embedded Webview. - */ -private fun Uri.withCustomParameters(): String { - val builder = buildUpon() - // Remove the existing query parameters - builder.clearQuery() - queryParameterNames.forEach { - if (it == APP_PROMPT_PARAMETER || it == CONFINE_TO_ROOM_PARAMETER) return@forEach - builder.appendQueryParameter(it, getQueryParameter(it)) - } - // Remove the existing fragment parameters, and build the new fragment - val currentFragment = fragment ?: "" - // Reset the current fragment - builder.fragment("") - val queryFragmentPosition = currentFragment.lastIndexOf("?") - val newFragment = if (queryFragmentPosition == -1) { - // No existing query, build it. - "$currentFragment?$APP_PROMPT_PARAMETER=false&$CONFINE_TO_ROOM_PARAMETER=true" - } else { - buildString { - append(currentFragment.substring(0, queryFragmentPosition + 1)) - val queryFragment = currentFragment.substring(queryFragmentPosition + 1) - // Replace the existing parameters - val newQueryFragment = queryFragment - .replace("$APP_PROMPT_PARAMETER=true", "$APP_PROMPT_PARAMETER=false") - .replace("$CONFINE_TO_ROOM_PARAMETER=false", "$CONFINE_TO_ROOM_PARAMETER=true") - append(newQueryFragment) - // Ensure the parameters are there - if (!newQueryFragment.contains("$APP_PROMPT_PARAMETER=false")) { - if (newQueryFragment.isNotEmpty()) { - append("&") - } - append("$APP_PROMPT_PARAMETER=false") - } - if (!newQueryFragment.contains("$CONFINE_TO_ROOM_PARAMETER=true")) { - append("&$CONFINE_TO_ROOM_PARAMETER=true") - } - } - } - // We do not want to encode the Fragment part, so append it manually - return builder.build().toString() + "#" + newFragment -} - -private const val APP_PROMPT_PARAMETER = "appPrompt" -private const val CONFINE_TO_ROOM_PARAMETER = "confineToRoom" diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/IntentProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/IntentProvider.kt index 0f74ba86d4..c6c607cbbc 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/IntentProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/IntentProvider.kt @@ -12,21 +12,21 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import androidx.core.app.PendingIntentCompat -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.DefaultElementCallEntryPoint import io.element.android.features.call.impl.ui.ElementCallActivity internal object IntentProvider { - fun createIntent(context: Context, callType: CallType): Intent = Intent(context, ElementCallActivity::class.java).apply { - putExtra(DefaultElementCallEntryPoint.EXTRA_CALL_TYPE, callType) + fun createIntent(context: Context, callData: CallData): Intent = Intent(context, ElementCallActivity::class.java).apply { + putExtra(DefaultElementCallEntryPoint.EXTRA_CALL_TYPE, callData) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_USER_ACTION) } - fun getPendingIntent(context: Context, callType: CallType): PendingIntent { + fun getPendingIntent(context: Context, callData: CallData): PendingIntent { return PendingIntentCompat.getActivity( context, DefaultElementCallEntryPoint.REQUEST_CODE, - createIntent(context, callType), + createIntent(context, callData), PendingIntent.FLAG_CANCEL_CURRENT, false )!! diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt index 85cec8c586..f21447cc85 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt @@ -11,7 +11,7 @@ package io.element.android.features.call import android.content.Intent import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.DefaultElementCallEntryPoint import io.element.android.features.call.impl.notifications.CallNotificationData import io.element.android.features.call.impl.ui.ElementCallActivity @@ -37,7 +37,7 @@ class DefaultElementCallEntryPointTest { @Test fun `startCall - starts ElementCallActivity setup with the needed extras`() = runTest { val entryPoint = createEntryPoint() - entryPoint.startCall(CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, isAudioCall = false)) + entryPoint.startCall(CallData(A_SESSION_ID, A_ROOM_ID, isAudioCall = false)) val expectedIntent = Intent(InstrumentationRegistry.getInstrumentation().targetContext, ElementCallActivity::class.java) val intent = shadowOf(RuntimeEnvironment.getApplication()).nextStartedActivity @@ -53,7 +53,7 @@ class DefaultElementCallEntryPointTest { val entryPoint = createEntryPoint(activeCallManager = activeCallManager) entryPoint.handleIncomingCall( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, isAudioCall = false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, isAudioCall = false), eventId = AN_EVENT_ID, senderId = A_USER_ID_2, roomName = "roomName", diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallDataTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallDataTest.kt new file mode 100644 index 0000000000..f0cdd44082 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallDataTest.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 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.features.call.ui + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallData +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import org.junit.Test + +class CallDataTest { + @Test + fun `RoomCall stringification does not contain the URL`() { + assertThat(CallData(A_SESSION_ID, A_ROOM_ID, false).toString()) + .isEqualTo("CallData(sessionId=$A_SESSION_ID, roomId=$A_ROOM_ID, isAudioCall=false)") + } +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt index b6b0120451..c2c576999c 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt @@ -13,7 +13,7 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.MobileScreen -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.ui.CallScreenEvents import io.element.android.features.call.impl.ui.CallScreenNavigator import io.element.android.features.call.impl.ui.CallScreenPresenter @@ -59,38 +59,13 @@ class CallScreenPresenterTest { val warmUpRule = WarmUpRule() @Test - fun `present - with CallType ExternalUrl just loads the URL and sets the call as active`() = runTest { - val analyticsLambda = lambdaRecorder {} - val joinedCallLambda = lambdaRecorder {} - val presenter = createCallScreenPresenter( - callType = CallType.ExternalUrl("https://call.element.io"), - screenTracker = FakeScreenTracker(analyticsLambda), - activeCallManager = FakeActiveCallManager(joinedCallResult = joinedCallLambda), - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - // Wait until the URL is loaded - advanceTimeBy(1.seconds) - skipItems(2) - val initialState = awaitItem() - assertThat(initialState.urlState).isEqualTo(AsyncData.Success("https://call.element.io")) - assertThat(initialState.webViewError).isNull() - assertThat(initialState.isInWidgetMode).isFalse() - assertThat(initialState.isCallActive).isFalse() - analyticsLambda.assertions().isNeverCalled() - joinedCallLambda.assertions().isCalledOnce() - } - } - - @Test - fun `present - with CallType RoomCall sets call as active, loads URL and runs WidgetDriver`() = runTest { + fun `present - with CallData sets call as active, loads URL and runs WidgetDriver`() = runTest { val widgetDriver = FakeMatrixWidgetDriver() val widgetProvider = FakeCallWidgetProvider(widgetDriver) val analyticsLambda = lambdaRecorder {} - val joinedCallLambda = lambdaRecorder {} + val joinedCallLambda = lambdaRecorder {} val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, widgetProvider = widgetProvider, screenTracker = FakeScreenTracker(analyticsLambda), @@ -107,7 +82,6 @@ class CallScreenPresenterTest { val initialState = awaitItem() assertThat(initialState.urlState).isInstanceOf(AsyncData.Loading::class.java) assertThat(initialState.isCallActive).isFalse() - assertThat(initialState.isInWidgetMode).isTrue() assertThat(widgetProvider.getWidgetCalled).isTrue() assertThat(widgetDriver.runCalledCount).isEqualTo(1) analyticsLambda.assertions().isCalledOnce().with(value(MobileScreen.ScreenName.RoomCall)) @@ -123,7 +97,7 @@ class CallScreenPresenterTest { fun `present - set message interceptor, send and receive messages`() = runTest { val widgetDriver = FakeMatrixWidgetDriver() val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, screenTracker = FakeScreenTracker {}, ) @@ -154,7 +128,7 @@ class CallScreenPresenterTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, navigator = navigator, dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), @@ -188,7 +162,7 @@ class CallScreenPresenterTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, navigator = navigator, dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), @@ -223,7 +197,7 @@ class CallScreenPresenterTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, navigator = navigator, dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), @@ -260,7 +234,7 @@ class CallScreenPresenterTest { val navigator = FakeCallScreenNavigator() val widgetDriver = FakeMatrixWidgetDriver() val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, navigator = navigator, dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), @@ -300,7 +274,7 @@ class CallScreenPresenterTest { val matrixClient = FakeMatrixClient(syncService = syncService) val appForegroundStateService = FakeAppForegroundStateService() val presenter = createCallScreenPresenter( - callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false), + callData = CallData(A_SESSION_ID, A_ROOM_ID, false), widgetDriver = widgetDriver, navigator = navigator, dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), @@ -338,53 +312,8 @@ class CallScreenPresenterTest { } } - @Test - fun `present - error from WebView are updating the state`() = runTest { - val presenter = createCallScreenPresenter( - callType = CallType.ExternalUrl("https://call.element.io"), - activeCallManager = FakeActiveCallManager(), - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - // Wait until the URL is loaded - advanceTimeBy(1.seconds) - skipItems(2) - val initialState = awaitItem() - initialState.eventSink(CallScreenEvents.OnWebViewError("A Webview error")) - val finalState = awaitItem() - assertThat(finalState.webViewError).isEqualTo("A Webview error") - } - } - - @Test - fun `present - error from WebView are ignored if Element Call is loaded`() = runTest { - val presenter = createCallScreenPresenter( - callType = CallType.ExternalUrl("https://call.element.io"), - activeCallManager = FakeActiveCallManager(), - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - // Wait until the URL is loaded - skipItems(1) - val initialState = awaitItem() - - val messageInterceptor = FakeWidgetMessageInterceptor() - initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor)) - // Emit a message - messageInterceptor.givenInterceptedMessage("A message") - // WebView emits an error, but it will be ignored - initialState.eventSink(CallScreenEvents.OnWebViewError("A Webview error")) - val finalState = awaitItem() - assertThat(finalState.webViewError).isNull() - - cancelAndIgnoreRemainingEvents() - } - } - private fun TestScope.createCallScreenPresenter( - callType: CallType, + callData: CallData, navigator: CallScreenNavigator = FakeCallScreenNavigator(), widgetDriver: FakeMatrixWidgetDriver = FakeMatrixWidgetDriver(), widgetProvider: FakeCallWidgetProvider = FakeCallWidgetProvider(widgetDriver), @@ -401,7 +330,7 @@ class CallScreenPresenterTest { } val clock = SystemClock { 0 } return CallScreenPresenter( - callType = callType, + callData = callData, navigator = navigator, callWidgetProvider = widgetProvider, userAgentProvider = userAgentProvider, diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallTypeTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallTypeTest.kt deleted file mode 100644 index c83408bd3b..0000000000 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallTypeTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.features.call.ui - -import com.google.common.truth.Truth.assertThat -import io.element.android.features.call.api.CallType -import io.element.android.features.call.impl.ui.getSessionId -import io.element.android.libraries.matrix.test.A_ROOM_ID -import io.element.android.libraries.matrix.test.A_SESSION_ID -import org.junit.Test - -class CallTypeTest { - @Test - fun `getSessionId returns null for ExternalUrl`() { - assertThat(CallType.ExternalUrl("aURL").getSessionId()).isNull() - } - - @Test - fun `getSessionId returns the sessionId for RoomCall`() { - assertThat( - CallType.RoomCall( - sessionId = A_SESSION_ID, - roomId = A_ROOM_ID, - isAudioCall = false, - ).getSessionId() - ).isEqualTo(A_SESSION_ID) - } - - @Test - fun `ExternalUrl stringification does not contain the URL`() { - assertThat(CallType.ExternalUrl("aURL").toString()).isEqualTo("ExternalUrl") - } - - @Test - fun `RoomCall stringification does not contain the URL`() { - assertThat(CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, false).toString()) - .isEqualTo("RoomCall(sessionId=$A_SESSION_ID, roomId=$A_ROOM_ID, isAudioCall=false)") - } -} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/CallIntentDataParserTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/CallIntentDataParserTest.kt deleted file mode 100644 index 43f7f931f1..0000000000 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/CallIntentDataParserTest.kt +++ /dev/null @@ -1,226 +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.features.call.utils - -import com.google.common.truth.Truth.assertThat -import io.element.android.features.call.impl.utils.CallIntentDataParser -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import java.net.URLEncoder - -@RunWith(RobolectricTestRunner::class) -class CallIntentDataParserTest { - private val callIntentDataParser = CallIntentDataParser() - - @Test - fun `a null data returns null`() { - val url: String? = null - assertThat(callIntentDataParser.parse(url)).isNull() - } - - @Test - fun `empty data returns null`() { - doTest("", null) - } - - @Test - fun `invalid data returns null`() { - doTest("!", null) - } - - @Test - fun `data with no scheme returns null`() { - doTest("test", null) - } - - @Test - fun `Element Call http urls returns null`() { - doTest("http://call.element.io", null) - doTest("http://call.element.io/some-actual-call?with=parameters", null) - } - - @Test - fun `Element Call urls with unknown host returns null`() { - // Check valid host first, should not return null - doTest("https://call.element.io", "https://call.element.io#?appPrompt=false&confineToRoom=true") - // Unknown host should return null - doTest("https://unknown.io", null) - doTest("https://call.unknown.io", null) - doTest("https://call.element.com", null) - doTest("https://call.element.io.tld", null) - } - - @Test - fun `Element Call urls will be returned as is`() { - doTest( - url = "https://call.element.io", - expectedResult = "https://call.element.io#?$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with url param gets url extracted`() { - doTest( - url = VALID_CALL_URL_WITH_PARAM, - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" - ) - } - - @Test - fun `HTTP and HTTPS urls that don't come from EC return null`() { - doTest("http://app.element.io", null) - doTest("https://app.element.io", null) - doTest("http://", null) - doTest("https://", null) - } - - @Test - fun `Element Call url with no url returns null`() { - val embeddedUrl = VALID_CALL_URL_WITH_PARAM - val encodedUrl = URLEncoder.encode(embeddedUrl, "utf-8") - val url = "io.element.call:/?no_url=$encodedUrl" - assertThat(callIntentDataParser.parse(url)).isNull() - } - - @Test - fun `element scheme with no call host returns null`() { - val embeddedUrl = VALID_CALL_URL_WITH_PARAM - val encodedUrl = URLEncoder.encode(embeddedUrl, "utf-8") - val url = "element://no-call?url=$encodedUrl" - assertThat(callIntentDataParser.parse(url)).isNull() - } - - @Test - fun `element scheme with no data returns null`() { - val url = "element://call?url=" - assertThat(callIntentDataParser.parse(url)).isNull() - } - - @Test - fun `Element Call url with no data returns null`() { - val url = "io.element.call:/?url=" - assertThat(callIntentDataParser.parse(url)).isNull() - } - - @Test - fun `element invalid scheme returns null`() { - val embeddedUrl = VALID_CALL_URL_WITH_PARAM - val encodedUrl = URLEncoder.encode(embeddedUrl, "utf-8") - val url = "bad.scheme:/?url=$encodedUrl" - assertThat(callIntentDataParser.parse(url)).isNull() - } - - @Test - fun `Element Call url with url extra param appPrompt gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM&appPrompt=true", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with url extra param in fragment appPrompt gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=true", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=false&confineToRoom=true" - ) - } - - @Test - fun `Element Call url with url extra param in fragment appPrompt and other gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=true&otherParam=maybe", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?appPrompt=false&otherParam=maybe&confineToRoom=true" - ) - } - - @Test - fun `Element Call url with url extra param confineToRoom gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM&confineToRoom=false", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with url extra param in fragment confineToRoom gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=false", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=true&appPrompt=false" - ) - } - - @Test - fun `Element Call url with url extra param in fragment confineToRoom and more gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=false&otherParam=maybe", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?confineToRoom=true&otherParam=maybe&appPrompt=false" - ) - } - - @Test - fun `Element Call url with url fragment gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#fragment", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#fragment?$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with url fragment with params gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#fragment?otherParam=maybe", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#fragment?otherParam=maybe&$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with url fragment with other params gets url extracted`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#?otherParam=maybe", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?otherParam=maybe&$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with empty fragment`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" - ) - } - - @Test - fun `Element Call url with empty fragment query`() { - doTest( - url = "$VALID_CALL_URL_WITH_PARAM#?", - expectedResult = "$VALID_CALL_URL_WITH_PARAM#?$EXTRA_PARAMS" - ) - } - - private fun doTest(url: String, expectedResult: String?) { - // Test direct parsing - assertThat(callIntentDataParser.parse(url)).isEqualTo(expectedResult) - - // Test embedded url, scheme 1 - val encodedUrl = URLEncoder.encode(url, "utf-8") - val urlScheme1 = "element://call?url=$encodedUrl" - assertThat(callIntentDataParser.parse(urlScheme1)).isEqualTo(expectedResult) - - // Test embedded url, scheme 2 - val urlScheme2 = "io.element.call:/?url=$encodedUrl" - assertThat(callIntentDataParser.parse(urlScheme2)).isEqualTo(expectedResult) - } - - companion object { - const val VALID_CALL_URL_WITH_PARAM = "https://call.element.io/some-actual-call?with=parameters" - const val EXTRA_PARAMS = "appPrompt=false&confineToRoom=true" - } -} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt index f9f6206ec7..3712904b03 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt @@ -13,7 +13,7 @@ import androidx.core.app.NotificationManagerCompat import androidx.core.content.getSystemService import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator import io.element.android.features.call.impl.notifications.aCallNotificationData import io.element.android.features.call.impl.utils.ActiveCall @@ -77,7 +77,7 @@ class DefaultActiveCallManagerTest { assertThat(manager.activeCall.value).isEqualTo( ActiveCall( - callType = CallType.RoomCall( + callData = CallData( sessionId = callNotificationData.sessionId, roomId = callNotificationData.roomId, isAudioCall = false, @@ -104,7 +104,7 @@ class DefaultActiveCallManagerTest { assertThat(manager.activeCall.value).isEqualTo( ActiveCall( - callType = CallType.RoomCall( + callData = CallData( sessionId = callNotificationData.sessionId, roomId = callNotificationData.roomId, isAudioCall = true, @@ -132,7 +132,7 @@ class DefaultActiveCallManagerTest { manager.registerIncomingCall(aCallNotificationData(roomId = A_ROOM_ID_2)) assertThat(manager.activeCall.value).isEqualTo(activeCall) - assertThat((manager.activeCall.value?.callType as? CallType.RoomCall)?.roomId).isNotEqualTo(A_ROOM_ID_2) + assertThat(manager.activeCall.value?.callData?.roomId).isNotEqualTo(A_ROOM_ID_2) advanceTimeBy(1) @@ -178,7 +178,7 @@ class DefaultActiveCallManagerTest { } @Test - fun `hangUpCall - removes existing call if the CallType matches`() = runTest { + fun `hangUpCall - removes existing call if the CallData matches`() = runTest { setupShadowPowerManager() val notificationManagerCompat = mockk(relaxed = true) val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) @@ -188,7 +188,7 @@ class DefaultActiveCallManagerTest { assertThat(manager.activeCall.value).isNotNull() assertThat(manager.activeWakeLock?.isHeld).isTrue() - manager.hangUpCall(CallType.RoomCall(notificationData.sessionId, notificationData.roomId, false)) + manager.hangUpCall(CallData(notificationData.sessionId, notificationData.roomId, false)) assertThat(manager.activeCall.value).isNull() assertThat(manager.activeWakeLock?.isHeld).isFalse() @@ -215,7 +215,7 @@ class DefaultActiveCallManagerTest { val notificationData = aCallNotificationData(roomId = A_ROOM_ID) manager.registerIncomingCall(notificationData) - manager.hangUpCall(CallType.RoomCall(notificationData.sessionId, notificationData.roomId, false)) + manager.hangUpCall(CallData(notificationData.sessionId, notificationData.roomId, false)) coVerify { room.declineCall(notificationEventId = notificationData.eventId) @@ -242,7 +242,7 @@ class DefaultActiveCallManagerTest { val notificationData = aCallNotificationData(roomId = A_ROOM_ID) // Do not register the incoming call, so the manager doesn't know about it manager.hangUpCall( - callType = CallType.RoomCall(notificationData.sessionId, notificationData.roomId, false), + callData = CallData(notificationData.sessionId, notificationData.roomId, false), notificationData = notificationData, ) coVerify { @@ -320,7 +320,7 @@ class DefaultActiveCallManagerTest { } @Test - fun `hangUpCall - does nothing if the CallType doesn't match`() = runTest { + fun `hangUpCall - does nothing if the CallData doesn't match`() = runTest { setupShadowPowerManager() val notificationManagerCompat = mockk(relaxed = true) val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) @@ -329,7 +329,13 @@ class DefaultActiveCallManagerTest { assertThat(manager.activeCall.value).isNotNull() assertThat(manager.activeWakeLock?.isHeld).isTrue() - manager.hangUpCall(CallType.ExternalUrl("https://example.com")) + manager.hangUpCall( + CallData( + sessionId = A_SESSION_ID, + roomId = A_ROOM_ID_2, + isAudioCall = true, + ) + ) assertThat(manager.activeCall.value).isNotNull() assertThat(manager.activeWakeLock?.isHeld).isTrue() @@ -344,10 +350,10 @@ class DefaultActiveCallManagerTest { val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) assertThat(manager.activeCall.value).isNull() - manager.joinedCall(CallType.RoomCall(A_SESSION_ID, A_ROOM_ID, true)) + manager.joinedCall(CallData(A_SESSION_ID, A_ROOM_ID, true)) assertThat(manager.activeCall.value).isEqualTo( ActiveCall( - callType = CallType.RoomCall( + callData = CallData( sessionId = A_SESSION_ID, roomId = A_ROOM_ID, isAudioCall = true, @@ -450,7 +456,7 @@ class DefaultActiveCallManagerTest { assertThat(manager.activeCall.value).isEqualTo( ActiveCall( - callType = CallType.RoomCall( + callData = CallData( sessionId = callNotificationData.sessionId, roomId = callNotificationData.roomId, isAudioCall = false, diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/FakeActiveCallManager.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/FakeActiveCallManager.kt index 2d0e126ab5..c2c38284a9 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/FakeActiveCallManager.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/FakeActiveCallManager.kt @@ -8,7 +8,7 @@ package io.element.android.features.call.utils -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.notifications.CallNotificationData import io.element.android.features.call.impl.utils.ActiveCall import io.element.android.features.call.impl.utils.ActiveCallManager @@ -17,8 +17,8 @@ import kotlinx.coroutines.flow.MutableStateFlow class FakeActiveCallManager( var registerIncomingCallResult: (CallNotificationData) -> Unit = {}, - var hangUpCallResult: (CallType, CallNotificationData?) -> Unit = { _, _ -> }, - var joinedCallResult: (CallType) -> Unit = {}, + var hangUpCallResult: (CallData, CallNotificationData?) -> Unit = { _, _ -> }, + var joinedCallResult: (CallData) -> Unit = {}, ) : ActiveCallManager { override val activeCall = MutableStateFlow(null) @@ -26,12 +26,12 @@ class FakeActiveCallManager( registerIncomingCallResult(notificationData) } - override suspend fun hangUpCall(callType: CallType, notificationData: CallNotificationData?) = simulateLongTask { - hangUpCallResult(callType, notificationData) + override suspend fun hangUpCall(callData: CallData, notificationData: CallNotificationData?) = simulateLongTask { + hangUpCallResult(callData, notificationData) } - override suspend fun joinedCall(callType: CallType) = simulateLongTask { - joinedCallResult(callType) + override suspend fun joinedCall(callData: CallData) = simulateLongTask { + joinedCallResult(callData) } fun setActiveCall(value: ActiveCall?) { diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt b/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt index fdf3ca566b..13b61feacb 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt +++ b/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt @@ -8,16 +8,16 @@ package io.element.android.features.call.test -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.tests.testutils.lambda.lambdaError class FakeElementCallEntryPoint( - var startCallResult: (CallType) -> Unit = { lambdaError() }, + var startCallResult: (CallData) -> Unit = { lambdaError() }, var handleIncomingCallResult: ( - CallType.RoomCall, + CallData, EventId, UserId, String?, @@ -27,12 +27,12 @@ class FakeElementCallEntryPoint( String?, ) -> Unit = { _, _, _, _, _, _, _, _ -> lambdaError() } ) : ElementCallEntryPoint { - override fun startCall(callType: CallType) { - startCallResult(callType) + override fun startCall(callData: CallData) { + startCallResult(callData) } override suspend fun handleIncomingCall( - callType: CallType.RoomCall, + callData: CallData, eventId: EventId, senderId: UserId, roomName: String?, @@ -44,7 +44,7 @@ class FakeElementCallEntryPoint( textContent: String?, ) { handleIncomingCallResult( - callType, + callData, eventId, senderId, roomName, 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 36e94ec456..c7b046dc14 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 @@ -24,7 +24,7 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.Interaction import io.element.android.annotations.ContributesNode -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.forward.api.ForwardEntryPoint import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint @@ -277,13 +277,13 @@ class MessagesFlowNode( } override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { - val callType = CallType.RoomCall( + val callData = CallData( sessionId = sessionId, roomId = roomId, - isAudioCall = isAudioCall + isAudioCall = isAudioCall, ) analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) - elementCallEntryPoint.startCall(callType) + elementCallEntryPoint.startCall(callData) } override fun navigateToPinnedMessagesList() { @@ -506,13 +506,13 @@ class MessagesFlowNode( } override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { - val callType = CallType.RoomCall( + val callData = CallData( sessionId = sessionId, roomId = roomId, isAudioCall = isAudioCall ) analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) - elementCallEntryPoint.startCall(callType) + elementCallEntryPoint.startCall(callData) } override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index c3ae902ba9..818287ab68 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -25,7 +25,7 @@ import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.Interaction import io.element.android.annotations.ContributesNode import io.element.android.appconfig.LearnMoreConfig -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint import io.element.android.features.messages.api.MessagesEntryPoint @@ -225,13 +225,13 @@ class RoomDetailsFlowNode( } override fun navigateToRoomCall(callIntent: CallIntent) { - val inputs = CallType.RoomCall( + val callData = CallData( sessionId = room.sessionId, roomId = room.roomId, isAudioCall = callIntent == CallIntent.AUDIO ) analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) - elementCallEntryPoint.startCall(inputs) + elementCallEntryPoint.startCall(callData) } override fun navigateToReportRoom() { @@ -288,7 +288,7 @@ class RoomDetailsFlowNode( override fun startCall(dmRoomId: RoomId, callIntent: CallIntent) { elementCallEntryPoint.startCall( - CallType.RoomCall( + CallData( roomId = dmRoomId, sessionId = room.sessionId, isAudioCall = callIntent == CallIntent.AUDIO diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt index aaafbe04be..aff9e3502d 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt @@ -20,7 +20,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.userprofile.api.UserProfileEntryPoint import io.element.android.features.userprofile.impl.root.UserProfileNode @@ -86,7 +86,7 @@ class UserProfileFlowNode( override fun startCall(dmRoomId: RoomId, callIntent: CallIntent) { elementCallEntryPoint.startCall( - CallType.RoomCall( + CallData( sessionId = sessionId, roomId = dmRoomId, isAudioCall = callIntent == CallIntent.AUDIO 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 0dd2761446..a97937f5d0 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 @@ -10,7 +10,7 @@ package io.element.android.libraries.push.impl.notifications import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn -import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.CallData import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.matrix.api.core.EventId @@ -215,9 +215,9 @@ class DefaultNotificationResultProcessor( private suspend fun handleRingingCallEvent(notifiableEvent: NotifiableRingingCallEvent) { Timber.i("## handleInternal() : Incoming call.") elementCallEntryPoint.handleIncomingCall( - callType = CallType.RoomCall( - notifiableEvent.sessionId, - notifiableEvent.roomId, + callData = CallData( + sessionId = notifiableEvent.sessionId, + roomId = notifiableEvent.roomId, isAudioCall = notifiableEvent.callIntent == CallIntent.AUDIO ), eventId = notifiableEvent.eventId, 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 6acb375bac..91f29dd28e 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 @@ -8,7 +8,7 @@ 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.api.CallData import io.element.android.features.call.test.FakeElementCallEntryPoint import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -104,7 +104,7 @@ class DefaultNotificationResultProcessorTest { @Test fun `when ringing call PushData is received, the incoming call will be handled`() = runTest { val handleIncomingCallLambda = lambdaRecorder< - CallType.RoomCall, + CallData, EventId, UserId, String?, @@ -140,7 +140,7 @@ class DefaultNotificationResultProcessorTest { fun `when notify call PushData is received, the incoming call will be treated as a normal notification`() = runTest { val onNotifiableEventsReceived = lambdaRecorder, Unit> {} val handleIncomingCallLambda = lambdaRecorder< - CallType.RoomCall, + CallData, EventId, UserId, String?, @@ -176,7 +176,7 @@ class DefaultNotificationResultProcessorTest { fun `when notify call PushData is received, the incoming call will be treated as a normal notification even if notification are disabled`() = runTest { val onNotifiableEventsReceived = lambdaRecorder, Unit> {} val handleIncomingCallLambda = lambdaRecorder< - CallType.RoomCall, + CallData, EventId, UserId, String?, diff --git a/tools/adb/callLinkCustomScheme.sh b/tools/adb/callLinkCustomScheme.sh deleted file mode 100755 index 7e6c9f02d3..0000000000 --- a/tools/adb/callLinkCustomScheme.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /bin/bash - -# Copyright (c) 2025 Element Creations Ltd. -# Copyright 2023-2024 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. - -# Format is: -# element://call?url=some-encoded-url -# For instance -# element://call?url=https%3A%2F%2Fcall.element.io%2FTestElementCall - -adb shell am start -a android.intent.action.VIEW -d element://call?url=https%3A%2F%2Fcall.element.io%2FTestElementCall diff --git a/tools/adb/callLinkCustomScheme2.sh b/tools/adb/callLinkCustomScheme2.sh deleted file mode 100755 index 43f427f22f..0000000000 --- a/tools/adb/callLinkCustomScheme2.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /bin/bash - -# Copyright (c) 2025 Element Creations Ltd. -# Copyright 2023-2024 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. - -# Format is: -# io.element.call:/?url=some-encoded-url -# For instance -# io.element.call:/?url=https%3A%2F%2Fcall.element.io%2FTestElementCall - -adb shell am start -a android.intent.action.VIEW -d io.element.call:/?url=https%3A%2F%2Fcall.element.io%2FTestElementCall From 2bcf10dd0bb78fe34309e76c0fca3f4e68dad5c9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 17:04:12 +0200 Subject: [PATCH 0251/1083] `CallScreenEvents` -> `CallScreenEvent` --- .../ui/{CallScreenEvents.kt => CallScreenEvent.kt} | 8 ++++---- .../features/call/impl/ui/CallScreenPresenter.kt | 8 ++++---- .../features/call/impl/ui/CallScreenState.kt | 2 +- .../call/impl/ui/CallScreenStateProvider.kt | 2 +- .../features/call/impl/ui/CallScreenView.kt | 10 +++++----- .../features/call/impl/ui/ElementCallActivity.kt | 6 +++--- .../features/call/ui/CallScreenPresenterTest.kt | 14 +++++++------- 7 files changed, 25 insertions(+), 25 deletions(-) rename features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/{CallScreenEvents.kt => CallScreenEvent.kt} (78%) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenEvents.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenEvent.kt similarity index 78% rename from features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenEvents.kt rename to features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenEvent.kt index 8fbbce896f..357559c3f9 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenEvents.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenEvent.kt @@ -10,8 +10,8 @@ package io.element.android.features.call.impl.ui import io.element.android.features.call.impl.utils.WidgetMessageInterceptor -sealed interface CallScreenEvents { - data object Hangup : CallScreenEvents - data class SetupMessageChannels(val widgetMessageInterceptor: WidgetMessageInterceptor) : CallScreenEvents - data class OnWebViewError(val description: String?) : CallScreenEvents +sealed interface CallScreenEvent { + data object Hangup : CallScreenEvent + data class SetupMessageChannels(val widgetMessageInterceptor: WidgetMessageInterceptor) : CallScreenEvent + data class OnWebViewError(val description: String?) : CallScreenEvent } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt index b9bd6640b4..7d8e20967f 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt @@ -152,9 +152,9 @@ class CallScreenPresenter( } } - fun handleEvent(event: CallScreenEvents) { + fun handleEvent(event: CallScreenEvent) { when (event) { - is CallScreenEvents.Hangup -> { + is CallScreenEvent.Hangup -> { val widgetId = callWidgetDriver.value?.id val interceptor = messageInterceptor.value if (widgetId != null && interceptor != null && isWidgetLoaded) { @@ -174,10 +174,10 @@ class CallScreenPresenter( } } } - is CallScreenEvents.SetupMessageChannels -> { + is CallScreenEvent.SetupMessageChannels -> { messageInterceptor.value = event.widgetMessageInterceptor } - is CallScreenEvents.OnWebViewError -> { + is CallScreenEvent.OnWebViewError -> { if (!ignoreWebViewError) { webViewError = event.description.orEmpty() } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt index 3608a2b620..86b4cc439f 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenState.kt @@ -15,5 +15,5 @@ data class CallScreenState( val webViewError: String?, val userAgent: String, val isCallActive: Boolean, - val eventSink: (CallScreenEvents) -> Unit, + val eventSink: (CallScreenEvent) -> Unit, ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt index 036bb6103a..155c5d3380 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenStateProvider.kt @@ -26,7 +26,7 @@ internal fun aCallScreenState( webViewError: String? = null, userAgent: String = "", isCallActive: Boolean = true, - eventSink: (CallScreenEvents) -> Unit = {}, + eventSink: (CallScreenEvent) -> Unit = {}, ): CallScreenState { return CallScreenState( urlState = urlState, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index f8657a9ece..a945f3c844 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -68,7 +68,7 @@ internal fun CallScreenView( if (pipState.supportPip) { pipState.eventSink.invoke(PictureInPictureEvents.EnterPictureInPicture) } else { - state.eventSink(CallScreenEvents.Hangup) + state.eventSink(CallScreenEvent.Hangup) } } @@ -84,7 +84,7 @@ internal fun CallScreenView( append(stringResource(CommonStrings.error_unknown)) state.webViewError.takeIf { it.isNotEmpty() }?.let { append("\n\n").append(it) } }, - onSubmit = { state.eventSink(CallScreenEvents.Hangup) }, + onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, ) } else { var webViewAudioManager by remember { mutableStateOf(null) } @@ -123,14 +123,14 @@ internal fun CallScreenView( Timber.d("Can't start in-call audio mode since the app is already in it.") } }, - onError = { state.eventSink(CallScreenEvents.OnWebViewError(it)) }, + onError = { state.eventSink(CallScreenEvent.OnWebViewError(it)) }, ) webViewAudioManager = WebViewAudioManager( webView = webView, coroutineScope = coroutineScope, onInvalidAudioDeviceAdded = { invalidAudioDeviceReason = it }, ) - state.eventSink(CallScreenEvents.SetupMessageChannels(interceptor)) + state.eventSink(CallScreenEvent.SetupMessageChannels(interceptor)) val pipController = WebViewPipController(webView) pipState.eventSink(PictureInPictureEvents.SetPipController(pipController)) }, @@ -147,7 +147,7 @@ internal fun CallScreenView( Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") ErrorDialog( content = state.urlState.error.message.orEmpty(), - onSubmit = { state.eventSink(CallScreenEvents.Hangup) }, + onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, ) } is AsyncData.Success -> Unit 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 dddcfceb50..bce882ec2d 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 @@ -79,7 +79,7 @@ class ElementCallActivity : private val webViewTarget = mutableStateOf(null) - private var eventSink: ((CallScreenEvents) -> Unit)? = null + private var eventSink: ((CallScreenEvent) -> Unit)? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -172,7 +172,7 @@ class ElementCallActivity : pipEventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(isInPictureInPictureMode)) if (!isInPictureInPictureMode && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { Timber.tag(loggerTag.value).d("Exiting PiP mode: Hangup the call") - eventSink?.invoke(CallScreenEvents.Hangup) + eventSink?.invoke(CallScreenEvent.Hangup) } } addOnPictureInPictureModeChangedListener(onPictureInPictureModeChangedListener) @@ -280,7 +280,7 @@ class ElementCallActivity : } override fun hangUp() { - eventSink?.invoke(CallScreenEvents.Hangup) + eventSink?.invoke(CallScreenEvent.Hangup) } } diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt index c2c576999c..99f10b46fc 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt @@ -14,7 +14,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.features.call.api.CallData -import io.element.android.features.call.impl.ui.CallScreenEvents +import io.element.android.features.call.impl.ui.CallScreenEvent import io.element.android.features.call.impl.ui.CallScreenNavigator import io.element.android.features.call.impl.ui.CallScreenPresenter import io.element.android.features.call.impl.utils.WidgetMessageSerializer @@ -109,7 +109,7 @@ class CallScreenPresenterTest { advanceTimeBy(1.seconds) val initialState = awaitItem() - initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor)) + initialState.eventSink(CallScreenEvent.SetupMessageChannels(messageInterceptor)) // And incoming message from the Widget Driver is passed to the WebView widgetDriver.givenIncomingMessage("A message") @@ -143,9 +143,9 @@ class CallScreenPresenterTest { // Give it time to load the URL and WidgetDriver advanceTimeBy(1.seconds) - initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor)) + initialState.eventSink(CallScreenEvent.SetupMessageChannels(messageInterceptor)) - initialState.eventSink(CallScreenEvents.Hangup) + initialState.eventSink(CallScreenEvent.Hangup) // Let background coroutines run and the widget drive be received runCurrent() @@ -177,7 +177,7 @@ class CallScreenPresenterTest { // Give it time to load the URL and WidgetDriver advanceTimeBy(1.seconds) - initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor)) + initialState.eventSink(CallScreenEvent.SetupMessageChannels(messageInterceptor)) messageInterceptor.givenInterceptedMessage("""{"action":"io.element.close","api":"fromWidget","widgetId":"1","requestId":"1"}""") @@ -212,7 +212,7 @@ class CallScreenPresenterTest { skipItems(2) val initialState = awaitItem() assertThat(initialState.isCallActive).isFalse() - initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor)) + initialState.eventSink(CallScreenEvent.SetupMessageChannels(messageInterceptor)) messageInterceptor.givenInterceptedMessage( """ { @@ -249,7 +249,7 @@ class CallScreenPresenterTest { skipItems(2) val initialState = awaitItem() assertThat(initialState.isCallActive).isFalse() - initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor)) + initialState.eventSink(CallScreenEvent.SetupMessageChannels(messageInterceptor)) skipItems(2) // Wait for the timeout to trigger From 944d8965f66989f92c2a03653debb82bfd987899 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 17:04:49 +0200 Subject: [PATCH 0252/1083] `PictureInPictureEvents` -> `PictureInPictureEvent` --- ...ctureEvents.kt => PictureInPictureEvent.kt} | 8 ++++---- .../call/impl/pip/PictureInPicturePresenter.kt | 8 ++++---- .../call/impl/pip/PictureInPictureState.kt | 2 +- .../impl/pip/PictureInPictureStateProvider.kt | 2 +- .../features/call/impl/ui/CallScreenView.kt | 6 +++--- .../call/impl/ui/ElementCallActivity.kt | 6 +++--- .../impl/pip/PictureInPicturePresenterTest.kt | 18 +++++++++--------- 7 files changed, 25 insertions(+), 25 deletions(-) rename features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/{PictureInPictureEvents.kt => PictureInPictureEvent.kt} (75%) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvent.kt similarity index 75% rename from features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt rename to features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvent.kt index 9522d44b22..1af13e148e 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvents.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureEvent.kt @@ -10,8 +10,8 @@ package io.element.android.features.call.impl.pip import io.element.android.features.call.impl.utils.PipController -sealed interface PictureInPictureEvents { - data class SetPipController(val pipController: PipController) : PictureInPictureEvents - data object EnterPictureInPicture : PictureInPictureEvents - data class OnPictureInPictureModeChanged(val isInPip: Boolean) : PictureInPictureEvents +sealed interface PictureInPictureEvent { + data class SetPipController(val pipController: PipController) : PictureInPictureEvent + data object EnterPictureInPicture : PictureInPictureEvent + data class OnPictureInPictureModeChanged(val isInPip: Boolean) : PictureInPictureEvent } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt index 5125b464dc..2dc16d7f26 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenter.kt @@ -36,17 +36,17 @@ class PictureInPicturePresenter( var isInPictureInPicture by remember { mutableStateOf(false) } var pipController by remember { mutableStateOf(null) } - fun handleEvent(event: PictureInPictureEvents) { + fun handleEvent(event: PictureInPictureEvent) { when (event) { - is PictureInPictureEvents.SetPipController -> { + is PictureInPictureEvent.SetPipController -> { pipController = event.pipController } - PictureInPictureEvents.EnterPictureInPicture -> { + PictureInPictureEvent.EnterPictureInPicture -> { coroutineScope.launch { switchToPip(pipController) } } - is PictureInPictureEvents.OnPictureInPictureModeChanged -> { + is PictureInPictureEvent.OnPictureInPictureModeChanged -> { Timber.tag(loggerTag.value).d("onPictureInPictureModeChanged: ${event.isInPip}") isInPictureInPicture = event.isInPip if (event.isInPip) { diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureState.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureState.kt index b1fef4f28b..108589edb9 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureState.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureState.kt @@ -11,5 +11,5 @@ package io.element.android.features.call.impl.pip data class PictureInPictureState( val supportPip: Boolean, val isInPictureInPicture: Boolean, - val eventSink: (PictureInPictureEvents) -> Unit, + val eventSink: (PictureInPictureEvent) -> Unit, ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureStateProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureStateProvider.kt index 6324820eec..f4a78294b6 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureStateProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/pip/PictureInPictureStateProvider.kt @@ -11,7 +11,7 @@ package io.element.android.features.call.impl.pip fun aPictureInPictureState( supportPip: Boolean = false, isInPictureInPicture: Boolean = false, - eventSink: (PictureInPictureEvents) -> Unit = {}, + eventSink: (PictureInPictureEvent) -> Unit = {}, ): PictureInPictureState { return PictureInPictureState( supportPip = supportPip, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index a945f3c844..1c68a62f55 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -33,7 +33,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.viewinterop.AndroidView import io.element.android.features.call.impl.R -import io.element.android.features.call.impl.pip.PictureInPictureEvents +import io.element.android.features.call.impl.pip.PictureInPictureEvent import io.element.android.features.call.impl.pip.PictureInPictureState import io.element.android.features.call.impl.pip.aPictureInPictureState import io.element.android.features.call.impl.utils.InvalidAudioDeviceReason @@ -66,7 +66,7 @@ internal fun CallScreenView( ) { fun handleBack() { if (pipState.supportPip) { - pipState.eventSink.invoke(PictureInPictureEvents.EnterPictureInPicture) + pipState.eventSink.invoke(PictureInPictureEvent.EnterPictureInPicture) } else { state.eventSink(CallScreenEvent.Hangup) } @@ -132,7 +132,7 @@ internal fun CallScreenView( ) state.eventSink(CallScreenEvent.SetupMessageChannels(interceptor)) val pipController = WebViewPipController(webView) - pipState.eventSink(PictureInPictureEvents.SetPipController(pipController)) + pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) }, onDestroyWebView = { // Reset audio mode 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 bce882ec2d..367328ed10 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 @@ -38,7 +38,7 @@ import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.call.api.CallData import io.element.android.features.call.impl.DefaultElementCallEntryPoint import io.element.android.features.call.impl.di.CallBindings -import io.element.android.features.call.impl.pip.PictureInPictureEvents +import io.element.android.features.call.impl.pip.PictureInPictureEvent import io.element.android.features.call.impl.pip.PictureInPicturePresenter import io.element.android.features.call.impl.pip.PictureInPictureState import io.element.android.features.call.impl.pip.PipView @@ -159,7 +159,7 @@ class ElementCallActivity : if (requestPermissionCallback != null) { Timber.tag(loggerTag.value).w("Ignoring onUserLeaveHint event because user is asked to grant permissions") } else { - pipEventSink(PictureInPictureEvents.EnterPictureInPicture) + pipEventSink(PictureInPictureEvent.EnterPictureInPicture) } } addOnUserLeaveHintListener(listener) @@ -169,7 +169,7 @@ class ElementCallActivity : } DisposableEffect(Unit) { val onPictureInPictureModeChangedListener = Consumer { _: PictureInPictureModeChangedInfo -> - pipEventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(isInPictureInPictureMode)) + pipEventSink(PictureInPictureEvent.OnPictureInPictureModeChanged(isInPictureInPictureMode)) if (!isInPictureInPictureMode && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { Timber.tag(loggerTag.value).d("Exiting PiP mode: Hangup the call") eventSink?.invoke(CallScreenEvent.Hangup) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt index c087fa3c35..97aa63947b 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt @@ -58,13 +58,13 @@ class PictureInPicturePresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.isInPictureInPicture).isFalse() - initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) + initialState.eventSink(PictureInPictureEvent.EnterPictureInPicture) enterPipModeResult.assertions().isCalledOnce() - initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(true)) + initialState.eventSink(PictureInPictureEvent.OnPictureInPictureModeChanged(true)) val pipState = awaitItem() assertThat(pipState.isInPictureInPicture).isTrue() // User stops pip - initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(false)) + initialState.eventSink(PictureInPictureEvent.OnPictureInPictureModeChanged(false)) val finalState = awaitItem() assertThat(finalState.isInPictureInPicture).isFalse() } @@ -84,8 +84,8 @@ class PictureInPicturePresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(PictureInPictureEvents.SetPipController(FakePipController(canEnterPipResult = { false }))) - initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) + initialState.eventSink(PictureInPictureEvent.SetPipController(FakePipController(canEnterPipResult = { false }))) + initialState.eventSink(PictureInPictureEvent.EnterPictureInPicture) handUpResult.assertions().isCalledOnce() } } @@ -107,7 +107,7 @@ class PictureInPicturePresenterTest { }.test { val initialState = awaitItem() initialState.eventSink( - PictureInPictureEvents.SetPipController( + PictureInPictureEvent.SetPipController( FakePipController( canEnterPipResult = { true }, enterPipResult = enterPipResult, @@ -115,16 +115,16 @@ class PictureInPicturePresenterTest { ) ) ) - initialState.eventSink(PictureInPictureEvents.EnterPictureInPicture) + initialState.eventSink(PictureInPictureEvent.EnterPictureInPicture) enterPipModeResult.assertions().isCalledOnce() enterPipResult.assertions().isNeverCalled() - initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(true)) + initialState.eventSink(PictureInPictureEvent.OnPictureInPictureModeChanged(true)) val pipState = awaitItem() assertThat(pipState.isInPictureInPicture).isTrue() enterPipResult.assertions().isCalledOnce() // User stops pip exitPipResult.assertions().isNeverCalled() - initialState.eventSink(PictureInPictureEvents.OnPictureInPictureModeChanged(false)) + initialState.eventSink(PictureInPictureEvent.OnPictureInPictureModeChanged(false)) val finalState = awaitItem() assertThat(finalState.isInPictureInPicture).isFalse() exitPipResult.assertions().isCalledOnce() From 4bb33fc36a6cb5b7238378b663214169fcaf512d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 27 Apr 2026 17:06:49 +0200 Subject: [PATCH 0253/1083] Use test extension on presenters. --- .../impl/pip/PictureInPicturePresenterTest.kt | 24 +++++------------- .../call/ui/CallScreenPresenterTest.kt | 25 ++++++------------- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt index 97aa63947b..c3d7fdf17b 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/impl/pip/PictureInPicturePresenterTest.kt @@ -8,11 +8,9 @@ package io.element.android.features.call.impl.pip -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.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Test @@ -20,9 +18,7 @@ class PictureInPicturePresenterTest { @Test fun `when pip is not supported, the state value supportPip is false`() = runTest { val presenter = createPictureInPicturePresenter(supportPip = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.supportPip).isFalse() } @@ -35,9 +31,7 @@ class PictureInPicturePresenterTest { supportPip = true, pipView = FakePipView(setPipParamsResult = { }), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.supportPip).isTrue() } @@ -53,9 +47,7 @@ class PictureInPicturePresenterTest { enterPipModeResult = enterPipModeResult, ), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.isInPictureInPicture).isFalse() initialState.eventSink(PictureInPictureEvent.EnterPictureInPicture) @@ -80,9 +72,7 @@ class PictureInPicturePresenterTest { handUpResult = handUpResult ), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(PictureInPictureEvent.SetPipController(FakePipController(canEnterPipResult = { false }))) initialState.eventSink(PictureInPictureEvent.EnterPictureInPicture) @@ -102,9 +92,7 @@ class PictureInPicturePresenterTest { enterPipModeResult = enterPipModeResult ), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink( PictureInPictureEvent.SetPipController( diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt index 99f10b46fc..276e6670f1 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt @@ -39,6 +39,7 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock 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 io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancelAndJoin @@ -71,9 +72,7 @@ class CallScreenPresenterTest { screenTracker = FakeScreenTracker(analyticsLambda), activeCallManager = FakeActiveCallManager(joinedCallResult = joinedCallLambda), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Wait until the URL is loaded advanceTimeBy(1.seconds) skipItems(1) @@ -102,9 +101,7 @@ class CallScreenPresenterTest { screenTracker = FakeScreenTracker {}, ) val messageInterceptor = FakeWidgetMessageInterceptor() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Give it time to load the URL and WidgetDriver advanceTimeBy(1.seconds) @@ -135,9 +132,7 @@ class CallScreenPresenterTest { screenTracker = FakeScreenTracker {}, ) val messageInterceptor = FakeWidgetMessageInterceptor() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // Give it time to load the URL and WidgetDriver @@ -169,9 +164,7 @@ class CallScreenPresenterTest { screenTracker = FakeScreenTracker {}, ) val messageInterceptor = FakeWidgetMessageInterceptor() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // Give it time to load the URL and WidgetDriver @@ -204,9 +197,7 @@ class CallScreenPresenterTest { screenTracker = FakeScreenTracker {}, ) val messageInterceptor = FakeWidgetMessageInterceptor() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Give it time to load the URL and WidgetDriver advanceTimeBy(1.seconds) skipItems(2) @@ -241,9 +232,7 @@ class CallScreenPresenterTest { screenTracker = FakeScreenTracker {}, ) val messageInterceptor = FakeWidgetMessageInterceptor() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Give it time to load the URL and WidgetDriver advanceTimeBy(1.seconds) skipItems(2) From 5bb0b92eeb7d8e6453d2e0084800e493d022880e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 17:36:41 +0200 Subject: [PATCH 0254/1083] Update dependency io.element.android:element-call-embedded to v0.19.2 (#6662) 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 edbfdc2489..53812f1d74 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -234,7 +234,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.19.1" +element_call_embedded = "io.element.android:element-call-embedded:0.19.2" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From fff27ff3f1e843d40023892800d01dad47f4fa16 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:31:20 +0000 Subject: [PATCH 0255/1083] Strip formatting from media captions in room summary --- .../impl/DefaultPinnedMessagesBannerFormatter.kt | 16 +++++++++------- .../impl/DefaultRoomLatestEventFormatter.kt | 16 +++++++++------- .../libraries/matrix/ui/messages/ToPlainText.kt | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt index 7878245aca..c8afba3603 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt @@ -77,26 +77,28 @@ class DefaultPinnedMessagesBannerFormatter( messageType.toPlainText(permalinkParser) } is VideoMessageType -> { - messageType.bestDescription.prefixWith(CommonStrings.common_video) + messageType.toPlainText(permalinkParser).prefixWith(CommonStrings.common_video) } is ImageMessageType -> { - messageType.bestDescription.prefixWith(CommonStrings.common_image) + messageType.toPlainText(permalinkParser).prefixWith(CommonStrings.common_image) } is StickerMessageType -> { - messageType.bestDescription.prefixWith(CommonStrings.common_sticker) + messageType.toPlainText(permalinkParser).prefixWith(CommonStrings.common_sticker) } is LocationMessageType -> { messageType.body.prefixWith(CommonStrings.common_shared_location) } is FileMessageType -> { - messageType.bestDescription.prefixWith(CommonStrings.common_file) + messageType.toPlainText(permalinkParser).prefixWith(CommonStrings.common_file) } is AudioMessageType -> { - messageType.bestDescription.prefixWith(CommonStrings.common_audio) + messageType.toPlainText(permalinkParser).prefixWith(CommonStrings.common_audio) } is VoiceMessageType -> { - // In this case, do not use bestDescription, because the filename is useless, only use the caption if available. - messageType.caption?.prefixWith(sp.getString(CommonStrings.common_voice_message)) + messageType + .toPlainText(permalinkParser, "") + .takeIf { it.isNotEmpty() } + ?.prefixWith(sp.getString(CommonStrings.common_voice_message)) ?: sp.getString(CommonStrings.common_voice_message) } is OtherMessageType -> { 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 3ecd7819e5..b9b6467c92 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 @@ -139,26 +139,28 @@ class DefaultRoomLatestEventFormatter( messageType.toPlainText(permalinkParser) } is VideoMessageType -> { - messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_video)) + messageType.toPlainText(permalinkParser).prefixWith(sp.getString(CommonStrings.common_video)) } is ImageMessageType -> { - messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_image)) + messageType.toPlainText(permalinkParser).prefixWith(sp.getString(CommonStrings.common_image)) } is StickerMessageType -> { - messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_sticker)) + messageType.toPlainText(permalinkParser).prefixWith(sp.getString(CommonStrings.common_sticker)) } is LocationMessageType -> { sp.getString(CommonStrings.common_shared_location) } is FileMessageType -> { - messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_file)) + messageType.toPlainText(permalinkParser).prefixWith(sp.getString(CommonStrings.common_file)) } is AudioMessageType -> { - messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_audio)) + messageType.toPlainText(permalinkParser).prefixWith(sp.getString(CommonStrings.common_audio)) } is VoiceMessageType -> { - // In this case, do not use bestDescription, because the filename is useless, only use the caption if available. - messageType.caption?.prefixWith(sp.getString(CommonStrings.common_voice_message)) + messageType + .toPlainText(permalinkParser, "") + .takeIf { it.isNotEmpty() } + ?.prefixWith(sp.getString(CommonStrings.common_voice_message)) ?: sp.getString(CommonStrings.common_voice_message) } is OtherMessageType -> { diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt index d58d12b785..34dc72aa1a 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.ui.messages import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.item.event.FormattedBody import io.element.android.libraries.matrix.api.timeline.item.event.MessageFormat +import io.element.android.libraries.matrix.api.timeline.item.event.MessageTypeWithAttachment import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType import org.jsoup.nodes.Document import org.jsoup.nodes.Element @@ -26,6 +27,19 @@ fun TextMessageType.toPlainText( permalinkParser: PermalinkParser, ) = formatted?.toPlainText(permalinkParser) ?: body +/** + * Converts the HTML string in [MessageTypeWithAttachment.formattedCaption] to a plain text representation by parsing it and removing all formatting. + * If the caption is not formatted or the format is not [MessageFormat.HTML], the [MessageTypeWithAttachment.caption] is returned instead. + * If there is no caption, returns [default]. + */ +fun MessageTypeWithAttachment.toPlainText( + permalinkParser: PermalinkParser, + default: String = filename, +): String { + val plainTextFromFormatted = formattedCaption?.toPlainText(permalinkParser) + return plainTextFromFormatted ?: caption ?: default +} + /** * Converts the HTML string in [FormattedBody.body] to a plain text representation by parsing it and removing all formatting. * If the message is not formatted or the format is not [MessageFormat.HTML] we return `null`. From 5e8db7400369cf0e133db5a6d87934cfd61878a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:16:50 +0200 Subject: [PATCH 0256/1083] Update dependencyAnalysis to v3.9.0 (#6657) 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 53812f1d74..97b1b959e8 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.7.0" +dependencyAnalysis = "3.9.0" # DI metro = "0.13.2" From 55084422229d824ccb1254f1655632cc91bf3220 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 28 Apr 2026 12:04:57 +0200 Subject: [PATCH 0257/1083] [Link new device] Implement code confirmation screen. --- .../impl/LinkNewDeviceFlowNode.kt | 22 ++- .../confirmation/CodeConfirmationNode.kt | 47 ++++++ .../confirmation/CodeConfirmationView.kt | 134 ++++++++++++++++++ .../impl/src/main/res/values/localazy.xml | 3 + tools/localazy/config.json | 4 +- 5 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationNode.kt create mode 100644 features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationView.kt diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index 54baee6663..f69abc944b 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -27,6 +27,7 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.compound.theme.ElementTheme import io.element.android.features.linknewdevice.api.LinkNewDeviceEntryPoint +import io.element.android.features.linknewdevice.impl.screens.confirmation.CodeConfirmationNode import io.element.android.features.linknewdevice.impl.screens.desktop.DesktopNoticeNode import io.element.android.features.linknewdevice.impl.screens.error.ErrorNode import io.element.android.features.linknewdevice.impl.screens.error.ErrorScreenType @@ -107,6 +108,11 @@ class LinkNewDeviceFlowNode( val data: String, ) : NavTarget + @Parcelize + data class CodeConfirmation( + val code: String, + ) : NavTarget + @Parcelize data object MobileEnterNumber : NavTarget @@ -166,7 +172,9 @@ class LinkNewDeviceFlowNode( is LinkDesktopStep.Error -> { navigateToError(linkDesktopStep.errorType) } - is LinkDesktopStep.EstablishingSecureChannel -> Unit + is LinkDesktopStep.EstablishingSecureChannel -> { + backstack.push(NavTarget.CodeConfirmation(linkDesktopStep.checkCodeString)) + } is LinkDesktopStep.InvalidQrCode -> { // This error will be handled by the ScanQrCodeNode } @@ -250,6 +258,18 @@ class LinkNewDeviceFlowNode( } createNode(buildContext, listOf(callback)) } + is NavTarget.CodeConfirmation -> { + val callback = object : CodeConfirmationNode.Callback { + override fun onCancel() { + // Push error + backstack.push(NavTarget.Error(ErrorScreenType.Cancelled)) + } + } + val inputs = CodeConfirmationNode.Inputs( + code = navTarget.code, + ) + createNode(buildContext, listOf(inputs, callback)) + } is NavTarget.MobileShowQrCode -> { val callback = object : ShowQrCodeNode.Callback { override fun navigateBack() { diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationNode.kt new file mode 100644 index 0000000000..a8db4d2d75 --- /dev/null +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationNode.kt @@ -0,0 +1,47 @@ +/* + * 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.linknewdevice.impl.screens.confirmation + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedInject +import io.element.android.annotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.callback +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +@AssistedInject +class CodeConfirmationNode( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : Node(buildContext = buildContext, plugins = plugins) { + interface Callback : Plugin { + fun onCancel() + } + + data class Inputs( + val code: String, + ) : NodeInputs + + private val callback: Callback = callback() + private val input = inputs() + + @Composable + override fun View(modifier: Modifier) { + CodeConfirmationView( + code = input.code, + onCancel = callback::onCancel, + ) + } +} diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationView.kt new file mode 100644 index 0000000000..d981574f86 --- /dev/null +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/confirmation/CodeConfirmationView.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.features.linknewdevice.impl.screens.confirmation + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +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.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +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.linknewdevice.impl.R +import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage +import io.element.android.libraries.designsystem.components.BigIcon +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.OutlinedButton +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun CodeConfirmationView( + code: String, + onCancel: () -> Unit, + modifier: Modifier = Modifier, +) { + BackHandler(onBack = onCancel) + FlowStepPage( + modifier = modifier, + iconStyle = BigIcon.Style.Default(CompoundIcons.Computer()), + title = stringResource(R.string.screen_qr_code_login_device_code_title), + subTitle = stringResource(R.string.screen_qr_code_login_device_code_subtitle), + content = { Content(code = code) }, + buttons = { Buttons(onCancel = onCancel) } + ) +} + +@Composable +private fun Content(code: String) { + Column( + modifier = Modifier.padding(top = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Digits(code = code) + Spacer(modifier = Modifier.height(32.dp)) + WaitingForOtherDevice() + } +} + +@OptIn(ExperimentalLayoutApi::class) +@Composable +private fun Digits(code: String) { + FlowRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + code.forEach { + Text( + modifier = Modifier + .padding(horizontal = 6.dp, vertical = 4.dp) + .clip(RoundedCornerShape(4.dp)) + .background(ElementTheme.colors.bgActionSecondaryPressed) + .padding(horizontal = 16.dp, vertical = 17.dp), + text = it.toString() + ) + } + } +} + +@Composable +private fun WaitingForOtherDevice() { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + CircularProgressIndicator( + modifier = Modifier + .size(20.dp) + .padding(2.dp), + strokeWidth = 2.dp, + ) + Text( + text = stringResource(R.string.screen_qr_code_login_verify_code_loading), + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + } +} + +@Composable +private fun Buttons( + onCancel: () -> Unit, +) { + Column(modifier = Modifier.fillMaxWidth()) { + OutlinedButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_cancel), + onClick = onCancel, + ) + } +} + +@PreviewsDayNight +@Composable +internal fun CodeConfirmationViewPreview() { + ElementPreview { + CodeConfirmationView( + code = "67", + onCancel = {}, + ) + } +} diff --git a/features/linknewdevice/impl/src/main/res/values/localazy.xml b/features/linknewdevice/impl/src/main/res/values/localazy.xml index 321b168751..6ffcce227a 100644 --- a/features/linknewdevice/impl/src/main/res/values/localazy.xml +++ b/features/linknewdevice/impl/src/main/res/values/localazy.xml @@ -34,6 +34,8 @@ "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi" "If that doesn’t work, sign in manually" "Connection not secure" + "You’ll be asked to enter the two digits shown on this device." + "Enter the number below on your other device" "The sign in was cancelled on the other device." "Sign in request cancelled" "The sign in was declined on the other device." @@ -54,4 +56,5 @@ Try signing in manually, or scan the QR code with another device." "You need to give permission for %1$s to use your device’s camera in order to continue." "Allow camera access to scan the QR code" "An unexpected error occurred. Please try again." + "Waiting for your other device" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index b38268e5f7..03ada90c4b 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -163,7 +163,9 @@ "screen_qr_code_login_connection_note_secure_state.*", "screen_qr_code_login_unknown_error_description", "screen_qr_code_login_invalid_scan_state_.*", - "screen_qr_code_login_no_camera_permission_state_.*" + "screen_qr_code_login_no_camera_permission_state_.*", + "screen_qr_code_login_device_code_.*", + "screen_qr_code_login_verify_code_loading" ] }, { From 5c9d8d917c6721a21395d6eadef3cbb26d97da79 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Tue, 28 Apr 2026 11:22:25 +0100 Subject: [PATCH 0258/1083] Update error mappings for Link new device --- .../impl/LinkNewDeviceFlowNode.kt | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index 54baee6663..ebaf1cda4e 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -183,20 +183,15 @@ class LinkNewDeviceFlowNode( private fun navigateToError(errorType: ErrorType) { // Map the error to an error screen - // TODO Update this mapping val error = when (errorType) { - is ErrorType.DeviceIdAlreadyInUse -> ErrorScreenType.UnknownError - is ErrorType.InvalidCheckCode -> ErrorScreenType.InsecureChannelDetected - is ErrorType.MissingSecretsBackup -> ErrorScreenType.UnknownError - is ErrorType.NotFound -> ErrorScreenType.Expired - is ErrorType.DeviceNotFound -> ErrorScreenType.UnknownError - is ErrorType.Unknown -> ErrorScreenType.UnknownError - is ErrorType.UnsupportedProtocol -> ErrorScreenType.UnknownError - is ErrorType.Cancelled -> ErrorScreenType.UnknownError + is ErrorType.InvalidCheckCode -> ErrorScreenType.Mismatch2Digits + is ErrorType.UnsupportedProtocol -> ErrorScreenType.ProtocolNotSupported + is ErrorType.Cancelled -> ErrorScreenType.Cancelled is ErrorType.ConnectionInsecure -> ErrorScreenType.InsecureChannelDetected - is ErrorType.Expired -> ErrorScreenType.Expired - is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError - is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError + is ErrorType.Expired, is ErrorType.NotFound, is ErrorType.DeviceNotFound -> ErrorScreenType.Expired + is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError // TODO: should show other_device_already_signed_in screen with checkmark when available + is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError // TODO: check if we expect to hit this here or if it should be caught earlier on + is ErrorType.MissingSecretsBackup, is ErrorType.DeviceIdAlreadyInUse, is ErrorType.Unknown -> ErrorScreenType.UnknownError } // It is OK to push on backstack, since when user leaves the error screen, a new root will be set, // or the whole flow will be popped. From cd61c6b3f072da39eef2a2731f47a954edb49f0d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 28 Apr 2026 11:10:56 +0000 Subject: [PATCH 0259/1083] Update screenshots --- ...impl.screens.confirmation_CodeConfirmationView_Day_0_en.png | 3 +++ ...pl.screens.confirmation_CodeConfirmationView_Night_0_en.png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png new file mode 100644 index 0000000000..a9e31653f6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8dab1dc964cea9a76dc7130d8ac2bfe5d3c866fd6d8d969101eb50e828775d3 +size 31915 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png new file mode 100644 index 0000000000..43c472ebb1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec67e3fef25c57331cb2425f8fc46a733e16a98c9945d0a4e5b950843c42fa34 +size 31087 From 90ed38574510137f86dc93bcd518a0f07ff952d8 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 28 Apr 2026 13:17:57 +0200 Subject: [PATCH 0260/1083] Fix record screenshots action permissions (#6679) --- .github/workflows/recordScreenshots.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 0f4c8ee581..4b70cffe61 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -17,6 +17,7 @@ jobs: permissions: # Need write permissions on PRs to remove the label "Record-Screenshots" pull-requests: write + contents: write name: Record screenshots on branch ${{ github.event.pull_request.head.ref || github.ref_name }} runs-on: ubuntu-latest if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'Record-Screenshots' From 997227b020dc16471dce69086b6ceb369bdc53c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:49:37 +0200 Subject: [PATCH 0261/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.04.27 (#6666) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency org.matrix.rustcomponents:sdk-android to v26.04.27 * Fix breaking API changes: - OIDC components are now prefixed `OAuth`. - `Room.startLiveLocationShare` now returns the event id of the beacon state event if it succeeds. - `RoomInfo` now contains an `activeServiceMembersCount` property. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- gradle/libs.versions.toml | 2 +- .../libraries/matrix/api/room/JoinedRoom.kt | 4 ++-- .../matrix/impl/RustMatrixClientFactory.kt | 2 +- .../matrix/impl/auth/AuthenticationException.kt | 14 +++++++------- .../matrix/impl/auth/HomeserverDetails.kt | 2 +- .../matrix/impl/auth/OidcConfigurationProvider.kt | 4 ++-- .../libraries/matrix/impl/auth/OidcPrompt.kt | 2 +- .../RustHomeServerLoginCompatibilityChecker.kt | 4 ++-- .../impl/auth/RustMatrixAuthenticationService.kt | 10 +++++----- .../matrix/impl/auth/qrlogin/QrErrorMapper.kt | 2 +- .../impl/encryption/RustIdentityResetHandle.kt | 2 +- .../libraries/matrix/impl/mapper/Session.kt | 2 +- .../libraries/matrix/impl/room/JoinedRustRoom.kt | 6 +++--- .../impl/room/location/LiveLocationSharesFlow.kt | 6 +++--- .../auth/AuthenticationExceptionMappingTest.kt | 12 ++++++------ .../matrix/impl/auth/qrlogin/QrErrorMapperTest.kt | 2 +- .../impl/fixtures/factories/NotificationItem.kt | 5 +++++ .../matrix/impl/fixtures/factories/RoomInfo.kt | 2 ++ .../matrix/impl/fixtures/factories/Session.kt | 2 +- .../fakes/FakeFfiHomeserverLoginDetails.kt | 2 +- .../libraries/matrix/test/room/FakeJoinedRoom.kt | 5 +++-- 21 files changed, 50 insertions(+), 42 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 97b1b959e8..b942901e19 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.21" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.27" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt index 32a6f2e409..f3fefab9a8 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt @@ -196,9 +196,9 @@ interface JoinedRoom : BaseRoom { /** * Start sharing live location in this room. * @param durationMillis How long to share location (in milliseconds). - * @return Result indicating success or failure. + * @return Result containing the [EventId] of the beacon state event on success or an error on failure. */ - suspend fun startLiveLocationShare(durationMillis: Long): Result + suspend fun startLiveLocationShare(durationMillis: Long): Result /** * Stop sharing live location in this room. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 933298bc6c..e5bae3bb9d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -214,5 +214,5 @@ fun SessionData.toSession() = Session( deviceId = deviceId, homeserverUrl = homeserverUrl, slidingSyncVersion = SlidingSyncVersion.NATIVE, - oidcData = oidcData, + oauthData = oidcData, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index ebe0c5e4e8..2a151057b3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.impl.auth import io.element.android.libraries.matrix.api.auth.AuthenticationException import org.matrix.rustcomponents.sdk.ClientBuildException -import org.matrix.rustcomponents.sdk.OidcException +import org.matrix.rustcomponents.sdk.OAuthException fun Throwable.mapAuthenticationException(): AuthenticationException { return when (this) { @@ -29,12 +29,12 @@ fun Throwable.mapAuthenticationException(): AuthenticationException { is ClientBuildException.WellKnownLookupFailed -> AuthenticationException.Generic(message) is ClientBuildException.EventCache -> AuthenticationException.Generic(message) } - is OidcException -> when (this) { - is OidcException.Generic -> AuthenticationException.Oidc(message) - is OidcException.CallbackUrlInvalid -> AuthenticationException.Oidc(message) - is OidcException.Cancelled -> AuthenticationException.Oidc(message) - is OidcException.MetadataInvalid -> AuthenticationException.Oidc(message) - is OidcException.NotSupported -> AuthenticationException.Oidc(message) + is OAuthException -> when (this) { + is OAuthException.Generic -> AuthenticationException.Oidc(message) + is OAuthException.CallbackUrlInvalid -> AuthenticationException.Oidc(message) + is OAuthException.Cancelled -> AuthenticationException.Oidc(message) + is OAuthException.MetadataInvalid -> AuthenticationException.Oidc(message) + is OAuthException.NotSupported -> AuthenticationException.Oidc(message) } else -> AuthenticationException.Generic(message) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt index acf96d69d4..acf3a5a55b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt @@ -15,6 +15,6 @@ fun HomeserverLoginDetails.map(): MatrixHomeServerDetails = use { MatrixHomeServerDetails( url = url(), supportsPasswordLogin = supportsPasswordLogin(), - supportsOidcLogin = supportsOidcLogin(), + supportsOidcLogin = supportsOauthLogin(), ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt index 6f9dd67b12..033b613dd8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt @@ -12,14 +12,14 @@ import dev.zacsweers.metro.Inject import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.auth.OidcConfig import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider -import org.matrix.rustcomponents.sdk.OidcConfiguration +import org.matrix.rustcomponents.sdk.OAuthConfiguration @Inject class OidcConfigurationProvider( private val buildMeta: BuildMeta, private val oidcRedirectUrlProvider: OidcRedirectUrlProvider, ) { - fun get(): OidcConfiguration = OidcConfiguration( + fun get(): OAuthConfiguration = OAuthConfiguration( clientName = buildMeta.applicationName, redirectUri = oidcRedirectUrlProvider.provide(), clientUri = OidcConfig.CLIENT_URI, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt index e21d8d94c6..a23a6e5041 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt @@ -9,7 +9,7 @@ package io.element.android.libraries.matrix.impl.auth import io.element.android.libraries.matrix.api.auth.OidcPrompt -import org.matrix.rustcomponents.sdk.OidcPrompt as RustOidcPrompt +import org.matrix.rustcomponents.sdk.OAuthPrompt as RustOidcPrompt internal fun OidcPrompt.toRustPrompt(): RustOidcPrompt { return when (this) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt index 0603fddec4..4f59906023 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt @@ -31,8 +31,8 @@ class RustHomeServerLoginCompatibilityChecker( it.homeserverLoginDetails() } .use { - Timber.d("Homeserver $url | OIDC: ${it.supportsOidcLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}") - it.supportsOidcLogin() || it.supportsPasswordLogin() + Timber.d("Homeserver $url | OIDC: ${it.supportsOauthLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}") + it.supportsOauthLogin() || it.supportsPasswordLogin() } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 9fe7c7cd1f..d186f06209 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -260,8 +260,8 @@ class RustMatrixAuthenticationService( return withContext(coroutineDispatchers.io) { runCatchingExceptions { val client = currentClient ?: error("You need to call `setHomeserver()` first") - val oAuthAuthorizationData = client.urlForOidc( - oidcConfiguration = oidcConfigurationProvider.get(), + val oAuthAuthorizationData = client.urlForOauth( + oauthConfiguration = oidcConfigurationProvider.get(), prompt = prompt.toRustPrompt(), loginHint = loginHint, // If we want to restore a previous session for which we have encryption keys, we can pass the deviceId here. At the moment, we don't @@ -282,7 +282,7 @@ class RustMatrixAuthenticationService( return withContext(coroutineDispatchers.io) { runCatchingExceptions { pendingOAuthAuthorizationData?.use { - currentClient?.abortOidcAuth(it) + currentClient?.abortOauthAuth(it) } pendingOAuthAuthorizationData = null }.mapFailure { failure -> @@ -304,7 +304,7 @@ class RustMatrixAuthenticationService( runCatchingExceptions { val client = currentClient ?: error("You need to call `setHomeserver()` first") val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first") - client.loginWithOidcCallback( + client.loginWithOauthCallback( callbackUrl = callbackUrl, ) // Free the pending data since we won't use it to abort the flow anymore @@ -368,7 +368,7 @@ class RustMatrixAuthenticationService( qrCodeData = sdkQrCodeLoginData, ) client.newLoginWithQrCodeHandler( - oidcConfiguration = oidcConfiguration, + oauthConfiguration = oidcConfiguration, ).use { it.scan( qrCodeData = qrCodeData.rustQrCodeData, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt index ae56cb10fa..1c4e300e91 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt @@ -42,7 +42,7 @@ object QrErrorMapper { is RustHumanQrLoginException.OtherDeviceNotSignedIn -> QrLoginException.OtherDeviceNotSignedIn is RustHumanQrLoginException.LinkingNotSupported -> QrLoginException.LinkingNotSupported is RustHumanQrLoginException.Unknown -> QrLoginException.Unknown - is RustHumanQrLoginException.OidcMetadataInvalid -> QrLoginException.OidcMetadataInvalid + is RustHumanQrLoginException.OAuthMetadataInvalid -> QrLoginException.OidcMetadataInvalid is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt index 4813ec1cc3..8a49d1b11b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt @@ -25,7 +25,7 @@ object RustIdentityResetHandleFactory { return runCatchingExceptions { identityResetHandle?.let { when (val authType = identityResetHandle.authType()) { - is CrossSigningResetAuthType.Oidc -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl) + is CrossSigningResetAuthType.OAuth -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl) // User interactive authentication (user + password) CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(userId, identityResetHandle) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt index 3199ebf71a..bfb200a994 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt @@ -27,7 +27,7 @@ internal fun Session.toSessionData( accessToken = accessToken, refreshToken = refreshToken, homeserverUrl = homeserverUrl ?: this.homeserverUrl, - oidcData = oidcData, + oidcData = oauthData, loginTimestamp = Date(), isTokenValid = isTokenValid, loginType = loginType, 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 6507cf38c8..87ef0815ce 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 @@ -516,10 +516,10 @@ class JoinedRustRoom( return innerRoom.liveLocationSharesFlow().timedByExpiry(systemClock::epochMillis) } - override suspend fun startLiveLocationShare(durationMillis: Long): Result = withContext(roomDispatcher) { + override suspend fun startLiveLocationShare(durationMillis: Long): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.startLiveLocationShare(durationMillis.toULong()) - } + }.map(::EventId) } override suspend fun stopLiveLocationShare(): Result = withContext(roomDispatcher) { @@ -538,7 +538,7 @@ class JoinedRustRoom( override fun destroy() { baseRoom.destroy() - liveInnerTimeline.destroy() + liveTimeline.close() threadsListService.destroy() Timber.d("Room $roomId destroyed") } 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 bae406a137..1a341d0dc2 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 @@ -16,8 +16,8 @@ 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.LiveLocationsListener import org.matrix.rustcomponents.sdk.RoomInterface import org.matrix.rustcomponents.sdk.LiveLocationShare as RustLiveLocationShare @@ -41,9 +41,9 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { } } return callbackFlow { - val liveLocationShares = liveLocationShares() + val liveLocationShares = liveLocationsObserver() val shares: MutableList = ArrayList() - val taskHandle = liveLocationShares.subscribe(object : LiveLocationShareListener { + val taskHandle = liveLocationShares.subscribe(object : LiveLocationsListener { override fun onUpdate(updates: List) { for (update in updates) { shares.applyUpdate(update) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt index 8449d9a6c3..7cfd3392a1 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt @@ -13,7 +13,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.auth.AuthenticationException import org.junit.Test import org.matrix.rustcomponents.sdk.ClientBuildException -import org.matrix.rustcomponents.sdk.OidcException +import org.matrix.rustcomponents.sdk.OAuthException class AuthenticationExceptionMappingTest { @Test @@ -65,15 +65,15 @@ class AuthenticationExceptionMappingTest { @Test fun `mapping Oidc exceptions map to the Oidc Kotlin`() { - assertThat(OidcException.Generic("Generic").mapAuthenticationException()) + assertThat(OAuthException.Generic("Generic").mapAuthenticationException()) .isException("Generic") - assertThat(OidcException.CallbackUrlInvalid("CallbackUrlInvalid").mapAuthenticationException()) + assertThat(OAuthException.CallbackUrlInvalid("CallbackUrlInvalid").mapAuthenticationException()) .isException("CallbackUrlInvalid") - assertThat(OidcException.Cancelled("Cancelled").mapAuthenticationException()) + assertThat(OAuthException.Cancelled("Cancelled").mapAuthenticationException()) .isException("Cancelled") - assertThat(OidcException.MetadataInvalid("MetadataInvalid").mapAuthenticationException()) + assertThat(OAuthException.MetadataInvalid("MetadataInvalid").mapAuthenticationException()) .isException("MetadataInvalid") - assertThat(OidcException.NotSupported("NotSupported").mapAuthenticationException()) + assertThat(OAuthException.NotSupported("NotSupported").mapAuthenticationException()) .isException("NotSupported") } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt index 0ef20c82a6..c20a77ace4 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt @@ -32,7 +32,7 @@ class QrErrorMapperTest { assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn) assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported) assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown) - assertThat(QrErrorMapper.map(RustHumanQrLoginException.OidcMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.OAuthMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid) assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt index 4db2db7107..82984c480d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.api.core.ThreadId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimelineEvent import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_USER_NAME @@ -68,6 +69,8 @@ internal fun aRustNotificationRoomInfo( isDirect: Boolean = false, joinRule: JoinRule? = null, isSpace: Boolean = false, + serviceMembers: List = emptyList(), + activeServiceMemberCount: Int = 0, ) = NotificationRoomInfo( displayName = displayName, avatarUrl = avatarUrl, @@ -78,6 +81,8 @@ internal fun aRustNotificationRoomInfo( isDirect = isDirect, joinRule = joinRule, isSpace = isSpace, + serviceMembers = serviceMembers.map { it.value }, + activeServiceMembersCount = activeServiceMemberCount.toULong(), ) internal fun aRustNotificationEventTimeline( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt index 1b0cc12461..491614a7fc 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt @@ -62,6 +62,7 @@ internal fun aRustRoomInfo( serviceMembers: List = emptyList(), isLowPriority: Boolean = false, activeRoomCallConsensusIntent: RtcCallIntentConsensus = RtcCallIntentConsensus.None, + activeServiceMembersCount: Int = 0, ) = RoomInfo( id = id, displayName = displayName, @@ -101,4 +102,5 @@ internal fun aRustRoomInfo( serviceMembers = serviceMembers, isLowPriority = isLowPriority, activeRoomCallConsensusIntent = activeRoomCallConsensusIntent, + activeServiceMembersCount = activeServiceMembersCount.toULong(), ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt index 4671c457b0..af7f44597c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt @@ -24,6 +24,6 @@ internal fun aRustSession( userId = A_USER_ID.value, deviceId = A_DEVICE_ID.value, homeserverUrl = A_HOMESERVER_URL, - oidcData = null, + oauthData = null, slidingSyncVersion = proxy, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt index ade3a2328f..65e24c2494 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt @@ -18,7 +18,7 @@ class FakeFfiHomeserverLoginDetails( private val supportsSsoLogin: Boolean = false, ) : HomeserverLoginDetails(NoHandle) { override fun url(): String = url - override fun supportsOidcLogin(): Boolean = supportsOidcLogin + override fun supportsOauthLogin(): Boolean = supportsOidcLogin override fun supportsPasswordLogin(): Boolean = supportsPasswordLogin override fun supportsSsoLogin(): Boolean = supportsSsoLogin } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index 84497b38de..d1cd340641 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings +import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.threads.FakeThreadsListService import io.element.android.libraries.matrix.test.timeline.FakeTimeline @@ -238,8 +239,8 @@ class FakeJoinedRoom( return liveLocationSharesFlow } - override suspend fun startLiveLocationShare(durationMillis: Long): Result = simulateLongTask { - startLiveLocationShareResult(durationMillis) + override suspend fun startLiveLocationShare(durationMillis: Long): Result = simulateLongTask { + startLiveLocationShareResult(durationMillis).map { AN_EVENT_ID } } override suspend fun stopLiveLocationShare(): Result = simulateLongTask { From 723b7486bcd8742f4c1b1d9aa1cff003adce3f07 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Tue, 28 Apr 2026 15:19:03 +0100 Subject: [PATCH 0262/1083] Improve detection of completion for Link new device flow The SDK emits a Done progress once complete, but our listener might have been deallocated before receiving the done. --- .../features/linknewdevice/impl/LinkNewDeviceFlowNode.kt | 5 +---- .../matrix/impl/linknewdevice/RustLinkDesktopHandler.kt | 2 ++ .../matrix/impl/linknewdevice/RustLinkMobileHandler.kt | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index 54baee6663..c48678f96c 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -145,10 +145,7 @@ class LinkNewDeviceFlowNode( LinkMobileStep.Starting -> { // This step is not received at the moment, so do nothing } - LinkMobileStep.SyncingSecrets -> { - // LinkMobileStep.Done is not received at the moment, so consider that the flow is done here - callback.onDone() - } + LinkMobileStep.SyncingSecrets -> Unit is LinkMobileStep.WaitingForAuth -> { navigateToBrowser(linkMobileStep.verificationUri) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandler.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandler.kt index 211bdc3d4e..83e657eb07 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandler.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandler.kt @@ -54,6 +54,8 @@ class RustLinkDesktopHandler( } } ) + // We emit Done in case the progress listener was deallocated before scan() sent the Done + _linkDesktopStep.emit(LinkDesktopStep.Done) } catch (e: QrCodeDecodeException) { Timber.tag(tag.value).w(e, "Invalid QR code scanned") _linkDesktopStep.emit( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt index 0189987d96..6d212d4784 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt @@ -49,6 +49,8 @@ class RustLinkMobileHandler( } } ) + // We emit Done in case the progress listener was deallocated before generate() sent the Done + _linkMobileStep.emit(LinkMobileStep.Done) } catch (e: HumanQrGrantLoginException) { Timber.tag(tag.value).w(e, "Error during QR login grant") _linkMobileStep.emit(LinkMobileStep.Error(e.map())) From fd69bbc57ada5bb409213f34c9f981b19d7e88f8 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Tue, 28 Apr 2026 15:42:24 +0100 Subject: [PATCH 0263/1083] Delint --- .../features/linknewdevice/impl/LinkNewDeviceFlowNode.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index ebaf1cda4e..4b3076bca9 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -189,7 +189,9 @@ class LinkNewDeviceFlowNode( is ErrorType.Cancelled -> ErrorScreenType.Cancelled is ErrorType.ConnectionInsecure -> ErrorScreenType.InsecureChannelDetected is ErrorType.Expired, is ErrorType.NotFound, is ErrorType.DeviceNotFound -> ErrorScreenType.Expired - is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError // TODO: should show other_device_already_signed_in screen with checkmark when available + // TODO: we should show other_device_already_signed_in screen with checkmark when available + // See: https://github.com/element-hq/element-x-android/issues/6678 + is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError // TODO: check if we expect to hit this here or if it should be caught earlier on is ErrorType.MissingSecretsBackup, is ErrorType.DeviceIdAlreadyInUse, is ErrorType.Unknown -> ErrorScreenType.UnknownError } From 1d03cbfc062bd6a22d0073075f39e1d8664fb681 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 10:34:50 +0200 Subject: [PATCH 0264/1083] Fix quality issues and formatting --- .../linknewdevice/impl/LinkNewDeviceFlowNode.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index dc17cfff81..2d8fe71949 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -196,12 +196,17 @@ class LinkNewDeviceFlowNode( is ErrorType.UnsupportedProtocol -> ErrorScreenType.ProtocolNotSupported is ErrorType.Cancelled -> ErrorScreenType.Cancelled is ErrorType.ConnectionInsecure -> ErrorScreenType.InsecureChannelDetected - is ErrorType.Expired, is ErrorType.NotFound, is ErrorType.DeviceNotFound -> ErrorScreenType.Expired - // TODO: we should show other_device_already_signed_in screen with checkmark when available + is ErrorType.Expired, + is ErrorType.NotFound, + is ErrorType.DeviceNotFound -> ErrorScreenType.Expired + // TODO we should show other_device_already_signed_in screen with checkmark when available // See: https://github.com/element-hq/element-x-android/issues/6678 is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError - is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError // TODO: check if we expect to hit this here or if it should be caught earlier on - is ErrorType.MissingSecretsBackup, is ErrorType.DeviceIdAlreadyInUse, is ErrorType.Unknown -> ErrorScreenType.UnknownError + // TODO check if we expect to hit this here or if it should be caught earlier on + is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError + is ErrorType.MissingSecretsBackup, + is ErrorType.DeviceIdAlreadyInUse, + is ErrorType.Unknown -> ErrorScreenType.UnknownError } // It is OK to push on backstack, since when user leaves the error screen, a new root will be set, // or the whole flow will be popped. From 083fc5c5fb0a4d3bab9c2f36423d59b41b6f6185 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 11:11:43 +0200 Subject: [PATCH 0265/1083] [Link new device] Add missing screen for the error case `OtherDeviceAlreadySignedIn` Closes #6678 --- .../impl/LinkNewDeviceFlowNode.kt | 4 +-- .../impl/screens/error/ErrorScreenType.kt | 3 ++ .../screens/error/ErrorScreenTypeProvider.kt | 1 + .../impl/screens/error/ErrorView.kt | 32 ++++++++++++++++--- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index 2d8fe71949..4ccdb6b387 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -199,9 +199,7 @@ class LinkNewDeviceFlowNode( is ErrorType.Expired, is ErrorType.NotFound, is ErrorType.DeviceNotFound -> ErrorScreenType.Expired - // TODO we should show other_device_already_signed_in screen with checkmark when available - // See: https://github.com/element-hq/element-x-android/issues/6678 - is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.UnknownError + is ErrorType.OtherDeviceAlreadySignedIn -> ErrorScreenType.OtherDeviceAlreadySignedIn // TODO check if we expect to hit this here or if it should be caught earlier on is ErrorType.UnsupportedQrCodeType -> ErrorScreenType.UnknownError is ErrorType.MissingSecretsBackup, diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenType.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenType.kt index b92a19ef8a..ad8cc276c5 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenType.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenType.kt @@ -20,6 +20,9 @@ sealed interface ErrorScreenType : NodeInputs, Parcelable { @Parcelize data object Expired : ErrorScreenType + @Parcelize + data object OtherDeviceAlreadySignedIn : ErrorScreenType + @Parcelize data object Mismatch2Digits : ErrorScreenType diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenTypeProvider.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenTypeProvider.kt index 7fd699101b..5946eb9ab2 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenTypeProvider.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorScreenTypeProvider.kt @@ -19,5 +19,6 @@ class ErrorScreenTypeProvider : PreviewParameterProvider { ErrorScreenType.InsecureChannelDetected, ErrorScreenType.SlidingSyncNotAvailable, ErrorScreenType.UnknownError, + ErrorScreenType.OtherDeviceAlreadySignedIn, ) } diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt index 9f67e8bc17..4db2aa9ad5 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt @@ -47,17 +47,26 @@ fun ErrorView( ) { val appName = LocalBuildMeta.current.applicationName BackHandler(onBack = onCancel) + val iconStyle = when (errorScreenType) { + ErrorScreenType.OtherDeviceAlreadySignedIn -> BigIcon.Style.SuccessSolid + else -> BigIcon.Style.AlertSolid + } FlowStepPage( modifier = modifier, - iconStyle = BigIcon.Style.AlertSolid, + iconStyle = iconStyle, title = titleText(errorScreenType, appName), subTitle = subtitleText(errorScreenType, appName), content = { Content(errorScreenType) }, buttons = { - Buttons( - onRetry = onRetry, - onCancel = onCancel, - ) + when (errorScreenType) { + ErrorScreenType.OtherDeviceAlreadySignedIn -> DoneButton( + onDone = onCancel, + ) + else -> Buttons( + onRetry = onRetry, + onCancel = onCancel, + ) + } }, ) } @@ -72,6 +81,7 @@ private fun titleText(errorScreenType: ErrorScreenType, appName: String) = when ErrorScreenType.Mismatch2Digits -> stringResource(id = R.string.screen_link_new_device_wrong_number_title) ErrorScreenType.SlidingSyncNotAvailable -> stringResource(id = R.string.screen_qr_code_login_error_sliding_sync_not_supported_title, appName) is ErrorScreenType.UnknownError -> stringResource(CommonStrings.common_something_went_wrong) + ErrorScreenType.OtherDeviceAlreadySignedIn -> stringResource(R.string.screen_qr_code_login_error_device_already_signed_in_title) } @Composable @@ -84,6 +94,7 @@ private fun subtitleText(errorScreenType: ErrorScreenType, appName: String) = wh ErrorScreenType.InsecureChannelDetected -> stringResource(id = R.string.screen_qr_code_login_connection_note_secure_state_description) ErrorScreenType.SlidingSyncNotAvailable -> stringResource(id = R.string.screen_qr_code_login_error_sliding_sync_not_supported_subtitle, appName) is ErrorScreenType.UnknownError -> stringResource(R.string.screen_qr_code_login_unknown_error_description) + ErrorScreenType.OtherDeviceAlreadySignedIn -> stringResource(R.string.screen_qr_code_login_error_device_already_signed_in_subtitle) } @Composable @@ -124,6 +135,17 @@ private fun Content(errorScreenType: ErrorScreenType) { } } +@Composable +private fun DoneButton( + onDone: () -> Unit, +) { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_done), + onClick = onDone, + ) +} + @Composable private fun Buttons( onRetry: () -> Unit, From c750fd102f5708718d2e0c1d595c191d39fb56e5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 11:12:17 +0200 Subject: [PATCH 0266/1083] Increase title and subtitle vertical padding on FlowStepPage. --- .../android/libraries/designsystem/atomic/pages/FlowStepPage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt index b62f634ece..a29e1b743c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/FlowStepPage.kt @@ -71,7 +71,7 @@ fun FlowStepPage( }, header = { IconTitleSubtitleMolecule( - modifier = Modifier.padding(bottom = 16.dp), + modifier = Modifier.padding(bottom = 16.dp, start = 8.dp, end = 8.dp), title = title, subTitle = subTitle, iconStyle = iconStyle, From 367995303dd4fc983ec11fd98e75b661fe89d8e4 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 29 Apr 2026 11:41:47 +0200 Subject: [PATCH 0267/1083] Rename `OIDC` components and variables to `OAuth` (#6686) * Rename `OIDC` components and variables to `OAuth`. This matches the new behavior in the SDK. --- app/build.gradle.kts | 8 +- app/src/main/AndroidManifest.xml | 2 +- ....kt => DefaultOAuthRedirectUrlProvider.kt} | 6 +- ...=> DefaultOAuthRedirectUrlProviderTest.kt} | 4 +- appnav/build.gradle.kts | 4 +- .../io/element/android/appnav/RootFlowNode.kt | 12 +-- .../android/appnav/intent/IntentResolver.kt | 14 +-- .../appnav/intent/IntentResolverTest.kt | 32 +++---- .../appnav/loggedin/LoggedInPresenterTest.kt | 2 +- docs/{oidc.md => oauth.md} | 8 +- features/linknewdevice/impl/build.gradle.kts | 4 +- features/login/impl/build.gradle.kts | 4 +- .../features/login/impl/LoginFlowNode.kt | 30 +++---- .../login/impl/error/ChangeServerError.kt | 2 +- .../features/login/impl/login/LoginHelper.kt | 38 ++++---- .../features/login/impl/login/LoginMode.kt | 4 +- .../login/impl/login/LoginModeView.kt | 8 +- .../login/impl/qrcode/QrCodeLoginFlowNode.kt | 4 +- .../ChooseAccountProviderNode.kt | 6 +- .../ChooseAccountProviderView.kt | 8 +- .../impl/screens/classic/ClassicFlowNode.kt | 8 +- .../loginwithclassic/LoginWithClassicNode.kt | 6 +- .../loginwithclassic/LoginWithClassicView.kt | 8 +- .../ConfirmAccountProviderNode.kt | 6 +- .../ConfirmAccountProviderView.kt | 8 +- .../impl/screens/onboarding/OnBoardingNode.kt | 6 +- .../impl/screens/onboarding/OnBoardingView.kt | 8 +- .../login/impl/DefaultLoginEntryPointTest.kt | 4 +- .../changeserver/ChangeServerPresenterTest.kt | 2 +- .../impl/qrcode/QrCodeLoginFlowNodeTest.kt | 2 +- .../ChooseAccountProviderViewTest.kt | 6 +- .../ConfirmAccountProviderPresenterTest.kt | 88 +++++++++---------- .../onboarding/OnBoardingPresenterTest.kt | 8 +- .../screens/onboarding/OnboardingViewTest.kt | 18 ++-- .../impl/root/PreferencesRootPresenterTest.kt | 2 +- features/securebackup/impl/build.gradle.kts | 2 +- .../impl/reset/ResetIdentityFlowNode.kt | 10 +-- .../signedout/impl/SignedOutStateProvider.kt | 2 +- .../libraries/matrix/api/MatrixClient.kt | 2 +- .../api/auth/AuthenticationException.kt | 2 +- .../api/auth/MatrixAuthenticationService.kt | 18 ++-- .../api/auth/MatrixHomeServerDetails.kt | 4 +- .../auth/{OidcConfig.kt => OAuthConfig.kt} | 2 +- .../auth/{OidcDetails.kt => OAuthDetails.kt} | 2 +- .../auth/{OidcPrompt.kt => OAuthPrompt.kt} | 8 +- ...rovider.kt => OAuthRedirectUrlProvider.kt} | 2 +- .../api/auth/qrlogin/QrLoginException.kt | 2 +- .../api/encryption/EncryptionService.kt | 8 +- .../AccountManagementAction.kt | 2 +- .../api/auth/MatrixHomeServerDetailsTest.kt | 8 +- .../libraries/matrix/impl/RustMatrixClient.kt | 4 +- .../matrix/impl/RustMatrixClientFactory.kt | 2 +- .../impl/auth/AuthenticationException.kt | 10 +-- .../matrix/impl/auth/HomeserverDetails.kt | 2 +- ...vider.kt => OAuthConfigurationProvider.kt} | 20 ++--- .../libraries/matrix/impl/auth/OidcPrompt.kt | 12 +-- ...RustHomeServerLoginCompatibilityChecker.kt | 2 +- .../auth/RustMatrixAuthenticationService.kt | 32 +++---- .../matrix/impl/auth/qrlogin/QrErrorMapper.kt | 2 +- .../encryption/RustIdentityResetHandle.kt | 10 +-- .../libraries/matrix/impl/mapper/Session.kt | 4 +- .../AccountManagementAction.kt | 4 +- .../AuthenticationExceptionMappingTest.kt | 12 +-- .../impl/auth/HomeserverDetailsKtTest.kt | 4 +- ...t.kt => OAuthConfigurationProviderTest.kt} | 8 +- ...HomeserverLoginCompatibilityCheckerTest.kt | 4 +- .../RustMatrixAuthenticationServiceTest.kt | 6 +- .../impl/auth/qrlogin/QrErrorMapperTest.kt | 2 +- .../fakes/FakeFfiHomeserverLoginDetails.kt | 4 +- .../matrix/impl/mapper/SessionKtTest.kt | 4 +- .../AccountManagementActionKtTest.kt | 4 +- .../libraries/matrix/test/FakeMatrixClient.kt | 2 +- .../auth/FakeMatrixAuthenticationService.kt | 32 +++---- ...der.kt => FakeOAuthRedirectUrlProvider.kt} | 6 +- .../test/auth/MatrixHomeServerDetails.kt | 4 +- .../encryption/FakeIdentityResetHandle.kt | 12 +-- .../{oidc => oauth}/api/build.gradle.kts | 2 +- .../libraries/oauth/api/OAuthAction.kt} | 8 +- .../libraries/oauth/api/OAuthActionFlow.kt} | 8 +- .../oauth/api/OAuthIntentResolver.kt} | 6 +- .../{oidc => oauth}/impl/build.gradle.kts | 4 +- .../oauth/impl/DefaultOAuthActionFlow.kt} | 16 ++-- .../oauth/impl/DefaultOAuthIntentResolver.kt | 24 +++++ .../libraries/oauth/impl/OAuthUrlParser.kt} | 28 +++--- .../oauth/impl/DefaultOAuthActionFlowTest.kt} | 17 ++-- .../impl/DefaultOAuthIntentResolverTest.kt} | 35 ++++---- .../oauth/impl/DefaultOAuthUrlParserTest.kt} | 31 ++++--- .../{oidc => oauth}/test/build.gradle.kts | 4 +- .../oauth/test/FakeOAuthIntentResolver.kt} | 14 +-- .../test/customtab/FakeOAuthActionFlow.kt | 33 +++++++ .../oidc/impl/DefaultOidcIntentResolver.kt | 24 ----- .../oidc/test/customtab/FakeOidcActionFlow.kt | 33 ------- .../sessionstorage/api/SessionData.kt | 4 +- .../sessionstorage/impl/SessionDataMapper.kt | 4 +- .../sessionstorage/test/SessionData.kt | 2 +- .../kotlin/extension/DependencyHandleScope.kt | 2 +- 96 files changed, 479 insertions(+), 482 deletions(-) rename app/src/main/kotlin/io/element/android/x/oidc/{DefaultOidcRedirectUrlProvider.kt => DefaultOAuthRedirectUrlProvider.kt} (82%) rename app/src/test/kotlin/io/element/android/x/oidc/{DefaultOidcRedirectUrlProviderTest.kt => DefaultOAuthRedirectUrlProviderTest.kt} (89%) rename docs/{oidc.md => oauth.md} (81%) rename libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/{OidcConfig.kt => OAuthConfig.kt} (97%) rename libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/{OidcDetails.kt => OAuthDetails.kt} (94%) rename libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/{OidcPrompt.kt => OAuthPrompt.kt} (81%) rename libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/{OidcRedirectUrlProvider.kt => OAuthRedirectUrlProvider.kt} (89%) rename libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/{oidc => oauth}/AccountManagementAction.kt (91%) rename libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/{OidcConfigurationProvider.kt => OAuthConfigurationProvider.kt} (53%) rename libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/{oidc => oauth}/AccountManagementAction.kt (86%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/{OidcConfigurationProviderTest.kt => OAuthConfigurationProviderTest.kt} (76%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/{oidc => oauth}/AccountManagementActionKtTest.kt (90%) rename libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/{FakeOidcRedirectUrlProvider.kt => FakeOAuthRedirectUrlProvider.kt} (75%) rename libraries/{oidc => oauth}/api/build.gradle.kts (87%) rename libraries/{oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt => oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthAction.kt} (54%) rename libraries/{oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt => oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthActionFlow.kt} (63%) rename libraries/{oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt => oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthIntentResolver.kt} (68%) rename libraries/{oidc => oauth}/impl/build.gradle.kts (93%) rename libraries/{oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlow.kt => oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlow.kt} (58%) create mode 100644 libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolver.kt rename libraries/{oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt => oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/OAuthUrlParser.kt} (51%) rename libraries/{oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlowTest.kt => oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlowTest.kt} (58%) rename libraries/{oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolverTest.kt => oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolverTest.kt} (64%) rename libraries/{oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcUrlParserTest.kt => oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthUrlParserTest.kt} (56%) rename libraries/{oidc => oauth}/test/build.gradle.kts (80%) rename libraries/{oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/FakeOidcIntentResolver.kt => oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/FakeOAuthIntentResolver.kt} (50%) create mode 100644 libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/customtab/FakeOAuthActionFlow.kt delete mode 100644 libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt delete mode 100644 libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/customtab/FakeOidcActionFlow.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a4ee1c8459..da90ec82e4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -103,13 +103,13 @@ android { logger.warnInBox("Building ${defaultConfig.applicationId} ($baseAppName) [$buildType]") buildTypes { - val oidcRedirectSchemeBase = BuildTimeConfig.METADATA_HOST_REVERSED ?: "io.element.android" + val oAuthRedirectSchemeBase = BuildTimeConfig.METADATA_HOST_REVERSED ?: "io.element.android" getByName("debug") { resValue("string", "app_name", "$baseAppName dbg") resValue( "string", "login_redirect_scheme", - "$oidcRedirectSchemeBase.debug", + "$oAuthRedirectSchemeBase.debug", ) applicationIdSuffix = ".debug" signingConfig = signingConfigs.getByName("debug") @@ -120,7 +120,7 @@ android { resValue( "string", "login_redirect_scheme", - oidcRedirectSchemeBase, + oAuthRedirectSchemeBase, ) signingConfig = signingConfigs.getByName("debug") @@ -157,7 +157,7 @@ android { resValue( "string", "login_redirect_scheme", - "$oidcRedirectSchemeBase.nightly", + "$oAuthRedirectSchemeBase.nightly", ) matchingFallbacks += listOf("release") signingConfig = signingConfigs.getByName("nightly") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6041fbb118..d63e18ec1a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -75,7 +75,7 @@ android:scheme="elementx" /> diff --git a/app/src/main/kotlin/io/element/android/x/oidc/DefaultOidcRedirectUrlProvider.kt b/app/src/main/kotlin/io/element/android/x/oidc/DefaultOAuthRedirectUrlProvider.kt similarity index 82% rename from app/src/main/kotlin/io/element/android/x/oidc/DefaultOidcRedirectUrlProvider.kt rename to app/src/main/kotlin/io/element/android/x/oidc/DefaultOAuthRedirectUrlProvider.kt index ad4f9a47b2..16db564aaf 100644 --- a/app/src/main/kotlin/io/element/android/x/oidc/DefaultOidcRedirectUrlProvider.kt +++ b/app/src/main/kotlin/io/element/android/x/oidc/DefaultOAuthRedirectUrlProvider.kt @@ -10,14 +10,14 @@ package io.element.android.x.oidc import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider +import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.x.R @ContributesBinding(AppScope::class) -class DefaultOidcRedirectUrlProvider( +class DefaultOAuthRedirectUrlProvider( private val stringProvider: StringProvider, -) : OidcRedirectUrlProvider { +) : OAuthRedirectUrlProvider { override fun provide() = buildString { append(stringProvider.getString(R.string.login_redirect_scheme)) append(":/") diff --git a/app/src/test/kotlin/io/element/android/x/oidc/DefaultOidcRedirectUrlProviderTest.kt b/app/src/test/kotlin/io/element/android/x/oidc/DefaultOAuthRedirectUrlProviderTest.kt similarity index 89% rename from app/src/test/kotlin/io/element/android/x/oidc/DefaultOidcRedirectUrlProviderTest.kt rename to app/src/test/kotlin/io/element/android/x/oidc/DefaultOAuthRedirectUrlProviderTest.kt index 18567355d2..c26e3dc692 100644 --- a/app/src/test/kotlin/io/element/android/x/oidc/DefaultOidcRedirectUrlProviderTest.kt +++ b/app/src/test/kotlin/io/element/android/x/oidc/DefaultOAuthRedirectUrlProviderTest.kt @@ -13,13 +13,13 @@ import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.x.R import org.junit.Test -class DefaultOidcRedirectUrlProviderTest { +class DefaultOAuthRedirectUrlProviderTest { @Test fun `test provide`() { val stringProvider = FakeStringProvider( defaultResult = "str" ) - val sut = DefaultOidcRedirectUrlProvider( + val sut = DefaultOAuthRedirectUrlProvider( stringProvider = stringProvider, ) val result = sut.provide() diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index 24a0355b3f..6be468b0d1 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { implementation(projects.libraries.deeplink.api) implementation(projects.libraries.featureflag.api) implementation(projects.libraries.matrix.api) - implementation(projects.libraries.oidc.api) + implementation(projects.libraries.oauth.api) implementation(projects.libraries.preferences.api) implementation(projects.libraries.push.api) implementation(projects.libraries.pushproviders.api) @@ -59,7 +59,7 @@ dependencies { testImplementation(projects.features.login.test) testImplementation(projects.features.share.test) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.libraries.oidc.test) + testImplementation(projects.libraries.oauth.test) testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt index 0e458d3b9c..acf7b66db9 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt @@ -63,8 +63,8 @@ import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.permalink.PermalinkData -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcActionFlow +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthActionFlow import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.ui.common.nodes.emptyNode @@ -95,7 +95,7 @@ class RootFlowNode( private val signedOutEntryPoint: SignedOutEntryPoint, private val accountSelectEntryPoint: AccountSelectEntryPoint, private val intentResolver: IntentResolver, - private val oidcActionFlow: OidcActionFlow, + private val oAuthActionFlow: OAuthActionFlow, private val featureFlagService: FeatureFlagService, private val announcementService: AnnouncementService, private val analyticsService: AnalyticsService, @@ -392,7 +392,7 @@ class RootFlowNode( navigateTo(resolvedIntent.deeplinkData) } is ResolvedIntent.Login -> onLoginLink(resolvedIntent.params) - is ResolvedIntent.Oidc -> onOidcAction(resolvedIntent.oidcAction) + is ResolvedIntent.OAuth -> onOAuthAction(resolvedIntent.oAuthAction) is ResolvedIntent.Permalink -> navigateTo(resolvedIntent.permalinkData) is ResolvedIntent.IncomingShare -> onIncomingShare(resolvedIntent.shareIntentData) } @@ -529,8 +529,8 @@ class RootFlowNode( } } - private fun onOidcAction(oidcAction: OidcAction) { - oidcActionFlow.post(oidcAction) + private fun onOAuthAction(oAuthAction: OAuthAction) { + oAuthActionFlow.post(oAuthAction) } private suspend fun attachSession(sessionId: SessionId): LoggedInFlowNode { diff --git a/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt b/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt index 6844db3ed6..ee316f00aa 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt @@ -18,13 +18,13 @@ import io.element.android.libraries.deeplink.api.DeeplinkData import io.element.android.libraries.deeplink.api.DeeplinkParser import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcIntentResolver +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthIntentResolver import timber.log.Timber sealed interface ResolvedIntent { data class Navigation(val deeplinkData: DeeplinkData) : ResolvedIntent - data class Oidc(val oidcAction: OidcAction) : ResolvedIntent + data class OAuth(val oAuthAction: OAuthAction) : ResolvedIntent data class Permalink(val permalinkData: PermalinkData) : ResolvedIntent data class Login(val params: LoginParams) : ResolvedIntent data class IncomingShare(val shareIntentData: ShareIntentData) : ResolvedIntent @@ -34,7 +34,7 @@ sealed interface ResolvedIntent { class IntentResolver( private val deeplinkParser: DeeplinkParser, private val loginIntentResolver: LoginIntentResolver, - private val oidcIntentResolver: OidcIntentResolver, + private val oAuthIntentResolver: OAuthIntentResolver, private val permalinkParser: PermalinkParser, private val shareIntentHandler: ShareIntentHandler, ) { @@ -45,9 +45,9 @@ class IntentResolver( val deepLinkData = deeplinkParser.getFromIntent(intent) if (deepLinkData != null) return ResolvedIntent.Navigation(deepLinkData) - // Coming during login using Oidc? - val oidcAction = oidcIntentResolver.resolve(intent) - if (oidcAction != null) return ResolvedIntent.Oidc(oidcAction) + // Coming during login using OAuth? + val oAuthAction = oAuthIntentResolver.resolve(intent) + if (oAuthAction != null) return ResolvedIntent.OAuth(oAuthAction) val actionViewData = intent .takeIf { it.action == Intent.ACTION_VIEW } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt index 576e1aaea6..451ca279f8 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt @@ -26,8 +26,8 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_THREAD_ID import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.test.FakeOidcIntentResolver +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.test.FakeOAuthIntentResolver import io.element.android.tests.testutils.lambda.lambdaError import org.junit.Test import org.junit.runner.RunWith @@ -170,9 +170,9 @@ class IntentResolverTest { } @Test - fun `test resolve oidc`() { + fun `test resolve OAuth`() { val sut = createIntentResolver( - oidcIntentResolverResult = { OidcAction.GoBack() }, + oAuthIntentResolverResult = { OAuthAction.GoBack() }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW @@ -180,8 +180,8 @@ class IntentResolverTest { } val result = sut.resolve(intent) assertThat(result).isEqualTo( - ResolvedIntent.Oidc( - oidcAction = OidcAction.GoBack() + ResolvedIntent.OAuth( + oAuthAction = OAuthAction.GoBack() ) ) } @@ -194,7 +194,7 @@ class IntentResolverTest { val sut = createIntentResolver( loginIntentResolverResult = { null }, permalinkParserResult = { permalinkData }, - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW @@ -213,7 +213,7 @@ class IntentResolverTest { val sut = createIntentResolver( permalinkParserResult = { PermalinkData.FallbackLink(Uri.parse("https://matrix.org")) }, loginIntentResolverResult = { null }, - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW @@ -230,7 +230,7 @@ class IntentResolverTest { ) val sut = createIntentResolver( permalinkParserResult = { permalinkData }, - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_BATTERY_LOW @@ -244,7 +244,7 @@ class IntentResolverTest { fun `test incoming share simple`() { val shareIntentData = ShareIntentData.PlainText("Hello") val sut = createIntentResolver( - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, onIncomingShareIntent = { shareIntentData }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { @@ -260,7 +260,7 @@ class IntentResolverTest { val fileUri = "content://com.example.app/file1.jpg".toUri() val shareIntentData = ShareIntentData.Uris(text = "Hello", uris = listOf(UriToShare(fileUri, "image/jpg"))) val sut = createIntentResolver( - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, onIncomingShareIntent = { shareIntentData }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { @@ -277,7 +277,7 @@ class IntentResolverTest { val sut = createIntentResolver( permalinkParserResult = { PermalinkData.FallbackLink(Uri.parse("https://matrix.org")) }, loginIntentResolverResult = { null }, - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW @@ -292,7 +292,7 @@ class IntentResolverTest { val aLoginParams = LoginParams("accountProvider", null) val sut = createIntentResolver( loginIntentResolverResult = { aLoginParams }, - oidcIntentResolverResult = { null }, + oAuthIntentResolverResult = { null }, ) val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW @@ -306,7 +306,7 @@ class IntentResolverTest { deeplinkParserResult: DeeplinkData? = null, permalinkParserResult: (String) -> PermalinkData = { lambdaError() }, loginIntentResolverResult: (String) -> LoginParams? = { lambdaError() }, - oidcIntentResolverResult: (Intent) -> OidcAction? = { lambdaError() }, + oAuthIntentResolverResult: (Intent) -> OAuthAction? = { lambdaError() }, onIncomingShareIntent: (Intent) -> ShareIntentData? = { null }, ): IntentResolver { return IntentResolver( @@ -314,8 +314,8 @@ class IntentResolverTest { loginIntentResolver = FakeLoginIntentResolver( parseResult = loginIntentResolverResult, ), - oidcIntentResolver = FakeOidcIntentResolver( - resolveResult = oidcIntentResolverResult, + oAuthIntentResolver = FakeOAuthIntentResolver( + resolveResult = oAuthIntentResolverResult, ), permalinkParser = FakePermalinkParser( result = permalinkParserResult 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 902f446a6f..18c8cfd7b9 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 @@ -21,7 +21,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.SessionId 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.oauth.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.SyncState diff --git a/docs/oidc.md b/docs/oauth.md similarity index 81% rename from docs/oidc.md rename to docs/oauth.md index 23709b608c..1080c64b0e 100644 --- a/docs/oidc.md +++ b/docs/oauth.md @@ -1,4 +1,4 @@ -This file contains some rough notes about Oidc implementation, with some examples of actual data. +This file contains some rough notes about OAuth implementation, with some examples of actual data. [ios implementation](https://github.com/element-hq/element-x-ios/compare/develop...doug/oidc-temp) @@ -25,7 +25,7 @@ tosUri = "https://element.io/user-terms-of-service", policyUri = "https://element.io/privacy" -Example of OidcData (from presentUrl callback): +Example of OAuthData (from presentUrl callback): url: https://auth-oidc.lab.element.dev/authorize?response_type=code&client_id=01GYCAGG3PA70CJ97ZVP0WFJY3&redirect_uri=io.element%3A%2Fcallback&scope=openid+urn%3Amatrix%3Aorg.matrix.msc2967.client%3Aapi%3A*+urn%3Amatrix%3Aorg.matrix.msc2967.client%3Adevice%3AYAgcPW4mcG&state=ex6mNJVFZ5jn9wL8&nonce=NZ93DOyIGQd9exPQ&code_challenge_method=S256&code_challenge=FFRcPALNSPCh-ZgpyTRFu_h8NZJVncfvihbfT9CyX8U&prompt=consent Formatted url: @@ -43,8 +43,8 @@ https://auth-oidc.lab.element.dev/authorize? state: ex6mNJVFZ5jn9wL8 -Oidc client example: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/examples/oidc_cli/src/main.rs -Oidc sdk doc: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/crates/matrix-sdk/src/oidc.rs +OAuth client example: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/examples/oidc_cli/src/main.rs +OAuth sdk doc: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/crates/matrix-sdk/src/oidc.rs Test server: diff --git a/features/linknewdevice/impl/build.gradle.kts b/features/linknewdevice/impl/build.gradle.kts index 9c1aa9e990..adbec91e6a 100644 --- a/features/linknewdevice/impl/build.gradle.kts +++ b/features/linknewdevice/impl/build.gradle.kts @@ -43,7 +43,7 @@ dependencies { implementation(projects.libraries.permissions.api) implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.qrcode) - implementation(projects.libraries.oidc.api) + implementation(projects.libraries.oauth.api) implementation(projects.libraries.uiUtils) implementation(projects.libraries.wellknown.api) implementation(libs.androidx.browser) @@ -56,7 +56,7 @@ dependencies { testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.libraries.oidc.test) + testImplementation(projects.libraries.oauth.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.libraries.wellknown.test) diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index 12af922cbe..e739beb20a 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -69,7 +69,7 @@ dependencies { implementation(projects.libraries.permissions.api) implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.qrcode) - implementation(projects.libraries.oidc.api) + implementation(projects.libraries.oauth.api) implementation(projects.libraries.uiUtils) implementation(projects.libraries.wellknown.api) implementation(libs.androidx.browser) @@ -83,7 +83,7 @@ dependencies { testImplementation(projects.features.preferences.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.libraries.oidc.test) + testImplementation(projects.libraries.oauth.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.libraries.wellknown.test) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt index fb384d505a..978d28dfa3 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt @@ -50,9 +50,9 @@ import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.matrix.api.auth.OidcDetails -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcActionFlow +import io.element.android.libraries.matrix.api.auth.OAuthDetails +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthActionFlow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -64,7 +64,7 @@ class LoginFlowNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val accountProviderDataSource: AccountProviderDataSource, - private val oidcActionFlow: OidcActionFlow, + private val oAuthActionFlow: OAuthActionFlow, @AppCoroutineScope private val appCoroutineScope: CoroutineScope, private val elementClassicConnection: ElementClassicConnection, @@ -100,7 +100,7 @@ class LoginFlowNode( // by pressing back or by closing the Custom Chrome Tab. lifecycleScope.launch { delay(5000) - oidcActionFlow.post(OidcAction.GoBack(toUnblock = true)) + oAuthActionFlow.post(OAuthAction.GoBack(toUnblock = true)) } } } @@ -161,8 +161,8 @@ class LoginFlowNode( backstack.push(NavTarget.LoginPassword()) } - override fun navigateToOidc(oidcDetails: OidcDetails) { - navigateToMas(oidcDetails) + override fun navigateToOAuth(oAuthDetails: OAuthDetails) { + navigateToMas(oAuthDetails) } override fun navigateToCreateAccount(url: String) { @@ -197,8 +197,8 @@ class LoginFlowNode( callback.navigateToBugReport() } - override fun navigateToOidc(oidcDetails: OidcDetails) { - navigateToMas(oidcDetails) + override fun navigateToOAuth(oAuthDetails: OAuthDetails) { + navigateToMas(oAuthDetails) } override fun navigateToCreateAccount(url: String) { @@ -243,8 +243,8 @@ class LoginFlowNode( } NavTarget.ChooseAccountProvider -> { val callback = object : ChooseAccountProviderNode.Callback { - override fun navigateToOidc(oidcDetails: OidcDetails) { - navigateToMas(oidcDetails) + override fun navigateToOAuth(oAuthDetails: OAuthDetails) { + navigateToMas(oAuthDetails) } override fun navigateToCreateAccount(url: String) { @@ -270,8 +270,8 @@ class LoginFlowNode( isAccountCreation = navTarget.isAccountCreation, ) val callback = object : ConfirmAccountProviderNode.Callback { - override fun navigateToOidc(oidcDetails: OidcDetails) { - navigateToMas(oidcDetails) + override fun navigateToOAuth(oAuthDetails: OAuthDetails) { + navigateToMas(oAuthDetails) } override fun navigateToCreateAccount(url: String) { @@ -333,10 +333,10 @@ class LoginFlowNode( } } - private fun navigateToMas(oidcDetails: OidcDetails) { + private fun navigateToMas(oAuthDetails: OAuthDetails) { activity?.let { externalAppStarted = true - it.openUrlInChromeCustomTab(null, darkTheme, oidcDetails.url) + it.openUrlInChromeCustomTab(null, darkTheme, oAuthDetails.url) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt index 2f4af14237..560e6123c1 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt @@ -41,7 +41,7 @@ sealed class ChangeServerError : Exception() { // AccountAlreadyLoggedIn error should not happen at this point is AuthenticationException.AccountAlreadyLoggedIn -> Error(messageStr = error.message) is AuthenticationException.Generic -> Error(messageStr = error.message) - is AuthenticationException.Oidc -> Error(messageStr = error.message) + is AuthenticationException.OAuth -> Error(messageStr = error.message) } } is AccountProviderAccessException.NeedElementProException -> NeedElementPro( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt index 78be770bfc..3c871a8a1d 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt @@ -23,9 +23,9 @@ import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationR import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService -import io.element.android.libraries.matrix.api.auth.OidcPrompt -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcActionFlow +import io.element.android.libraries.matrix.api.auth.OAuthPrompt +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthActionFlow /** * This class is responsible for managing the login flow, including handling OIDC actions and @@ -35,7 +35,7 @@ import io.element.android.libraries.oidc.api.OidcActionFlow */ @Inject class LoginHelper( - private val oidcActionFlow: OidcActionFlow, + private val oAuthActionFlow: OAuthActionFlow, private val authenticationService: MatrixAuthenticationService, private val webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever, ) { @@ -44,9 +44,9 @@ class LoginHelper( @Composable fun collectLoginMode(): State> { LaunchedEffect(Unit) { - oidcActionFlow.collect { oidcAction -> - if (oidcAction != null) { - onOidcAction(oidcAction) + oAuthActionFlow.collect { oAuthAction -> + if (oAuthAction != null) { + onOAuthAction(oAuthAction) } } } @@ -73,11 +73,11 @@ class LoginHelper( throw it } }.map { matrixHomeServerDetails -> - if (matrixHomeServerDetails.supportsOidcLogin) { + if (matrixHomeServerDetails.supportsOAuthLogin) { // Retrieve the details right now - val oidcPrompt = if (isAccountCreation) OidcPrompt.Create else OidcPrompt.Login - LoginMode.Oidc( - authenticationService.getOidcUrl(prompt = oidcPrompt, loginHint = loginHint).getOrThrow() + val oAuthPrompt = if (isAccountCreation) OAuthPrompt.Create else OAuthPrompt.Login + LoginMode.OAuth( + authenticationService.getOAuthUrl(prompt = oAuthPrompt, loginHint = loginHint).getOrThrow() ) } else if (isAccountCreation) { val url = webClientUrlForAuthenticationRetriever.retrieve(homeserverUrl) @@ -99,16 +99,16 @@ class LoginHelper( ) } - private suspend fun onOidcAction(oidcAction: OidcAction) { - if (oidcAction is OidcAction.GoBack && oidcAction.toUnblock && loginModeState.value !is AsyncData.Loading) { + private suspend fun onOAuthAction(oAuthAction: OAuthAction) { + if (oAuthAction is OAuthAction.GoBack && oAuthAction.toUnblock && loginModeState.value !is AsyncData.Loading) { // Ignore GoBack action if the current state is not Loading. This GoBack action is coming from LoginFlowNode. // This can happen if there is an error, for instance attempt to login again on the same account. return } loginModeState.value = AsyncData.Loading() - when (oidcAction) { - is OidcAction.GoBack -> { - authenticationService.cancelOidcLogin() + when (oAuthAction) { + is OAuthAction.GoBack -> { + authenticationService.cancelOAuthLogin() .onSuccess { loginModeState.value = AsyncData.Uninitialized } @@ -116,13 +116,13 @@ class LoginHelper( loginModeState.value = AsyncData.Failure(failure) } } - is OidcAction.Success -> { - authenticationService.loginWithOidc(oidcAction.url) + is OAuthAction.Success -> { + authenticationService.loginWithOAuth(oAuthAction.url) .onFailure { failure -> loginModeState.value = AsyncData.Failure(failure) } } } - oidcActionFlow.reset() + oAuthActionFlow.reset() } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginMode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginMode.kt index 08e604ef20..5ea52e0ebd 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginMode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginMode.kt @@ -8,10 +8,10 @@ package io.element.android.features.login.impl.login -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails sealed interface LoginMode { data object PasswordLogin : LoginMode - data class Oidc(val oidcDetails: OidcDetails) : LoginMode + data class OAuth(val oAuthDetails: OAuthDetails) : LoginMode data class AccountCreation(val url: String) : LoginMode } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeView.kt index f88e34bf4a..3549e17457 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeView.kt @@ -24,7 +24,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.LocalBuildMeta import io.element.android.libraries.matrix.api.auth.AuthenticationException -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.ui.strings.CommonStrings @Composable @@ -32,7 +32,7 @@ fun LoginModeView( loginMode: AsyncData, onClearError: () -> Unit, onLearnMoreClick: () -> Unit, - onOidcDetails: (OidcDetails) -> Unit, + onOAuthDetails: (OAuthDetails) -> Unit, onNeedLoginPassword: () -> Unit, onCreateAccountContinue: (url: String) -> Unit ) { @@ -118,7 +118,7 @@ fun LoginModeView( is AsyncData.Loading -> Unit // The Continue button shows the loading state is AsyncData.Success -> { when (val loginModeData = loginMode.data) { - is LoginMode.Oidc -> onOidcDetails(loginModeData.oidcDetails) + is LoginMode.OAuth -> onOAuthDetails(loginModeData.oAuthDetails) LoginMode.PasswordLogin -> onNeedLoginPassword() is LoginMode.AccountCreation -> onCreateAccountContinue(loginModeData.url) } @@ -137,7 +137,7 @@ internal fun LoginModeViewPreview(@PreviewParameter(LoginModeViewErrorProvider:: loginMode = AsyncData.Failure(error), onClearError = {}, onLearnMoreClick = {}, - onOidcDetails = {}, + onOAuthDetails = {}, onNeedLoginPassword = {}, onCreateAccountContinue = {} ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNode.kt index 613aa6aeb6..03264551a5 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNode.kt @@ -135,8 +135,8 @@ class QrCodeLoginFlowNode( is QrLoginException.SlidingSyncNotAvailable -> { backstack.replace(NavTarget.Error(QrCodeErrorScreenType.SlidingSyncNotAvailable)) } - is QrLoginException.OidcMetadataInvalid -> { - Timber.e(error, "OIDC metadata is invalid") + is QrLoginException.OAuthMetadataInvalid -> { + Timber.e(error, "OAuth metadata is invalid") backstack.replace(NavTarget.Error(QrCodeErrorScreenType.UnknownError)) } QrLoginException.CheckCodeAlreadySent, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderNode.kt index 5dc6ebbd6b..5f79f197d9 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderNode.kt @@ -20,7 +20,7 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.features.login.impl.util.openLearnMorePage import io.element.android.libraries.architecture.callback -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails @ContributesNode(AppScope::class) @AssistedInject @@ -31,7 +31,7 @@ class ChooseAccountProviderNode( ) : Node(buildContext, plugins = plugins) { interface Callback : Plugin { fun navigateToLoginPassword() - fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToOAuth(oAuthDetails: OAuthDetails) fun navigateToCreateAccount(url: String) } @@ -45,7 +45,7 @@ class ChooseAccountProviderNode( state = state, modifier = modifier, onBackClick = ::navigateUp, - onOidcDetails = callback::navigateToOidc, + onOAuthDetails = callback::navigateToOAuth, onNeedLoginPassword = callback::navigateToLoginPassword, onLearnMoreClick = { openLearnMorePage(context) }, onCreateAccountContinue = callback::navigateToCreateAccount, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderView.kt index cdb80304a7..f05606dbc3 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderView.kt @@ -43,14 +43,14 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.TopAppBar -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.ui.strings.CommonStrings @Composable fun ChooseAccountProviderView( state: ChooseAccountProviderState, onBackClick: () -> Unit, - onOidcDetails: (OidcDetails) -> Unit, + onOAuthDetails: (OAuthDetails) -> Unit, onNeedLoginPassword: () -> Unit, onLearnMoreClick: () -> Unit, onCreateAccountContinue: (url: String) -> Unit, @@ -129,7 +129,7 @@ fun ChooseAccountProviderView( state.eventSink(ChooseAccountProviderEvents.ClearError) }, onLearnMoreClick = onLearnMoreClick, - onOidcDetails = onOidcDetails, + onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, onCreateAccountContinue = onCreateAccountContinue, ) @@ -144,7 +144,7 @@ internal fun ChooseAccountProviderViewPreview(@PreviewParameter(ChooseAccountPro state = state, onBackClick = { }, onLearnMoreClick = { }, - onOidcDetails = { }, + onOAuthDetails = { }, onNeedLoginPassword = { }, onCreateAccountContinue = { }, ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt index f2ff998652..cfbd86f363 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/ClassicFlowNode.kt @@ -31,7 +31,7 @@ import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.appyx.rememberFaderOrSliderTransitionHandler import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.createNode -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.api.core.UserId import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -54,7 +54,7 @@ class ClassicFlowNode( interface Callback : Plugin { fun navigateToOnBoarding(allowBackNavigation: Boolean) fun navigateToLoginPassword() - fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToOAuth(oAuthDetails: OAuthDetails) fun navigateToCreateAccount(url: String) } @@ -111,8 +111,8 @@ class ClassicFlowNode( callback.navigateToLoginPassword() } - override fun navigateToOidc(oidcDetails: OidcDetails) { - callback.navigateToOidc(oidcDetails) + override fun navigateToOAuth(oAuthDetails: OAuthDetails) { + callback.navigateToOAuth(oAuthDetails) } override fun navigateToCreateAccount(url: String) { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt index c42248a3f8..d5acca38ae 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicNode.kt @@ -21,7 +21,7 @@ import io.element.android.features.login.impl.util.openLearnMorePage import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.inputs -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.api.core.UserId @ContributesNode(AppScope::class) @@ -35,7 +35,7 @@ class LoginWithClassicNode( interface Callback : Plugin { fun navigateToOtherOptions() fun navigateToLoginPassword() - fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToOAuth(oAuthDetails: OAuthDetails) fun navigateToCreateAccount(url: String) fun navigateToMissingKeyBackup() } @@ -60,7 +60,7 @@ class LoginWithClassicNode( state = state, modifier = modifier, onOtherOptionsClick = callback::navigateToOtherOptions, - onOidcDetails = callback::navigateToOidc, + onOAuthDetails = callback::navigateToOAuth, onNeedLoginPassword = callback::navigateToLoginPassword, onLearnMoreClick = { openLearnMorePage(context) }, onCreateAccountContinue = callback::navigateToCreateAccount, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt index 6b5c48f1ec..b1ca50fe61 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/classic/loginwithclassic/LoginWithClassicView.kt @@ -49,7 +49,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -59,7 +59,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun LoginWithClassicView( state: LoginWithClassicState, onOtherOptionsClick: () -> Unit, - onOidcDetails: (OidcDetails) -> Unit, + onOAuthDetails: (OAuthDetails) -> Unit, onNeedLoginPassword: () -> Unit, onLearnMoreClick: () -> Unit, onCreateAccountContinue: (url: String) -> Unit, @@ -200,7 +200,7 @@ fun LoginWithClassicView( state.eventSink(LoginWithClassicEvent.ClearError) }, onLearnMoreClick = onLearnMoreClick, - onOidcDetails = onOidcDetails, + onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, onCreateAccountContinue = onCreateAccountContinue, ) @@ -212,7 +212,7 @@ internal fun LoginWithClassicViewPreview(@PreviewParameter(LoginWithClassicState LoginWithClassicView( state = state, onOtherOptionsClick = {}, - onOidcDetails = {}, + onOAuthDetails = {}, onNeedLoginPassword = {}, onLearnMoreClick = {}, onCreateAccountContinue = {}, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt index e3643afbf2..928a493dc1 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt @@ -22,7 +22,7 @@ import io.element.android.features.login.impl.util.openLearnMorePage import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.inputs -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails @ContributesNode(AppScope::class) @AssistedInject @@ -44,7 +44,7 @@ class ConfirmAccountProviderNode( interface Callback : Plugin { fun navigateToLoginPassword() - fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToOAuth(oAuthDetails: OAuthDetails) fun navigateToCreateAccount(url: String) fun navigateToChangeAccountProvider() } @@ -58,7 +58,7 @@ class ConfirmAccountProviderNode( ConfirmAccountProviderView( state = state, modifier = modifier, - onOidcDetails = callback::navigateToOidc, + onOAuthDetails = callback::navigateToOAuth, onNeedLoginPassword = callback::navigateToLoginPassword, onCreateAccountContinue = callback::navigateToCreateAccount, onChange = callback::navigateToChangeAccountProvider, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt index a175ab556d..c2525f3756 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt @@ -30,7 +30,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.TextButton -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -38,7 +38,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun ConfirmAccountProviderView( state: ConfirmAccountProviderState, - onOidcDetails: (OidcDetails) -> Unit, + onOAuthDetails: (OAuthDetails) -> Unit, onNeedLoginPassword: () -> Unit, onLearnMoreClick: () -> Unit, onCreateAccountContinue: (url: String) -> Unit, @@ -103,7 +103,7 @@ fun ConfirmAccountProviderView( eventSink(ConfirmAccountProviderEvents.ClearError) }, onLearnMoreClick = onLearnMoreClick, - onOidcDetails = onOidcDetails, + onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, onCreateAccountContinue = onCreateAccountContinue, ) @@ -117,7 +117,7 @@ internal fun ConfirmAccountProviderViewPreview( ) = ElementPreview { ConfirmAccountProviderView( state = state, - onOidcDetails = {}, + onOAuthDetails = {}, onNeedLoginPassword = {}, onCreateAccountContinue = {}, onLearnMoreClick = {}, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt index 5572c412a0..99f7e86fd3 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingNode.kt @@ -22,7 +22,7 @@ import io.element.android.features.login.impl.util.openLearnMorePage import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.inputs -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails @ContributesNode(AppScope::class) @AssistedInject @@ -40,7 +40,7 @@ class OnBoardingNode( fun navigateToQrCode() fun navigateToBugReport() fun navigateToLoginPassword() - fun navigateToOidc(oidcDetails: OidcDetails) + fun navigateToOAuth(oAuthDetails: OAuthDetails) fun navigateToCreateAccount(url: String) fun navigateToDeveloperSettings() fun onDone() @@ -71,7 +71,7 @@ class OnBoardingNode( onCreateAccount = callback::navigateToSignUpFlow, onSignInWithQrCode = callback::navigateToQrCode, onReportProblem = callback::navigateToBugReport, - onOidcDetails = callback::navigateToOidc, + onOAuthDetails = callback::navigateToOAuth, onNeedLoginPassword = callback::navigateToLoginPassword, onLearnMoreClick = { openLearnMorePage(context) }, onCreateAccountContinue = callback::navigateToCreateAccount, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt index 5ee7ab6ac4..53c36ac4f8 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingView.kt @@ -50,7 +50,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -68,7 +68,7 @@ fun OnBoardingView( onSignInWithQrCode: () -> Unit, onSignIn: (mustChooseAccountProvider: Boolean) -> Unit, onCreateAccount: () -> Unit, - onOidcDetails: (OidcDetails) -> Unit, + onOAuthDetails: (OAuthDetails) -> Unit, onNeedLoginPassword: () -> Unit, onLearnMoreClick: () -> Unit, onCreateAccountContinue: (url: String) -> Unit, @@ -82,7 +82,7 @@ fun OnBoardingView( state.eventSink(OnBoardingEvents.ClearError) }, onLearnMoreClick = onLearnMoreClick, - onOidcDetails = onOidcDetails, + onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, onCreateAccountContinue = onCreateAccountContinue, ) @@ -354,7 +354,7 @@ internal fun OnBoardingViewPreview( onSignIn = {}, onCreateAccount = {}, onReportProblem = {}, - onOidcDetails = {}, + onOAuthDetails = {}, onNeedLoginPassword = {}, onLearnMoreClick = {}, onCreateAccountContinue = {}, diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt index 86a629270f..a05194d008 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt @@ -17,7 +17,7 @@ import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.classic.FakeElementClassicConnection import io.element.android.features.preferences.test.FakePreferencesEntryPoint -import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow +import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import kotlinx.coroutines.test.runTest @@ -39,7 +39,7 @@ class DefaultLoginEntryPointTest { buildContext = buildContext, plugins = plugins, accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), - oidcActionFlow = FakeOidcActionFlow(), + oAuthActionFlow = FakeOAuthActionFlow(), appCoroutineScope = backgroundScope, elementClassicConnection = FakeElementClassicConnection(), preferencesEntryPoint = FakePreferencesEntryPoint(), diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt index 1fb5d37627..274b58ee49 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt @@ -50,7 +50,7 @@ class ChangeServerPresenterTest { fun `present - change server ok`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) createPresenter( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNodeTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNodeTest.kt index 9d2628005c..112d8d7108 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNodeTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/qrcode/QrCodeLoginFlowNodeTest.kt @@ -79,7 +79,7 @@ class QrCodeLoginFlowNodeTest { qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.ConnectionInsecure) assertThat(flowNode.currentNavTarget()).isEqualTo(QrCodeLoginFlowNode.NavTarget.Error(QrCodeErrorScreenType.InsecureChannelDetected)) - qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.OidcMetadataInvalid) + qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.OAuthMetadataInvalid) assertThat(flowNode.currentNavTarget()).isEqualTo(QrCodeLoginFlowNode.NavTarget.Error(QrCodeErrorScreenType.UnknownError)) qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.Unknown) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt index f7ff5d384d..c6610b212c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.login.impl.accountprovider.anAccountProvider import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -84,7 +84,7 @@ class ChooseAccountProviderViewTest { private fun AndroidComposeTestRule.setChooseAccountProviderView( state: ChooseAccountProviderState, onBackClick: () -> Unit = EnsureNeverCalled(), - onOidcDetails: (OidcDetails) -> Unit = EnsureNeverCalledWithParam(), + onOAuthDetails: (OAuthDetails) -> Unit = EnsureNeverCalledWithParam(), onNeedLoginPassword: () -> Unit = EnsureNeverCalled(), onLearnMoreClick: () -> Unit = EnsureNeverCalled(), onCreateAccountContinue: (url: String) -> Unit = EnsureNeverCalledWithParam(), @@ -93,7 +93,7 @@ class ChooseAccountProviderViewTest { ChooseAccountProviderView( state = state, onBackClick = onBackClick, - onOidcDetails = onOidcDetails, + onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, onLearnMoreClick = onLearnMoreClick, onCreateAccountContinue = onCreateAccountContinue, diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt index 6372841250..a9045ab152 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt @@ -22,9 +22,9 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.aMatrixHomeServerDetails -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcActionFlow -import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthActionFlow +import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest @@ -74,7 +74,7 @@ class ConfirmAccountProviderPresenterTest { fun `present - continue oidc`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) val presenter = createConfirmAccountProviderPresenter( @@ -89,21 +89,21 @@ class ConfirmAccountProviderPresenterTest { val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) + assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) } } @Test - fun `present - oidc - cancel with failure`() = runTest { + fun `present - OAuth - cancel with failure`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) - val defaultOidcActionFlow = FakeOidcActionFlow() + val defaultOAuthActionFlow = FakeOAuthActionFlow() val presenter = createConfirmAccountProviderPresenter( matrixAuthenticationService = authenticationService, - defaultOidcActionFlow = defaultOidcActionFlow, + defaultOAuthActionFlow = defaultOAuthActionFlow, ) presenter.test { val initialState = awaitItem() @@ -114,25 +114,25 @@ class ConfirmAccountProviderPresenterTest { val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) - authenticationService.givenOidcCancelError(AN_EXCEPTION) - defaultOidcActionFlow.post(OidcAction.GoBack()) + assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + authenticationService.givenOAuthCancelError(AN_EXCEPTION) + defaultOAuthActionFlow.post(OAuthAction.GoBack()) val cancelFailureState = awaitItem() assertThat(cancelFailureState.loginMode).isInstanceOf(AsyncData.Failure::class.java) } } @Test - fun `present - oidc - cancel with success`() = runTest { + fun `present - OAuth - cancel with success`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) - val defaultOidcActionFlow = FakeOidcActionFlow() + val defaultOAuthActionFlow = FakeOAuthActionFlow() val presenter = createConfirmAccountProviderPresenter( matrixAuthenticationService = authenticationService, - defaultOidcActionFlow = defaultOidcActionFlow, + defaultOAuthActionFlow = defaultOAuthActionFlow, ) presenter.test { val initialState = awaitItem() @@ -143,24 +143,24 @@ class ConfirmAccountProviderPresenterTest { val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) - defaultOidcActionFlow.post(OidcAction.GoBack()) + assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + defaultOAuthActionFlow.post(OAuthAction.GoBack()) val cancelFinalState = awaitItem() assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) } } @Test - fun `present - oidc - cancel to unblock`() = runTest { + fun `present - OAuth - cancel to unblock`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) - val defaultOidcActionFlow = FakeOidcActionFlow() + val defaultOAuthActionFlow = FakeOAuthActionFlow() val presenter = createConfirmAccountProviderPresenter( matrixAuthenticationService = authenticationService, - defaultOidcActionFlow = defaultOidcActionFlow, + defaultOAuthActionFlow = defaultOAuthActionFlow, ) presenter.test { val initialState = awaitItem() @@ -168,23 +168,23 @@ class ConfirmAccountProviderPresenterTest { val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) - defaultOidcActionFlow.post(OidcAction.GoBack(toUnblock = true)) + defaultOAuthActionFlow.post(OAuthAction.GoBack(toUnblock = true)) val cancelFinalState = awaitItem() assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) } } @Test - fun `present - oidc - success with failure`() = runTest { + fun `present - OAuth - success with failure`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) - val defaultOidcActionFlow = FakeOidcActionFlow() + val defaultOAuthActionFlow = FakeOAuthActionFlow() val presenter = createConfirmAccountProviderPresenter( matrixAuthenticationService = authenticationService, - defaultOidcActionFlow = defaultOidcActionFlow, + defaultOAuthActionFlow = defaultOAuthActionFlow, ) presenter.test { val initialState = awaitItem() @@ -195,9 +195,9 @@ class ConfirmAccountProviderPresenterTest { val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) + assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) authenticationService.givenLoginError(AN_EXCEPTION) - defaultOidcActionFlow.post(OidcAction.Success("aUrl")) + defaultOAuthActionFlow.post(OAuthAction.Success("aUrl")) val cancelLoadingState = awaitItem() assertThat(cancelLoadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val cancelFailureState = awaitItem() @@ -206,16 +206,16 @@ class ConfirmAccountProviderPresenterTest { } @Test - fun `present - oidc - success with success`() = runTest { + fun `present - OAuth - success with success`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) - val defaultOidcActionFlow = FakeOidcActionFlow() + val defaultOidcActionFlow = FakeOAuthActionFlow() val presenter = createConfirmAccountProviderPresenter( matrixAuthenticationService = authenticationService, - defaultOidcActionFlow = defaultOidcActionFlow, + defaultOAuthActionFlow = defaultOidcActionFlow, ) presenter.test { val initialState = awaitItem() @@ -226,8 +226,8 @@ class ConfirmAccountProviderPresenterTest { val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) - defaultOidcActionFlow.post(OidcAction.Success("aUrl")) + assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + defaultOidcActionFlow.post(OAuthAction.Success("aUrl")) val successSuccessState = awaitItem() assertThat(successSuccessState.loginMode).isInstanceOf(AsyncData.Loading::class.java) } @@ -311,10 +311,10 @@ class ConfirmAccountProviderPresenterTest { } @Test - fun `present - confirm account creation with oidc is successful`() = runTest { + fun `present - confirm account creation with OAuth is successful`() = runTest { val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) val presenter = createConfirmAccountProviderPresenter( @@ -327,16 +327,16 @@ class ConfirmAccountProviderPresenterTest { skipItems(1) // Loading val submittedState = awaitItem() assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) + assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) } } @Test - fun `present - confirm account creation with oidc and url continues with oidc`() = runTest { + fun `present - confirm account creation with OAuth and url continues with OAuth`() = runTest { val aUrl = "aUrl" val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { - Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) + Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, ) val presenter = createConfirmAccountProviderPresenter( @@ -350,12 +350,12 @@ class ConfirmAccountProviderPresenterTest { skipItems(1) // Loading val submittedState = awaitItem() assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) + assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) } } @Test - fun `present - confirm account creation without oidc and with url continuing with url`() = runTest { + fun `present - confirm account creation without OAuth and with url continuing with url`() = runTest { val aUrl = "aUrl" val authenticationService = FakeMatrixAuthenticationService( setHomeserverResult = { @@ -380,14 +380,14 @@ class ConfirmAccountProviderPresenterTest { params: ConfirmAccountProviderPresenter.Params = ConfirmAccountProviderPresenter.Params(isAccountCreation = false), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), - defaultOidcActionFlow: OidcActionFlow = FakeOidcActionFlow(), + defaultOAuthActionFlow: OAuthActionFlow = FakeOAuthActionFlow(), webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), ) = ConfirmAccountProviderPresenter( params = params, accountProviderDataSource = accountProviderDataSource, loginHelper = createLoginHelper( authenticationService = matrixAuthenticationService, - oidcActionFlow = defaultOidcActionFlow, + oAuthActionFlow = defaultOAuthActionFlow, webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever, ), ) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt index 1fdfb7e070..8249694278 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt @@ -31,8 +31,8 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER_URL_2 import io.element.android.libraries.matrix.test.A_LOGIN_HINT import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.core.aBuildMeta -import io.element.android.libraries.oidc.api.OidcActionFlow -import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow +import io.element.android.libraries.oauth.api.OAuthActionFlow +import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData @@ -312,11 +312,11 @@ private fun createPresenter( ) fun createLoginHelper( - oidcActionFlow: OidcActionFlow = FakeOidcActionFlow(), + oAuthActionFlow: OAuthActionFlow = FakeOAuthActionFlow(), authenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), ): LoginHelper = LoginHelper( - oidcActionFlow = oidcActionFlow, + oAuthActionFlow = oAuthActionFlow, authenticationService = authenticationService, webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever, ) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt index ad09445075..a8f0ccbb5a 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt @@ -19,7 +19,7 @@ import com.google.testing.junit.testparameterinjector.TestParameter import io.element.android.features.login.impl.R import io.element.android.features.login.impl.login.LoginMode import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -224,14 +224,14 @@ class OnboardingViewTest { @Test fun `when success Oidc - the expected callback is invoked and the event is received`() { val eventSink = EventsRecorder() - val oidcDetails = OidcDetails("aUrl") - ensureCalledOnceWithParam(oidcDetails) { callback -> + val oAuthDetails = OAuthDetails("aUrl") + ensureCalledOnceWithParam(oAuthDetails) { callback -> rule.setOnboardingView( state = anOnBoardingState( - loginMode = AsyncData.Success(LoginMode.Oidc(oidcDetails)), + loginMode = AsyncData.Success(LoginMode.OAuth(oAuthDetails)), eventSink = eventSink, ), - onOidcDetails = callback, + onOAuthDetails = callback, ) } eventSink.assertSingle(OnBoardingEvents.ClearError) @@ -240,8 +240,8 @@ class OnboardingViewTest { @Test fun `when success AccountCreation - the expected callback is invoked and the event is received`() { val eventSink = EventsRecorder() - val oidcDetails = OidcDetails("aUrl") - ensureCalledOnceWithParam(oidcDetails.url) { callback -> + val oAuthDetails = OAuthDetails("aUrl") + ensureCalledOnceWithParam(oAuthDetails.url) { callback -> rule.setOnboardingView( state = anOnBoardingState( loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl")), @@ -261,7 +261,7 @@ class OnboardingViewTest { onSignIn: (Boolean) -> Unit = EnsureNeverCalledWithParam(), onCreateAccount: () -> Unit = EnsureNeverCalled(), onReportProblem: () -> Unit = EnsureNeverCalled(), - onOidcDetails: (OidcDetails) -> Unit = EnsureNeverCalledWithParam(), + onOAuthDetails: (OAuthDetails) -> Unit = EnsureNeverCalledWithParam(), onNeedLoginPassword: () -> Unit = EnsureNeverCalled(), onLearnMoreClick: () -> Unit = EnsureNeverCalled(), onCreateAccountContinue: (url: String) -> Unit = EnsureNeverCalledWithParam(), @@ -275,7 +275,7 @@ class OnboardingViewTest { onSignIn = onSignIn, onCreateAccount = onCreateAccount, onReportProblem = onReportProblem, - onOidcDetails = onOidcDetails, + onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, onLearnMoreClick = onLearnMoreClick, onCreateAccountContinue = onCreateAccountContinue, 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 e5d48ec175..d324f5eb3a 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 @@ -23,7 +23,7 @@ import io.element.android.libraries.featureflag.test.FakeFeature import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.indicator.api.IndicatorService import io.element.android.libraries.indicator.test.FakeIndicatorService -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.api.oauth.AccountManagementAction 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 diff --git a/features/securebackup/impl/build.gradle.kts b/features/securebackup/impl/build.gradle.kts index b6117271f7..82f30fa5ce 100644 --- a/features/securebackup/impl/build.gradle.kts +++ b/features/securebackup/impl/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) - implementation(projects.libraries.oidc.api) + implementation(projects.libraries.oauth.api) implementation(projects.libraries.uiStrings) implementation(projects.libraries.testtags) api(libs.statemachine) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index c4a007f1d5..4e2284890f 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -36,7 +36,7 @@ import io.element.android.libraries.architecture.createNode import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope -import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityOAuthResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -123,12 +123,12 @@ class ResetIdentityFlowNode( null -> { Timber.d("No reset handle return, the reset is done.") } - is IdentityOidcResetHandle -> { + is IdentityOAuthResetHandle -> { Timber.d("Launching reset confirmation in MAS") activity.openUrlInChromeCustomTab(null, darkTheme, handle.url) - Timber.d("Starting resetOidc") - resetJob = launch { handle.resetOidc() } - resetJob?.invokeOnCompletion { Timber.d("resetOidc ended") } + Timber.d("Starting resetOAuth") + resetJob = launch { handle.resetOAuth() } + resetJob?.invokeOnCompletion { Timber.d("resetOAuth ended") } } is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) } diff --git a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt index 396339adbb..95a57db93e 100644 --- a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt +++ b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt @@ -36,7 +36,7 @@ private fun aSessionData( accessToken = "anAccessToken", refreshToken = "aRefreshToken", homeserverUrl = "aHomeserverUrl", - oidcData = null, + oAuthData = null, loginTimestamp = null, isTokenValid = isTokenValid, loginType = LoginType.UNKNOWN, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 35fd7e8551..59fd7a4940 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.api.oauth.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.JoinedRoom diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt index c50ec09609..d5fd6a734a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt @@ -16,6 +16,6 @@ sealed class AuthenticationException(message: String?) : Exception(message) { class InvalidServerName(message: String?) : AuthenticationException(message) class SlidingSyncVersion(message: String?) : AuthenticationException(message) class ServerUnreachable(message: String?) : AuthenticationException(message) - class Oidc(message: String?) : AuthenticationException(message) + class OAuth(message: String?) : AuthenticationException(message) class Generic(message: String?) : AuthenticationException(message) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt index 7c82668242..04d1d13593 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt @@ -37,21 +37,21 @@ interface MatrixAuthenticationService { suspend fun importCreatedSession(externalSession: ExternalSession): Result /* - * OIDC part. + * OAuth part. */ /** - * Get the Oidc url to display to the user. + * Get the OAuth url to display to the user. */ - suspend fun getOidcUrl( - prompt: OidcPrompt, + suspend fun getOAuthUrl( + prompt: OAuthPrompt, loginHint: String?, - ): Result + ): Result /** - * Cancel Oidc login sequence. + * Cancel OAuth login sequence. */ - suspend fun cancelOidcLogin(): Result + suspend fun cancelOAuthLogin(): Result /** * Set the existing data about Element Classic session, if any. @@ -68,9 +68,9 @@ interface MatrixAuthenticationService { ): Boolean /** - * Attempt to login using the [callbackUrl] provided by the Oidc page. + * Attempt to log in using the [callbackUrl] provided by the OAuth page. */ - suspend fun loginWithOidc(callbackUrl: String): Result + suspend fun loginWithOAuth(callbackUrl: String): Result suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetails.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetails.kt index aa5ed9a41d..8dcb5c4a48 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetails.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetails.kt @@ -11,7 +11,7 @@ package io.element.android.libraries.matrix.api.auth data class MatrixHomeServerDetails( val url: String, val supportsPasswordLogin: Boolean, - val supportsOidcLogin: Boolean, + val supportsOAuthLogin: Boolean, ) { - val isSupported = supportsPasswordLogin || supportsOidcLogin + val isSupported = supportsPasswordLogin || supportsOAuthLogin } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcConfig.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt similarity index 97% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcConfig.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt index ee8b7ec50e..d3a42f42b9 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcConfig.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt @@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.api.auth import io.element.android.libraries.matrix.api.BuildConfig -object OidcConfig { +object OAuthConfig { const val CLIENT_URI = BuildConfig.CLIENT_URI // Note: host must match with the host of CLIENT_URI diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcDetails.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthDetails.kt similarity index 94% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcDetails.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthDetails.kt index c4fb87e3c2..d504f891ee 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcDetails.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthDetails.kt @@ -12,6 +12,6 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize -data class OidcDetails( +data class OAuthDetails( val url: String, ) : Parcelable diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcPrompt.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthPrompt.kt similarity index 81% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcPrompt.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthPrompt.kt index 8ddad9f52e..45b4e18533 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcPrompt.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthPrompt.kt @@ -8,12 +8,12 @@ package io.element.android.libraries.matrix.api.auth -sealed interface OidcPrompt { +sealed interface OAuthPrompt { /** * The Authorization Server should prompt the End-User for * reauthentication. */ - data object Login : OidcPrompt + data object Login : OAuthPrompt /** * The Authorization Server should prompt the End-User to create a user @@ -21,10 +21,10 @@ sealed interface OidcPrompt { * * Defined in [Initiating User Registration via OpenID Connect](https://openid.net/specs/openid-connect-prompt-create-1_0.html). */ - data object Create : OidcPrompt + data object Create : OAuthPrompt /** * An unknown value. */ - data class Unknown(val value: String) : OidcPrompt + data class Unknown(val value: String) : OAuthPrompt } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcRedirectUrlProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthRedirectUrlProvider.kt similarity index 89% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcRedirectUrlProvider.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthRedirectUrlProvider.kt index ad4d862474..669d47501d 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OidcRedirectUrlProvider.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthRedirectUrlProvider.kt @@ -8,6 +8,6 @@ package io.element.android.libraries.matrix.api.auth -interface OidcRedirectUrlProvider { +interface OAuthRedirectUrlProvider { fun provide(): String } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/qrlogin/QrLoginException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/qrlogin/QrLoginException.kt index a3b567fa46..3f22244405 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/qrlogin/QrLoginException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/qrlogin/QrLoginException.kt @@ -15,7 +15,7 @@ sealed class QrLoginException : Exception() { data object Expired : QrLoginException() data object NotFound : QrLoginException() data object LinkingNotSupported : QrLoginException() - data object OidcMetadataInvalid : QrLoginException() + data object OAuthMetadataInvalid : QrLoginException() data object SlidingSyncNotAvailable : QrLoginException() data object OtherDeviceNotSignedIn : QrLoginException() data object CheckCodeAlreadySent : QrLoginException() diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index aefad517dc..333cfb709b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt @@ -112,19 +112,19 @@ interface IdentityPasswordResetHandle : IdentityResetHandle { } /** - * A handle to reset the user's identity with an OIDC login type. + * A handle to reset the user's identity with an OAuth login type. */ -interface IdentityOidcResetHandle : IdentityResetHandle { +interface IdentityOAuthResetHandle : IdentityResetHandle { /** * The URL to open in a webview/custom tab to reset the identity. */ val url: String /** - * Reset the identity using the OIDC flow. + * Reset the identity using the OAuth flow. * * This method will block the coroutine it's running on and keep polling indefinitely until either the coroutine is cancelled, the [cancel] method is * called, or the identity is reset. */ - suspend fun resetOidc(): Result + suspend fun resetOAuth(): Result } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oauth/AccountManagementAction.kt similarity index 91% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oauth/AccountManagementAction.kt index e1c7764e58..6dd0f6e53c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oauth/AccountManagementAction.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.matrix.api.oidc +package io.element.android.libraries.matrix.api.oauth import io.element.android.libraries.matrix.api.core.DeviceId diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetailsTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetailsTest.kt index d4b360ef53..9babb7a738 100644 --- a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetailsTest.kt +++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/auth/MatrixHomeServerDetailsTest.kt @@ -16,7 +16,7 @@ class MatrixHomeServerDetailsTest { @Test fun `if homeserver supports oidc, then it is supported`() { val sut = aMatrixHomeServerDetails( - supportsOidcLogin = true, + supportsOAuthLogin = true, supportsPasswordLogin = false, ) assertThat(sut.isSupported).isTrue() @@ -25,7 +25,7 @@ class MatrixHomeServerDetailsTest { @Test fun `if homeserver supports password, then it is supported`() { val sut = aMatrixHomeServerDetails( - supportsOidcLogin = false, + supportsOAuthLogin = false, supportsPasswordLogin = true, ) assertThat(sut.isSupported).isTrue() @@ -34,7 +34,7 @@ class MatrixHomeServerDetailsTest { @Test fun `if homeserver supports both, then it is supported`() { val sut = aMatrixHomeServerDetails( - supportsOidcLogin = true, + supportsOAuthLogin = true, supportsPasswordLogin = true, ) assertThat(sut.isSupported).isTrue() @@ -43,7 +43,7 @@ class MatrixHomeServerDetailsTest { @Test fun `if homeserver supports none, then it is not supported`() { val sut = aMatrixHomeServerDetails( - supportsOidcLogin = false, + supportsOAuthLogin = false, supportsPasswordLogin = false, ) assertThat(sut.isSupported).isFalse() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index bb6806b5d4..5a1dc9da4b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -31,7 +31,7 @@ import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopHandler import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileHandler import io.element.android.libraries.matrix.api.media.MatrixMediaLoader -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.api.oauth.AccountManagementAction import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.JoinedRoom @@ -59,7 +59,7 @@ import io.element.android.libraries.matrix.impl.media.RustMediaLoader import io.element.android.libraries.matrix.impl.media.RustMediaPreviewService import io.element.android.libraries.matrix.impl.notification.RustNotificationService import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService -import io.element.android.libraries.matrix.impl.oidc.toRustAction +import io.element.android.libraries.matrix.impl.oauth.toRustAction import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.room.GetRoomResult import io.element.android.libraries.matrix.impl.room.NotJoinedRustRoom diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index e5bae3bb9d..0bf26091c2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -214,5 +214,5 @@ fun SessionData.toSession() = Session( deviceId = deviceId, homeserverUrl = homeserverUrl, slidingSyncVersion = SlidingSyncVersion.NATIVE, - oauthData = oidcData, + oauthData = oAuthData, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index 2a151057b3..20dbf76a31 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -30,11 +30,11 @@ fun Throwable.mapAuthenticationException(): AuthenticationException { is ClientBuildException.EventCache -> AuthenticationException.Generic(message) } is OAuthException -> when (this) { - is OAuthException.Generic -> AuthenticationException.Oidc(message) - is OAuthException.CallbackUrlInvalid -> AuthenticationException.Oidc(message) - is OAuthException.Cancelled -> AuthenticationException.Oidc(message) - is OAuthException.MetadataInvalid -> AuthenticationException.Oidc(message) - is OAuthException.NotSupported -> AuthenticationException.Oidc(message) + is OAuthException.Generic -> AuthenticationException.OAuth(message) + is OAuthException.CallbackUrlInvalid -> AuthenticationException.OAuth(message) + is OAuthException.Cancelled -> AuthenticationException.OAuth(message) + is OAuthException.MetadataInvalid -> AuthenticationException.OAuth(message) + is OAuthException.NotSupported -> AuthenticationException.OAuth(message) } else -> AuthenticationException.Generic(message) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt index acf3a5a55b..810b8d8e0d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetails.kt @@ -15,6 +15,6 @@ fun HomeserverLoginDetails.map(): MatrixHomeServerDetails = use { MatrixHomeServerDetails( url = url(), supportsPasswordLogin = supportsPasswordLogin(), - supportsOidcLogin = supportsOauthLogin(), + supportsOAuthLogin = supportsOauthLogin(), ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OAuthConfigurationProvider.kt similarity index 53% rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OAuthConfigurationProvider.kt index 033b613dd8..d80dea2e7f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OAuthConfigurationProvider.kt @@ -10,22 +10,22 @@ package io.element.android.libraries.matrix.impl.auth import dev.zacsweers.metro.Inject import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.matrix.api.auth.OidcConfig -import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider +import io.element.android.libraries.matrix.api.auth.OAuthConfig +import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider import org.matrix.rustcomponents.sdk.OAuthConfiguration @Inject -class OidcConfigurationProvider( +class OAuthConfigurationProvider( private val buildMeta: BuildMeta, - private val oidcRedirectUrlProvider: OidcRedirectUrlProvider, + private val oAuthRedirectUrlProvider: OAuthRedirectUrlProvider, ) { fun get(): OAuthConfiguration = OAuthConfiguration( clientName = buildMeta.applicationName, - redirectUri = oidcRedirectUrlProvider.provide(), - clientUri = OidcConfig.CLIENT_URI, - logoUri = OidcConfig.LOGO_URI, - tosUri = OidcConfig.TOS_URI, - policyUri = OidcConfig.POLICY_URI, - staticRegistrations = OidcConfig.STATIC_REGISTRATIONS, + redirectUri = oAuthRedirectUrlProvider.provide(), + clientUri = OAuthConfig.CLIENT_URI, + logoUri = OAuthConfig.LOGO_URI, + tosUri = OAuthConfig.TOS_URI, + policyUri = OAuthConfig.POLICY_URI, + staticRegistrations = OAuthConfig.STATIC_REGISTRATIONS, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt index a23a6e5041..e97ddbee84 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcPrompt.kt @@ -8,13 +8,13 @@ package io.element.android.libraries.matrix.impl.auth -import io.element.android.libraries.matrix.api.auth.OidcPrompt -import org.matrix.rustcomponents.sdk.OAuthPrompt as RustOidcPrompt +import io.element.android.libraries.matrix.api.auth.OAuthPrompt +import org.matrix.rustcomponents.sdk.OAuthPrompt as RustOAuthPrompt -internal fun OidcPrompt.toRustPrompt(): RustOidcPrompt { +internal fun OAuthPrompt.toRustPrompt(): RustOAuthPrompt { return when (this) { - OidcPrompt.Login -> RustOidcPrompt.Unknown("consent") - OidcPrompt.Create -> RustOidcPrompt.Create - is OidcPrompt.Unknown -> RustOidcPrompt.Unknown(value) + OAuthPrompt.Login -> RustOAuthPrompt.Unknown("consent") + OAuthPrompt.Create -> RustOAuthPrompt.Create + is OAuthPrompt.Unknown -> RustOAuthPrompt.Unknown(value) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt index 4f59906023..3f8893138f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeServerLoginCompatibilityChecker.kt @@ -31,7 +31,7 @@ class RustHomeServerLoginCompatibilityChecker( it.homeserverLoginDetails() } .use { - Timber.d("Homeserver $url | OIDC: ${it.supportsOauthLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}") + Timber.d("Homeserver $url | OAuth: ${it.supportsOauthLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}") it.supportsOauthLogin() || it.supportsPasswordLogin() } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index d186f06209..79793e4e77 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -19,8 +19,8 @@ import io.element.android.libraries.matrix.api.auth.AuthenticationException import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails -import io.element.android.libraries.matrix.api.auth.OidcDetails -import io.element.android.libraries.matrix.api.auth.OidcPrompt +import io.element.android.libraries.matrix.api.auth.OAuthDetails +import io.element.android.libraries.matrix.api.auth.OAuthPrompt import io.element.android.libraries.matrix.api.auth.SessionRestorationException import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData @@ -65,7 +65,7 @@ class RustMatrixAuthenticationService( private val sessionStore: SessionStore, private val rustMatrixClientFactory: RustMatrixClientFactory, private val passphraseGenerator: PassphraseGenerator, - private val oidcConfigurationProvider: OidcConfigurationProvider, + private val oAuthConfigurationProvider: OAuthConfigurationProvider, ) : MatrixAuthenticationService { // Any existing Element Classic session that we want to try to import secrets from during login. private var elementClassicSession: ElementClassicSession? = null @@ -253,15 +253,15 @@ class RustMatrixAuthenticationService( private var pendingOAuthAuthorizationData: OAuthAuthorizationData? = null - override suspend fun getOidcUrl( - prompt: OidcPrompt, + override suspend fun getOAuthUrl( + prompt: OAuthPrompt, loginHint: String?, - ): Result { + ): Result { return withContext(coroutineDispatchers.io) { runCatchingExceptions { val client = currentClient ?: error("You need to call `setHomeserver()` first") val oAuthAuthorizationData = client.urlForOauth( - oauthConfiguration = oidcConfigurationProvider.get(), + oauthConfiguration = oAuthConfigurationProvider.get(), prompt = prompt.toRustPrompt(), loginHint = loginHint, // If we want to restore a previous session for which we have encryption keys, we can pass the deviceId here. At the moment, we don't @@ -270,15 +270,15 @@ class RustMatrixAuthenticationService( ) val url = oAuthAuthorizationData.loginUrl() pendingOAuthAuthorizationData = oAuthAuthorizationData - OidcDetails(url) + OAuthDetails(url) }.mapFailure { failure -> - Timber.e(failure, "Failed to get OIDC URL") + Timber.e(failure, "Failed to get OAuth URL") failure.mapAuthenticationException() } } } - override suspend fun cancelOidcLogin(): Result { + override suspend fun cancelOAuthLogin(): Result { return withContext(coroutineDispatchers.io) { runCatchingExceptions { pendingOAuthAuthorizationData?.use { @@ -286,7 +286,7 @@ class RustMatrixAuthenticationService( } pendingOAuthAuthorizationData = null }.mapFailure { failure -> - Timber.e(failure, "Failed to cancel OIDC login") + Timber.e(failure, "Failed to cancel OAuth login") failure.mapAuthenticationException() } } @@ -297,9 +297,9 @@ class RustMatrixAuthenticationService( } /** - * callbackUrl should be the uriRedirect from OidcClientMetadata (with all the parameters). + * callbackUrl should be the `url` from `OAuthAction` (with all the parameters). */ - override suspend fun loginWithOidc(callbackUrl: String): Result { + override suspend fun loginWithOAuth(callbackUrl: String): Result { return withContext(coroutineDispatchers.io) { runCatchingExceptions { val client = currentClient ?: error("You need to call `setHomeserver()` first") @@ -330,7 +330,7 @@ class RustMatrixAuthenticationService( SessionId(sessionData.userId) }.mapFailure { failure -> - Timber.e(failure, "Failed to login with OIDC") + Timber.e(failure, "Failed to login with OAuth") failure.mapAuthenticationException() } } @@ -355,7 +355,7 @@ class RustMatrixAuthenticationService( withContext(coroutineDispatchers.io) { val sdkQrCodeLoginData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData val emptySessionPaths = rotateSessionPath() - val oidcConfiguration = oidcConfigurationProvider.get() + val oAuthConfiguration = oAuthConfigurationProvider.get() val progressListener = object : QrLoginProgressListener { override fun onUpdate(state: QrLoginProgress) { Timber.d("QR Code login progress: $state") @@ -368,7 +368,7 @@ class RustMatrixAuthenticationService( qrCodeData = sdkQrCodeLoginData, ) client.newLoginWithQrCodeHandler( - oauthConfiguration = oidcConfiguration, + oauthConfiguration = oAuthConfiguration, ).use { it.scan( qrCodeData = qrCodeData.rustQrCodeData, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt index 1c4e300e91..23b9c6be5e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt @@ -42,7 +42,7 @@ object QrErrorMapper { is RustHumanQrLoginException.OtherDeviceNotSignedIn -> QrLoginException.OtherDeviceNotSignedIn is RustHumanQrLoginException.LinkingNotSupported -> QrLoginException.LinkingNotSupported is RustHumanQrLoginException.Unknown -> QrLoginException.Unknown - is RustHumanQrLoginException.OAuthMetadataInvalid -> QrLoginException.OidcMetadataInvalid + is RustHumanQrLoginException.OAuthMetadataInvalid -> QrLoginException.OAuthMetadataInvalid is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt index 8a49d1b11b..7ee9c7d0b3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustIdentityResetHandle.kt @@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.impl.encryption import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityOAuthResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import org.matrix.rustcomponents.sdk.AuthData @@ -25,7 +25,7 @@ object RustIdentityResetHandleFactory { return runCatchingExceptions { identityResetHandle?.let { when (val authType = identityResetHandle.authType()) { - is CrossSigningResetAuthType.OAuth -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl) + is CrossSigningResetAuthType.OAuth -> RustIdentityOAuthResetHandle(identityResetHandle, authType.info.approvalUrl) // User interactive authentication (user + password) CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(userId, identityResetHandle) } @@ -47,11 +47,11 @@ class RustPasswordIdentityResetHandle( } } -class RustOidcIdentityResetHandle( +class RustIdentityOAuthResetHandle( private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle, override val url: String, -) : IdentityOidcResetHandle { - override suspend fun resetOidc(): Result { +) : IdentityOAuthResetHandle { + override suspend fun resetOAuth(): Result { return runCatchingExceptions { identityResetHandle.reset(null) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt index bfb200a994..dfda37d7e1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt @@ -27,7 +27,7 @@ internal fun Session.toSessionData( accessToken = accessToken, refreshToken = refreshToken, homeserverUrl = homeserverUrl ?: this.homeserverUrl, - oidcData = oauthData, + oAuthData = oauthData, loginTimestamp = Date(), isTokenValid = isTokenValid, loginType = loginType, @@ -52,7 +52,7 @@ internal fun ExternalSession.toSessionData( accessToken = accessToken, refreshToken = refreshToken, homeserverUrl = homeserverUrl, - oidcData = null, + oAuthData = null, loginTimestamp = Date(), isTokenValid = isTokenValid, loginType = loginType, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oauth/AccountManagementAction.kt similarity index 86% rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oauth/AccountManagementAction.kt index f86c57543a..974ae08923 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oauth/AccountManagementAction.kt @@ -6,9 +6,9 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.oidc +package io.element.android.libraries.matrix.impl.oauth -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.api.oauth.AccountManagementAction import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction fun AccountManagementAction.toRustAction(): RustAccountManagementAction { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt index 7cfd3392a1..cc5fb4a394 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt @@ -64,17 +64,17 @@ class AuthenticationExceptionMappingTest { } @Test - fun `mapping Oidc exceptions map to the Oidc Kotlin`() { + fun `mapping Oidc exceptions map to the OAuth Kotlin`() { assertThat(OAuthException.Generic("Generic").mapAuthenticationException()) - .isException("Generic") + .isException("Generic") assertThat(OAuthException.CallbackUrlInvalid("CallbackUrlInvalid").mapAuthenticationException()) - .isException("CallbackUrlInvalid") + .isException("CallbackUrlInvalid") assertThat(OAuthException.Cancelled("Cancelled").mapAuthenticationException()) - .isException("Cancelled") + .isException("Cancelled") assertThat(OAuthException.MetadataInvalid("MetadataInvalid").mapAuthenticationException()) - .isException("MetadataInvalid") + .isException("MetadataInvalid") assertThat(OAuthException.NotSupported("NotSupported").mapAuthenticationException()) - .isException("NotSupported") + .isException("NotSupported") } private inline fun ThrowableSubject.isException(message: String) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt index a5c7b2dbc8..63f573536c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt @@ -20,7 +20,7 @@ class HomeserverDetailsKtTest { val homeserverLoginDetails = FakeFfiHomeserverLoginDetails( url = "https://example.org", supportsPasswordLogin = true, - supportsOidcLogin = false + supportsOAuthLogin = false ) // When @@ -31,7 +31,7 @@ class HomeserverDetailsKtTest { MatrixHomeServerDetails( url = "https://example.org", supportsPasswordLogin = true, - supportsOidcLogin = false + supportsOAuthLogin = false ) ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OAuthConfigurationProviderTest.kt similarity index 76% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OAuthConfigurationProviderTest.kt index 095cf54946..3b54f2d1f3 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OAuthConfigurationProviderTest.kt @@ -10,18 +10,18 @@ package io.element.android.libraries.matrix.impl.auth import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.test.auth.FAKE_REDIRECT_URL -import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider +import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider import io.element.android.libraries.matrix.test.core.aBuildMeta import org.junit.Test -class OidcConfigurationProviderTest { +class OAuthConfigurationProviderTest { @Test fun get() { - val result = OidcConfigurationProvider( + val result = OAuthConfigurationProvider( buildMeta = aBuildMeta( applicationName = "myName", ), - oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), + oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), ).get() assertThat(result.clientName).isEqualTo("myName") assertThat(result.redirectUri).isEqualTo(FAKE_REDIRECT_URL) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt index 50d1f3723b..903273113b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustHomeserverLoginCompatibilityCheckerTest.kt @@ -18,8 +18,8 @@ import org.junit.Test class RustHomeserverLoginCompatibilityCheckerTest { @Test - fun `check - is valid if it supports OIDC login`() = runTest { - val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsOidcLogin = true) } + fun `check - is valid if it supports OAuth login`() = runTest { + val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsOAuthLogin = true) } assertThat(sut.check("https://matrix.host.org").getOrNull()).isTrue() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index f4ce7b1fdd..bff2711bc5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -16,7 +16,7 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory -import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider +import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore @@ -64,9 +64,9 @@ class RustMatrixAuthenticationServiceTest { sessionStore = sessionStore, rustMatrixClientFactory = rustMatrixClientFactory, passphraseGenerator = FakePassphraseGenerator(), - oidcConfigurationProvider = OidcConfigurationProvider( + oAuthConfigurationProvider = OAuthConfigurationProvider( buildMeta = aBuildMeta(), - oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), + oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), ), ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt index c20a77ace4..4de5e55985 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt @@ -32,7 +32,7 @@ class QrErrorMapperTest { assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn) assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported) assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown) - assertThat(QrErrorMapper.map(RustHumanQrLoginException.OAuthMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.OAuthMetadataInvalid())).isEqualTo(QrLoginException.OAuthMetadataInvalid) assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt index 65e24c2494..5351fbc8df 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiHomeserverLoginDetails.kt @@ -14,11 +14,11 @@ import org.matrix.rustcomponents.sdk.NoHandle class FakeFfiHomeserverLoginDetails( private val url: String = "https://example.org", private val supportsPasswordLogin: Boolean = false, - private val supportsOidcLogin: Boolean = false, + private val supportsOAuthLogin: Boolean = false, private val supportsSsoLogin: Boolean = false, ) : HomeserverLoginDetails(NoHandle) { override fun url(): String = url - override fun supportsOauthLogin(): Boolean = supportsOidcLogin + override fun supportsOauthLogin(): Boolean = supportsOAuthLogin override fun supportsPasswordLogin(): Boolean = supportsPasswordLogin override fun supportsSsoLogin(): Boolean = supportsSsoLogin } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt index e5fc8b154f..fb9ec6625b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt @@ -36,7 +36,7 @@ class SessionKtTest { assertThat(result.refreshToken).isEqualTo("refreshToken") assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL) assertThat(result.isTokenValid).isTrue() - assertThat(result.oidcData).isNull() + assertThat(result.oAuthData).isNull() assertThat(result.loginType).isEqualTo(LoginType.PASSWORD) assertThat(result.loginTimestamp).isNotNull() assertThat(result.passphrase).isEqualTo(A_SECRET) @@ -82,7 +82,7 @@ class SessionKtTest { assertThat(result.refreshToken).isNull() assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL) assertThat(result.isTokenValid).isTrue() - assertThat(result.oidcData).isNull() + assertThat(result.oAuthData).isNull() assertThat(result.loginType).isEqualTo(LoginType.PASSWORD) assertThat(result.loginTimestamp).isNotNull() assertThat(result.passphrase).isEqualTo(A_SECRET) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oauth/AccountManagementActionKtTest.kt similarity index 90% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oauth/AccountManagementActionKtTest.kt index 3637ef78cc..1495716e87 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oauth/AccountManagementActionKtTest.kt @@ -6,10 +6,10 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.oidc +package io.element.android.libraries.matrix.impl.oauth import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.api.oauth.AccountManagementAction import io.element.android.libraries.matrix.test.A_DEVICE_ID import org.junit.Test import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 742af160ae..26bc0af8c1 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.api.oauth.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.JoinedRoom diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt index 238ad2663d..3b2fdeafb1 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt @@ -12,8 +12,8 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails -import io.element.android.libraries.matrix.api.auth.OidcDetails -import io.element.android.libraries.matrix.api.auth.OidcPrompt +import io.element.android.libraries.matrix.api.auth.OAuthDetails +import io.element.android.libraries.matrix.api.auth.OAuthPrompt import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep @@ -26,7 +26,7 @@ import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.simulateLongTask -val A_OIDC_DATA = OidcDetails(url = "a-url") +val AN_OAUTH_DATA = OAuthDetails(url = "a-url") class FakeMatrixAuthenticationService( var matrixClientResult: ((SessionId) -> Result)? = null, @@ -37,8 +37,8 @@ class FakeMatrixAuthenticationService( private val setElementClassicSessionResult: (ElementClassicSession?) -> Unit = { lambdaError() }, private val doSecretsContainBackupKeyResult: (UserId, String, String) -> Boolean = { _, _, _ -> lambdaError() }, ) : MatrixAuthenticationService { - private var oidcError: Throwable? = null - private var oidcCancelError: Throwable? = null + private var oAuthError: Throwable? = null + private var oAuthCancelError: Throwable? = null private var loginError: Throwable? = null private var matrixClient: MatrixClient? = null private var onAuthenticationListener: ((MatrixClient) -> Unit)? = null @@ -70,18 +70,18 @@ class FakeMatrixAuthenticationService( return importCreatedSessionLambda(externalSession) } - override suspend fun getOidcUrl( - prompt: OidcPrompt, + override suspend fun getOAuthUrl( + prompt: OAuthPrompt, loginHint: String?, - ): Result = simulateLongTask { - oidcError?.let { Result.failure(it) } ?: Result.success(A_OIDC_DATA) + ): Result = simulateLongTask { + oAuthError?.let { Result.failure(it) } ?: Result.success(AN_OAUTH_DATA) } - override suspend fun cancelOidcLogin(): Result { - return oidcCancelError?.let { Result.failure(it) } ?: Result.success(Unit) + override suspend fun cancelOAuthLogin(): Result { + return oAuthCancelError?.let { Result.failure(it) } ?: Result.success(Unit) } - override suspend fun loginWithOidc(callbackUrl: String): Result = simulateLongTask { + override suspend fun loginWithOAuth(callbackUrl: String): Result = simulateLongTask { loginError?.let { Result.failure(it) } ?: run { onAuthenticationListener?.invoke(matrixClient ?: FakeMatrixClient()) Result.success(A_USER_ID) @@ -97,12 +97,12 @@ class FakeMatrixAuthenticationService( onAuthenticationListener = lambda } - fun givenOidcError(throwable: Throwable?) { - oidcError = throwable + fun givenOAuthError(throwable: Throwable?) { + oAuthError = throwable } - fun givenOidcCancelError(throwable: Throwable?) { - oidcCancelError = throwable + fun givenOAuthCancelError(throwable: Throwable?) { + oAuthCancelError = throwable } fun givenLoginError(throwable: Throwable?) { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeOidcRedirectUrlProvider.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeOAuthRedirectUrlProvider.kt similarity index 75% rename from libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeOidcRedirectUrlProvider.kt rename to libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeOAuthRedirectUrlProvider.kt index 47c9b0951d..fcb28b48ba 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeOidcRedirectUrlProvider.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeOAuthRedirectUrlProvider.kt @@ -8,12 +8,12 @@ package io.element.android.libraries.matrix.test.auth -import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider +import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider const val FAKE_REDIRECT_URL = "io.element.android:/" -class FakeOidcRedirectUrlProvider( +class FakeOAuthRedirectUrlProvider( private val provideResult: String = FAKE_REDIRECT_URL, -) : OidcRedirectUrlProvider { +) : OAuthRedirectUrlProvider { override fun provide() = provideResult } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/MatrixHomeServerDetails.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/MatrixHomeServerDetails.kt index 3b9573bcfc..56fd4de4c3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/MatrixHomeServerDetails.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/MatrixHomeServerDetails.kt @@ -14,9 +14,9 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER_URL fun aMatrixHomeServerDetails( url: String = A_HOMESERVER_URL, supportsPasswordLogin: Boolean = false, - supportsOidcLogin: Boolean = false, + supportsOAuthLogin: Boolean = false, ) = MatrixHomeServerDetails( url = url, supportsPasswordLogin = supportsPasswordLogin, - supportsOidcLogin = supportsOidcLogin, + supportsOAuthLogin = supportsOAuthLogin, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt index 06ffeb547c..d65328d7fe 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeIdentityResetHandle.kt @@ -8,16 +8,16 @@ package io.element.android.libraries.matrix.test.encryption -import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle +import io.element.android.libraries.matrix.api.encryption.IdentityOAuthResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle -class FakeIdentityOidcResetHandle( +class FakeIdentityOAuthResetHandle( override val url: String = "", - var resetOidcLambda: () -> Result = { error("Not implemented") }, + var resetOAuthLambda: () -> Result = { error("Not implemented") }, var cancelLambda: () -> Unit = { error("Not implemented") }, -) : IdentityOidcResetHandle { - override suspend fun resetOidc(): Result { - return resetOidcLambda() +) : IdentityOAuthResetHandle { + override suspend fun resetOAuth(): Result { + return resetOAuthLambda() } override suspend fun cancel() { diff --git a/libraries/oidc/api/build.gradle.kts b/libraries/oauth/api/build.gradle.kts similarity index 87% rename from libraries/oidc/api/build.gradle.kts rename to libraries/oauth/api/build.gradle.kts index 8cc0125142..8c863db0bf 100644 --- a/libraries/oidc/api/build.gradle.kts +++ b/libraries/oauth/api/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } android { - namespace = "io.element.android.libraries.oidc.api" + namespace = "io.element.android.libraries.oauth.api" } dependencies { diff --git a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt b/libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthAction.kt similarity index 54% rename from libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt rename to libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthAction.kt index d7c061ab25..033516b93d 100644 --- a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcAction.kt +++ b/libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthAction.kt @@ -6,9 +6,9 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.oidc.api +package io.element.android.libraries.oauth.api -sealed interface OidcAction { - data class GoBack(val toUnblock: Boolean = false) : OidcAction - data class Success(val url: String) : OidcAction +sealed interface OAuthAction { + data class GoBack(val toUnblock: Boolean = false) : OAuthAction + data class Success(val url: String) : OAuthAction } diff --git a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt b/libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthActionFlow.kt similarity index 63% rename from libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt rename to libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthActionFlow.kt index 17340eb5ec..c6791e3197 100644 --- a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcActionFlow.kt +++ b/libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthActionFlow.kt @@ -6,12 +6,12 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.oidc.api +package io.element.android.libraries.oauth.api import kotlinx.coroutines.flow.FlowCollector -interface OidcActionFlow { - fun post(oidcAction: OidcAction) - suspend fun collect(collector: FlowCollector) +interface OAuthActionFlow { + fun post(oAuthAction: OAuthAction) + suspend fun collect(collector: FlowCollector) fun reset() } diff --git a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt b/libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthIntentResolver.kt similarity index 68% rename from libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt rename to libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthIntentResolver.kt index 97fa1baa27..2091a86db4 100644 --- a/libraries/oidc/api/src/main/kotlin/io/element/android/libraries/oidc/api/OidcIntentResolver.kt +++ b/libraries/oauth/api/src/main/kotlin/io/element/android/libraries/oauth/api/OAuthIntentResolver.kt @@ -6,10 +6,10 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.oidc.api +package io.element.android.libraries.oauth.api import android.content.Intent -interface OidcIntentResolver { - fun resolve(intent: Intent): OidcAction? +interface OAuthIntentResolver { + fun resolve(intent: Intent): OAuthAction? } diff --git a/libraries/oidc/impl/build.gradle.kts b/libraries/oauth/impl/build.gradle.kts similarity index 93% rename from libraries/oidc/impl/build.gradle.kts rename to libraries/oauth/impl/build.gradle.kts index e11ce11c70..d051c06497 100644 --- a/libraries/oidc/impl/build.gradle.kts +++ b/libraries/oauth/impl/build.gradle.kts @@ -16,7 +16,7 @@ plugins { } android { - namespace = "io.element.android.libraries.oidc.impl" + namespace = "io.element.android.libraries.oauth.impl" testOptions { unitTests { @@ -39,7 +39,7 @@ dependencies { implementation(platform(libs.network.retrofit.bom)) implementation(libs.network.retrofit) implementation(libs.serialization.json) - api(projects.libraries.oidc.api) + api(projects.libraries.oauth.api) testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlow.kt b/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlow.kt similarity index 58% rename from libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlow.kt rename to libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlow.kt index 6096ef7eef..6b23676059 100644 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlow.kt +++ b/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlow.kt @@ -6,26 +6,26 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.oidc.impl +package io.element.android.libraries.oauth.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcActionFlow +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthActionFlow import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.MutableStateFlow @ContributesBinding(AppScope::class) @SingleIn(AppScope::class) -class DefaultOidcActionFlow : OidcActionFlow { - private val mutableStateFlow = MutableStateFlow(null) +class DefaultOAuthActionFlow : OAuthActionFlow { + private val mutableStateFlow = MutableStateFlow(null) - override fun post(oidcAction: OidcAction) { - mutableStateFlow.value = oidcAction + override fun post(oAuthAction: OAuthAction) { + mutableStateFlow.value = oAuthAction } - override suspend fun collect(collector: FlowCollector) { + override suspend fun collect(collector: FlowCollector) { mutableStateFlow.collect(collector) } diff --git a/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolver.kt b/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolver.kt new file mode 100644 index 0000000000..c2a29e228c --- /dev/null +++ b/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolver.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.oauth.impl + +import android.content.Intent +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthIntentResolver + +@ContributesBinding(AppScope::class) +class DefaultOAuthIntentResolver( + private val oAuthUrlParser: OAuthUrlParser, +) : OAuthIntentResolver { + override fun resolve(intent: Intent): OAuthAction? { + return oAuthUrlParser.parse(intent.dataString.orEmpty()) + } +} diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt b/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/OAuthUrlParser.kt similarity index 51% rename from libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt rename to libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/OAuthUrlParser.kt index 8933873dc2..e62dea696f 100644 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/OidcUrlParser.kt +++ b/libraries/oauth/impl/src/main/kotlin/io/element/android/libraries/oauth/impl/OAuthUrlParser.kt @@ -6,37 +6,37 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.oidc.impl +package io.element.android.libraries.oauth.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider -import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider +import io.element.android.libraries.oauth.api.OAuthAction -fun interface OidcUrlParser { - fun parse(url: String): OidcAction? +fun interface OAuthUrlParser { + fun parse(url: String): OAuthAction? } /** - * Simple parser for oidc url interception. + * Simple parser for OAuth url interception. * TODO Find documentation about the format. */ @ContributesBinding(AppScope::class) -class DefaultOidcUrlParser( - private val oidcRedirectUrlProvider: OidcRedirectUrlProvider, -) : OidcUrlParser { +class DefaultOAuthUrlParser( + private val oAuthRedirectUrlProvider: OAuthRedirectUrlProvider, +) : OAuthUrlParser { /** - * Return a OidcAction, or null if the url is not a OidcUrl. + * Return a [OAuthAction], or null if the url is not an OAuth url. * Note: * When user press button "Cancel", we get the url: * `io.element.android:/?error=access_denied&state=IFF1UETGye2ZA8pO` * On success, we get: * `io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB` */ - override fun parse(url: String): OidcAction? { - if (url.startsWith(oidcRedirectUrlProvider.provide()).not()) return null - if (url.contains("error=access_denied")) return OidcAction.GoBack() - if (url.contains("code=")) return OidcAction.Success(url) + override fun parse(url: String): OAuthAction? { + if (url.startsWith(oAuthRedirectUrlProvider.provide()).not()) return null + if (url.contains("error=access_denied")) return OAuthAction.GoBack() + if (url.contains("code=")) return OAuthAction.Success(url) // Other case not supported, let's crash the app for now error("Not supported: $url") diff --git a/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlowTest.kt b/libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlowTest.kt similarity index 58% rename from libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlowTest.kt rename to libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlowTest.kt index 387b9aceb0..817487b3ff 100644 --- a/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcActionFlowTest.kt +++ b/libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthActionFlowTest.kt @@ -1,34 +1,33 @@ /* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. + * 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.oidc.impl +package io.element.android.libraries.oauth.impl import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.oauth.api.OAuthAction import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import org.junit.Test -class DefaultOidcActionFlowTest { +class DefaultOAuthActionFlowTest { @Test fun `collect gets all the posted events`() = runTest { - val data = mutableListOf() - val sut = DefaultOidcActionFlow() + val data = mutableListOf() + val sut = DefaultOAuthActionFlow() backgroundScope.launch { sut.collect { action -> data.add(action) } } - sut.post(OidcAction.GoBack()) + sut.post(OAuthAction.GoBack()) delay(1) sut.reset() delay(1) - assertThat(data).containsExactly(OidcAction.GoBack(), null) + assertThat(data).containsExactly(OAuthAction.GoBack(), null) } } diff --git a/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolverTest.kt b/libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolverTest.kt similarity index 64% rename from libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolverTest.kt rename to libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolverTest.kt index 64068030d7..ff34ae8220 100644 --- a/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolverTest.kt +++ b/libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthIntentResolverTest.kt @@ -1,19 +1,18 @@ /* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2025 New Vector Ltd. + * 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.oidc.impl +package io.element.android.libraries.oauth.impl import android.app.Activity import android.content.Intent import androidx.core.net.toUri import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider -import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider +import io.element.android.libraries.oauth.api.OAuthAction import org.junit.Assert.assertThrows import org.junit.Test import org.junit.runner.RunWith @@ -21,36 +20,36 @@ import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment @RunWith(RobolectricTestRunner::class) -class DefaultOidcIntentResolverTest { +class DefaultOAuthIntentResolverTest { @Test - fun `test resolve oidc go back`() { - val sut = createDefaultOidcIntentResolver() + fun `test resolve OAuth go back`() { + val sut = createDefaultOAuthIntentResolver() val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW data = "io.element.android:/?error=access_denied&state=IFF1UETGye2ZA8pO".toUri() } val result = sut.resolve(intent) - assertThat(result).isEqualTo(OidcAction.GoBack()) + assertThat(result).isEqualTo(OAuthAction.GoBack()) } @Test - fun `test resolve oidc success`() { - val sut = createDefaultOidcIntentResolver() + fun `test resolve OAuth success`() { + val sut = createDefaultOAuthIntentResolver() val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW data = "io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB".toUri() } val result = sut.resolve(intent) assertThat(result).isEqualTo( - OidcAction.Success( + OAuthAction.Success( url = "io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB" ) ) } @Test - fun `test resolve oidc invalid`() { - val sut = createDefaultOidcIntentResolver() + fun `test resolve OAuth invalid`() { + val sut = createDefaultOAuthIntentResolver() val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { action = Intent.ACTION_VIEW data = "io.element.android:/invalid".toUri() @@ -60,10 +59,10 @@ class DefaultOidcIntentResolverTest { } } - private fun createDefaultOidcIntentResolver(): DefaultOidcIntentResolver { - return DefaultOidcIntentResolver( - oidcUrlParser = DefaultOidcUrlParser( - oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), + private fun createDefaultOAuthIntentResolver(): DefaultOAuthIntentResolver { + return DefaultOAuthIntentResolver( + oAuthUrlParser = DefaultOAuthUrlParser( + oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), ), ) } diff --git a/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcUrlParserTest.kt b/libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthUrlParserTest.kt similarity index 56% rename from libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcUrlParserTest.kt rename to libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthUrlParserTest.kt index 7f145c053d..6377414862 100644 --- a/libraries/oidc/impl/src/test/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcUrlParserTest.kt +++ b/libraries/oauth/impl/src/test/kotlin/io/element/android/libraries/oauth/impl/DefaultOAuthUrlParserTest.kt @@ -1,59 +1,58 @@ /* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2023-2025 New Vector Ltd. + * 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.oidc.impl +package io.element.android.libraries.oauth.impl import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.test.auth.FAKE_REDIRECT_URL -import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider -import io.element.android.libraries.oidc.api.OidcAction +import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider +import io.element.android.libraries.oauth.api.OAuthAction import org.junit.Assert import org.junit.Test -class DefaultOidcUrlParserTest { +class DefaultOAuthUrlParserTest { @Test fun `test empty url`() { - val sut = createDefaultOidcUrlParser() + val sut = createDefaultOAuthUrlParser() assertThat(sut.parse("")).isNull() } @Test fun `test regular url`() { - val sut = createDefaultOidcUrlParser() + val sut = createDefaultOAuthUrlParser() assertThat(sut.parse("https://matrix.org")).isNull() } @Test fun `test cancel url`() { - val sut = createDefaultOidcUrlParser() + val sut = createDefaultOAuthUrlParser() val aCancelUrl = "$FAKE_REDIRECT_URL?error=access_denied&state=IFF1UETGye2ZA8pO" - assertThat(sut.parse(aCancelUrl)).isEqualTo(OidcAction.GoBack()) + assertThat(sut.parse(aCancelUrl)).isEqualTo(OAuthAction.GoBack()) } @Test fun `test success url`() { - val sut = createDefaultOidcUrlParser() + val sut = createDefaultOAuthUrlParser() val aSuccessUrl = "$FAKE_REDIRECT_URL?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB" - assertThat(sut.parse(aSuccessUrl)).isEqualTo(OidcAction.Success(aSuccessUrl)) + assertThat(sut.parse(aSuccessUrl)).isEqualTo(OAuthAction.Success(aSuccessUrl)) } @Test fun `test unknown url`() { - val sut = createDefaultOidcUrlParser() + val sut = createDefaultOAuthUrlParser() val anUnknownUrl = "$FAKE_REDIRECT_URL?state=IFF1UETGye2ZA8pO&goat=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB" Assert.assertThrows(IllegalStateException::class.java) { assertThat(sut.parse(anUnknownUrl)) } } - private fun createDefaultOidcUrlParser(): DefaultOidcUrlParser { - return DefaultOidcUrlParser( - oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), + private fun createDefaultOAuthUrlParser(): DefaultOAuthUrlParser { + return DefaultOAuthUrlParser( + oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), ) } } diff --git a/libraries/oidc/test/build.gradle.kts b/libraries/oauth/test/build.gradle.kts similarity index 80% rename from libraries/oidc/test/build.gradle.kts rename to libraries/oauth/test/build.gradle.kts index efe32d404a..6850653ddc 100644 --- a/libraries/oidc/test/build.gradle.kts +++ b/libraries/oauth/test/build.gradle.kts @@ -11,11 +11,11 @@ plugins { } android { - namespace = "io.element.android.libraries.oidc.test" + namespace = "io.element.android.libraries.oauth.test" } dependencies { implementation(libs.coroutines.core) - api(projects.libraries.oidc.api) + api(projects.libraries.oauth.api) implementation(projects.tests.testutils) } diff --git a/libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/FakeOidcIntentResolver.kt b/libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/FakeOAuthIntentResolver.kt similarity index 50% rename from libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/FakeOidcIntentResolver.kt rename to libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/FakeOAuthIntentResolver.kt index 45b400868b..893289023e 100644 --- a/libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/FakeOidcIntentResolver.kt +++ b/libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/FakeOAuthIntentResolver.kt @@ -6,17 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.oidc.test +package io.element.android.libraries.oauth.test import android.content.Intent -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcIntentResolver +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthIntentResolver import io.element.android.tests.testutils.lambda.lambdaError -class FakeOidcIntentResolver( - private val resolveResult: (Intent) -> OidcAction? = { lambdaError() } -) : OidcIntentResolver { - override fun resolve(intent: Intent): OidcAction? { +class FakeOAuthIntentResolver( + private val resolveResult: (Intent) -> OAuthAction? = { lambdaError() } +) : OAuthIntentResolver { + override fun resolve(intent: Intent): OAuthAction? { return resolveResult(intent) } } diff --git a/libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/customtab/FakeOAuthActionFlow.kt b/libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/customtab/FakeOAuthActionFlow.kt new file mode 100644 index 0000000000..5a5ca4369e --- /dev/null +++ b/libraries/oauth/test/src/main/kotlin/io/element/android/libraries/oauth/test/customtab/FakeOAuthActionFlow.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 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.oauth.test.customtab + +import io.element.android.libraries.oauth.api.OAuthAction +import io.element.android.libraries.oauth.api.OAuthActionFlow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.MutableStateFlow + +/** + * This is actually a copy of DefaultOAuthActionFlow. + */ +class FakeOAuthActionFlow : OAuthActionFlow { + private val mutableStateFlow = MutableStateFlow(null) + + override fun post(oAuthAction: OAuthAction) { + mutableStateFlow.value = oAuthAction + } + + override suspend fun collect(collector: FlowCollector) { + mutableStateFlow.collect(collector) + } + + override fun reset() { + mutableStateFlow.value = null + } +} diff --git a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt b/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt deleted file mode 100644 index 2a16030b3b..0000000000 --- a/libraries/oidc/impl/src/main/kotlin/io/element/android/libraries/oidc/impl/DefaultOidcIntentResolver.kt +++ /dev/null @@ -1,24 +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.oidc.impl - -import android.content.Intent -import dev.zacsweers.metro.AppScope -import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcIntentResolver - -@ContributesBinding(AppScope::class) -class DefaultOidcIntentResolver( - private val oidcUrlParser: OidcUrlParser, -) : OidcIntentResolver { - override fun resolve(intent: Intent): OidcAction? { - return oidcUrlParser.parse(intent.dataString.orEmpty()) - } -} diff --git a/libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/customtab/FakeOidcActionFlow.kt b/libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/customtab/FakeOidcActionFlow.kt deleted file mode 100644 index 5362aefa7c..0000000000 --- a/libraries/oidc/test/src/main/kotlin/io/element/android/libraries/oidc/test/customtab/FakeOidcActionFlow.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 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.oidc.test.customtab - -import io.element.android.libraries.oidc.api.OidcAction -import io.element.android.libraries.oidc.api.OidcActionFlow -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.flow.MutableStateFlow - -/** - * This is actually a copy of DefaultOidcActionFlow. - */ -class FakeOidcActionFlow : OidcActionFlow { - private val mutableStateFlow = MutableStateFlow(null) - - override fun post(oidcAction: OidcAction) { - mutableStateFlow.value = oidcAction - } - - override suspend fun collect(collector: FlowCollector) { - mutableStateFlow.collect(collector) - } - - override fun reset() { - mutableStateFlow.value = null - } -} diff --git a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt index 568dbe7e3a..88cf9558b3 100644 --- a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt +++ b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt @@ -24,8 +24,8 @@ data class SessionData( val refreshToken: String?, /** The homeserver URL of the session. */ val homeserverUrl: String, - /** The Open ID Connect info for this session, if any. */ - val oidcData: String?, + /** The Open Authorization info for this session, if any. */ + val oAuthData: String?, /** The timestamp of the last login. May be `null` in very old sessions. */ val loginTimestamp: Date?, /** Whether the [accessToken] is valid or not. */ diff --git a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt index ea69709bbd..316bf86c1c 100644 --- a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt +++ b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt @@ -20,7 +20,7 @@ internal fun SessionData.toDbModel(): DbSessionData { accessToken = accessToken, refreshToken = refreshToken, homeserverUrl = homeserverUrl, - oidcData = oidcData, + oidcData = oAuthData, loginTimestamp = loginTimestamp?.time, isTokenValid = if (isTokenValid) 1L else 0L, loginType = loginType.name, @@ -41,7 +41,7 @@ internal fun DbSessionData.toApiModel(): SessionData { accessToken = accessToken, refreshToken = refreshToken, homeserverUrl = homeserverUrl, - oidcData = oidcData, + oAuthData = oidcData, loginTimestamp = loginTimestamp?.let { Date(it) }, isTokenValid = isTokenValid == 1L, loginType = LoginType.fromName(loginType ?: LoginType.UNKNOWN.name), diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt index c791a20620..c5acd77755 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt @@ -30,7 +30,7 @@ fun aSessionData( accessToken = accessToken, refreshToken = refreshToken, homeserverUrl = "aHomeserverUrl", - oidcData = null, + oAuthData = null, loginTimestamp = null, isTokenValid = isTokenValid, loginType = LoginType.UNKNOWN, diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index ce5c324ff4..f832136083 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -120,7 +120,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:troubleshoot:impl")) implementation(project(":libraries:fullscreenintent:impl")) implementation(project(":libraries:wellknown:impl")) - implementation(project(":libraries:oidc:impl")) + implementation(project(":libraries:oauth:impl")) implementation(project(":libraries:workmanager:impl")) implementation(project(":libraries:recentemojis:impl")) } From 6de6e13f259dd3a2592ca6dc9fc3cbc1e47a8b4a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 29 Apr 2026 10:06:55 +0000 Subject: [PATCH 0268/1083] Update screenshots --- ...mpl.screens.confirmation_CodeConfirmationView_Day_0_en.png | 4 ++-- ...l.screens.confirmation_CodeConfirmationView_Night_0_en.png | 4 ++-- ...es.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png | 4 ++-- ...es.linknewdevice.impl.screens.error_ErrorView_Day_4_en.png | 4 ++-- ...es.linknewdevice.impl.screens.error_ErrorView_Day_6_en.png | 4 ++-- ...es.linknewdevice.impl.screens.error_ErrorView_Day_7_en.png | 4 ++-- ...es.linknewdevice.impl.screens.error_ErrorView_Day_8_en.png | 3 +++ ....linknewdevice.impl.screens.error_ErrorView_Night_3_en.png | 4 ++-- ....linknewdevice.impl.screens.error_ErrorView_Night_4_en.png | 4 ++-- ....linknewdevice.impl.screens.error_ErrorView_Night_6_en.png | 4 ++-- ....linknewdevice.impl.screens.error_ErrorView_Night_7_en.png | 4 ++-- ....linknewdevice.impl.screens.error_ErrorView_Night_8_en.png | 3 +++ ...newdevice.impl.screens.number_EnterNumberView_Day_0_en.png | 4 ++-- ...newdevice.impl.screens.number_EnterNumberView_Day_1_en.png | 4 ++-- ...newdevice.impl.screens.number_EnterNumberView_Day_2_en.png | 4 ++-- ...newdevice.impl.screens.number_EnterNumberView_Day_3_en.png | 4 ++-- ...newdevice.impl.screens.number_EnterNumberView_Day_4_en.png | 4 ++-- ...newdevice.impl.screens.number_EnterNumberView_Day_5_en.png | 4 ++-- ...wdevice.impl.screens.number_EnterNumberView_Night_0_en.png | 4 ++-- ...wdevice.impl.screens.number_EnterNumberView_Night_1_en.png | 4 ++-- ...wdevice.impl.screens.number_EnterNumberView_Night_2_en.png | 4 ++-- ...wdevice.impl.screens.number_EnterNumberView_Night_3_en.png | 4 ++-- ...wdevice.impl.screens.number_EnterNumberView_Night_4_en.png | 4 ++-- ...wdevice.impl.screens.number_EnterNumberView_Night_5_en.png | 4 ++-- ...evice.impl.screens.root_LinkNewDeviceRootView_Day_0_en.png | 4 ++-- ...evice.impl.screens.root_LinkNewDeviceRootView_Day_1_en.png | 4 ++-- ...evice.impl.screens.root_LinkNewDeviceRootView_Day_3_en.png | 4 ++-- ...evice.impl.screens.root_LinkNewDeviceRootView_Day_4_en.png | 4 ++-- ...evice.impl.screens.root_LinkNewDeviceRootView_Day_5_en.png | 4 ++-- ...ice.impl.screens.root_LinkNewDeviceRootView_Night_0_en.png | 4 ++-- ...ice.impl.screens.root_LinkNewDeviceRootView_Night_1_en.png | 4 ++-- ...ice.impl.screens.root_LinkNewDeviceRootView_Night_3_en.png | 4 ++-- ...ice.impl.screens.root_LinkNewDeviceRootView_Night_4_en.png | 4 ++-- ...ice.impl.screens.root_LinkNewDeviceRootView_Night_5_en.png | 4 ++-- ...classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png | 4 ++-- ...assic.missingkeybackup_MissingKeyBackupView_Night_0_en.png | 4 ++-- ...ns.qrcode.confirmation_QrCodeConfirmationView_Day_0_en.png | 4 ++-- ...ns.qrcode.confirmation_QrCodeConfirmationView_Day_1_en.png | 4 ++-- ...ns.qrcode.confirmation_QrCodeConfirmationView_Day_2_en.png | 4 ++-- ....qrcode.confirmation_QrCodeConfirmationView_Night_0_en.png | 4 ++-- ....qrcode.confirmation_QrCodeConfirmationView_Night_1_en.png | 4 ++-- ....qrcode.confirmation_QrCodeConfirmationView_Night_2_en.png | 4 ++-- ...gin.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en.png | 4 ++-- ...gin.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en.png | 4 ++-- ...gin.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en.png | 4 ++-- ...n.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en.png | 4 ++-- ...n.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en.png | 4 ++-- ...n.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en.png | 4 ++-- ...gin.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en.png | 4 ++-- ...gin.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en.png | 4 ++-- ...n.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en.png | 4 ++-- ...n.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_10_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_11_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_1_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_2_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_3_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_7_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_8_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Day_9_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_10_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_11_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_1_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_2_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_3_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_7_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_8_en.png | 4 ++-- .../images/features.logout.impl_LogoutView_Night_9_en.png | 4 ++-- ...impl.reset.password_ResetIdentityPasswordView_Day_0_en.png | 4 ++-- ...impl.reset.password_ResetIdentityPasswordView_Day_1_en.png | 4 ++-- ...impl.reset.password_ResetIdentityPasswordView_Day_2_en.png | 4 ++-- ...impl.reset.password_ResetIdentityPasswordView_Day_3_en.png | 4 ++-- ...pl.reset.password_ResetIdentityPasswordView_Night_0_en.png | 4 ++-- ...pl.reset.password_ResetIdentityPasswordView_Night_1_en.png | 4 ++-- ...pl.reset.password_ResetIdentityPasswordView_Night_2_en.png | 4 ++-- ...pl.reset.password_ResetIdentityPasswordView_Night_3_en.png | 4 ++-- ...backup.impl.setup_SecureBackupSetupViewChange_Day_0_en.png | 4 ++-- ...backup.impl.setup_SecureBackupSetupViewChange_Day_1_en.png | 4 ++-- ...backup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png | 4 ++-- ...ckup.impl.setup_SecureBackupSetupViewChange_Night_0_en.png | 4 ++-- ...ckup.impl.setup_SecureBackupSetupViewChange_Night_1_en.png | 4 ++-- ...ckup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png | 4 ++-- ...securebackup.impl.setup_SecureBackupSetupView_Day_0_en.png | 4 ++-- ...securebackup.impl.setup_SecureBackupSetupView_Day_1_en.png | 4 ++-- ...securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png | 4 ++-- ...curebackup.impl.setup_SecureBackupSetupView_Night_0_en.png | 4 ++-- ...curebackup.impl.setup_SecureBackupSetupView_Night_1_en.png | 4 ++-- ...curebackup.impl.setup_SecureBackupSetupView_Night_5_en.png | 4 ++-- 88 files changed, 178 insertions(+), 172 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_8_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png index a9e31653f6..18b186ce98 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8dab1dc964cea9a76dc7130d8ac2bfe5d3c866fd6d8d969101eb50e828775d3 -size 31915 +oid sha256:23d54e777c8c9ade84bec155e3aef42f5b1c13b98a23ea6ecbd956d0090b5ad3 +size 32186 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png index 43c472ebb1..d1698e913f 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec67e3fef25c57331cb2425f8fc46a733e16a98c9945d0a4e5b950843c42fa34 -size 31087 +oid sha256:4bde248827b1c53b66c5ea7112af24cac43aea378266e3d7b7ad8a5fa2047258 +size 31261 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png index 3832b8d087..19a824127e 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe92b35b0fe2e5481eeb497f2ada1a639cb1a66f937b4245798edffea75b1f5c -size 35932 +oid sha256:d30e200c3e73775ed7081d3fbdc9f8843c5a5bf9e5f1b9ab3535cc6f0ea7f1f6 +size 35946 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_4_en.png index 4821d3ab76..292e8f0ead 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f60e02e48d483fe8d6b2bdf46192ccc8911fad1e79c7ac1e0272824cc04d3d1c -size 35648 +oid sha256:90e602edde377f866071ec78f391bb7cd0d9b59bec79be91d6a42108f604a32d +size 35833 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_6_en.png index 720026f561..6c9c87f774 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60333d74c8d940b32621defc5cdb3c3776b2980c137244dd34304365ee9ff447 -size 24158 +oid sha256:ced04df939214952c513aa8b4ef4c7a02dfe3bb3bce81f9ec6ea1827f639bf3f +size 24471 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_7_en.png index 0fcd59d198..429daba97a 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bec4c7d06dc2cc287d2165f588c6764e5314287119960947d7e24dbc19ce901 -size 23971 +oid sha256:018e6226239c439fc683eead0acb733d1e06eebad54b1a6c2b43d8cbd2e822cc +size 24324 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_8_en.png new file mode 100644 index 0000000000..14a6d77fe9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94e0cec5dac39083da711bdd30762eb84c794ecc41ab74f6dbe8cf5053402ea1 +size 22080 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png index 368e908499..f1f3896ab8 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f6bc4bb2233067ab6d07e596f8d5ca294501a47a21451a1115aa46e238b31a5 -size 34996 +oid sha256:a78b0677d896de960ce8ce7c5818b1d52004c91917c73c460a605e5e1342554f +size 35129 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_4_en.png index c9d622683c..51d6a1bc13 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:766e65cfceb2e9ff3895ecd5c2be2b80d7b2833b30a5c67a0075ef823bb77cc0 -size 34816 +oid sha256:31b97291b16fd0872891ad2341d95d34d8c0608f92e7a5e39b5f27d40769b111 +size 34955 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_6_en.png index ab0b09c575..3bd50c5655 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd50a4cb9848602b08b853f4fa36314b981a858b98349d68decfcbd6f402d719 -size 23631 +oid sha256:43cf679fbb9a83f14209e61129afb8e7f18a60f9bc127bfcf4f5dff05c79598e +size 24033 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_7_en.png index 4194458de9..2a85b2cf7f 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e2de9b362092dbd08deadac70591d4682304c69981fe27cbbeae4f26233d4aa -size 23444 +oid sha256:7ee6f9fbf05261efe52c247da3869c68c6e87f5132c52da72e56cf833ea6864d +size 23833 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_8_en.png new file mode 100644 index 0000000000..d36887d3e5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:144ea7ed8bba7d5ded34b5e00d7f3f036c4dc882be0cf8a644817ffee4c531f7 +size 21429 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en.png index 136812ccab..474a2b43a5 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11a877e3e4810777b7ddb15fa11b8410976142ee4fb5e9d4103f4248acf121cf -size 29685 +oid sha256:cc0409c3e6c60994c81d83c429bbfb7ebc4ee53ac4114d1913b089a8068ca51e +size 30046 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en.png index e04f62d6aa..fab5d228a6 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:471129545a85e702e8b59391f47630f128f80e819b042e91ee356684e4ae2438 -size 29680 +oid sha256:3670e0f777491b7f6101c3c1c3cc006e4848a8f6e481b9740fb42ee8807ccf9e +size 30024 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en.png index e5f8926345..764cb92eef 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a932c055ae0704cd62358c5442658c1cb059d7d3c0c56518de3e763c8eab3c52 -size 30355 +oid sha256:79b7dd684dcec4a06271eed34794e7546ba441ad2cc9796641ba570871e45cd3 +size 30659 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en.png index a1d475ecdd..9a795c080c 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ca49fb335880670a3b71fdd1f2e2be50e9a5a6677d2e17e9534c9724d9d55b1 -size 30534 +oid sha256:29233a6bad671608f5e1a1d20b24b454cfd70f8a846e4d9572cc86b8c7da45a0 +size 30843 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en.png index 116337e4be..58ae956b13 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be4f85040190c658d5734000e602b4cb43cb0a5ab2e2cea0a993959702c4722f -size 33681 +oid sha256:5d30ae8d9d3b3820dc17d7aff3bd5c6794f5a267993a5dae4dc601278ccaaa5c +size 33999 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en.png index bf1561d23e..7ba887d858 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29d7aac2eaef7850cc9b0f5583d6c9a8aef230525d40011a9a7cb5401b681d03 -size 33409 +oid sha256:bf5b6e85e57aef0d52253dc7563bbe0aae3f38e4a65e2fdc8e0460bccf26b006 +size 33722 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en.png index 99c888caba..a0404e5e72 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cb49a80d6ff771484743be2efc4900d053ccf84372614b98e9284d66d19056f -size 28895 +oid sha256:e0c446ba7fc8e0c0c68732ba34058b41e04d8641dcdbc83255f9417706044c8c +size 29067 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en.png index 4415136e95..fedf612386 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68845451924a562238f2c75dced10697cae75171d976e19c0de927eacfdc3210 -size 28853 +oid sha256:da2778e384c9f749e888690660f496b4af93b7cff6f93c9fef346580a477e1cf +size 29029 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en.png index 13df6a6877..6faf2d1cba 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cc21d3fe55a5dba7b9e70d445877b07f0c88bee61fbd64f929a2321473ea8ad -size 29581 +oid sha256:62c79d08701dad73ab3f5f7744cd2683febeb34cb8bab986685e0cd8bd33c0f6 +size 29773 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en.png index 5e08ee2145..d4c10cf76f 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf6312a9e19892c9db949474cb9aa3b7572cc132d3d5474278abb3c4d91b7ab1 -size 29505 +oid sha256:fad2e4dbc822c79fbd8569dd8db7a5c08b335793aff6923129175bd4479cb218 +size 29744 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en.png index e84f38285e..ff882fdaea 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f24e410e2715019c5fbba40a2f79750781e8db0f4b36c772cb7b37f0d3b0d26f -size 32697 +oid sha256:7a85f79b0167efdc0277d05a41712c39d10115482242bb84a140c6647c28d85d +size 32895 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en.png index 16f85bba9f..1fbbba121f 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd1e04c468c0daae10917f8e66a8e5a6ef8f72fa02f3ad4ca507b714dae7898d -size 32449 +oid sha256:865d4c7ff07834027411a76767aaaa8aa0febf529b910eaa51e5de9bd8a776fa +size 32641 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en.png index d6faf7dd8f..fb88b5b2a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b4a99e2ea65816e35ec8fb1cf40d8aafebb6fd5ae688911d7d009dda15cd0f9 -size 18123 +oid sha256:0ec014c00a19fb280f4e2047d873f1698eedde51a765948bd2652079921588a7 +size 18264 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en.png index db46722b7b..9bf1f8609c 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfbe2c73c732d671278ed411d76915d04d6e7ffce130c2a6dbe30ea43628e231 -size 24247 +oid sha256:ba8f1717d752a93cdda51a6ee5e8bac043a4572aadc4d1c0dba2bfe80e6c55db +size 24372 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en.png index c0703e447a..139ae28bda 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9168cc32d47f15de0ce961d841d872181b8aadf5151d4b5fd4d305c87cdda75 -size 21597 +oid sha256:7bc87f28234d11c58f5b43a7f87ee4e5a5d631e5a41ba11756c057a2a5eea1ff +size 21745 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en.png index 457e334ac2..a36301f230 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96448542138570c8615e24dd3b26be55145570c64ac9d410bbc4dac36280c345 -size 23769 +oid sha256:c97be1636f039afaab65c1b6858c439fcf47e6643681a886fd9c24ab6c7b0901 +size 23901 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en.png index 4621b6c95e..78e7e0d1bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:672e617ab62c72127a4c57bed6da8ba4710cfc24ca455ea6edc765d7a424a0f3 -size 33766 +oid sha256:90ca0d9059538259cd19e7e75f6adc11f21b3a1cc77aec8d5efaf3d55abf8505 +size 34006 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en.png index 52e64e87c3..e6153a4a2d 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:451565c6881885b51de299c2d71e77f78a62e68f96a75bc859050e64b87ef79e -size 17372 +oid sha256:1cd2061366439af2139a1ace15557ecdd8aa91c0d2f1e0adfc76a7d63e17133c +size 17615 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en.png index 5610b70d00..03c7fd3b0c 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:def1de8d3a76255e72e0d65dbbf6364f77c2764e2ac99b32a0145174cf0f3a28 -size 23244 +oid sha256:541b4cd380fee2f2a445fe25a1171492c865b10980dd79de70f42b0f3dc120c4 +size 23475 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en.png index 3784bbcac7..3cc9326747 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bd9567f7a504590da66993a2da6771c1a4157bc37301510f6d91d62efed7c16 -size 20745 +oid sha256:b71e2ba137ec1ffc65c07fc836074f7fa0ef310fb81a15db905db819ea29dd0e +size 20980 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en.png index e511df48c7..d6bb6bcc8d 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d662774653bcec6246ac6529ec98bcff77b02e4a6a8ef42ed0a640fed3770dff -size 22698 +oid sha256:de97697d988d0cc25626c7e31f153a7dca6987215edbe2e42ec16367ea9b4b3c +size 22952 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en.png index d35cdd7397..59789476b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee6a0cf330b30e4fdc7cb8b4268251850f2f112e1ad0ce4af1166341f04a0638 -size 32103 +oid sha256:9b3a92c98a93b1d9e7f127a13c664c7275e26030d59a0ebcd3641428d9a21683 +size 32303 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 47145ebd49..3314252e26 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:62df5826abbcd47bc2a18743f2baeef8c9c85ebc547660a9ae92328cd49499b0 -size 62768 +oid sha256:6e97cab70b9ee3e870154ad4ae4cf1bf0bb413facf8253f5f9fe9429eddf76b1 +size 60303 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 fa68b6c988..d58e079ced 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:c92a6ada8c2aa5991c28935dafd8e35a0c0efc2c40660c16105b3cf381914cdd -size 61097 +oid sha256:caaa2a0f4de455704a6b5c78e19c2f723be7deaeec470c77ff1e87df194dd95c +size 58620 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en.png index 878e97a06e..048c9beb26 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbcf2216fe8f2653d44df345c157eb66f54ff8767c210bfeab5719d6d70230a8 -size 31686 +oid sha256:647163b31578572c9bf4a63a1d110f732fc3b0c41c3991651996608d6265c536 +size 31960 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en.png index 05edb58b0f..d27a10bf39 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:324b1392f40bb408b6469e656e774f5b1f7cbd9bb6557ec7a2587a971b548ccc -size 31288 +oid sha256:6e447151f2a7aaf9052130d5b915e9aea8180880c66fa51afb06d212079a0ced +size 31159 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en.png index 096b521d75..4b7e849116 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1075e98dac6a50a282a39dfd5855833080becd377e1bf3f9db8fb20104bda80d -size 33479 +oid sha256:e215ffdf8ba90e3f7a047d25206dfef4a08d25137ee2e4d3e5c16f254282927c +size 33371 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en.png index e738c998a3..276d9919f7 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f55c2e968f464ba9593dc8841a0e633c2f0a75cb3f85857aa3b4b716770629e -size 30831 +oid sha256:76613fd85c3211bd2c96e50f2d481d2d994aad20368713c1da309d0147ce1101 +size 31015 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en.png index ae7ffe2dd4..c1da84be8e 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8484c5300a8da5b120a24513b29bdd697dd3edd7d6b7c91e5925aa55c6290fd -size 30366 +oid sha256:5f32133324f20fc97c3473ca6ea3b1705d3b0beab5bed11af9199e4f5b9ab124 +size 30410 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en.png index 1cf5572c4e..e06e5ccaaa 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b87fe16a96a8c34b49aab481f65c3223fd098360048b7dcd1ee8bef85fdf378 -size 32650 +oid sha256:00556b6c310f63b548bc1a88b3b882a93412a2a7dacff008862faeb2ad572eb3 +size 32671 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en.png index 98039ad35b..d13b526c94 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:647b5d2512180674b14a93903de4ee0539720dc1ddc7eaadec23940aa8b3befa -size 35934 +oid sha256:c95c7e7f68133f25bca9c33246983cdd1b448ca822b1221eba54c171c8f2e051 +size 35898 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en.png index 9751c25cb4..aa8c5c7858 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:010a03fc52fb0ec9b39701d75ef26c7f23ba6195e7d3e0c4e2b7e03518425b57 -size 24287 +oid sha256:b4b6b193a6c9bd9188cde36056a512ebe10f9b24d07a33926b51876712b453b2 +size 24468 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en.png index 0fcd59d198..429daba97a 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bec4c7d06dc2cc287d2165f588c6764e5314287119960947d7e24dbc19ce901 -size 23971 +oid sha256:018e6226239c439fc683eead0acb733d1e06eebad54b1a6c2b43d8cbd2e822cc +size 24324 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en.png index ce263c7d02..0fc27b0af4 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb22d79ff43ce9a1931537880829cf5d2c13aafe3c06136c80703f2599d676cf -size 35000 +oid sha256:ecc5f3820395a67eee396556344663844fb97dc843cda96b2545c954d133795f +size 35118 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en.png index 2c4de61a77..fb5e9a7448 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3c16c9a89228f83eaaa7f9bdd7c0e36a333efb541738bd38411f9f853e20103 -size 23797 +oid sha256:dc0360e2705f3e029c1f8cabf91787a98f7d7b67e6d1f003c54ca4ffd52d08be +size 23961 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en.png index 4194458de9..2a85b2cf7f 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e2de9b362092dbd08deadac70591d4682304c69981fe27cbbeae4f26233d4aa -size 23444 +oid sha256:7ee6f9fbf05261efe52c247da3869c68c6e87f5132c52da72e56cf833ea6864d +size 23833 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en.png index a1b5d1bb59..afd2b2cbe5 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:919595acfee379e3aaee66a3abba61515e8bee35a9fe0250a8a227f772109864 -size 49693 +oid sha256:94014619417d8c530dc80316c9aca36dc08997f516890d7199b24afa46e71c86 +size 50004 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en.png index 665a36ad0a..f86302a8ee 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:079ef0792efb31fbd773beb77a95bfa713213f8f5428ea1c12060094deac5442 -size 48620 +oid sha256:0a3d3c574589f06729b58775ca37bab9711c5566adff366d4a0196eaa7e10ab7 +size 47410 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en.png index 32d07be159..3ee9db165b 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17cd489adfd7a417a6972f8e36a61ecb2bcaf2a045d33e4d2236004271d4d9ff -size 48317 +oid sha256:277665230a31e1a47489a5124efa6dcaf51a5a442f0e6d4dfb510ff4896c9bd0 +size 48738 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en.png index 9ad4c83991..ba4e6885b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:215e1dbc213d493ee6e24712aa93c9a103f1148a3ea2858ff185dfdc7084ea3b -size 46546 +oid sha256:2044881fe3e54179333fc0b125972b2b410a4d3657faa10769b964e8ae0d2643 +size 45278 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png index d996699f1a..da7923cf50 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31e32566506ef9c6d34b144663b308a53f893b810960c50e394271ed5dc02fc0 -size 28564 +oid sha256:b1c09cbb0217a1fb844828590e7827c27a2e9a99ecf5aed225f4d1bd0e413c8d +size 29343 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png index 9df382c0db..68b16e509f 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6e129a426f95432f31ecb5776ae24e5fed7a3025217c70831dcab30ac270fc3 -size 33329 +oid sha256:6ee66772b20b9c1cacf1f9387c173f8170d0c132d6caddfbd389d254b2ae7aa5 +size 33977 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png index 68d54d002a..56510ac1e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2eb71eb5d1cac83a03abbdc6ac670cb96993da8825ab224b43e593ae4b6ee8f -size 53719 +oid sha256:3eed90dbcc789f3db882d61a31924668a42cf78e00cd634192a5bfb831f67190 +size 53659 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png index f71897a57b..3bc29fbe6e 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71e7b0aba9acb702371ed0eacd6d86735d47d02dfadc67e55079a454c9c8733f -size 30242 +oid sha256:228a9ed83c86a160fe494254ec654fc0bf1d6923e78f5de2b4057d386e25b333 +size 30750 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png index 68d54d002a..56510ac1e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2eb71eb5d1cac83a03abbdc6ac670cb96993da8825ab224b43e593ae4b6ee8f -size 53719 +oid sha256:3eed90dbcc789f3db882d61a31924668a42cf78e00cd634192a5bfb831f67190 +size 53659 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png index c34ec228cd..bdad7df7bc 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1c6a823d353aa2f63633bce1d0336239196f26136b532718fdf2c49c183fbe9 -size 38014 +oid sha256:64c4173147686886d5021cdaf6480644a5a520f81392ca84aa7ab5d705211bc7 +size 38682 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png index 651a16265f..f52aac7f1c 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:359b8ffc79afd24ba68c2e7c13ba551e9d63c72b787e530667cd5de5c16782f6 -size 48002 +oid sha256:c6c73dd018eb82fe9e54ffbe38dcc491938da69791f4ff32081b2dac7549a4b2 +size 47958 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png index 651a16265f..f52aac7f1c 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:359b8ffc79afd24ba68c2e7c13ba551e9d63c72b787e530667cd5de5c16782f6 -size 48002 +oid sha256:c6c73dd018eb82fe9e54ffbe38dcc491938da69791f4ff32081b2dac7549a4b2 +size 47958 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png index 12fa559ca5..4d2c26d91d 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84d3be38de70c774b36592543eb5636029b08f9a847566dea4f90979ec9be97c -size 27529 +oid sha256:0b0e1f00b98e463a97c9334da018ba944414526f771aa4ceaea18ab192a36863 +size 28080 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png index 543aa41952..a650636f24 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93f49929a2e696bfa8a8938107d3263dcda514f34c8b5eeb6315267126d138d0 -size 32095 +oid sha256:87e337a40741a5c7bdcb2015b8f82282ae69e1eff98e30641a02314660ecbd73 +size 32583 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png index 53bf92ea9c..62596baf31 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4701f103d24353378826f66e6d602b0bdf43904ef6b28ee03d25af4a1062411 -size 51650 +oid sha256:66a0dc249d2df7e52a6a5f7cb3f1a94be011164eaf23d365f548b99f093d3d14 +size 51681 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png index 68647ba764..f97ba2a853 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2223132d7446121d8bd37b3561fc24ce056aeffc8828b197a2be8c92ce64cd27 -size 29197 +oid sha256:aba88e94521e05328079fb2ac0b06fd97987f81694b3378f02c19a20bfae2572 +size 29636 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png index 53bf92ea9c..62596baf31 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4701f103d24353378826f66e6d602b0bdf43904ef6b28ee03d25af4a1062411 -size 51650 +oid sha256:66a0dc249d2df7e52a6a5f7cb3f1a94be011164eaf23d365f548b99f093d3d14 +size 51681 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png index d233b2890d..17526d949c 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7aa9c94a5f9c324a3229a5db951411fba6759aee18987d61f6ffc6d74ac79a60 -size 36665 +oid sha256:fd6d4b2d03d0e86a22c48f89f05c83b0e7622f4b6fc2a946ace1ef33e66b2e9a +size 37183 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png index 084de2c14a..bf33b63f8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a952926d397cab2a689e3f4096de103bbb3075f27dbe45fff311a153ab1c9ace -size 46181 +oid sha256:d8f9a50b522d34a29ec48fcef545a0880ff0f43d464f1874c3486adb9c79e202 +size 46251 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png index 084de2c14a..bf33b63f8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a952926d397cab2a689e3f4096de103bbb3075f27dbe45fff311a153ab1c9ace -size 46181 +oid sha256:d8f9a50b522d34a29ec48fcef545a0880ff0f43d464f1874c3486adb9c79e202 +size 46251 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png index de42fdfe94..fd32767a41 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15f9aa77f9f8fe09a10e2e22b194f2ba505d56c9097db0872b317840c0fa84c4 -size 28661 +oid sha256:218a8bafb58855056ab07b05d45c87df482483c02a5144c0117c1159135e924a +size 28637 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png index 6ded082e3c..a3c91c139d 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f1762442b6dcd37d5710437239055e7d40d2b741cacd1045a3eacd327fc12ee -size 28053 +oid sha256:76f1e9db9260cb23bd80bce5f45bdf323a8d24cb87757d7a32f9c6e6b632913c +size 27993 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png index 6ded082e3c..a3c91c139d 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f1762442b6dcd37d5710437239055e7d40d2b741cacd1045a3eacd327fc12ee -size 28053 +oid sha256:76f1e9db9260cb23bd80bce5f45bdf323a8d24cb87757d7a32f9c6e6b632913c +size 27993 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png index 88df849ef5..6c8ad3018b 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea5df9ecebf686ac65c265d1b74e3a0a5169d1e308eaaf4f9c205a754d8bddcc -size 40150 +oid sha256:4fda40268a68acf664e90a48391658b8dedb3d7f5d5e6b76d680ab25180d5a55 +size 40121 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png index 58a01b25a3..4317869283 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06170ddb862b337c00d50a531caa1f673952cc0194cb38410d3aa7cc61d95c16 -size 27653 +oid sha256:6c8f9e633578f46a6b8126ea6dcbdb5c113dd0e1107fbc4d5b2206c2f5acfb1c +size 27835 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png index f346d344e0..eed9b50326 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc1a0fd307ba6ea9a9f578527bae5a074e5ad67035201d8aa7d85877ee697af5 -size 26690 +oid sha256:d55afb5f76aac3d1a8ff0f1c223502fc798dc0684f9d84df79256c41ca5ea1cc +size 26706 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png index f346d344e0..eed9b50326 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc1a0fd307ba6ea9a9f578527bae5a074e5ad67035201d8aa7d85877ee697af5 -size 26690 +oid sha256:d55afb5f76aac3d1a8ff0f1c223502fc798dc0684f9d84df79256c41ca5ea1cc +size 26706 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png index f38139bcf2..0b3c962498 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:763ddaf10dfed74dbef17deccfa7037d8b643e9b8654409ce96e8192ab5ee38c -size 38418 +oid sha256:9410147c7a6a496fbd356b0dbc3b14998f20ddea6a2eeabb79b9600485285a80 +size 38628 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en.png index 21b17d8656..e1573dacb9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:562e8457321ec1afe9ca9a2111ee19815aa25401cd925c0bcc880a25db99e0c4 -size 42100 +oid sha256:01d03620cae8382ee41703d7553913fbd1e463fcd55fd661e9b99087e14bf6b1 +size 42162 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en.png index c26e5c44c1..bea6d32d38 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4498edc796206821f346a2dfceb966f59f4b7adf513ae184c84d20b323ed0d67 -size 39800 +oid sha256:54d9e8714cbbc3785ccd25d6bff9c791d57acea007d6cb8774a4a5d61646b54f +size 39857 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png index e798d07cac..dd9010b013 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f3d6bcf6b603ea2e2a619f569960438337fe9e2ae9eea2657587cd211bbf278 -size 35444 +oid sha256:9f6ce15f59eba49738b9df2117764e760f2ddc06bd52f8386f6d78af307a4104 +size 34630 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en.png index fa0b46361e..3264a61179 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9c17b8ca9966e4239e5c5fb9d9e5f0f061bd8d7fbf3bd9c76ce6473af537d05 -size 40962 +oid sha256:9a0a377b34502fb55b3ee72468533914de3c68df62531a6f40a41984c94d0047 +size 40996 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en.png index 0072d95bed..6d6a189589 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e73375d44fcd158c7cc2cd0f97b49c8a0f2d523772cab58778ed7b31a8a0d5e -size 38602 +oid sha256:433de908676d053d3728b8cfe03636d082691059dbe4c15b950483cfdc3e1ce8 +size 38634 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png index b8629728ea..0d1e17b957 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cb10d8ef6b7c6fd25e772428e03755f1c731197660ed7123b79c56629f74583 -size 33086 +oid sha256:56030e621f122f288b00dc642cf5ab4a3a09100cdcb92e068d8fc0f47f9a5328 +size 32421 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en.png index f3d5c2ec82..5c0a10cffc 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cef767ba47c98c5b693cfadef2ea0a260a35d3144c2dc26a3bb52bf632700d9c -size 44141 +oid sha256:61b6259baf820caca8eb8a28052142c56ee88a952148e204c25a53f709b87fe4 +size 44542 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en.png index 5c91aae383..599ce75592 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ef46c819c931938a4fd856bb2fc697c964d4445d6cf9f8b5e2f341f22805061 -size 42001 +oid sha256:2f246482f43b0298e8948925fda23d9c306f56b484d42eeedbca1cce2dfb6bb2 +size 42382 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png index 214e107f12..224e1705c4 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de188fac87a59e6765360282655c081d7b93e7dfa47837b0c56dd77a9892ed03 -size 34616 +oid sha256:2ab51540f79f485e98b311210fc7d8b98ccb174b9e689587559878c245877f4a +size 38492 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en.png index 7f69976784..654f566376 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b53f00607190915bfb683c0bef1bd11f0804651fe6bf57bc9312afa20768a75 -size 42924 +oid sha256:b9962bf5c4f9870d51cd3eb3346bf0e2054c5f7e21111f57c7a7bb1938e81aab +size 43211 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en.png index 20dcda7f44..564035b900 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cd74bb51213ae932addc3dbaff2bd20d877a249c46ac5bb7656e03566189b38 -size 40748 +oid sha256:fbf5c303797332b7419e1529ddaa8d1f2f1cd6ed2086654880c7702fc3d62070 +size 40971 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png index 82f91a65d5..3d21f69991 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcad0014629c828846e05247a1ca0767c45906bc15378a00cb9d4e6cd7280dc1 -size 32380 +oid sha256:47fc45150924e2c1aacc86889824f7c0d7382af94ef420ff690871d75c7c3e23 +size 36212 From d215354e6482c9c0fce12295bf9672a0948fef7a Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 29 Apr 2026 12:54:03 +0200 Subject: [PATCH 0269/1083] Remove legacy `mx-reply` from `toPlainText` formatted event contents (#6683) --- .../matrix/ui/messages/ToHtmlDocument.kt | 40 +++++++++++++++++-- .../matrix/ui/messages/ToPlainText.kt | 5 +++ .../matrix/ui/messages/ToPlainTextTest.kt | 15 +++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToHtmlDocument.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToHtmlDocument.kt index ee9de51681..d29a28cba9 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToHtmlDocument.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToHtmlDocument.kt @@ -12,8 +12,10 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.item.event.FormattedBody import io.element.android.libraries.matrix.api.timeline.item.event.MessageFormat -import io.element.android.wysiwyg.utils.HtmlToDomParser +import org.jsoup.Jsoup import org.jsoup.nodes.Document +import org.jsoup.nodes.Document.OutputSettings +import org.jsoup.safety.Safelist /** * Converts the HTML string [FormattedBody.body] to a [Document] by parsing it. @@ -34,9 +36,9 @@ fun FormattedBody.toHtmlDocument( ?.trimEnd() ?.let { formattedBody -> val dom = if (prefix != null) { - HtmlToDomParser.document("$prefix $formattedBody") + CustomHtmlToDomParser.document("$prefix $formattedBody") } else { - HtmlToDomParser.document(formattedBody) + CustomHtmlToDomParser.document(formattedBody) } // Prepend `@` to mentions @@ -60,3 +62,35 @@ private fun fixMentions( } } } + +/** Custom Html to DOM parser, based on the one included in the rich text editor library. */ +private object CustomHtmlToDomParser { + fun document(html: String): Document { + val outputSettings = OutputSettings().prettyPrint(false).indentAmount(0) + val cleanHtml = Jsoup.clean(html, "", safeList, outputSettings) + return Jsoup.parse(cleanHtml) + } + + private val safeList = Safelist() + .addTags( + "a", + "b", + "strong", + "i", + "em", + "u", + "del", + "code", + "ul", + "ol", + "li", + "pre", + "blockquote", + "p", + "br", + // Add custom `mx-reply` tag, even if it's just to remove its contents from the plain text version of the message + "mx-reply" + ) + .addAttributes("a", "href", "data-mention-type", "contenteditable") + .addAttributes("ol", "start") +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt index 34dc72aa1a..cf8b03b80d 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainText.kt @@ -65,6 +65,8 @@ fun Document.toPlainText(): String { return visitor.build() } +private const val FALLBACK_REPLY_NODE_TAG = "mx-reply" + private class PlainTextNodeVisitor : NodeVisitor { private val builder = StringBuilder() @@ -92,6 +94,9 @@ private class PlainTextNodeVisitor : NodeVisitor { } else { builder.append("• ") } + } else if (node is Element && node.tagName() == FALLBACK_REPLY_NODE_TAG) { + // Remove the fallback reply node and its contents so they aren't added to the plain text message + node.remove() } else if (node is Element && node.isBlock && builder.lastOrNull() != '\n') { builder.append("\n") } diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainTextTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainTextTest.kt index 607f825401..ce0ef4cf31 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainTextTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/ToPlainTextTest.kt @@ -136,4 +136,19 @@ class ToPlainTextTest { ) assertThat(messageType.toPlainText(permalinkParser = FakePermalinkParser())).isEqualTo("This is the fallback text") } + + @Test + fun `TextMessageType toPlainText - ignores mx-reply element`() { + val messageType = TextMessageType( + body = "This is the fallback text", + formatted = FormattedBody( + format = MessageFormat.HTML, + body = """ + In reply to... + This is the message content. + """.trimIndent() + ) + ) + assertThat(messageType.toPlainText(permalinkParser = FakePermalinkParser())).isEqualTo("This is the message content.") + } } From 3b21d698eefee5a427b8f0cd6f6352ed923b2b99 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 29 Apr 2026 12:05:16 +0100 Subject: [PATCH 0270/1083] Fix tests Co-Authored-By: Benoit Marty <3940906+bmarty@users.noreply.github.com> --- .../FakeFfiGrantLoginWithQrCodeHandler.kt | 4 +- .../RustLinkDesktopHandlerTest.kt | 39 ++++++++++++++++++- .../RustLinkMobileHandlerTest.kt | 39 ++++++++++++++++++- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiGrantLoginWithQrCodeHandler.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiGrantLoginWithQrCodeHandler.kt index cd0733695b..0899b16325 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiGrantLoginWithQrCodeHandler.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiGrantLoginWithQrCodeHandler.kt @@ -16,8 +16,8 @@ import org.matrix.rustcomponents.sdk.NoHandle import org.matrix.rustcomponents.sdk.QrCodeData class FakeFfiGrantLoginWithQrCodeHandler( - private val generateResult: () -> Unit = {}, - private val scanResult: (QrCodeData) -> Unit = {}, + private val generateResult: suspend () -> Unit = {}, + private val scanResult: suspend (QrCodeData) -> Unit = {}, ) : GrantLoginWithQrCodeHandler(NoHandle) { private var generateProgressListener: GrantGeneratedQrLoginProgressListener? = null private var scanProgressListener: GrantQrLoginProgressListener? = null diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandlerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandlerTest.kt index a180e4d515..fd635e2da6 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandlerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkDesktopHandlerTest.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.linknewdevice.ErrorType import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopStep import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler import io.element.android.libraries.matrix.test.QR_CODE_DATA +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import kotlinx.coroutines.test.StandardTestDispatcher @@ -29,7 +30,13 @@ import org.matrix.rustcomponents.sdk.QrCodeDecodeException class RustLinkDesktopHandlerTest { @Test fun `handleScannedQrCode function works as expected`() = runTest { - val handler = FakeFfiGrantLoginWithQrCodeHandler() + val completable = CompletableDeferred() + val handler = FakeFfiGrantLoginWithQrCodeHandler( + scanResult = { + // Ensure that the coroutine is hold + completable.await() + } + ) val sut = createRustLinkDesktopHandler( handler, ) @@ -53,6 +60,36 @@ class RustLinkDesktopHandlerTest { handler.emitScanProgress(progress) assertThat(awaitItem()).isEqualTo(expectedStep) } + // scan returns, no new event is emitted + completable.complete(Unit) + expectNoEvents() + } + } + + @Test + fun `when scan does not emits the Done state, the code emits it`() = runTest { + val completable = CompletableDeferred() + val handler = FakeFfiGrantLoginWithQrCodeHandler( + scanResult = { + // Ensure that the coroutine is hold + completable.await() + } + ) + val sut = createRustLinkDesktopHandler( + handler, + ) + sut.linkDesktopStep.test { + val initialItem = awaitItem() + assertThat(initialItem).isEqualTo(LinkDesktopStep.Uninitialized) + backgroundScope.launch { + sut.handleScannedQrCode(QR_CODE_DATA) + } + runCurrent() + handler.emitScanProgress(GrantQrLoginProgress.Starting) + assertThat(awaitItem()).isEqualTo(LinkDesktopStep.Starting) + // scan returns, Done event is emitted + completable.complete(Unit) + assertThat(awaitItem()).isEqualTo(LinkDesktopStep.Done) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt index aa13996e8a..9f71cb7169 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiCheckCodeS import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData import io.element.android.libraries.matrix.test.QR_CODE_DATA_RECIPROCATE +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import kotlinx.coroutines.test.StandardTestDispatcher @@ -30,7 +31,13 @@ import org.matrix.rustcomponents.sdk.HumanQrGrantLoginException class RustLinkMobileHandlerTest { @Test fun `start function works as expected`() = runTest { - val handler = FakeFfiGrantLoginWithQrCodeHandler() + val completable = CompletableDeferred() + val handler = FakeFfiGrantLoginWithQrCodeHandler( + generateResult = { + // Ensure that the coroutine is hold + completable.await() + } + ) val sut = createRustLinkMobileHandler( handler, ) @@ -56,6 +63,36 @@ class RustLinkMobileHandlerTest { handler.emitGenerateProgress(progress) assertThat(awaitItem()).isInstanceOf(expectedStepClass) } + // generate returns, no new event is emitted + completable.complete(Unit) + expectNoEvents() + } + } + + @Test + fun `when generates does not emits the Done state, the code emits it`() = runTest { + val completable = CompletableDeferred() + val handler = FakeFfiGrantLoginWithQrCodeHandler( + generateResult = { + // Ensure that the coroutine is hold + completable.await() + } + ) + val sut = createRustLinkMobileHandler( + handler, + ) + sut.linkMobileStep.test { + val initialItem = awaitItem() + assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized) + backgroundScope.launch { + sut.start() + } + runCurrent() + handler.emitGenerateProgress(GrantGeneratedQrLoginProgress.Starting) + assertThat(awaitItem()).isEqualTo(LinkMobileStep.Starting) + // generate returns, Done event is emitted + completable.complete(Unit) + assertThat(awaitItem()).isEqualTo(LinkMobileStep.Done) } } From f0dc4eeace0c8f19304fce4f701afa749809a9cd Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 24 Apr 2026 11:37:00 +0200 Subject: [PATCH 0271/1083] feat: Update call started timeline item + declined support --- .../components/TimelineItemCallNotifyView.kt | 94 ++++++++++++------- .../timeline/components/TimelineItemRow.kt | 1 + .../event/TimelineItemContentFactory.kt | 8 +- .../TimelineItemRtcNotificationContent.kt | 21 ++++- .../DefaultMessageSummaryFormatter.kt | 8 +- .../impl/DefaultRoomLatestEventFormatter.kt | 3 +- .../impl/RtcNotificationContentFormatter.kt | 39 ++++++++ .../api/timeline/item/event/EventContent.kt | 3 +- .../item/event/TimelineEventContentMapper.kt | 3 +- 9 files changed, 138 insertions(+), 42 deletions(-) create mode 100644 libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index dfd1b2ed0e..aa004a6259 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -22,17 +22,19 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent -import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -42,6 +44,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun TimelineItemCallNotifyView( + timelineRoomInfo: TimelineRoomInfo, event: TimelineItem.Event, content: TimelineItemRtcNotificationContent, onLongClick: (TimelineItem.Event) -> Unit, @@ -62,37 +65,22 @@ internal fun TimelineItemCallNotifyView( horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically, ) { - Avatar( - avatarData = event.senderAvatar, - avatarType = AvatarType.User, + Icon( + modifier = Modifier.size(20.sp.toDp()), + imageVector = getIcon(timelineRoomInfo, content), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary, ) - Column(modifier = Modifier.weight(1f)) { - Text( - text = event.safeSenderName, - style = ElementTheme.typography.fontBodyLgMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(20.sp.toDp()), - imageVector = - if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), - contentDescription = null, - tint = ElementTheme.colors.iconSecondary, - ) - Text( - text = stringResource(CommonStrings.common_call_started), - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - } + + Text( + modifier = Modifier.weight(1f), + text = stringResource(getTextRes(timelineRoomInfo, content)), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( text = event.sentTime, style = ElementTheme.typography.fontBodyMdRegular, @@ -103,15 +91,51 @@ internal fun TimelineItemCallNotifyView( } } +private fun getTextRes( + timelineRoomInfo: TimelineRoomInfo, + content: TimelineItemRtcNotificationContent +): Int = if (timelineRoomInfo.isDm) { + when (content.state) { + RtcNotificationState.Declined -> CommonStrings.common_call_declined + RtcNotificationState.DeclinedByMe -> CommonStrings.common_call_you_declined + RtcNotificationState.None -> CommonStrings.common_call_started + } +} else { + // Only show declined info in DMs + CommonStrings.common_call_started +} + +@Composable +private fun getIcon( + timelineRoomInfo: TimelineRoomInfo, + content: TimelineItemRtcNotificationContent +): ImageVector { + val showAsDeclined = timelineRoomInfo.isDm && ( + content.state == RtcNotificationState.Declined || + content.state == RtcNotificationState.DeclinedByMe + ) + val icon = if (showAsDeclined) { + if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallDeclinedSolid() else CompoundIcons.VideoCallDeclinedSolid() + } else { + if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid() + } + return icon +} + @PreviewsDayNight @Composable internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { listOf( - TimelineItemRtcNotificationContent(CallIntent.AUDIO), - TimelineItemRtcNotificationContent(CallIntent.VIDEO), - ).forEach { content -> + (aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.None)), + (aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None)), + (aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Declined)), + (aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined)), + (aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.DeclinedByMe)), + (aTimelineRoomInfo(isDm = false) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None)), + ).forEach { (info, content) -> TimelineItemCallNotifyView( + timelineRoomInfo = info, event = aTimelineItemEvent(content = content), content = content, onLongClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index e75df2f89f..7cd99651a4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -125,6 +125,7 @@ internal fun TimelineItemRow( is TimelineItemRtcNotificationContent -> { TimelineItemCallNotifyView( modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp), + timelineRoomInfo = timelineRoomInfo, event = timelineItem, content = timelineItem.content, onLongClick = onLongClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt index dff195e833..64320622ba 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.timeline.factories.event import dev.zacsweers.metro.Inject import io.element.android.features.location.api.Location +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent @@ -104,7 +105,12 @@ class TimelineItemContentFactory( is PollContent -> pollFactory.create(eventId, isEditable, isOutgoing, itemContent) is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent( - itemContent.callIntent + callIntent = itemContent.callIntent, + state = when { + itemContent.declinedBy.isEmpty().not() && itemContent.declinedBy.any { it == sessionId } -> RtcNotificationState.DeclinedByMe + itemContent.declinedBy.isEmpty().not() -> RtcNotificationState.Declined + else -> RtcNotificationState.None + } ) is UnknownContent -> TimelineItemUnknownContent is LiveLocationContent -> { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index 53facfc675..df1c9f5693 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -9,7 +9,24 @@ package io.element.android.features.messages.impl.timeline.model.event import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.api.timeline.item.event.EventType -class TimelineItemRtcNotificationContent(val callIntent: CallIntent) : TimelineItemEventContent { - override val type: String = "org.matrix.msc4075.rtc.notification" +// For now this is just an enum, but could be a +// sealed class if we need the list of users who declined. +enum class RtcNotificationState { + /** Some users have declined */ + Declined, + + /** I have declined this call */ + DeclinedByMe, + + // Future sates could be `Missed`? `ongoing`... + None +} + +class TimelineItemRtcNotificationContent( + val callIntent: CallIntent, + val state: RtcNotificationState, +) : TimelineItemEventContent { + override val type: String = EventType.RTC_NOTIFICATION } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt index c48f2dae40..5437711bb7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.utils.messagesummary import android.content.Context import dev.zacsweers.metro.ContributesBinding +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent @@ -56,7 +57,12 @@ class DefaultMessageSummaryFormatter( is TimelineItemFileContent -> context.getString(CommonStrings.common_file) is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio) is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call) - is TimelineItemRtcNotificationContent -> context.getString(CommonStrings.common_call_started) + is TimelineItemRtcNotificationContent -> when (content.state) { + RtcNotificationState.Declined -> + context.getString(CommonStrings.common_call_declined) + RtcNotificationState.DeclinedByMe -> context.getString(CommonStrings.common_call_you_declined) + RtcNotificationState.None -> context.getString(CommonStrings.common_call_started) + } } // Truncate the message to a safe length to avoid crashes in Compose .toSafeLength() diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt index b9b6467c92..eac0e9e88d 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 @@ -55,6 +55,7 @@ class DefaultRoomLatestEventFormatter( private val profileChangeContentFormatter: ProfileChangeContentFormatter, private val stateContentFormatter: StateContentFormatter, private val permalinkParser: PermalinkParser, + private val rtcNotificationContentFormatter: RtcNotificationContentFormatter, ) : RoomLatestEventFormatter { override fun format( latestEvent: LatestEventValue.Local, @@ -121,7 +122,7 @@ class DefaultRoomLatestEventFormatter( message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is LegacyCallInviteContent -> sp.getString(CommonStrings.common_unsupported_call) - is CallNotifyContent -> sp.getString(CommonStrings.common_call_started) + is CallNotifyContent -> rtcNotificationContentFormatter.format(content, isDmRoom) }?.take(DEFAULT_SAFE_LENGTH) } diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt new file mode 100644 index 0000000000..ab3fb9433d --- /dev/null +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.eventformatter.impl + +import dev.zacsweers.metro.Inject +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.services.toolbox.api.strings.StringProvider + +@Inject +class RtcNotificationContentFormatter( + private val matrixClient: MatrixClient, + private val sp: StringProvider, +) { + fun format( + content: CallNotifyContent, + isDm: Boolean, + ): CharSequence { + return if (isDm) { + val isDeclined = content.declinedBy.isNotEmpty() + val isDeclinedByMe = content.declinedBy.any { matrixClient.isMe(it) } + if (isDeclinedByMe) { + sp.getString(CommonStrings.common_call_you_declined) + } else if (isDeclined) { + sp.getString(CommonStrings.common_call_declined) + } else { + sp.getString(CommonStrings.common_call_started) + } + } else { + sp.getString(CommonStrings.common_call_started) + } + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt index d91d404a0b..f323b316f7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt @@ -119,7 +119,8 @@ data class LiveLocationContent( data object LegacyCallInviteContent : EventContent data class CallNotifyContent( - val callIntent: CallIntent + val callIntent: CallIntent, + val declinedBy: List ) : EventContent data object UnknownContent : EventContent diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index edfe9a3543..fa671bc546 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -153,7 +153,8 @@ class TimelineEventContentMapper( CallIntent.AUDIO } else { CallIntent.VIDEO - } + }, + declinedBy = it.declinedBy.map(::UserId) ) } } From a6622c678714bec5bc8a749e8e65c1c8dbd51fbb Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 Apr 2026 16:03:19 +0200 Subject: [PATCH 0272/1083] fix deteckt | unneeded paranthesis --- .../components/TimelineItemCallNotifyView.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index aa004a6259..c11aab08ff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -127,12 +127,12 @@ private fun getIcon( internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { listOf( - (aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.None)), - (aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None)), - (aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Declined)), - (aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined)), - (aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.DeclinedByMe)), - (aTimelineRoomInfo(isDm = false) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None)), + aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.None), + aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None), + aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Declined), + aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined), + aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.DeclinedByMe), + aTimelineRoomInfo(isDm = false) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None), ).forEach { (info, content) -> TimelineItemCallNotifyView( timelineRoomInfo = info, From 61548167967e18b4e217af6d75dff5bee13cf39b Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 Apr 2026 16:21:36 +0200 Subject: [PATCH 0273/1083] cleanup of the RTCNotificationState enum --- .../components/TimelineItemCallNotifyView.kt | 24 +++++++++---------- .../event/TimelineItemContentFactory.kt | 8 +++---- .../TimelineItemRtcNotificationContent.kt | 15 ++++-------- .../DefaultMessageSummaryFormatter.kt | 12 ++++++---- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index c11aab08ff..f4d0d97495 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -96,9 +96,10 @@ private fun getTextRes( content: TimelineItemRtcNotificationContent ): Int = if (timelineRoomInfo.isDm) { when (content.state) { - RtcNotificationState.Declined -> CommonStrings.common_call_declined - RtcNotificationState.DeclinedByMe -> CommonStrings.common_call_you_declined - RtcNotificationState.None -> CommonStrings.common_call_started + is RtcNotificationState.Declined -> { + if (content.state.byMe) CommonStrings.common_call_you_declined else CommonStrings.common_call_declined + } + RtcNotificationState.Started -> CommonStrings.common_call_started } } else { // Only show declined info in DMs @@ -110,10 +111,7 @@ private fun getIcon( timelineRoomInfo: TimelineRoomInfo, content: TimelineItemRtcNotificationContent ): ImageVector { - val showAsDeclined = timelineRoomInfo.isDm && ( - content.state == RtcNotificationState.Declined || - content.state == RtcNotificationState.DeclinedByMe - ) + val showAsDeclined = timelineRoomInfo.isDm && content.state is RtcNotificationState.Declined val icon = if (showAsDeclined) { if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallDeclinedSolid() else CompoundIcons.VideoCallDeclinedSolid() } else { @@ -127,12 +125,12 @@ private fun getIcon( internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { listOf( - aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.None), - aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None), - aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Declined), - aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined), - aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.DeclinedByMe), - aTimelineRoomInfo(isDm = false) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.None), + aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Started), + aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Started), + aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Declined(false)), + aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined(false)), + aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined(true)), + aTimelineRoomInfo(isDm = false) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Started), ).forEach { (info, content) -> TimelineItemCallNotifyView( timelineRoomInfo = info, 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 64320622ba..2d884d75fd 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 @@ -106,10 +106,10 @@ class TimelineItemContentFactory( is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent( callIntent = itemContent.callIntent, - state = when { - itemContent.declinedBy.isEmpty().not() && itemContent.declinedBy.any { it == sessionId } -> RtcNotificationState.DeclinedByMe - itemContent.declinedBy.isEmpty().not() -> RtcNotificationState.Declined - else -> RtcNotificationState.None + state = if (itemContent.declinedBy.isNotEmpty()) { + RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) + } else { + RtcNotificationState.Started } ) is UnknownContent -> TimelineItemUnknownContent diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index df1c9f5693..c09ccd1d21 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -11,17 +11,12 @@ package io.element.android.features.messages.impl.timeline.model.event import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.timeline.item.event.EventType -// For now this is just an enum, but could be a -// sealed class if we need the list of users who declined. -enum class RtcNotificationState { - /** Some users have declined */ - Declined, +// State of the call, for now only isDeclined but in the future could be missed, active. +sealed class RtcNotificationState { + /** Some users have declined, byMe indicates if the current user is one of them. */ + data class Declined(val byMe: Boolean) : RtcNotificationState() - /** I have declined this call */ - DeclinedByMe, - - // Future sates could be `Missed`? `ongoing`... - None + object Started : RtcNotificationState() } class TimelineItemRtcNotificationContent( 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 5437711bb7..210e123595 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt @@ -58,10 +58,14 @@ class DefaultMessageSummaryFormatter( is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio) is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call) is TimelineItemRtcNotificationContent -> when (content.state) { - RtcNotificationState.Declined -> - context.getString(CommonStrings.common_call_declined) - RtcNotificationState.DeclinedByMe -> context.getString(CommonStrings.common_call_you_declined) - RtcNotificationState.None -> context.getString(CommonStrings.common_call_started) + is RtcNotificationState.Declined -> { + if (content.state.byMe) { + context.getString(CommonStrings.common_call_you_declined) + } else { + context.getString(CommonStrings.common_call_declined) + } + } + RtcNotificationState.Started -> context.getString(CommonStrings.common_call_started) } } // Truncate the message to a safe length to avoid crashes in Compose From 531d9b3d47d61b1ba82230a477f654007979332d Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 Apr 2026 16:29:13 +0200 Subject: [PATCH 0274/1083] fix: consist, use sealed interface instead of class --- .../model/event/TimelineItemRtcNotificationContent.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index c09ccd1d21..2359f196a9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -12,11 +12,11 @@ import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.timeline.item.event.EventType // State of the call, for now only isDeclined but in the future could be missed, active. -sealed class RtcNotificationState { +sealed interface RtcNotificationState { /** Some users have declined, byMe indicates if the current user is one of them. */ - data class Declined(val byMe: Boolean) : RtcNotificationState() + data class Declined(val byMe: Boolean) : RtcNotificationState - object Started : RtcNotificationState() + object Started : RtcNotificationState } class TimelineItemRtcNotificationContent( From 66f68fdccb292d95425a0e1227dc61f06d836a23 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 29 Apr 2026 17:27:51 +0200 Subject: [PATCH 0275/1083] fixup test compilation --- .../messages/impl/actionlist/ActionListPresenterTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index 8c7f290441..20b636081a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -17,6 +17,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent @@ -1169,7 +1170,7 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, - content = TimelineItemRtcNotificationContent(callIntent = CallIntent.VIDEO), + content = TimelineItemRtcNotificationContent(callIntent = CallIntent.VIDEO, state = RtcNotificationState.Started), ) initialState.eventSink.invoke( ActionListEvent.ComputeForMessage( From 6ba4679908ae1a3c7b0f698c10fda649aff9f8a5 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Thu, 30 Apr 2026 00:08:33 +0800 Subject: [PATCH 0276/1083] Change native back button behavior in EC view (close settings in EC with os native back) (#6642) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change native back button behavior in EC view: - inject escape into webview instead of going back. - the webview will call back when no other modal is open. * call down and up in the webview + make sure that we fall back to close pip in case the webview did not handle the esc action. --------- Co-authored-by: Jorge Martín --- .../call/impl/ui/CallScreenBackPressPolicy.kt | 26 +++ .../features/call/impl/ui/CallScreenView.kt | 36 +++-- .../call/ui/CallScreenBackPressPolicyTest.kt | 96 +++++++++++ .../features/call/ui/CallScreenViewTest.kt | 150 ++++++++++++++++++ 4 files changed, 298 insertions(+), 10 deletions(-) create mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt new file mode 100644 index 0000000000..cd47cd8bb1 --- /dev/null +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.impl.ui +internal sealed interface CallScreenBackPressAction { + data object DispatchEscapeToWebView : CallScreenBackPressAction + data object EnterPictureInPicture : CallScreenBackPressAction +} + +internal object CallScreenBackPressPolicy { + fun resolve( + supportPip: Boolean, + hasWebView: Boolean, + fromNative: Boolean, + ): CallScreenBackPressAction? { + return when { + hasWebView && fromNative -> CallScreenBackPressAction.DispatchEscapeToWebView + hasWebView && supportPip -> CallScreenBackPressAction.EnterPictureInPicture + else -> null + } + } +} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index f8657a9ece..a54b726a78 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -64,11 +64,15 @@ internal fun CallScreenView( requestPermissions: (Array, RequestPermissionCallback) -> Unit, modifier: Modifier = Modifier, ) { - fun handleBack() { - if (pipState.supportPip) { - pipState.eventSink.invoke(PictureInPictureEvents.EnterPictureInPicture) - } else { - state.eventSink(CallScreenEvents.Hangup) + var callWebView by remember { mutableStateOf(null) } + + fun handleBack(fromNative: Boolean = false) { + when (CallScreenBackPressPolicy.resolve(supportPip = pipState.supportPip, hasWebView = callWebView != null, fromNative)) { + CallScreenBackPressAction.EnterPictureInPicture -> + pipState.eventSink(PictureInPictureEvents.EnterPictureInPicture) + CallScreenBackPressAction.DispatchEscapeToWebView -> + callWebView?.dispatchEscKeyEvent() + null -> Timber.d("Back press with unsupported pip is a no-op") } } @@ -76,7 +80,7 @@ internal fun CallScreenView( modifier = modifier, ) { padding -> BackHandler { - handleBack() + handleBack(fromNative = true) } if (state.webViewError != null) { ErrorDialog( @@ -111,6 +115,7 @@ internal fun CallScreenView( }, onConsoleMessage = onConsoleMessage, onCreateWebView = { webView -> + callWebView = webView webView.addBackHandler(onBackPressed = ::handleBack) val interceptor = WebViewWidgetMessageInterceptor( webView = webView, @@ -135,6 +140,7 @@ internal fun CallScreenView( pipState.eventSink(PictureInPictureEvents.SetPipController(pipController)) }, onDestroyWebView = { + callWebView = null // Reset audio mode webViewAudioManager?.onCallStopped() } @@ -143,6 +149,7 @@ internal fun CallScreenView( AsyncData.Uninitialized, is AsyncData.Loading -> ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait)) + is AsyncData.Failure -> { Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") ErrorDialog( @@ -150,6 +157,7 @@ internal fun CallScreenView( onSubmit = { state.eventSink(CallScreenEvents.Hangup) }, ) } + is AsyncData.Success -> Unit } } @@ -248,15 +256,18 @@ private fun WebView.setup( private fun WebView.addBackHandler(onBackPressed: () -> Unit) { addJavascriptInterface( - object { - @Suppress("unused") - @JavascriptInterface - fun onBackPressed() = onBackPressed() + JavascriptBackHandler { + onBackPressed() }, "backHandler" ) } +private fun WebView.dispatchEscKeyEvent() { + dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_ESCAPE)) + dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_ESCAPE)) +} + @PreviewsDayNight @Composable internal fun CallScreenViewPreview( @@ -275,3 +286,8 @@ internal fun CallScreenViewPreview( internal fun InvalidAudioDeviceDialogPreview() = ElementPreview { InvalidAudioDeviceDialog(invalidAudioDeviceReason = InvalidAudioDeviceReason.BT_AUDIO_DEVICE_DISABLED) {} } + +internal fun interface JavascriptBackHandler { + @JavascriptInterface + fun onBackPressed() +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt new file mode 100644 index 0000000000..f07f7039d3 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.ui + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.impl.ui.CallScreenBackPressAction +import io.element.android.features.call.impl.ui.CallScreenBackPressPolicy +import org.junit.Test + +class CallScreenBackPressPolicyTest { + @Test + fun `resolve returns dispatch escape when a web view is available and native button is pressed`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = true, + fromNative = true, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) + } + + @Test + fun `resolve dispatch escape when there is a web view and pip is supported on native button press`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = true, + fromNative = true, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) + } + + @Test + fun `resolve returns hangup when there is no web view and pip is not supported from native button`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = false, + fromNative = true, + ) + + assertThat(result).isNull() + } + + @Test + fun `resolve returns hangup when there is no web view even though pip is supported from native button`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = false, + fromNative = true, + ) + + assertThat(result).isNull() + } + + @Test + fun `resolve goes to pip if its not from native but from the webview`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = true, + fromNative = false, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.EnterPictureInPicture) + } + @Test + fun `resolve hangs up if its not from native but from the webview and pip is not supported`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = true, + fromNative = false, + ) + + assertThat(result).isNull() + } + + @Test + fun `invalid cases (event comes from webview but there is now webview) all result in hangup`() { + val withPipSupport = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = false, + fromNative = false, + ) + assertThat(withPipSupport).isNull() + val withOutPipSupport = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = false, + fromNative = false, + ) + assertThat(withOutPipSupport).isNull() + } +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt new file mode 100644 index 0000000000..35b90a6716 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.ui + +import android.view.KeyEvent +import android.webkit.WebView +import androidx.activity.ComponentActivity +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.call.impl.pip.PictureInPictureEvents +import io.element.android.features.call.impl.pip.aPictureInPictureState +import io.element.android.features.call.impl.ui.CallScreenEvents +import io.element.android.features.call.impl.ui.CallScreenView +import io.element.android.features.call.impl.ui.JavascriptBackHandler +import io.element.android.features.call.impl.ui.aCallScreenState +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.pressBackKey +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements +import org.robolectric.annotation.Resetter +import org.robolectric.shadows.ShadowWebView + +@RunWith(AndroidJUnit4::class) +class CallScreenViewTest { + @get:Rule + val rule = createAndroidComposeRule() + + @Test + fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() { + val callEvents = EventsRecorder() + + rule.setCallScreenView( + state = aCallScreenState(eventSink = callEvents), + useInspectionMode = true, + ) + + rule.pressBackKey() + + callEvents.assertEmpty() + } + + @Config(shadows = [RecordingShadowWebView::class]) + @Test + fun `pressing back key dispatches escape key events to web view when pip is unsupported`() { + rule.setCallScreenView( + state = aCallScreenState(), + useInspectionMode = false, + ) + + rule.pressBackKey() + + val dispatchedEvents = RecordingShadowWebView.dispatchedEvents + assertEquals(2, dispatchedEvents.size) + assertEquals(KeyEvent.ACTION_DOWN, dispatchedEvents[0].action) + assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[0].keyCode) + assertEquals(KeyEvent.ACTION_UP, dispatchedEvents[1].action) + assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[1].keyCode) + } + + @Config(shadows = [RecordingShadowWebView::class]) + @Test + fun `web view javascript back handler emits pip event when pip is supported`() { + val pipEvents = EventsRecorder() + + rule.setCallScreenView( + state = aCallScreenState(), + useInspectionMode = false, + pipState = aPictureInPictureState( + supportPip = true, + eventSink = pipEvents, + ), + ) + + rule.runOnIdle { + RecordingShadowWebView.invokeJavascriptBackHandler() + } + + pipEvents.assertSize(2) + pipEvents.assertTrue(0) { it is PictureInPictureEvents.SetPipController } + pipEvents.assertTrue(1) { it is PictureInPictureEvents.EnterPictureInPicture } + } +} + +private fun AndroidComposeTestRule.setCallScreenView( + state: io.element.android.features.call.impl.ui.CallScreenState, + useInspectionMode: Boolean, + pipState: io.element.android.features.call.impl.pip.PictureInPictureState = aPictureInPictureState(supportPip = false), +) { + setContent { + // Inspection mode disables AndroidView creation; keep it configurable per test. + CompositionLocalProvider(LocalInspectionMode provides useInspectionMode) { + CallScreenView( + state = state, + pipState = pipState, + onConsoleMessage = {}, + requestPermissions = { _, _ -> }, + ) + } + } +} + +@Implements(WebView::class) +internal class RecordingShadowWebView : ShadowWebView() { + companion object { + val dispatchedEvents = mutableListOf() + private var backHandlerJavascriptInterface: JavascriptBackHandler? = null + + @Resetter + @JvmStatic + @Suppress("unused") + fun resetRecordedEvents() { + dispatchedEvents.clear() + backHandlerJavascriptInterface = null + } + + fun invokeJavascriptBackHandler() { + val backHandler = checkNotNull(backHandlerJavascriptInterface) { "Expected backHandler JavaScript interface to be registered" } + backHandler.onBackPressed() + } + } + + @Implementation + protected override fun addJavascriptInterface(`object`: Any, name: String) { + super.addJavascriptInterface(`object`, name) + if (name == "backHandler") { + backHandlerJavascriptInterface = `object` as? JavascriptBackHandler + } + } + + @Implementation + @Suppress("unused") + fun dispatchKeyEvent(event: KeyEvent): Boolean { + dispatchedEvents += KeyEvent(event) + return false + } +} From 7940b8f86511d45e19ba1be4900d5ac708c6fecd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:11:36 +0000 Subject: [PATCH 0277/1083] Update dependency io.sentry:sentry-android to v8.40.0 --- 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 b942901e19..19b9c29468 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -222,7 +222,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.39.0" -sentry = "io.sentry:sentry-android:8.39.1" +sentry = "io.sentry:sentry-android:8.40.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From da36323006643ac0c59f87e6f699055cc2138caa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 20:27:57 +0000 Subject: [PATCH 0278/1083] Update dependency androidx.compose:compose-bom to v2026.04.01 --- 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 b942901e19..85cea1c436 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ camera = "1.6.0" work = "2.11.2" # Compose -compose_bom = "2026.03.01" +compose_bom = "2026.04.01" # Coroutines coroutines = "1.10.2" From a76b55e5808c4f8dcdcf7d6e000e14dbf029269d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 28 Apr 2026 17:55:56 +0200 Subject: [PATCH 0279/1083] Add a way to tweak MAS url. --- enterprise | 2 +- .../features/enterprise/api/EnterpriseService.kt | 1 + .../enterprise/api/SessionEnterpriseService.kt | 1 + .../enterprise/impl/DefaultEnterpriseService.kt | 2 +- .../enterprise/impl/DefaultSessionEnterpriseService.kt | 1 + .../features/enterprise/test/FakeEnterpriseService.kt | 5 +++++ .../enterprise/test/FakeSessionEnterpriseService.kt | 5 +++++ .../linknewdevice/impl/LinkNewDeviceFlowNode.kt | 10 ++++++++-- .../impl/DefaultLinkNewDeviceEntryPointTest.kt | 2 ++ .../preferences/impl/root/PreferencesRootPresenter.kt | 8 +++++++- .../impl/root/PreferencesRootPresenterTest.kt | 9 ++++++++- features/securebackup/impl/build.gradle.kts | 1 + .../securebackup/impl/reset/ResetIdentityFlowNode.kt | 5 ++++- libraries/matrix/impl/build.gradle.kts | 1 + .../impl/auth/RustMatrixAuthenticationService.kt | 8 ++++++++ .../libraries/wellknown/api/ElementWellKnown.kt | 1 + .../wellknown/impl/InternalElementWellKnown.kt | 2 ++ .../element/android/libraries/wellknown/impl/Mapper.kt | 1 + .../android/features/wellknown/test/Fixtures.kt | 2 ++ 19 files changed, 60 insertions(+), 7 deletions(-) diff --git a/enterprise b/enterprise index cdde60c158..1ed9a7e8b4 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit cdde60c158ecd0987a3ba6fd79a4617551aff463 +Subproject commit 1ed9a7e8b4406a5e6d12f603cfc2083e84f8576f diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt index 65fe3fe087..92d8b9b646 100644 --- a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.Flow interface EnterpriseService { val isEnterpriseBuild: Boolean suspend fun isEnterpriseUser(sessionId: SessionId): Boolean + suspend fun tweakMasUrl(url: String, homeserver: String): String fun defaultHomeserverList(): List suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String): Boolean diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/SessionEnterpriseService.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/SessionEnterpriseService.kt index 6bd6c78de5..f87dc743e8 100644 --- a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/SessionEnterpriseService.kt +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/SessionEnterpriseService.kt @@ -10,6 +10,7 @@ package io.element.android.features.enterprise.api interface SessionEnterpriseService { suspend fun isElementCallAvailable(): Boolean + suspend fun tweakMasUrl(url: String): String suspend fun init() } diff --git a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt index 932d082fd9..6e3ed5d3cc 100644 --- a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt +++ b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt @@ -23,7 +23,7 @@ class DefaultEnterpriseService : EnterpriseService { override val isEnterpriseBuild = false override suspend fun isEnterpriseUser(sessionId: SessionId) = false - + override suspend fun tweakMasUrl(url: String, homeserver: String) = url override fun defaultHomeserverList(): List = emptyList() override suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String) = true diff --git a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultSessionEnterpriseService.kt b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultSessionEnterpriseService.kt index 3441063a8a..9aafcd343c 100644 --- a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultSessionEnterpriseService.kt +++ b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultSessionEnterpriseService.kt @@ -15,5 +15,6 @@ import io.element.android.libraries.di.SessionScope @ContributesBinding(SessionScope::class) class DefaultSessionEnterpriseService : SessionEnterpriseService { override suspend fun init() = Unit + override suspend fun tweakMasUrl(url: String): String = url override suspend fun isElementCallAvailable(): Boolean = true } diff --git a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt index 3c17a4de7c..805c75be6a 100644 --- a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt +++ b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt @@ -30,6 +30,7 @@ class FakeEnterpriseService( private val firebasePushGatewayResult: () -> String? = { lambdaError() }, private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() }, + private val tweakMasUrlResult: (String, String) -> String = { _, _ -> lambdaError() }, ) : EnterpriseService { private val brandColorState = MutableStateFlow(initialBrandColor) private val semanticColorsState = MutableStateFlow(initialSemanticColors) @@ -38,6 +39,10 @@ class FakeEnterpriseService( isEnterpriseUserResult(sessionId) } + override suspend fun tweakMasUrl(url: String, homeserver: String): String = simulateLongTask { + tweakMasUrlResult(url, homeserver) + } + override fun defaultHomeserverList(): List { return defaultHomeserverListResult() } diff --git a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeSessionEnterpriseService.kt b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeSessionEnterpriseService.kt index 3914c60155..0bcad13033 100644 --- a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeSessionEnterpriseService.kt +++ b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeSessionEnterpriseService.kt @@ -14,10 +14,15 @@ import io.element.android.tests.testutils.simulateLongTask class FakeSessionEnterpriseService( private val isElementCallAvailableResult: () -> Boolean = { lambdaError() }, + private val tweakMasUrlResult: (String) -> String = { lambdaError() }, ) : SessionEnterpriseService { override suspend fun init() { } + override suspend fun tweakMasUrl(url: String): String = simulateLongTask { + tweakMasUrlResult(url) + } + override suspend fun isElementCallAvailable(): Boolean = simulateLongTask { isElementCallAvailableResult() } diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index 4ccdb6b387..9674d213f9 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -26,6 +26,7 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.compound.theme.ElementTheme +import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.linknewdevice.api.LinkNewDeviceEntryPoint import io.element.android.features.linknewdevice.impl.screens.confirmation.CodeConfirmationNode import io.element.android.features.linknewdevice.impl.screens.desktop.DesktopNoticeNode @@ -65,6 +66,7 @@ class LinkNewDeviceFlowNode( private val sessionCoroutineScope: CoroutineScope, private val linkNewMobileHandler: LinkNewMobileHandler, private val linkNewDesktopHandler: LinkNewDesktopHandler, + private val sessionEnterpriseService: SessionEnterpriseService, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Root, @@ -301,8 +303,12 @@ class LinkNewDeviceFlowNode( } } - private fun navigateToBrowser(url: String) { - activity?.openUrlInChromeCustomTab(null, darkTheme, url) + private suspend fun navigateToBrowser(url: String) { + activity?.openUrlInChromeCustomTab( + session = null, + darkTheme = darkTheme, + url = sessionEnterpriseService.tweakMasUrl(url), + ) } @Composable diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/DefaultLinkNewDeviceEntryPointTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/DefaultLinkNewDeviceEntryPointTest.kt index 2957a89495..1b2af8f4c3 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/DefaultLinkNewDeviceEntryPointTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/DefaultLinkNewDeviceEntryPointTest.kt @@ -11,6 +11,7 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.testing.junit4.util.MainDispatcherRule import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.linknewdevice.api.LinkNewDeviceEntryPoint import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.tests.testutils.lambda.lambdaError @@ -37,6 +38,7 @@ class DefaultLinkNewDeviceEntryPointTest { sessionCoroutineScope = backgroundScope, linkNewMobileHandler = LinkNewMobileHandler(client), linkNewDesktopHandler = LinkNewDesktopHandler(client), + sessionEnterpriseService = FakeSessionEnterpriseService(), ) } val callback: LinkNewDeviceEntryPoint.Callback = object : LinkNewDeviceEntryPoint.Callback { 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 43da681a37..f407149007 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 @@ -19,6 +19,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject +import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider import io.element.android.features.rageshake.api.RageshakeFeatureAvailability @@ -55,6 +56,7 @@ class PreferencesRootPresenter( private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, private val featureFlagService: FeatureFlagService, private val sessionStore: SessionStore, + private val sessionEnterpriseService: SessionEnterpriseService, ) : Presenter { @Composable override fun present(): PreferencesRootState { @@ -158,6 +160,10 @@ class PreferencesRootPresenter( private fun CoroutineScope.initAccountManagementUrl( accountManagementUrl: MutableState, ) = launch { - accountManagementUrl.value = matrixClient.getAccountManagementUrl(null).getOrNull() + accountManagementUrl.value = matrixClient.getAccountManagementUrl(null) + .getOrNull() + ?.let { + sessionEnterpriseService.tweakMasUrl(it) + } } } 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 d324f5eb3a..a6861be12d 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 @@ -12,6 +12,8 @@ package io.element.android.features.preferences.impl.root import app.cash.turbine.ReceiveTurbine import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.api.SessionEnterpriseService +import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.logout.api.direct.aDirectLogoutState import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider import io.element.android.features.rageshake.api.RageshakeFeatureAvailability @@ -65,6 +67,9 @@ class PreferencesRootPresenterTest { ) createPresenter( matrixClient = matrixClient, + sessionEnterpriseService = FakeSessionEnterpriseService( + tweakMasUrlResult = { "tweaked $it" }, + ), ).test { val initialState = awaitItem() assertThat(initialState.myUser).isEqualTo( @@ -100,7 +105,7 @@ class PreferencesRootPresenterTest { val finalState = awaitItem() accountManagementUrlResult.assertions().isCalledOnce() .with(value(null)) - assertThat(finalState.accountManagementUrl).isEqualTo("null url") + assertThat(finalState.accountManagementUrl).isEqualTo("tweaked null url") } } @@ -327,6 +332,7 @@ class PreferencesRootPresenterTest { indicatorService: IndicatorService = FakeIndicatorService(), featureFlagService: FeatureFlagService = FakeFeatureFlagService(), sessionStore: SessionStore = InMemorySessionStore(), + sessionEnterpriseService: SessionEnterpriseService = FakeSessionEnterpriseService(), ) = PreferencesRootPresenter( matrixClient = matrixClient, sessionVerificationService = sessionVerificationService, @@ -339,5 +345,6 @@ class PreferencesRootPresenterTest { rageshakeFeatureAvailability = rageshakeFeatureAvailability, featureFlagService = featureFlagService, sessionStore = sessionStore, + sessionEnterpriseService = sessionEnterpriseService, ) } diff --git a/features/securebackup/impl/build.gradle.kts b/features/securebackup/impl/build.gradle.kts index 82f30fa5ce..54d87ef22e 100644 --- a/features/securebackup/impl/build.gradle.kts +++ b/features/securebackup/impl/build.gradle.kts @@ -28,6 +28,7 @@ setupDependencyInjection() dependencies { implementation(projects.appconfig) + implementation(projects.features.enterprise.api) implementation(projects.libraries.core) implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt index 4e2284890f..7dd6bf632a 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/ResetIdentityFlowNode.kt @@ -25,6 +25,7 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.compound.theme.ElementTheme +import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.securebackup.impl.reset.password.ResetIdentityPasswordNode import io.element.android.features.securebackup.impl.reset.root.ResetIdentityRootNode import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab @@ -53,6 +54,7 @@ class ResetIdentityFlowNode( private val resetIdentityFlowManager: ResetIdentityFlowManager, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, + private val sessionEnterpriseService: SessionEnterpriseService, ) : BaseFlowNode( backstack = BackStack(initialElement = NavTarget.Root, savedStateMap = buildContext.savedStateMap), buildContext = buildContext, @@ -125,7 +127,8 @@ class ResetIdentityFlowNode( } is IdentityOAuthResetHandle -> { Timber.d("Launching reset confirmation in MAS") - activity.openUrlInChromeCustomTab(null, darkTheme, handle.url) + val url = sessionEnterpriseService.tweakMasUrl(handle.url) + activity.openUrlInChromeCustomTab(null, darkTheme, url) Timber.d("Starting resetOAuth") resetJob = launch { handle.resetOAuth() } resetJob?.invokeOnCompletion { Timber.d("resetOAuth ended") } diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 67386cc592..7dcc835781 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { implementation(projects.libraries.rustlsTls) implementation(projects.appconfig) + implementation(projects.features.enterprise.api) implementation(projects.libraries.androidutils) implementation(projects.libraries.di) implementation(projects.libraries.featureflag.api) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 79793e4e77..6cd30d4f70 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.impl.auth import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions @@ -66,6 +67,7 @@ class RustMatrixAuthenticationService( private val rustMatrixClientFactory: RustMatrixClientFactory, private val passphraseGenerator: PassphraseGenerator, private val oAuthConfigurationProvider: OAuthConfigurationProvider, + private val enterpriseService: EnterpriseService, ) : MatrixAuthenticationService { // Any existing Element Classic session that we want to try to import secrets from during login. private var elementClassicSession: ElementClassicSession? = null @@ -269,6 +271,12 @@ class RustMatrixAuthenticationService( additionalScopes = emptyList(), ) val url = oAuthAuthorizationData.loginUrl() + .let { + enterpriseService.tweakMasUrl( + url = it, + homeserver = client.server() ?: client.homeserver(), + ) + } pendingOAuthAuthorizationData = oAuthAuthorizationData OAuthDetails(url) }.mapFailure { failure -> diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt index 134a9bcdb5..4c1c476c7a 100644 --- a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt @@ -14,4 +14,5 @@ data class ElementWellKnown( val rageshakeUrl: String?, val brandColor: String?, val notificationSound: String?, + val identityProviderAppScheme: String?, ) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt index d4661d1be0..2e2b5de16f 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt @@ -32,4 +32,6 @@ data class InternalElementWellKnown( val brandColor: String? = null, @SerialName("notification_sound") val notificationSound: String? = null, + @SerialName("idp_app_scheme") + val identityProviderAppScheme: String? = null, ) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt index c7ca088e68..41ed54d7db 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt @@ -16,4 +16,5 @@ internal fun InternalElementWellKnown.map() = ElementWellKnown( rageshakeUrl = rageshakeUrl, brandColor = brandColor, notificationSound = notificationSound, + identityProviderAppScheme = identityProviderAppScheme, ) diff --git a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt index 7457aafc98..ae7d1c629c 100644 --- a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt +++ b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt @@ -16,10 +16,12 @@ fun anElementWellKnown( rageshakeUrl: String? = null, brandColor: String? = null, notificationSound: String? = null, + identityProviderAppScheme: String? = null, ) = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, enforceElementPro = enforceElementPro, rageshakeUrl = rageshakeUrl, brandColor = brandColor, notificationSound = notificationSound, + identityProviderAppScheme = identityProviderAppScheme, ) From c1e908a8e64e2699bc70a05265bdfd3122cfa876 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 09:19:41 +0200 Subject: [PATCH 0280/1083] Fix tests. --- libraries/matrix/impl/build.gradle.kts | 1 + .../matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt | 4 ++++ .../wellknown/impl/DefaultSessionWellknownRetrieverTest.kt | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 7dcc835781..32bbeb082a 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { implementation(libs.kotlinx.collections.immutable) testCommonDependencies(libs) + testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.preferences.test) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index bff2711bc5..7f422acfcf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -9,6 +9,8 @@ package io.element.android.libraries.matrix.impl.auth import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.libraries.matrix.impl.ClientBuilderProvider import io.element.android.libraries.matrix.impl.FakeClientBuilderProvider import io.element.android.libraries.matrix.impl.createRustMatrixClientFactory @@ -50,6 +52,7 @@ class RustMatrixAuthenticationServiceTest { private fun TestScope.createRustMatrixAuthenticationService( sessionStore: SessionStore = InMemorySessionStore(), clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(), + enterpriseService: EnterpriseService = FakeEnterpriseService(), ): RustMatrixAuthenticationService { val baseDirectory = File("/base") val cacheDirectory = File("/cache") @@ -68,6 +71,7 @@ class RustMatrixAuthenticationServiceTest { buildMeta = aBuildMeta(), oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), ), + enterpriseService = enterpriseService, ) } } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index faad139a36..8a230c0317 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -36,6 +36,7 @@ class DefaultSessionWellknownRetrieverTest { rageshakeUrl = null, brandColor = null, notificationSound = null, + identityProviderAppScheme = null, ) ) ) @@ -53,7 +54,8 @@ class DefaultSessionWellknownRetrieverTest { "enforce_element_pro": true, "rageshake_url": "a_rageshake_url", "brand_color": "#FF0000", - "notification_sound": "a_notification_sound.flac" + "notification_sound": "a_notification_sound.flac", + "idp_app_scheme": "an_app_scheme" }""".trimIndent().toByteArray() ) } @@ -66,6 +68,7 @@ class DefaultSessionWellknownRetrieverTest { rageshakeUrl = "a_rageshake_url", brandColor = "#FF0000", notificationSound = "a_notification_sound.flac", + identityProviderAppScheme = "an_app_scheme", ) ) ) @@ -93,6 +96,7 @@ class DefaultSessionWellknownRetrieverTest { rageshakeUrl = "a_rageshake_url", brandColor = null, notificationSound = null, + identityProviderAppScheme = null, ) ) ) From 29e0a08dd93e4df5d7fce4fbf456cab738b274c4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 16:39:07 +0200 Subject: [PATCH 0281/1083] Add a CacheStore module. --- libraries/cachestore/api/build.gradle.kts | 13 ++++ .../libraries/cachestore/api/CacheData.kt | 13 ++++ .../libraries/cachestore/api/CacheStore.kt | 14 ++++ libraries/cachestore/impl/build.gradle.kts | 48 +++++++++++++ .../cachestore/impl/CacheDataMapper.kt | 27 +++++++ .../cachestore/impl/DatabaseCacheStore.kt | 36 ++++++++++ .../cachestore/impl/di/CacheStoreModule.kt | 43 +++++++++++ .../impl/src/main/sqldelight/databases/1.db | Bin 0 -> 12288 bytes .../android/libraries/cachestore/CacheData.sq | 26 +++++++ .../impl/DatabaseCacheStoreTest.kt | 68 ++++++++++++++++++ .../libraries/sessionstorage/impl/Fixtures.kt | 21 ++++++ libraries/cachestore/test/build.gradle.kts | 17 +++++ .../sessionstorage/test/CacheData.kt | 18 +++++ .../sessionstorage/test/InMemoryCacheStore.kt | 29 ++++++++ .../kotlin/extension/DependencyHandleScope.kt | 1 + 15 files changed, 374 insertions(+) create mode 100644 libraries/cachestore/api/build.gradle.kts create mode 100644 libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheData.kt create mode 100644 libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt create mode 100644 libraries/cachestore/impl/build.gradle.kts create mode 100644 libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt create mode 100644 libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt create mode 100644 libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt create mode 100644 libraries/cachestore/impl/src/main/sqldelight/databases/1.db create mode 100644 libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq create mode 100644 libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt create mode 100644 libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/Fixtures.kt create mode 100644 libraries/cachestore/test/build.gradle.kts create mode 100644 libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/CacheData.kt create mode 100644 libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt diff --git a/libraries/cachestore/api/build.gradle.kts b/libraries/cachestore/api/build.gradle.kts new file mode 100644 index 0000000000..0e03bb5136 --- /dev/null +++ b/libraries/cachestore/api/build.gradle.kts @@ -0,0 +1,13 @@ +/* + * 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. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.cachestore.api" +} diff --git a/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheData.kt b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheData.kt new file mode 100644 index 0000000000..a448ba7df8 --- /dev/null +++ b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheData.kt @@ -0,0 +1,13 @@ +/* + * 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.cachestore.api + +data class CacheData( + val value: String, + val updatedAt: Long, +) diff --git a/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt new file mode 100644 index 0000000000..f16a663ed7 --- /dev/null +++ b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.cachestore.api + +interface CacheStore { + suspend fun storeData(key: String, data: CacheData) + suspend fun getData(key: String): CacheData? + suspend fun deleteData(key: String) +} diff --git a/libraries/cachestore/impl/build.gradle.kts b/libraries/cachestore/impl/build.gradle.kts new file mode 100644 index 0000000000..f0c7ba237c --- /dev/null +++ b/libraries/cachestore/impl/build.gradle.kts @@ -0,0 +1,48 @@ +import extension.setupDependencyInjection +import extension.testCommonDependencies + +/* + * 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. + */ +plugins { + id("io.element.android-library") + alias(libs.plugins.sqldelight) +} + +android { + namespace = "io.element.android.libraries.cachestore.impl" +} + +setupDependencyInjection() + +dependencies { + implementation(projects.libraries.androidutils) + implementation(projects.libraries.core) + implementation(projects.libraries.encryptedDb) + api(projects.libraries.cachestore.api) + implementation(libs.sqldelight.driver.android) + implementation(libs.sqlcipher) + implementation(libs.sqlite) + implementation(projects.libraries.di) + implementation(libs.sqldelight.coroutines) + + testCommonDependencies(libs) + testImplementation(libs.sqldelight.driver.jvm) +} + +sqldelight { + databases { + create("CacheDatabase") { + // https://sqldelight.github.io/sqldelight/2.1.0/android_sqlite/migrations/ + // To generate a .db file from your latest schema, run this task + // ./gradlew generateDebugCacheDatabaseSchema + // Test migration by running + // ./gradlew verifySqlDelightMigration + schemaOutputDirectory = File("src/main/sqldelight/databases") + verifyMigrations = true + } + } +} diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt new file mode 100644 index 0000000000..7e67b6de72 --- /dev/null +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.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.cachestore.impl + +import io.element.android.libraries.cachestore.api.CacheData +import java.util.Date +import io.element.android.libraries.cachestore.CacheData as DbCacheData + +internal fun CacheData.toDbModel(key: String): DbCacheData { + return DbCacheData( + key = key, + value_ = value, + updatedAt = updatedAt.time, + ) +} + +internal fun DbCacheData.toApiModel(): CacheData { + return CacheData( + value = value_, + updatedAt = Date(updatedAt), + ) +} diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt new file mode 100644 index 0000000000..126387da11 --- /dev/null +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt @@ -0,0 +1,36 @@ +/* + * 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.cachestore.impl + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.cachestore.api.CacheData +import io.element.android.libraries.cachestore.api.CacheStore + +@SingleIn(AppScope::class) +@ContributesBinding(AppScope::class) +class DatabaseCacheStore( + private val database: CacheDatabase, +) : CacheStore { + override suspend fun getData(key: String): CacheData? { + return database.cacheDataQueries.selectData(key) + .executeAsOneOrNull() + ?.toApiModel() + } + + override suspend fun storeData(key: String, data: CacheData) { + database.cacheDataQueries.insertData( + data.toDbModel(key) + ) + } + + override suspend fun deleteData(key: String) { + database.cacheDataQueries.deleteData(key) + } +} diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt new file mode 100644 index 0000000000..05fa3d9d97 --- /dev/null +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.cachestore.impl.di + +import android.content.Context +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.BindingContainer +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.cachestore.impl.CacheDatabase +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.encrypteddb.SqlCipherDriverFactory +import io.element.encrypteddb.passphrase.RandomSecretPassphraseProvider + +@BindingContainer +@ContributesTo(AppScope::class) +object CacheStoreModule { + @Provides + @SingleIn(AppScope::class) + fun provideCacheDatabase( + @ApplicationContext context: Context, + ): CacheDatabase { + val name = "cache_database" + val secretFile = context.getDatabasePath("$name.key") + + // Make sure the parent directory of the key file exists, otherwise it will crash in older Android versions + val parentDir = secretFile.parentFile + if (parentDir != null && !parentDir.exists()) { + parentDir.mkdirs() + } + + val passphraseProvider = RandomSecretPassphraseProvider(context, secretFile) + val driver = SqlCipherDriverFactory(passphraseProvider) + .create(CacheDatabase.Schema, "$name.db", context) + return CacheDatabase(driver) + } +} diff --git a/libraries/cachestore/impl/src/main/sqldelight/databases/1.db b/libraries/cachestore/impl/src/main/sqldelight/databases/1.db new file mode 100644 index 0000000000000000000000000000000000000000..8e4b0cac72d8a31cf1c7038ebce700b66768eaa2 GIT binary patch literal 12288 zcmeI#&r8EF6bJC6ib`R02Vuv);{+)T{{ia^GOU}{2<}v(jX12%AL-QN{s8|h|0ltV zNo4^~I|}3b;H7y@TAEK!@BA#A7)>|R=X+&nkF^=+Y@diR#%-?IT!gFF7lpmLdRcIm ze0;Z}FBU`zi<0Pb*#lUI00bZa0SG_<0uX=z1Rwwb2>idme4B4};+W50jk>CIUtQno zLuHho1pQp3Qjkm!GC}?}bwjdor{776OG(3#&5JCf(|mA}=3_b*gQ5Rl)!&PAK>z{}fB*y_009U<00Izz00bI= EA429uc>n+a literal 0 HcmV?d00001 diff --git a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq new file mode 100644 index 0000000000..4683d9aa7d --- /dev/null +++ b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq @@ -0,0 +1,26 @@ +-------------------------------------------------------------------- +-- Current version of the DB is the highest value of filename +-- in the folder `sqldelight/databases`. +-- +-- When upgrading the schema, you have to create a file .sqm in the +-- `sqldelight/databases` folder and run the following task to +-- generate a .db file using the latest schema +-- > ./gradlew generateDebugCacheDatabaseSchema +-------------------------------------------------------------------- + +CREATE TABLE CacheData ( + key TEXT NOT NULL PRIMARY KEY, + value TEXT NOT NULL, + updatedAt INTEGER NOT NULL +); + + +selectData: +SELECT * FROM CacheData WHERE key = ?; + +-- insert or update data by key +insertData: +INSERT INTO CacheData VALUES ? ON CONFLICT(key) DO UPDATE SET value = excluded.value, updatedAt = excluded.updatedAt; + +deleteData: +DELETE FROM CacheData WHERE key = ?; diff --git a/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt new file mode 100644 index 0000000000..a2216daa06 --- /dev/null +++ b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt @@ -0,0 +1,68 @@ +/* + * 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.sessionstorage.impl + +import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.cachestore.api.CacheData +import io.element.android.libraries.cachestore.impl.CacheDatabase +import io.element.android.libraries.cachestore.impl.DatabaseCacheStore +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import io.element.android.libraries.cachestore.CacheData as DbCacheData + +private const val A_KEY = "aKey" +private const val A_DATA_1 = "aData1" +private const val A_DATA_2 = "aData2" + +class DatabaseCacheStoreTest { + private lateinit var database: CacheDatabase + private lateinit var databaseCacheStore: DatabaseCacheStore + + @OptIn(ExperimentalCoroutinesApi::class) + @Before + fun setup() { + // Initialise in memory SQLite driver + val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) + CacheDatabase.Schema.create(driver) + + database = CacheDatabase(driver) + databaseCacheStore = DatabaseCacheStore( + database = database, + ) + } + + @Test + fun `storeData persists the CacheData into the DB, deleteData deletes it`() = runTest { + // Assert that no data is stored for the key + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() + // Store data + databaseCacheStore.storeData(A_KEY, CacheData(A_DATA_1, 1)) + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isEqualTo( + DbCacheData( + key = A_KEY, + value_ = A_DATA_1, + updatedAt = 1, + ) + ) + // Update data + databaseCacheStore.storeData(A_KEY, CacheData(A_DATA_2, 2)) + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isEqualTo( + DbCacheData( + key = A_KEY, + value_ = A_DATA_2, + updatedAt = 2, + ) + ) + // Delete data + databaseCacheStore.deleteData(A_KEY) + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() + } +} diff --git a/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/Fixtures.kt b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/Fixtures.kt new file mode 100644 index 0000000000..3dca9efaf3 --- /dev/null +++ b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/Fixtures.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.sessionstorage.impl + +import io.element.android.libraries.cachestore.CacheData +import java.util.Date + +internal fun aCacheData( + key: String = "aKey", + value: String = "aValue", + updatedAt: Date = Date(), +) = CacheData( + key = key, + value_ = value, + updatedAt = updatedAt.time, +) diff --git a/libraries/cachestore/test/build.gradle.kts b/libraries/cachestore/test/build.gradle.kts new file mode 100644 index 0000000000..7ad2ac48d9 --- /dev/null +++ b/libraries/cachestore/test/build.gradle.kts @@ -0,0 +1,17 @@ +/* + * 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. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.cachestore.test" +} + +dependencies { + implementation(projects.libraries.cachestore.api) +} diff --git a/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/CacheData.kt b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/CacheData.kt new file mode 100644 index 0000000000..30633e8ff9 --- /dev/null +++ b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/CacheData.kt @@ -0,0 +1,18 @@ +/* + * 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.sessionstorage.test + +import io.element.android.libraries.cachestore.api.CacheData + +fun aCacheData( + value: String = "aValue", + updatedAt: Long = 0, +) = CacheData( + value = value, + updatedAt = updatedAt, +) diff --git a/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt new file mode 100644 index 0000000000..b0f77062ba --- /dev/null +++ b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt @@ -0,0 +1,29 @@ +/* + * 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.sessionstorage.test + +import io.element.android.libraries.cachestore.api.CacheData +import io.element.android.libraries.cachestore.api.CacheStore + +class InMemoryCacheStore( + initialData: Map = emptyMap(), +) : CacheStore { + val dataMap = initialData.toMutableMap() + + override suspend fun storeData(key: String, data: CacheData) { + dataMap[key] = data + } + + override suspend fun getData(key: String): CacheData? { + return dataMap[key] + } + + override suspend fun deleteData(key: String) { + dataMap.remove(key) + } +} diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index f832136083..3e01ffc25f 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -104,6 +104,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:architecture")) implementation(project(":libraries:dateformatter:impl")) implementation(project(":libraries:di")) + implementation(project(":libraries:cachestore:impl")) implementation(project(":libraries:session-storage:impl")) implementation(project(":libraries:mediapickers:impl")) implementation(project(":libraries:mediaupload:impl")) From 8512279d9619d97370984e1dd426cee5d6e0e2ed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 22:05:14 +0200 Subject: [PATCH 0282/1083] Add a cache for Element .well-known file. --- libraries/wellknown/impl/build.gradle.kts | 4 + .../impl/DefaultSessionWellknownRetriever.kt | 48 ++++++- .../DefaultSessionWellknownRetrieverTest.kt | 132 ++++++++++++++++-- 3 files changed, 173 insertions(+), 11 deletions(-) diff --git a/libraries/wellknown/impl/build.gradle.kts b/libraries/wellknown/impl/build.gradle.kts index f803eeec3c..1e2c4d7d61 100644 --- a/libraries/wellknown/impl/build.gradle.kts +++ b/libraries/wellknown/impl/build.gradle.kts @@ -33,9 +33,13 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.network) + implementation(projects.libraries.cachestore.api) + implementation(projects.services.toolbox.api) testCommonDependencies(libs) testImplementation(libs.coroutines.core) + testImplementation(projects.libraries.cachestore.test) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.wellknown.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt index 3bcf9bf573..a0223e93cc 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt @@ -10,29 +10,70 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.libraries.cachestore.api.CacheData +import io.element.android.libraries.cachestore.api.CacheStore import io.element.android.libraries.core.extensions.mapCatchingExceptions import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.SessionWellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.services.toolbox.api.systemclock.SystemClock +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import timber.log.Timber @ContributesBinding(SessionScope::class) class DefaultSessionWellknownRetriever( private val matrixClient: MatrixClient, private val json: JsonProvider, + private val cacheStore: CacheStore, + private val systemClock: SystemClock, + @SessionCoroutineScope + private val sessionCoroutineScope: CoroutineScope, ) : SessionWellknownRetriever { private val domain by lazy { matrixClient.userIdServerName() } override suspend fun getElementWellKnown(): WellknownRetrieverResult { val url = "https://$domain/.well-known/element/element.json" + val cacheData = cacheStore.getData(url) + if (cacheData != null) { + Timber.d("Element .well-known data retrieved from cache for $domain") + // If the cache is outdated, trigger a refresh in background but still return the cached value + if (systemClock.epochMillis() > cacheData.updatedAt + CACHE_VALIDITY_MILLIS) { + sessionCoroutineScope.launch { + fetchElementWellKnown(url) + } + } + try { + val parsed = json().decodeFromString(cacheData.value).map() + return WellknownRetrieverResult.Success(parsed) + } catch (e: Exception) { + Timber.e(e, "Failed to parse cached Element .well-known data for $domain, deleting cache") + cacheStore.deleteData(url) + } + } + + return fetchElementWellKnown(url) + } + + private suspend fun fetchElementWellKnown(url: String): WellknownRetrieverResult { return matrixClient .getUrl(url) .mapCatchingExceptions { val data = String(it) - json().decodeFromString(data).map() + val parsed = json().decodeFromString(data).map() + // Also store in cache, if valid + cacheStore.storeData( + key = url, + data = CacheData( + value = data, + updatedAt = systemClock.epochMillis(), + ) + ) + parsed } .toWellknownRetrieverResult() } @@ -51,4 +92,9 @@ class DefaultSessionWellknownRetriever( } } ) + + companion object { + // 1 day + private const val CACHE_VALIDITY_MILLIS = 1 * 24 * 60 * 60 * 1000L + } } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index 8a230c0317..2824a7e112 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -6,16 +6,30 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.element.android.libraries.wellknown.impl import com.google.common.truth.Truth.assertThat +import io.element.android.features.wellknown.test.anElementWellKnown import io.element.android.libraries.androidutils.json.DefaultJsonProvider +import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.libraries.cachestore.api.CacheData +import io.element.android.libraries.cachestore.api.CacheStore import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.services.toolbox.api.systemclock.SystemClock +import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -49,14 +63,7 @@ class DefaultSessionWellknownRetrieverTest { val sut = createDefaultSessionWellknownRetriever( getUrlLambda = { Result.success( - """{ - "registration_helper_url": "a_registration_url", - "enforce_element_pro": true, - "rageshake_url": "a_rageshake_url", - "brand_color": "#FF0000", - "notification_sound": "a_notification_sound.flac", - "idp_app_scheme": "an_app_scheme" - }""".trimIndent().toByteArray() + WELLKNOWN_CONTENT.toByteArray() ) } ) @@ -127,13 +134,118 @@ class DefaultSessionWellknownRetrieverTest { assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) } - private fun createDefaultSessionWellknownRetriever( + @Test + fun `get element wellknown hitting cache`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { lambdaError() }, + cacheStore = InMemoryCacheStore( + initialData = mapOf( + WELLKNOWN_URL to CacheData( + value = WELLKNOWN_CONTENT, + updatedAt = A_FAKE_TIMESTAMP, + ) + ) + ) + ) + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success( + ElementWellKnown( + registrationHelperUrl = "a_registration_url", + enforceElementPro = true, + rageshakeUrl = "a_rageshake_url", + brandColor = "#FF0000", + notificationSound = "a_notification_sound.flac", + identityProviderAppScheme = "an_app_scheme", + ) + ) + ) + } + + @Test + fun `get element wellknown hitting cache containing invalid json`() = runTest { + val cacheStore = InMemoryCacheStore( + initialData = mapOf( + WELLKNOWN_URL to CacheData( + value = WELLKNOWN_CONTENT, + updatedAt = A_FAKE_TIMESTAMP, + ) + ) + ) + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.success("{}".toByteArray()) + }, + cacheStore = cacheStore, + jsonProvider = JsonProvider { throw Exception("Failed to parse JSON") } + ) + assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) + // Ensure that the cache is deleted after the failure to parse it + assertThat(cacheStore.dataMap).isEmpty() + } + + @Test + fun `get element wellknown hitting outdated cache`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.success("{}".toByteArray()) + }, + cacheStore = InMemoryCacheStore( + initialData = mapOf( + WELLKNOWN_URL to CacheData( + value = WELLKNOWN_CONTENT, + updatedAt = 0L, + ) + ), + ), + // 3 days later, so the cache is outdated + systemClock = FakeSystemClock(3 * 24 * 60 * 60 * 1000L) + ) + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success( + ElementWellKnown( + registrationHelperUrl = "a_registration_url", + enforceElementPro = true, + rageshakeUrl = "a_rageshake_url", + brandColor = "#FF0000", + notificationSound = "a_notification_sound.flac", + identityProviderAppScheme = "an_app_scheme", + ) + ) + ) + // Next call returns the updated value + runCurrent() + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success( + anElementWellKnown() + ) + ) + } + + private fun TestScope.createDefaultSessionWellknownRetriever( getUrlLambda: (String) -> Result, + jsonProvider: JsonProvider = DefaultJsonProvider(), + cacheStore: CacheStore = InMemoryCacheStore(), + systemClock: SystemClock = FakeSystemClock(), ) = DefaultSessionWellknownRetriever( matrixClient = FakeMatrixClient( userIdServerNameLambda = { "user.domain.org" }, getUrlLambda = getUrlLambda, ), - json = DefaultJsonProvider(), + json = jsonProvider, + cacheStore = cacheStore, + systemClock = systemClock, + sessionCoroutineScope = backgroundScope, ) + + companion object { + private const val WELLKNOWN_URL = "https://user.domain.org/.well-known/element/element.json" + private const val WELLKNOWN_CONTENT = """{ + "registration_helper_url": "a_registration_url", + "enforce_element_pro": true, + "rageshake_url": "a_rageshake_url", + "brand_color": "#FF0000", + "notification_sound": "a_notification_sound.flac", + "idp_app_scheme": "an_app_scheme" + }""" + } } From 35a3a0ba063cf85f1cbe3bc4d0b1a8d8955c0066 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 22:43:42 +0200 Subject: [PATCH 0283/1083] Fix compilation issue. --- .../android/libraries/cachestore/impl/CacheDataMapper.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt index 7e67b6de72..2a33ce4fda 100644 --- a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/CacheDataMapper.kt @@ -8,20 +8,19 @@ package io.element.android.libraries.cachestore.impl import io.element.android.libraries.cachestore.api.CacheData -import java.util.Date import io.element.android.libraries.cachestore.CacheData as DbCacheData internal fun CacheData.toDbModel(key: String): DbCacheData { return DbCacheData( key = key, value_ = value, - updatedAt = updatedAt.time, + updatedAt = updatedAt, ) } internal fun DbCacheData.toApiModel(): CacheData { return CacheData( value = value_, - updatedAt = Date(updatedAt), + updatedAt = updatedAt, ) } From 3dd2a60b3a1994a6dbd8f246460604bb71ba08e2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 29 Apr 2026 22:51:54 +0200 Subject: [PATCH 0284/1083] Do not use generic Exception --- .../wellknown/impl/DefaultSessionWellknownRetrieverTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index 2824a7e112..5b1cebd6cf 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -176,7 +176,7 @@ class DefaultSessionWellknownRetrieverTest { Result.success("{}".toByteArray()) }, cacheStore = cacheStore, - jsonProvider = JsonProvider { throw Exception("Failed to parse JSON") } + jsonProvider = JsonProvider { error("Failed to parse JSON") } ) assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) // Ensure that the cache is deleted after the failure to parse it From 7f5ce768600b65eb54213435e5f954962537ae23 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Wed, 29 Apr 2026 15:41:05 -0700 Subject: [PATCH 0285/1083] Feature: add jump to unread button with badge count --- .../features/messages/impl/MessagesView.kt | 38 ++- .../impl/timeline/TimelinePresenter.kt | 72 ++++- .../messages/impl/timeline/TimelineState.kt | 4 + .../impl/timeline/TimelineStateProvider.kt | 16 + .../messages/impl/timeline/TimelineView.kt | 203 ++++++++++-- .../model/event/TimelineItemEventContent.kt | 22 ++ .../impl/timeline/TimelinePresenterTest.kt | 302 ++++++++++++++++++ .../libraries/featureflag/api/FeatureFlags.kt | 7 + .../src/main/res/values/temporary.xml | 5 + .../tests/konsist/KonsistPreviewTest.kt | 2 + 10 files changed, 634 insertions(+), 37 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 5a0b14b820..4ffbaed4dc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -500,7 +500,10 @@ private fun MessagesViewContent( pinnedMessagesCount = (state.pinnedMessagesBannerState as? PinnedMessagesBannerState.Visible)?.pinnedMessagesCount() ?: 0, ) val density = LocalDensity.current - var pinnedBannerHeightDp by remember { mutableStateOf(0.dp) } + // Combined height of every banner overlaid above the timeline (pinned messages, + // knock requests). Used to push both the floating date badge and the jump-to-unread + // FAB below any banner that's currently showing. + var topBannersHeightDp by remember { mutableStateOf(0.dp) } TimelineView( state = state.timelineState, @@ -516,28 +519,31 @@ private fun MessagesViewContent( onReadReceiptClick = onReadReceiptClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, nestedScrollConnection = scrollBehavior.nestedScrollConnection, - floatingDateTopOffset = pinnedBannerHeightDp, + floatingDateTopOffset = topBannersHeightDp, ) if (state.timelineState.timelineMode !is Timeline.Mode.Thread) { - AnimatedVisibility( - visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, - modifier = Modifier.onSizeChanged { pinnedBannerHeightDp = with(density) { it.height.toDp() } }, - enter = expandVertically(), - exit = shrinkVertically(), + Column( + modifier = Modifier.onSizeChanged { topBannersHeightDp = with(density) { it.height.toDp() } }, ) { - fun focusOnPinnedEvent(eventId: EventId) { - state.timelineState.eventSink( - TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + AnimatedVisibility( + visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, + enter = expandVertically(), + exit = shrinkVertically(), + ) { + fun focusOnPinnedEvent(eventId: EventId) { + state.timelineState.eventSink( + TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + ) + } + PinnedMessagesBannerView( + state = state.pinnedMessagesBannerState, + onClick = ::focusOnPinnedEvent, + onViewAllClick = onViewAllPinnedMessagesClick, ) } - PinnedMessagesBannerView( - state = state.pinnedMessagesBannerState, - onClick = ::focusOnPinnedEvent, - onViewAllClick = onViewAllPinnedMessagesClick, - ) + knockRequestsBannerView() } - knockRequestsBannerView() } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index edd8d446dc..82f7717a8d 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 @@ -10,16 +10,19 @@ package io.element.android.features.messages.impl.timeline import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableIntState import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.Snapshot import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject @@ -32,6 +35,8 @@ import io.element.android.features.messages.impl.timeline.factories.TimelineItem import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactoryConfig import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.isMessageContent +import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemTypingNotificationModel import io.element.android.features.messages.impl.typing.TypingNotificationState import io.element.android.features.messages.impl.userEventPermissions @@ -133,6 +138,7 @@ class TimelinePresenter( val prevMostRecentItemId = rememberSaveable { mutableStateOf(null) } val newEventState = remember { mutableStateOf(NewEventState.None) } + val newMessagesCount = remember { mutableIntStateOf(0) } val messageShieldDialogData: MutableState = remember { mutableStateOf(null) } val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() @@ -152,6 +158,9 @@ class TimelinePresenter( val displayFloatingDateBadge by produceState(false) { value = featureFlagService.isFeatureEnabled(FeatureFlags.FloatingDateBadge) } + val displayJumpToUnread by produceState(false) { + value = featureFlagService.isFeatureEnabled(FeatureFlags.JumpToUnread) + } fun handleEvent(event: TimelineEvent) { when (event) { @@ -168,6 +177,7 @@ class TimelinePresenter( if (isLive) { if (event.firstIndex == 0) { newEventState.value = NewEventState.None + newMessagesCount.intValue = 0 } Timber.tag(tag).d("## sendReadReceiptIfNeeded firstVisibleIndex: ${event.firstIndex}") sessionCoroutineScope.sendReadReceiptIfNeeded( @@ -268,7 +278,39 @@ class TimelinePresenter( } LaunchedEffect(timelineItems.size) { - computeNewItemState(timelineItems, prevMostRecentItemId, newEventState) + computeNewItemState(timelineItems, prevMostRecentItemId, newEventState, newMessagesCount) + } + + // Read marker position + unread count, scanned off the main thread. The UI gates display via + // [displayJumpToUnread]; the values are always computed so the state stays up to date if the + // feature flag flips at runtime. + val readMarkerIndex = remember { mutableIntStateOf(-1) } + val unreadMessagesCount = remember { mutableIntStateOf(0) } + LaunchedEffect(timelineItems) { + val items = timelineItems + withContext(dispatchers.computation) { + var markerIdx = -1 + var unread = 0 + for ((i, item) in items.withIndex()) { + if ((item as? TimelineItem.Virtual)?.model is TimelineItemReadMarkerModel) { + markerIdx = i + break + } + if (item is TimelineItem.Event && + !item.isMine && + item.origin != TimelineItemEventOrigin.PAGINATION && + item.content.isMessageContent() + ) { + unread++ + } + } + // Apply both writes atomically so consumers never see a half-updated pair + // (e.g. a non-negative markerIdx with the previous unread count). + Snapshot.withMutableSnapshot { + readMarkerIndex.intValue = markerIdx + unreadMessagesCount.intValue = if (markerIdx < 0) 0 else unread + } + } } LaunchedEffect(timelineItems.size, focusRequestState.value) { @@ -320,6 +362,10 @@ class TimelinePresenter( resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, + displayJumpToUnread = displayJumpToUnread, + readMarkerIndex = readMarkerIndex.intValue, + unreadMessagesCount = unreadMessagesCount.intValue, + newMessagesCount = newMessagesCount.intValue, eventSink = ::handleEvent, ) } @@ -377,11 +423,17 @@ class TimelinePresenter( * This method compute the hasNewItem state passed as a [MutableState] each time the timeline items size changes. * Basically, if we got new timeline event from sync or local, either from us or another user, we update the state so we tell we have new items. * The state never goes back to None from this method, but need to be reset from somewhere else. + * + * It also maintains [newMessagesCount], counting how many incoming messages from other users have arrived in + * each batch since [prevMostRecentItemId] — this drives the badge on the scroll-to-bottom button. The count is + * reset to zero when the most recent event is from the local user (they're back to active engagement); the + * scroll-finish handler resets it when the user returns to the bottom of the timeline. */ private suspend fun computeNewItemState( timelineItems: ImmutableList, prevMostRecentItemId: MutableState, - newEventState: MutableState + newEventState: MutableState, + newMessagesCount: MutableIntState, ) = withContext(dispatchers.computation) { // FromMe is prioritized over FromOther, so skip if we already have a FromMe if (newEventState.value == NewEventState.FromMe) { @@ -406,6 +458,22 @@ class TimelinePresenter( } else { NewEventState.FromOther } + if (fromMe) { + newMessagesCount.intValue = 0 + } else { + var delta = 0 + for (item in timelineItems) { + if (item.identifier() == prevMostRecentItemIdValue) break + if (item is TimelineItem.Event && + item.origin != TimelineItemEventOrigin.PAGINATION && + !item.isMine && + item.content.isMessageContent() + ) { + delta++ + } + } + newMessagesCount.intValue += delta + } } prevMostRecentItemId.value = newMostRecentItemId } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 1869ad6906..ccd4d44ea8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -35,6 +35,10 @@ data class TimelineState( val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val displayThreadSummaries: Boolean, val displayFloatingDateBadge: Boolean, + val displayJumpToUnread: Boolean, + val readMarkerIndex: Int, + val unreadMessagesCount: Int, + val newMessagesCount: Int, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 9840ac5107..e30eb1be97 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -23,6 +23,7 @@ import io.element.android.features.messages.impl.timeline.model.anAggregatedReac import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel import io.element.android.features.messages.impl.typing.TypingNotificationState import io.element.android.features.messages.impl.typing.aTypingNotificationState @@ -57,6 +58,10 @@ fun aTimelineState( resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), displayThreadSummaries: Boolean = false, displayFloatingDateBadge: Boolean = false, + displayJumpToUnread: Boolean = true, + readMarkerIndex: Int = -1, + unreadMessagesCount: Int = 0, + newMessagesCount: Int = 0, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId @@ -77,10 +82,21 @@ fun aTimelineState( resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, + displayJumpToUnread = displayJumpToUnread, + readMarkerIndex = readMarkerIndex, + unreadMessagesCount = unreadMessagesCount, + newMessagesCount = newMessagesCount, eventSink = eventSink, ) } +internal fun aTimelineItemReadMarker(): TimelineItem.Virtual { + return TimelineItem.Virtual( + id = UniqueId(UUID.randomUUID().toString()), + model = TimelineItemReadMarkerModel, + ) +} + internal fun aTimelineItemList(content: TimelineItemEventContent): ImmutableList { return persistentListOf( // 3 items (First Middle Last) with isMine = false diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 2105cf9df7..8c7d890d2f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -14,10 +14,14 @@ import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut +import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -39,15 +43,18 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.rememberNestedScrollInteropConnection +import androidx.compose.ui.res.pluralStringResource 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 androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -70,15 +77,18 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.FloatingActionButton import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag +import io.element.android.libraries.ui.strings.CommonPlurals import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.time.isTalkbackActive import io.element.android.wysiwyg.link.Link +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine @@ -106,6 +116,7 @@ fun TimelineView( modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState(), forceJumpToBottomVisibility: Boolean = false, + forceJumpToReadMarkerVisibility: Boolean = false, nestedScrollConnection: NestedScrollConnection = rememberNestedScrollInteropConnection(), floatingDateTopOffset: Dp = 0.dp, ) { @@ -205,9 +216,15 @@ fun TimelineView( hasAnyEvent = state.hasAnyEvent, lazyListState = lazyListState, forceJumpToBottomVisibility = forceJumpToBottomVisibility, + forceJumpToReadMarkerVisibility = forceJumpToReadMarkerVisibility, newEventState = state.newEventState, isLive = state.isLive, focusRequestState = state.focusRequestState, + readMarkerIndex = state.readMarkerIndex, + unreadMessagesCount = state.unreadMessagesCount, + newMessagesCount = state.newMessagesCount, + displayJumpToUnread = state.displayJumpToUnread, + topInset = floatingDateTopOffset, onScrollFinishAt = ::onScrollFinishAt, onJumpToLive = ::onJumpToLive, onFocusEventRender = ::onFocusEventRender, @@ -289,7 +306,13 @@ private fun BoxScope.TimelineScrollHelper( newEventState: NewEventState, isLive: Boolean, forceJumpToBottomVisibility: Boolean, + forceJumpToReadMarkerVisibility: Boolean, focusRequestState: FocusRequestState, + readMarkerIndex: Int, + unreadMessagesCount: Int, + newMessagesCount: Int, + displayJumpToUnread: Boolean, + topInset: Dp, onScrollFinishAt: (Int) -> Unit, onJumpToLive: () -> Unit, onFocusEventRender: () -> Unit, @@ -301,6 +324,19 @@ private fun BoxScope.TimelineScrollHelper( lazyListState.firstVisibleItemIndex < 3 && isLive } } + val isReadMarkerOffTop by remember { + derivedStateOf { + if (!displayJumpToUnread || readMarkerIndex < 0) { + false + } else if (forceJumpToReadMarkerVisibility) { + true + } else { + val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false + readMarkerIndex > lastVisibleIndex + } + } + } + val isJumpToBottomVisible = !canAutoScroll || forceJumpToBottomVisibility || !isLive var jumpToLiveHandled by remember { mutableStateOf(true) } /** @@ -327,6 +363,13 @@ private fun BoxScope.TimelineScrollHelper( } } + fun jumpToReadMarker() { + if (readMarkerIndex < 0) return + coroutineScope.launch { + lazyListState.animateScrollToItemCenter(readMarkerIndex) + } + } + LaunchedEffect(jumpToLiveHandled, isLive) { if (!jumpToLiveHandled && isLive) { lazyListState.scrollToItem(0) @@ -358,19 +401,41 @@ private fun BoxScope.TimelineScrollHelper( } } - JumpToBottomButton( - // Use inverse of canAutoScroll otherwise we might briefly see the before the scroll animation is triggered - isVisible = !canAutoScroll || forceJumpToBottomVisibility || !isLive, + TimelineFab( + icon = CompoundIcons.ChevronDown(), + contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), + isVisible = isJumpToBottomVisible, + // Hide the badge entirely when the feature is off, regardless of the count value. + count = if (displayJumpToUnread) newMessagesCount else 0, modifier = Modifier .align(Alignment.BottomEnd) .padding(end = 24.dp, bottom = 12.dp), - onClick = { jumpToBottom() }, + onClick = ::jumpToBottom, + ) + val jumpToUnreadDescription = if (unreadMessagesCount > 0) { + pluralStringResource(CommonPlurals.a11y_jump_to_unread_messages_count, unreadMessagesCount, unreadMessagesCount) + } else { + stringResource(id = CommonStrings.a11y_jump_to_unread_messages) + } + TimelineFab( + icon = CompoundIcons.ChevronUp(), + contentDescription = jumpToUnreadDescription, + isVisible = isReadMarkerOffTop, + count = unreadMessagesCount, + // Top padding includes [topInset] so the FAB sits below any pinned-events banner. + modifier = Modifier + .align(Alignment.TopEnd) + .padding(end = 24.dp, top = topInset + 12.dp), + onClick = ::jumpToReadMarker, ) } @Composable -private fun JumpToBottomButton( +private fun TimelineFab( + icon: ImageVector, + contentDescription: String, isVisible: Boolean, + count: Int, onClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -380,25 +445,67 @@ private fun JumpToBottomButton( enter = scaleIn(animationSpec = tween(100)), exit = scaleOut(animationSpec = tween(100)), ) { - FloatingActionButton( - onClick = onClick, - elevation = FloatingActionButtonDefaults.elevation(4.dp, 4.dp, 4.dp, 4.dp), - shape = CircleShape, - modifier = Modifier.size(36.dp), - containerColor = ElementTheme.colors.bgSubtleSecondary, - contentColor = ElementTheme.colors.iconSecondary, - ) { - Icon( + Box { + FloatingActionButton( + onClick = onClick, + elevation = FloatingActionButtonDefaults.elevation(4.dp, 4.dp, 4.dp, 4.dp), + shape = CircleShape, + modifier = Modifier.size(36.dp), + containerColor = ElementTheme.colors.bgSubtleSecondary, + contentColor = ElementTheme.colors.iconSecondary, + ) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = icon, + contentDescription = contentDescription, + ) + } + TimelineCountBadge( + count = count, modifier = Modifier - .size(24.dp) - .rotate(90f), - imageVector = CompoundIcons.ArrowRight(), - contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom) + .align(Alignment.TopEnd) + .offset { IntOffset(x = 4.dp.roundToPx(), y = -4.dp.roundToPx()) }, ) } } } +/** + * Small accent badge overlaid on a timeline FAB. Shows the count when it's between 1 and 9, otherwise a dot. + * Renders nothing when [count] is zero or negative. + */ +@Composable +private fun TimelineCountBadge( + count: Int, + modifier: Modifier = Modifier, +) { + if (count <= 0) return + if (count <= 9) { + Box( + modifier = modifier + .defaultMinSize(minWidth = 16.dp, minHeight = 16.dp) + .background(color = ElementTheme.colors.bgActionPrimaryRest, shape = CircleShape) + .border(width = 2.dp, color = ElementTheme.colors.iconOnSolidPrimary, shape = CircleShape) + .padding(horizontal = 4.dp), + contentAlignment = Alignment.Center, + ) { + Text( + text = count.toString(), + color = ElementTheme.colors.textOnSolidPrimary, + style = ElementTheme.typography.fontBodyXsMedium, + textAlign = TextAlign.Center, + ) + } + } else { + Box( + modifier = modifier + .size(12.dp) + .background(color = ElementTheme.colors.bgActionPrimaryRest, shape = CircleShape) + .border(width = 2.dp, color = ElementTheme.colors.iconOnSolidPrimary, shape = CircleShape), + ) + } +} + @PreviewsDayNight @Composable internal fun TimelineViewPreview( @@ -433,3 +540,61 @@ internal fun TimelineViewPreview( ) } } + +@Composable +private fun TimelineViewWithReadMarker( + unreadMessagesCount: Int, + newMessagesCount: Int, +) { + val readMarker = aTimelineItemReadMarker() + val timelineItems = persistentListOf( + aTimelineItemEvent(isMine = false), + aTimelineItemEvent(isMine = false), + aTimelineItemEvent(isMine = true), + readMarker, + aTimelineItemEvent(isMine = false), + aTimelineItemEvent(isMine = false), + ) + CompositionLocalProvider( + LocalTimelineItemPresenterFactories provides aFakeTimelineItemPresenterFactories(), + ) { + TimelineView( + state = aTimelineState( + timelineItems = timelineItems, + readMarkerIndex = timelineItems.indexOf(readMarker), + unreadMessagesCount = unreadMessagesCount, + newMessagesCount = newMessagesCount, + ), + timelineProtectionState = aTimelineProtectionState(), + onUserDataClick = {}, + onLinkClick = {}, + onContentClick = {}, + onMessageLongClick = {}, + onSwipeToReply = {}, + onReactionClick = { _, _ -> }, + onReactionLongClick = { _, _ -> }, + onMoreReactionsClick = {}, + onReadReceiptClick = {}, + forceJumpToBottomVisibility = true, + forceJumpToReadMarkerVisibility = true, + ) + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineViewWithReadMarkerNoBadgesPreview() = ElementPreview { + TimelineViewWithReadMarker(unreadMessagesCount = 0, newMessagesCount = 0) +} + +@PreviewsDayNight +@Composable +internal fun TimelineViewWithReadMarkerPreview() = ElementPreview { + TimelineViewWithReadMarker(unreadMessagesCount = 3, newMessagesCount = 12) +} + +@PreviewsDayNight +@Composable +internal fun TimelineViewWithReadMarkerDotBadgesPreview() = ElementPreview { + TimelineViewWithReadMarker(unreadMessagesCount = 47, newMessagesCount = 99) +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt index 9c4c48d11e..fe2c264932 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt @@ -99,6 +99,28 @@ fun TimelineItemEventContent.isEdited(): Boolean = when (this) { */ fun TimelineItemEventContent.isRedacted(): Boolean = this is TimelineItemRedactedContent +/** + * Whether the event content is a user-facing message that should be counted toward unread totals. + * Excludes state events, profile changes, membership changes, redactions, and unknown content. + */ +fun TimelineItemEventContent.isMessageContent(): Boolean = when (this) { + is TimelineItemTextBasedContent, + is TimelineItemAudioContent, + is TimelineItemEncryptedContent, + is TimelineItemFileContent, + is TimelineItemImageContent, + is TimelineItemStickerContent, + is TimelineItemLocationContent, + is TimelineItemPollContent, + is TimelineItemVoiceContent, + is TimelineItemVideoContent, + is TimelineItemLegacyCallInviteContent, + is TimelineItemRtcNotificationContent -> true + is TimelineItemStateContent, + is TimelineItemRedactedContent, + TimelineItemUnknownContent -> false +} + fun TimelineItemEventContentWithAttachment.duration(): Duration? { return when (this) { is TimelineItemAudioContent -> duration diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 194694714b..e4ddbf6c82 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -42,6 +42,7 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender import io.element.android.libraries.matrix.api.timeline.item.event.Receipt +import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 @@ -58,12 +59,14 @@ import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermiss import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.aMessageContent import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem +import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.awaitLastSequentialItem import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.consumeItemsUntilTimeout import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaError @@ -365,6 +368,305 @@ class TimelinePresenterTest { } } + @Test + fun `present - unreadMessagesCount counts message-content items between newest and read marker, excluding state events`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + val initialState = awaitFirstItem() + assertThat(initialState.readMarkerIndex).isEqualTo(-1) + assertThat(initialState.unreadMessagesCount).isEqualTo(0) + // SDK delivers items oldest-first; the factory reverses so output index 0 is the newest. + // After processing: [msg-newest, membership, msg-2, read-marker, msg-old] + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("msg-old"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker), + MatrixTimelineItem.Event(UniqueId("msg-2"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Event(UniqueId("membership"), anEventTimelineItem(content = aRoomMembershipContent())), + MatrixTimelineItem.Event(UniqueId("msg-newest"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.readMarkerIndex >= 0 }.last().also { state -> + // 2 message items above the marker; the membership state event is skipped. + assertThat(state.readMarkerIndex).isEqualTo(3) + assertThat(state.unreadMessagesCount).isEqualTo(2) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - unreadMessagesCount excludes own messages and PAGINATION-origin events`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + awaitFirstItem() + // After processing (factory reverses): [other-newest, own-msg, paginated, read-marker, msg-old] + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("msg-old"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker), + MatrixTimelineItem.Event( + UniqueId("paginated"), + anEventTimelineItem(content = aMessageContent()).copy(origin = TimelineItemEventOrigin.PAGINATION), + ), + MatrixTimelineItem.Event(UniqueId("own-msg"), anEventTimelineItem(content = aMessageContent(), isOwn = true)), + MatrixTimelineItem.Event(UniqueId("other-newest"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.readMarkerIndex >= 0 }.last().also { state -> + assertThat(state.readMarkerIndex).isEqualTo(3) + // Only `other-newest` counts: own-msg and paginated are filtered out. + assertThat(state.unreadMessagesCount).isEqualTo(1) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - readMarkerIndex is -1 when no read marker present`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + val initialState = awaitFirstItem() + assertThat(initialState.readMarkerIndex).isEqualTo(-1) + assertThat(initialState.unreadMessagesCount).isEqualTo(0) + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> + assertThat(state.readMarkerIndex).isEqualTo(-1) + assertThat(state.unreadMessagesCount).isEqualTo(0) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount increments by N when N events from others arrive in one batch`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + val initialState = awaitFirstItem() + assertThat(initialState.newMessagesCount).isEqualTo(0) + // Seed prevMostRecentItemId so subsequent emissions count as new events. + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + // Three new events from another user arrive in a single batch. + timelineItems.getAndUpdate { items -> + items + listOf( + MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Event(UniqueId("3"), anEventTimelineItem(content = aMessageContent())), + ) + } + consumeItemsUntilPredicate { it.newMessagesCount == 3 }.last().also { state -> + assertThat(state.newMessagesCount).isEqualTo(3) + assertThat(state.newEventState).isEqualTo(NewEventState.FromOther) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount resets to 0 on OnScrollFinished firstIndex 0`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline( + timelineItems = timelineItems, + markAsReadResult = { Result.success(Unit) }, + ) + val presenter = createTimelinePresenter(timeline) + presenter.test { + val initialState = awaitFirstItem() + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + timelineItems.getAndUpdate { items -> + items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) + } + val countedState = consumeItemsUntilPredicate { it.newMessagesCount == 1 }.last() + assertThat(countedState.newMessagesCount).isEqualTo(1) + initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(0)) + consumeItemsUntilPredicate { it.newMessagesCount == 0 }.last().also { state -> + assertThat(state.newMessagesCount).isEqualTo(0) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount resets to 0 when latest event is from me`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + // First, an event from another user increments the count. + timelineItems.getAndUpdate { items -> + items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) + } + consumeItemsUntilPredicate { it.newMessagesCount == 1 } + // Then the local user sends a message: count should reset. + timelineItems.getAndUpdate { items -> + items + listOf( + MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent(), isOwn = true)), + ) + } + consumeItemsUntilPredicate { + it.newEventState == NewEventState.FromMe && it.newMessagesCount == 0 + }.last().also { state -> + assertThat(state.newMessagesCount).isEqualTo(0) + assertThat(state.newEventState).isEqualTo(NewEventState.FromMe) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount does not reset on OnScrollFinished firstIndex other than 0`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + val initialState = awaitFirstItem() + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + timelineItems.getAndUpdate { items -> + items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) + } + consumeItemsUntilPredicate { it.newMessagesCount == 1 } + // Scrolling stops above the bottom: the count must NOT reset. + initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(5)) + advanceUntilIdle() + // No state should emit with newMessagesCount == 0. + val drained = consumeItemsUntilTimeout() + assertThat(drained.any { it.newMessagesCount == 0 }).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount does not increment for events with PAGINATION origin`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + // A back-paginated event arrives. It should not bump the badge. + timelineItems.getAndUpdate { items -> + items + listOf( + MatrixTimelineItem.Event( + UniqueId("paginated"), + anEventTimelineItem(content = aMessageContent()).copy(origin = TimelineItemEventOrigin.PAGINATION), + ) + ) + } + consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> + assertThat(state.newMessagesCount).isEqualTo(0) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount does not increment for state events`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + // A membership change arrives. It should not bump the badge. + timelineItems.getAndUpdate { items -> + items + listOf( + MatrixTimelineItem.Event(UniqueId("membership"), anEventTimelineItem(content = aRoomMembershipContent())), + ) + } + consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> + assertThat(state.newMessagesCount).isEqualTo(0) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - readMarkerIndex is 0 when the read marker is the only item`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf(MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker)) + ) + consumeItemsUntilPredicate { it.readMarkerIndex >= 0 }.last().also { state -> + assertThat(state.readMarkerIndex).isEqualTo(0) + assertThat(state.unreadMessagesCount).isEqualTo(0) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newMessagesCount accumulates across multiple batches as prevMostRecentItemId advances`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter(timeline) + presenter.test { + awaitFirstItem() + // Seed prevMostRecentItemId so subsequent emissions count as new events. + timelineItems.emit( + listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 } + // Batch 1: 1 new event → count = 1. + timelineItems.getAndUpdate { items -> + items + listOf(MatrixTimelineItem.Event(UniqueId("b1-1"), anEventTimelineItem(content = aMessageContent()))) + } + consumeItemsUntilPredicate { it.newMessagesCount == 1 } + // Batch 2: 2 more new events → count = 3. + timelineItems.getAndUpdate { items -> + items + listOf( + MatrixTimelineItem.Event(UniqueId("b2-1"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Event(UniqueId("b2-2"), anEventTimelineItem(content = aMessageContent())), + ) + } + consumeItemsUntilPredicate { it.newMessagesCount == 3 } + // Batch 3: 1 more new event → count = 4. + timelineItems.getAndUpdate { items -> + items + listOf(MatrixTimelineItem.Event(UniqueId("b3-1"), anEventTimelineItem(content = aMessageContent()))) + } + consumeItemsUntilPredicate { it.newMessagesCount == 4 }.last().also { state -> + assertThat(state.newMessagesCount).isEqualTo(4) + } + cancelAndIgnoreRemainingEvents() + } + } + @Test fun `present - reaction ordering`() = runTest { val timelineItems = MutableStateFlow(emptyList()) 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 15e61f4260..60e164df0f 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 @@ -136,6 +136,13 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + JumpToUnread( + key = "feature.jump_to_unread", + title = "Jump to unread messages", + description = "Show a button to jump to the read marker, plus a count badge on the scroll-to-bottom button when new messages arrive while scrolled away.", + defaultValue = { false }, + isFinished = false, + ), SlashCommand( key = "feature.slash_command", title = "Parse slash commands in the message composer", diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index ba6c431d8b..26c83aaa53 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -7,4 +7,9 @@ "Black" + "Jump to unread messages" + + "Jump to %1$d unread message" + "Jump to %1$d unread messages" + 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 433237cd13..8817561e8f 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 @@ -160,6 +160,8 @@ class KonsistPreviewTest { "TimelineItemVoiceViewUnifiedPreview", "TimelineVideoWithCaptionRowPreview", "TimelineViewMessageShieldPreview", + "TimelineViewWithReadMarkerDotBadgesPreview", + "TimelineViewWithReadMarkerNoBadgesPreview", "UserAvatarColorsPreview", "UserProfileHeaderSectionWithVerificationViolationPreview", "VoiceItemViewPlayPreview", From 9f26079b842ea6a53b4189fa8a33cb21b677d142 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:34:47 -0700 Subject: [PATCH 0286/1083] Add missing preview: both fabs have counts --- .../android/features/messages/impl/timeline/TimelineView.kt | 6 ++++++ .../io/element/android/tests/konsist/KonsistPreviewTest.kt | 1 + 2 files changed, 7 insertions(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 8c7d890d2f..cef9af5dd5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -598,3 +598,9 @@ internal fun TimelineViewWithReadMarkerPreview() = ElementPreview { internal fun TimelineViewWithReadMarkerDotBadgesPreview() = ElementPreview { TimelineViewWithReadMarker(unreadMessagesCount = 47, newMessagesCount = 99) } + +@PreviewsDayNight +@Composable +internal fun TimelineViewWithReadMarkerBothCountsPreview() = ElementPreview { + TimelineViewWithReadMarker(unreadMessagesCount = 5, newMessagesCount = 3) +} 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 8817561e8f..cbe4b674cc 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 @@ -160,6 +160,7 @@ class KonsistPreviewTest { "TimelineItemVoiceViewUnifiedPreview", "TimelineVideoWithCaptionRowPreview", "TimelineViewMessageShieldPreview", + "TimelineViewWithReadMarkerBothCountsPreview", "TimelineViewWithReadMarkerDotBadgesPreview", "TimelineViewWithReadMarkerNoBadgesPreview", "UserAvatarColorsPreview", From 2579e68edcbeed68cf6a840040e80d7e694ac439 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:29:51 -0700 Subject: [PATCH 0287/1083] Don't show NEW timeline divider when not applicable in previews --- .../messages/impl/timeline/TimelineStateProvider.kt | 8 -------- .../features/messages/impl/timeline/TimelineView.kt | 10 ++++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index e30eb1be97..08ddf56c8c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -23,7 +23,6 @@ import io.element.android.features.messages.impl.timeline.model.anAggregatedReac import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent -import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel import io.element.android.features.messages.impl.typing.TypingNotificationState import io.element.android.features.messages.impl.typing.aTypingNotificationState @@ -90,13 +89,6 @@ fun aTimelineState( ) } -internal fun aTimelineItemReadMarker(): TimelineItem.Virtual { - return TimelineItem.Virtual( - id = UniqueId(UUID.randomUUID().toString()), - model = TimelineItemReadMarkerModel, - ) -} - internal fun aTimelineItemList(content: TimelineItemEventContent): ImmutableList { return persistentListOf( // 3 items (First Middle Last) with isMine = false diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index cef9af5dd5..51bd67a382 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -546,12 +546,11 @@ private fun TimelineViewWithReadMarker( unreadMessagesCount: Int, newMessagesCount: Int, ) { - val readMarker = aTimelineItemReadMarker() val timelineItems = persistentListOf( aTimelineItemEvent(isMine = false), aTimelineItemEvent(isMine = false), aTimelineItemEvent(isMine = true), - readMarker, + aTimelineItemEvent(isMine = false), aTimelineItemEvent(isMine = false), aTimelineItemEvent(isMine = false), ) @@ -561,7 +560,10 @@ private fun TimelineViewWithReadMarker( TimelineView( state = aTimelineState( timelineItems = timelineItems, - readMarkerIndex = timelineItems.indexOf(readMarker), + // Index points past the loaded items, mirroring the real-world state the FAB + // represents: the user has scrolled past the read marker, so it's no longer in + // view. The actual scroll target doesn't matter for a static preview. + readMarkerIndex = timelineItems.size, unreadMessagesCount = unreadMessagesCount, newMessagesCount = newMessagesCount, ), @@ -590,7 +592,7 @@ internal fun TimelineViewWithReadMarkerNoBadgesPreview() = ElementPreview { @PreviewsDayNight @Composable internal fun TimelineViewWithReadMarkerPreview() = ElementPreview { - TimelineViewWithReadMarker(unreadMessagesCount = 3, newMessagesCount = 12) + TimelineViewWithReadMarker(unreadMessagesCount = 3, newMessagesCount = 0) } @PreviewsDayNight From ef7cb35de81c8c2d69f56d1eef62a5bb567efbc0 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:13:38 -0700 Subject: [PATCH 0288/1083] Quality checks/fixes --- .../impl/timeline/TimelinePresenter.kt | 22 ++++++++++--------- .../messages/impl/timeline/TimelineView.kt | 2 +- .../libraries/featureflag/api/FeatureFlags.kt | 3 ++- 3 files changed, 15 insertions(+), 12 deletions(-) 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 82f7717a8d..5462112fd4 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 @@ -296,11 +296,7 @@ class TimelinePresenter( markerIdx = i break } - if (item is TimelineItem.Event && - !item.isMine && - item.origin != TimelineItemEventOrigin.PAGINATION && - item.content.isMessageContent() - ) { + if (item is TimelineItem.Event && item.isCountableNewMessage()) { unread++ } } @@ -464,11 +460,7 @@ class TimelinePresenter( var delta = 0 for (item in timelineItems) { if (item.identifier() == prevMostRecentItemIdValue) break - if (item is TimelineItem.Event && - item.origin != TimelineItemEventOrigin.PAGINATION && - !item.isMine && - item.content.isMessageContent() - ) { + if (item is TimelineItem.Event && item.isCountableNewMessage()) { delta++ } } @@ -519,6 +511,16 @@ private fun FocusRequestState.onFocusEventRender(): FocusRequestState { } } +/** + * Whether this event should be counted toward the unread / new-message badges: a user-facing + * message from someone other than the local user, that wasn't pulled in via back-pagination. + */ +private fun TimelineItem.Event.isCountableNewMessage(): Boolean { + return !isMine && + origin != TimelineItemEventOrigin.PAGINATION && + content.isMessageContent() +} + // Workaround for not having the server names available, get possible server names from the user ids of the room members private fun calculateServerNamesForRoom(room: JoinedRoom): List { // If we have no room members, return right ahead diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 51bd67a382..ce62f1ef9f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -598,7 +598,7 @@ internal fun TimelineViewWithReadMarkerPreview() = ElementPreview { @PreviewsDayNight @Composable internal fun TimelineViewWithReadMarkerDotBadgesPreview() = ElementPreview { - TimelineViewWithReadMarker(unreadMessagesCount = 47, newMessagesCount = 99) + TimelineViewWithReadMarker(unreadMessagesCount = 47, newMessagesCount = 0) } @PreviewsDayNight 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 60e164df0f..6c8f9e9d8f 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 @@ -139,7 +139,8 @@ enum class FeatureFlags( JumpToUnread( key = "feature.jump_to_unread", title = "Jump to unread messages", - description = "Show a button to jump to the read marker, plus a count badge on the scroll-to-bottom button when new messages arrive while scrolled away.", + description = "Show a button to jump to the read marker, plus a count badge on the scroll-to-bottom button " + + "when new messages arrive while scrolled away.", defaultValue = { false }, isFinished = false, ), From c8773c890f2fe88d7075cc5f8ea37c6eb1be44c2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 08:49:56 +0200 Subject: [PATCH 0289/1083] Fix SQL query --- .../io/element/android/libraries/cachestore/CacheData.sq | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq index 4683d9aa7d..aa8bacf90b 100644 --- a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq +++ b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq @@ -18,9 +18,8 @@ CREATE TABLE CacheData ( selectData: SELECT * FROM CacheData WHERE key = ?; --- insert or update data by key insertData: -INSERT INTO CacheData VALUES ? ON CONFLICT(key) DO UPDATE SET value = excluded.value, updatedAt = excluded.updatedAt; +INSERT OR REPLACE INTO CacheData VALUES ?; deleteData: DELETE FROM CacheData WHERE key = ?; From b50969437df63935db744977d7c09bbf57093500 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 09:01:35 +0200 Subject: [PATCH 0290/1083] Ensure clearing the cache delete the CacheStore. --- features/preferences/impl/build.gradle.kts | 2 ++ .../impl/tasks/ClearCacheUseCase.kt | 4 ++++ .../impl/tasks/DefaultClearCacheUseCaseTest.kt | 7 +++++++ .../libraries/cachestore/api/CacheStore.kt | 1 + .../cachestore/impl/DatabaseCacheStore.kt | 8 ++++++-- .../android/libraries/cachestore/CacheData.sq | 3 +++ .../impl/DatabaseCacheStoreTest.kt | 18 ++++++++++++++++++ .../sessionstorage/test/InMemoryCacheStore.kt | 4 ++++ 8 files changed, 45 insertions(+), 2 deletions(-) diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index ad28c90966..33936760f5 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -51,6 +51,7 @@ dependencies { implementation(projects.appconfig) implementation(projects.libraries.core) implementation(projects.libraries.architecture) + implementation(projects.libraries.cachestore.api) implementation(projects.libraries.matrix.api) implementation(projects.libraries.designsystem) implementation(projects.libraries.featureflag.api) @@ -114,6 +115,7 @@ dependencies { testImplementation(projects.features.logout.test) testImplementation(projects.libraries.indicator.test) testImplementation(projects.libraries.pushproviders.test) + testImplementation(projects.libraries.cachestore.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.appnavstate.impl) testImplementation(projects.services.analytics.test) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt index 6c26866e93..141adafe2b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt @@ -14,6 +14,7 @@ import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Provider import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.preferences.impl.DefaultCacheService +import io.element.android.libraries.cachestore.api.CacheStore import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.ApplicationContext @@ -37,8 +38,11 @@ class DefaultClearCacheUseCase( private val pushService: PushService, private val seenInvitesStore: SeenInvitesStore, private val activeRoomsHolder: ActiveRoomsHolder, + private val cacheStore: CacheStore, ) : ClearCacheUseCase { override suspend fun invoke() = withContext(coroutineDispatchers.io) { + // Clear cache store + cacheStore.deleteAll() // Active rooms should be disposed of before clearing the cache activeRoomsHolder.clear(matrixClient.sessionId) // Clear Matrix cache diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt index 6845ecb3a4..1c1cb83def 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt @@ -19,6 +19,8 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.push.test.FakePushService +import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore +import io.element.android.libraries.sessionstorage.test.aCacheData import io.element.android.services.appnavstate.impl.DefaultActiveRoomsHolder import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -49,6 +51,9 @@ class DefaultClearCacheUseCaseTest { ) val seenInvitesStore = InMemorySeenInvitesStore(setOf(A_ROOM_ID)) assertThat(seenInvitesStore.seenRoomIds().first()).isNotEmpty() + val cacheStore = InMemoryCacheStore( + initialData = mapOf("key1" to aCacheData()) + ) val sut = DefaultClearCacheUseCase( context = InstrumentationRegistry.getInstrumentation().context, matrixClient = matrixClient, @@ -58,9 +63,11 @@ class DefaultClearCacheUseCaseTest { pushService = pushService, seenInvitesStore = seenInvitesStore, activeRoomsHolder = activeRoomsHolder, + cacheStore = cacheStore, ) defaultCacheService.clearedCacheEventFlow.test { sut.invoke() + assertThat(cacheStore.dataMap).isEmpty() clearCacheLambda.assertions().isCalledOnce() setIgnoreRegistrationErrorLambda.assertions().isCalledOnce() .with(value(matrixClient.sessionId), value(false)) diff --git a/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt index f16a663ed7..5df446f688 100644 --- a/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt +++ b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt @@ -11,4 +11,5 @@ interface CacheStore { suspend fun storeData(key: String, data: CacheData) suspend fun getData(key: String): CacheData? suspend fun deleteData(key: String) + suspend fun deleteAll() } diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt index 126387da11..54766803f9 100644 --- a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt @@ -27,10 +27,14 @@ class DatabaseCacheStore( override suspend fun storeData(key: String, data: CacheData) { database.cacheDataQueries.insertData( data.toDbModel(key) - ) + ).await() } override suspend fun deleteData(key: String) { - database.cacheDataQueries.deleteData(key) + database.cacheDataQueries.deleteData(key).await() + } + + override suspend fun deleteAll() { + database.cacheDataQueries.deleteAll().await() } } diff --git a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq index aa8bacf90b..fd350ac7ba 100644 --- a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq +++ b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq @@ -23,3 +23,6 @@ INSERT OR REPLACE INTO CacheData VALUES ?; deleteData: DELETE FROM CacheData WHERE key = ?; + +deleteAll: +DELETE FROM CacheData; diff --git a/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt index a2216daa06..36d7e05532 100644 --- a/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt +++ b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt @@ -65,4 +65,22 @@ class DatabaseCacheStoreTest { databaseCacheStore.deleteData(A_KEY) assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() } + + @Test + fun `deleteAll deletes all the data`() = runTest { + // Assert that no data is stored for the key + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() + // Store data + databaseCacheStore.storeData(A_KEY, CacheData(A_DATA_1, 1)) + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isEqualTo( + DbCacheData( + key = A_KEY, + value_ = A_DATA_1, + updatedAt = 1, + ) + ) + // Delete all data + databaseCacheStore.deleteAll() + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() + } } diff --git a/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt index b0f77062ba..f029c8bcde 100644 --- a/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt +++ b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt @@ -26,4 +26,8 @@ class InMemoryCacheStore( override suspend fun deleteData(key: String) { dataMap.remove(key) } + + override suspend fun deleteAll() { + dataMap.clear() + } } From 4d0be69b4c22945270dfceeb675410f221234ff3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 09:52:10 +0200 Subject: [PATCH 0291/1083] In the module `:libraries:matrix.api`, change the dependencies to: - libraries.sessionStorage.api - projects.libraries.architecture from `api` to `implementation`. Modules who need `:libraries:matrix.api` do not necessarily need to use the session storage api. --- appconfig/build.gradle.kts | 2 ++ appnav/build.gradle.kts | 1 + features/enterprise/test/build.gradle.kts | 1 + features/home/impl/build.gradle.kts | 1 + features/invite/impl/build.gradle.kts | 1 + features/invite/test/build.gradle.kts | 1 + features/location/test/build.gradle.kts | 2 +- features/logout/impl/build.gradle.kts | 1 + features/messages/test/build.gradle.kts | 1 + features/poll/test/build.gradle.kts | 1 + features/preferences/impl/build.gradle.kts | 1 + features/preferences/test/build.gradle.kts | 1 + features/signedout/impl/build.gradle.kts | 1 + libraries/matrix/api/build.gradle.kts | 4 ++-- libraries/matrix/impl/build.gradle.kts | 2 ++ libraries/matrix/test/build.gradle.kts | 1 + libraries/matrixmedia/impl/build.gradle.kts | 2 ++ libraries/mediaupload/test/build.gradle.kts | 1 + libraries/mediaviewer/test/build.gradle.kts | 1 + libraries/preferences/impl/build.gradle.kts | 1 + libraries/pushproviders/firebase/build.gradle.kts | 1 + libraries/recentemojis/impl/build.gradle.kts | 1 + libraries/session-storage/test/build.gradle.kts | 1 + libraries/voiceplayer/api/build.gradle.kts | 1 + libraries/voiceplayer/impl/build.gradle.kts | 1 + libraries/workmanager/api/build.gradle.kts | 2 +- libraries/workmanager/impl/build.gradle.kts | 1 + services/analyticsproviders/sentry/build.gradle.kts | 2 ++ 28 files changed, 33 insertions(+), 4 deletions(-) diff --git a/appconfig/build.gradle.kts b/appconfig/build.gradle.kts index 45496acb77..64b9b76a14 100644 --- a/appconfig/build.gradle.kts +++ b/appconfig/build.gradle.kts @@ -48,6 +48,8 @@ android { } dependencies { + implementation(libs.coroutines.core) implementation(libs.androidx.annotationjvm) + implementation(libs.androidx.corektx) implementation(projects.libraries.matrix.api) } diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index 6be468b0d1..7440ecd2bf 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.matrixui) implementation(projects.libraries.matrixmedia.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.uiCommon) implementation(projects.libraries.uiStrings) implementation(projects.features.login.api) diff --git a/features/enterprise/test/build.gradle.kts b/features/enterprise/test/build.gradle.kts index 542e73717a..c37fc53de3 100644 --- a/features/enterprise/test/build.gradle.kts +++ b/features/enterprise/test/build.gradle.kts @@ -15,6 +15,7 @@ android { dependencies { api(projects.features.enterprise.api) + implementation(projects.libraries.architecture) implementation(projects.libraries.compound) implementation(projects.libraries.matrix.api) implementation(projects.tests.testutils) diff --git a/features/home/impl/build.gradle.kts b/features/home/impl/build.gradle.kts index b36ee6aed2..0635da39a5 100644 --- a/features/home/impl/build.gradle.kts +++ b/features/home/impl/build.gradle.kts @@ -46,6 +46,7 @@ dependencies { implementation(projects.libraries.permissions.noop) implementation(projects.libraries.preferences.api) implementation(projects.libraries.push.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.features.announcement.api) implementation(projects.features.invite.api) implementation(projects.features.networkmonitor.api) diff --git a/features/invite/impl/build.gradle.kts b/features/invite/impl/build.gradle.kts index 80b98464f7..e033f2740c 100644 --- a/features/invite/impl/build.gradle.kts +++ b/features/invite/impl/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.designsystem) implementation(projects.libraries.uiStrings) implementation(projects.services.analytics.api) diff --git a/features/invite/test/build.gradle.kts b/features/invite/test/build.gradle.kts index 2df267f155..080ed765bb 100644 --- a/features/invite/test/build.gradle.kts +++ b/features/invite/test/build.gradle.kts @@ -16,6 +16,7 @@ android { dependencies { implementation(libs.coroutines.core) + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.test) implementation(projects.tests.testutils) diff --git a/features/location/test/build.gradle.kts b/features/location/test/build.gradle.kts index f84e8ba772..e51737d40c 100644 --- a/features/location/test/build.gradle.kts +++ b/features/location/test/build.gradle.kts @@ -16,7 +16,7 @@ android { dependencies { api(projects.features.location.api) + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) - implementation(libs.appyx.core) implementation(projects.tests.testutils) } diff --git a/features/logout/impl/build.gradle.kts b/features/logout/impl/build.gradle.kts index 8de7718980..d5356ced63 100644 --- a/features/logout/impl/build.gradle.kts +++ b/features/logout/impl/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) implementation(projects.libraries.dateformatter.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.workmanager.api) api(projects.features.logout.api) diff --git a/features/messages/test/build.gradle.kts b/features/messages/test/build.gradle.kts index b839f8de06..f89dd8de06 100644 --- a/features/messages/test/build.gradle.kts +++ b/features/messages/test/build.gradle.kts @@ -16,6 +16,7 @@ android { dependencies { api(projects.features.messages.impl) + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.test) implementation(projects.libraries.audio.test) implementation(projects.libraries.mediaplayer.test) diff --git a/features/poll/test/build.gradle.kts b/features/poll/test/build.gradle.kts index a3779809d7..d0adc8e94f 100644 --- a/features/poll/test/build.gradle.kts +++ b/features/poll/test/build.gradle.kts @@ -15,6 +15,7 @@ android { } dependencies { + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) api(projects.features.poll.api) implementation(libs.kotlinx.collections.immutable) diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index ad28c90966..889e030213 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -68,6 +68,7 @@ dependencies { implementation(projects.libraries.permissions.api) implementation(projects.libraries.push.api) implementation(projects.libraries.pushproviders.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.uiUtils) implementation(projects.libraries.fullscreenintent.api) implementation(projects.features.rageshake.api) diff --git a/features/preferences/test/build.gradle.kts b/features/preferences/test/build.gradle.kts index 7e3da4a6e8..a066fe4707 100644 --- a/features/preferences/test/build.gradle.kts +++ b/features/preferences/test/build.gradle.kts @@ -14,6 +14,7 @@ android { } dependencies { + implementation(projects.libraries.architecture) implementation(projects.features.preferences.api) implementation(projects.tests.testutils) } diff --git a/features/signedout/impl/build.gradle.kts b/features/signedout/impl/build.gradle.kts index 3c8aac5e25..b3801288be 100644 --- a/features/signedout/impl/build.gradle.kts +++ b/features/signedout/impl/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.uiStrings) testCommonDependencies(libs) diff --git a/libraries/matrix/api/build.gradle.kts b/libraries/matrix/api/build.gradle.kts index 1c70006cc8..2a7586d6c9 100644 --- a/libraries/matrix/api/build.gradle.kts +++ b/libraries/matrix/api/build.gradle.kts @@ -49,9 +49,9 @@ dependencies { implementation(projects.libraries.core) implementation(projects.services.analytics.api) implementation(libs.serialization.json) - api(projects.libraries.sessionStorage.api) + implementation(projects.libraries.sessionStorage.api) implementation(libs.coroutines.core) - api(projects.libraries.architecture) + implementation(projects.libraries.architecture) testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 67386cc592..92e8a3ba9e 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -32,10 +32,12 @@ dependencies { implementation(projects.appconfig) implementation(projects.libraries.androidutils) + implementation(projects.libraries.architecture) implementation(projects.libraries.di) implementation(projects.libraries.featureflag.api) implementation(projects.libraries.network) implementation(projects.libraries.preferences.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.workmanager.api) implementation(projects.services.analytics.api) implementation(projects.services.toolbox.api) diff --git a/libraries/matrix/test/build.gradle.kts b/libraries/matrix/test/build.gradle.kts index 63836d857a..ccfa56f1aa 100644 --- a/libraries/matrix/test/build.gradle.kts +++ b/libraries/matrix/test/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { api(projects.libraries.matrix.api) api(libs.coroutines.core) implementation(libs.coroutines.test) + implementation(projects.libraries.architecture) implementation(projects.services.analytics.api) implementation(projects.tests.testutils) implementation(libs.kotlinx.collections.immutable) diff --git a/libraries/matrixmedia/impl/build.gradle.kts b/libraries/matrixmedia/impl/build.gradle.kts index 82afc2f62c..56ccc79afc 100644 --- a/libraries/matrixmedia/impl/build.gradle.kts +++ b/libraries/matrixmedia/impl/build.gradle.kts @@ -19,8 +19,10 @@ android { setupDependencyInjection() dependencies { + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixmedia.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.designsystem) implementation(libs.coil.compose) implementation(libs.coil.gif) diff --git a/libraries/mediaupload/test/build.gradle.kts b/libraries/mediaupload/test/build.gradle.kts index 7e729089c7..f271ae1316 100644 --- a/libraries/mediaupload/test/build.gradle.kts +++ b/libraries/mediaupload/test/build.gradle.kts @@ -15,6 +15,7 @@ android { } dependencies { + implementation(libs.coroutines.core) api(projects.libraries.mediaupload.api) implementation(projects.libraries.core) implementation(projects.tests.testutils) diff --git a/libraries/mediaviewer/test/build.gradle.kts b/libraries/mediaviewer/test/build.gradle.kts index 1918714d7b..87665e6d69 100644 --- a/libraries/mediaviewer/test/build.gradle.kts +++ b/libraries/mediaviewer/test/build.gradle.kts @@ -18,6 +18,7 @@ android { dependencies { api(projects.libraries.mediaviewer.impl) + implementation(projects.libraries.architecture) implementation(projects.libraries.core) implementation(projects.tests.testutils) implementation(projects.libraries.matrix.api) diff --git a/libraries/preferences/impl/build.gradle.kts b/libraries/preferences/impl/build.gradle.kts index c567471da4..0478d303ea 100644 --- a/libraries/preferences/impl/build.gradle.kts +++ b/libraries/preferences/impl/build.gradle.kts @@ -25,4 +25,5 @@ dependencies { implementation(projects.libraries.di) implementation(projects.libraries.core) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.sessionStorage.api) } diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 49ce7135d5..ffa4e9fa70 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { implementation(projects.libraries.di) implementation(projects.libraries.matrix.api) implementation(projects.libraries.push.api) + implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.uiStrings) implementation(projects.libraries.troubleshoot.api) implementation(projects.services.toolbox.api) diff --git a/libraries/recentemojis/impl/build.gradle.kts b/libraries/recentemojis/impl/build.gradle.kts index a1a72c8672..061a7ecd89 100644 --- a/libraries/recentemojis/impl/build.gradle.kts +++ b/libraries/recentemojis/impl/build.gradle.kts @@ -21,6 +21,7 @@ setupDependencyInjection() dependencies { api(projects.libraries.recentemojis.api) + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(libs.kotlinx.collections.immutable) implementation(libs.matrix.emojibase.bindings) diff --git a/libraries/session-storage/test/build.gradle.kts b/libraries/session-storage/test/build.gradle.kts index cfdc3018a9..7a89746812 100644 --- a/libraries/session-storage/test/build.gradle.kts +++ b/libraries/session-storage/test/build.gradle.kts @@ -14,6 +14,7 @@ android { } dependencies { + implementation(libs.coroutines.core) implementation(projects.libraries.matrix.api) implementation(projects.libraries.sessionStorage.api) } diff --git a/libraries/voiceplayer/api/build.gradle.kts b/libraries/voiceplayer/api/build.gradle.kts index f37c263d83..e058210b7d 100644 --- a/libraries/voiceplayer/api/build.gradle.kts +++ b/libraries/voiceplayer/api/build.gradle.kts @@ -16,5 +16,6 @@ android { dependencies { implementation(libs.androidx.annotationjvm) implementation(libs.coroutines.core) + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) } diff --git a/libraries/voiceplayer/impl/build.gradle.kts b/libraries/voiceplayer/impl/build.gradle.kts index 4aa00e188b..8fe79fb774 100644 --- a/libraries/voiceplayer/impl/build.gradle.kts +++ b/libraries/voiceplayer/impl/build.gradle.kts @@ -21,6 +21,7 @@ setupDependencyInjection() dependencies { api(projects.libraries.voiceplayer.api) + implementation(projects.libraries.architecture) implementation(projects.libraries.audio.api) implementation(projects.libraries.core) implementation(projects.libraries.di) diff --git a/libraries/workmanager/api/build.gradle.kts b/libraries/workmanager/api/build.gradle.kts index b53ed40394..238dc57664 100644 --- a/libraries/workmanager/api/build.gradle.kts +++ b/libraries/workmanager/api/build.gradle.kts @@ -15,6 +15,6 @@ android { dependencies { api(libs.androidx.workmanager.runtime) - + implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) } diff --git a/libraries/workmanager/impl/build.gradle.kts b/libraries/workmanager/impl/build.gradle.kts index 878edb6fe2..c1874bfa74 100644 --- a/libraries/workmanager/impl/build.gradle.kts +++ b/libraries/workmanager/impl/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.matrix.api) implementation(projects.libraries.di) + implementation(projects.libraries.sessionStorage.api) testCommonDependencies(libs, false) testImplementation(projects.libraries.sessionStorage.test) diff --git a/services/analyticsproviders/sentry/build.gradle.kts b/services/analyticsproviders/sentry/build.gradle.kts index 02dde35ef4..3350df864b 100644 --- a/services/analyticsproviders/sentry/build.gradle.kts +++ b/services/analyticsproviders/sentry/build.gradle.kts @@ -50,6 +50,8 @@ setupDependencyInjection() dependencies { implementation(libs.sentry) + implementation(libs.coroutines.core) + implementation(libs.androidx.annotationjvm) implementation(projects.libraries.core) implementation(projects.libraries.di) implementation(projects.libraries.matrix.api) From 078e942a28ef6fe761172615274e8953bd76da93 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 09:54:54 +0200 Subject: [PATCH 0292/1083] Cleanup dependencies --- libraries/matrix/api/build.gradle.kts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/matrix/api/build.gradle.kts b/libraries/matrix/api/build.gradle.kts index 2a7586d6c9..2a326527df 100644 --- a/libraries/matrix/api/build.gradle.kts +++ b/libraries/matrix/api/build.gradle.kts @@ -44,14 +44,12 @@ android { } dependencies { - implementation(projects.libraries.di) - implementation(projects.libraries.androidutils) - implementation(projects.libraries.core) - implementation(projects.services.analytics.api) - implementation(libs.serialization.json) - implementation(projects.libraries.sessionStorage.api) implementation(libs.coroutines.core) + implementation(libs.serialization.json) + implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) + implementation(projects.libraries.sessionStorage.api) + implementation(projects.services.analytics.api) testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) From 4a79b272ef9bc33aaad05557f97fc105838eca34 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 30 Apr 2026 10:51:29 +0200 Subject: [PATCH 0293/1083] Fix ANRs when receiving push notifications (#6696) In Sentry there are some reports of methods called when notifications are fetched that end up having ANRs. This looked weird because everything is asynchronous... but it's still running with a `Main` dispatcher. Using the `Default/computation` one instead should be the right call. --- .../libraries/push/impl/push/DefaultPushHandler.kt | 9 ++++++--- .../libraries/push/impl/push/DefaultPushHandlerTest.kt | 9 +++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index 44cf6edefc..d5c3f04348 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.push.impl.push import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.push.impl.db.PushRequest @@ -35,6 +36,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import timber.log.Timber private val loggerTag = LoggerTag("PushHandler", LoggerTag.PushLoggerTag) @@ -53,6 +55,7 @@ class DefaultPushHandler( private val workManagerScheduler: WorkManagerScheduler, private val syncPendingNotificationsRequestFactory: SyncPendingNotificationsRequestBuilder.Factory, resultProcessor: NotificationResultProcessor, + private val dispatchers: CoroutineDispatchers, ) : PushHandler { init { resultProcessor.start() @@ -64,7 +67,7 @@ class DefaultPushHandler( * @param pushData the data received in the push. * @param providerInfo the provider info. */ - override suspend fun handle(pushData: PushData, providerInfo: String): Boolean { + override suspend fun handle(pushData: PushData, providerInfo: String): Boolean = withContext(dispatchers.computation) { // Start measuring how long it takes to display a notification from when the push is received Timber.d("Calculating push-to-notification for event ${pushData.eventId}") val parent = analyticsService.startLongRunningTransaction(AnalyticsLongRunningTransaction.PushToNotification(pushData.eventId.value)) @@ -81,7 +84,7 @@ class DefaultPushHandler( } // Diagnostic Push - return if (pushData.eventId == DefaultTestPush.TEST_EVENT_ID) { + if (pushData.eventId == DefaultTestPush.TEST_EVENT_ID) { pushHistoryService.onDiagnosticPush(providerInfo) diagnosticPushHandler.handlePush() false @@ -90,7 +93,7 @@ class DefaultPushHandler( } } - override suspend fun handleInvalid(providerInfo: String, data: String) { + override suspend fun handleInvalid(providerInfo: String, data: String) = withContext(dispatchers.computation) { incrementPushDataStore.incrementPushCounter() pushHistoryService.onInvalidPushReceived(providerInfo, data) } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt index a16568d400..f0dee4446c 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.push.impl.push import app.cash.turbine.test +import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -40,7 +41,9 @@ import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value +import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -212,7 +215,7 @@ class DefaultPushHandlerTest { .isCalledOnce() } - private fun createDefaultPushHandler( + private fun TestScope.createDefaultPushHandler( incrementPushCounterResult: () -> Unit = { lambdaError() }, userPushStore: FakeUserPushStore = FakeUserPushStore(), pushClientSecret: PushClientSecret = FakePushClientSecret(), @@ -227,6 +230,7 @@ class DefaultPushHandlerTest { start = {}, stop = {}, ), + dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), ): DefaultPushHandler { return DefaultPushHandler( incrementPushDataStore = object : IncrementPushDataStore { @@ -246,7 +250,8 @@ class DefaultPushHandlerTest { resultProcessor = resultProcessor, syncPendingNotificationsRequestFactory = SyncPendingNotificationsRequestBuilder.Factory { FakeSyncPendingNotificationsRequestBuilder() - } + }, + dispatchers = dispatchers, ) } } From fabdcee520ea2714e6f8ab825e70762676b7801c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 11:19:10 +0200 Subject: [PATCH 0294/1083] Remove SignInWithClassic FeatureFlag to enable the feature. Closes #6669 --- features/login/impl/build.gradle.kts | 2 -- .../impl/classic/ElementClassicConnection.kt | 12 --------- .../DefaultElementClassicConnectionTest.kt | 25 ------------------- .../libraries/featureflag/api/FeatureFlags.kt | 7 ------ 4 files changed, 46 deletions(-) diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index e739beb20a..86a8e0e7bc 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -60,7 +60,6 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) - implementation(projects.libraries.featureflag.api) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.api) implementation(projects.libraries.designsystem) @@ -81,7 +80,6 @@ dependencies { testImplementation(projects.features.login.test) testImplementation(projects.features.enterprise.test) testImplementation(projects.features.preferences.test) - testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oauth.test) testImplementation(projects.libraries.permissions.test) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt index c928c05239..dfddd1d496 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/classic/ElementClassicConnection.kt @@ -28,8 +28,6 @@ import io.element.android.libraries.androidutils.service.ServiceBinder import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.uri.ensureProtocol 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.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService @@ -71,7 +69,6 @@ class DefaultElementClassicConnection( private val coroutineScope: CoroutineScope, private val matrixAuthenticationService: MatrixAuthenticationService, private val homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker, - private val featureFlagService: FeatureFlagService, ) : ElementClassicConnection { // Messenger for communicating with the service. private var messenger: Messenger? = null @@ -119,10 +116,6 @@ class DefaultElementClassicConnection( override fun start() { Timber.tag(loggerTag.value).d("start()") coroutineScope.launch { - if (!featureFlagService.isFeatureEnabled(FeatureFlags.SignInWithClassic)) { - Timber.tag(loggerTag.value).d("Login with Element Classic is disabled, not starting connection") - return@launch - } // Establish a connection with the service. We use an explicit // class name because there is no reason to be able to let other // applications replace our component. @@ -158,11 +151,6 @@ class DefaultElementClassicConnection( override fun requestSession() { Timber.tag(loggerTag.value).d("requestSession()") coroutineScope.launch { - if (!featureFlagService.isFeatureEnabled(FeatureFlags.SignInWithClassic)) { - Timber.tag(loggerTag.value).d("Login with Element Classic is disabled") - emitState(ElementClassicConnectionState.Error("The feature is disabled")) - return@launch - } val finalMessenger = messenger if (finalMessenger == null) { Timber.tag(loggerTag.value).d("The messenger is null, can't request data") diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt index 5da3c97f3c..8ea1b2e3d3 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/classic/DefaultElementClassicConnectionTest.kt @@ -15,9 +15,6 @@ import androidx.core.graphics.createBitmap import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.service.ServiceBinder -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService @@ -112,21 +109,6 @@ class DefaultElementClassicConnectionTest { } } - @Test - fun `requestSession when the feature is disabled emits an error`() = runTest { - val connection = createDefaultElementClassicConnection( - matrixAuthenticationService = FakeMatrixAuthenticationService( - setElementClassicSessionResult = {}, - ), - isFeatureEnabled = false, - ) - connection.stateFlow.test { - assertThat(awaitItem()).isEqualTo(ElementClassicConnectionState.Idle) - connection.requestSession() - assertThat(awaitItem()).isInstanceOf(ElementClassicConnectionState.Error::class.java) - } - } - @Test fun `when an error is received, an error is emitted`() = runTest { val connection = createDefaultElementClassicConnection( @@ -514,17 +496,10 @@ class DefaultElementClassicConnectionTest { homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker( checkResult = { Result.success(true) } ), - isFeatureEnabled: Boolean = true, - featureFlagService: FeatureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.SignInWithClassic.key to isFeatureEnabled, - ) - ), ) = DefaultElementClassicConnection( serviceBinder = serviceBinder, coroutineScope = coroutineScope, matrixAuthenticationService = matrixAuthenticationService, homeServerLoginCompatibilityChecker = homeServerLoginCompatibilityChecker, - featureFlagService = featureFlagService, ) } 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 15e61f4260..2378a25fc5 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 @@ -100,13 +100,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - SignInWithClassic( - key = "feature.signin_with_classic", - title = "Sign in with Element Classic", - description = "Allow the application to sign in to the current Element Classic account.", - defaultValue = { false }, - isFinished = false, - ), AllowBlackTheme( key = "feature.allow_black_theme", title = "Allow black theme", From c9bc8791e95a10c8e64d91fa25040b6034760aa9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:19:59 +0000 Subject: [PATCH 0295/1083] Update kotlin --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b942901e19..c42858bc64 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,9 +5,9 @@ # Project android_gradle_plugin = "8.13.2" # When updating this, please also update the version in the file ./idea/kotlinc.xml -kotlin = "2.3.20" +kotlin = "2.3.21" kotlinpoet = "2.3.0" -ksp = "2.3.6" +ksp = "2.3.7" firebaseAppDistribution = "5.2.1" # AndroidX From 795299ed0ccab9ad629f1f9d62778a066342ab90 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 30 Apr 2026 09:20:58 +0000 Subject: [PATCH 0296/1083] Update screenshots --- ...imeline.components_TimelineItemCallNotifyView_Day_0_en.png | 4 ++-- ...eline.components_TimelineItemCallNotifyView_Night_0_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png index afec980e10..13b76dc106 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3624fe8448ae4af2481e2023a978ffab2d69f2784b7cef41e5ae2e2dbe8fdbd5 -size 17804 +oid sha256:0a618360cff745818c0ad066b4c6599ff804d9c022e6b54dfec97aa152a84f29 +size 27716 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png index 8f7f14e64a..4d1d5d8f00 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bd02d39619efbcaa6d96f1e75a0d14a572c43e60bad0c3f84d6a5a48b6fbda1 -size 17395 +oid sha256:54e56f77c535db49bb9352ca09033fc81ba21b71e7c28079aec8f9bc09dcc1ad +size 26644 From f5737e9d2b2fb9e202c68533c22fb5ef588eddef Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 15:44:02 +0200 Subject: [PATCH 0297/1083] a11y: add alternative text to the info icon. Closes #6379 --- .../io/element/android/libraries/textcomposer/TextComposer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4860a53ae7..3993b3d64c 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 @@ -679,7 +679,7 @@ private fun TextInputBox( .align(Alignment.CenterEnd), imageVector = CompoundIcons.InfoSolid(), tint = ElementTheme.colors.iconCriticalPrimary, - contentDescription = null, + contentDescription = stringResource(CommonStrings.a11y_info), ) if (showBottomSheet) { CaptionWarningBottomSheet( From b815aaabc9b550192a80fad97f432dcecb954121 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 15:54:07 +0200 Subject: [PATCH 0298/1083] a11y: let section header be implemented as a heading. Closes #6386 --- .../designsystem/theme/components/ListSectionHeader.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt index 403ed6da97..3a86d72e7d 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt @@ -17,6 +17,8 @@ import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -48,6 +50,9 @@ fun ListSectionHeader( verticalArrangement = Arrangement.spacedBy(8.dp) ) { Text( + modifier = Modifier.semantics { + heading() + }, text = title, style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textPrimary, From 0a99b28963ed247da62b2bbd0b54081b48ca8771 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 16:10:19 +0200 Subject: [PATCH 0299/1083] a11y: let banner title be implemented as a heading. Closes #6384 --- .../libraries/designsystem/components/Announcement.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Announcement.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Announcement.kt index dcd3f8fa21..037c37e3a8 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Announcement.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Announcement.kt @@ -24,6 +24,8 @@ import androidx.compose.runtime.Immutable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -148,7 +150,11 @@ private fun TitleAndDescription( text = title, style = ElementTheme.typography.fontBodyLgMedium, color = titleColor, - modifier = Modifier.weight(1f), + modifier = Modifier + .weight(1f) + .semantics { + heading() + }, ) if (trailingContent != null) { Spacer(Modifier.width(12.dp)) From 0c333235f808113c9a37d6d1aacb3b97a0874ff4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 16:16:15 +0200 Subject: [PATCH 0300/1083] a11y: set role = button for "learn more" texts. Closes #6405 --- .../choosemode/ChooseSelfVerificationModeView.kt | 9 ++++++++- .../impl/outgoing/OutgoingVerificationView.kt | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt index 0ca25c9455..1bfa10daf2 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSelfVerificationModeView.kt @@ -19,6 +19,9 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -90,7 +93,11 @@ fun ChooseSelfVerificationModeView( Text( modifier = Modifier .clickable(onClick = onLearnMore) - .padding(vertical = 4.dp, horizontal = 16.dp), + .padding(vertical = 4.dp, horizontal = 16.dp) + .semantics { + // Note: there is no Role.Link, so we use Role.Button for better accessibility support + role = Role.Button + }, text = stringResource(CommonStrings.action_learn_more), style = ElementTheme.typography.fontBodyLgMedium ) diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt index 2dd2850174..1c199f8826 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationView.kt @@ -24,8 +24,10 @@ 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.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.focused +import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -227,7 +229,11 @@ private fun ContentInitial( Text( modifier = Modifier .clickable { onLearnMoreClick() } - .padding(vertical = 4.dp, horizontal = 16.dp), + .padding(vertical = 4.dp, horizontal = 16.dp) + .semantics { + // Note: there is no Role.Link, so we use Role.Button for better accessibility support + role = Role.Button + }, text = stringResource(CommonStrings.action_learn_more), style = ElementTheme.typography.fontBodyLgMedium ) From 9912d763d41719f57fab36d05d5891b170ba01b6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 16:41:32 +0200 Subject: [PATCH 0301/1083] a11y: use different content description when the red dot is displayed Closes #6395 --- .../features/home/impl/components/HomeTopBar.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt index ff0fc00496..5c3075fc75 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt @@ -237,6 +237,7 @@ private fun SpaceFilterButton( else -> Unit } } + val isSelected = spaceFiltersState is SpaceFiltersState.Selected IconButton( onClick = ::onClick, @@ -320,7 +321,15 @@ private fun AccountIcon( Avatar( avatarData = avatarData, avatarType = AvatarType.User, - contentDescription = if (isCurrentAccount) stringResource(CommonStrings.common_settings) else null, + contentDescription = if (isCurrentAccount) { + if (showAvatarIndicator) { + stringResource(CommonStrings.a11y_settings_with_required_action) + } else { + stringResource(CommonStrings.common_settings) + } + } else { + null + }, ) if (showAvatarIndicator) { RedIndicatorAtom( From 70583fc3fce11779dc532104cc509e80158bc976 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 17:25:15 +0200 Subject: [PATCH 0302/1083] Remove unused content parameter. --- .../io/element/android/libraries/architecture/BaseFlowNode.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BaseFlowNode.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BaseFlowNode.kt index ce89e8a9d9..da849b753e 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BaseFlowNode.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/BaseFlowNode.kt @@ -11,7 +11,6 @@ package io.element.android.libraries.architecture import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxScope import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.ui.Modifier @@ -88,11 +87,9 @@ inline fun BaseFlowNode.OverlayView( @Composable inline fun BaseFlowNode.BackstackWithOverlayBox( modifier: Modifier = Modifier, - content: @Composable BoxScope.() -> Unit = {}, ) { Box(modifier = modifier) { BackstackView() OverlayView() - content() } } From 4e46f12a120f987bcf8c3899aec18d496824e3d2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 17:45:53 +0200 Subject: [PATCH 0303/1083] Remove useless Box --- .../impl/viewer/MediaViewerView.kt | 78 +++++++++---------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index abea2f66d2..7149592a26 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -204,48 +204,42 @@ fun MediaViewerView( } // Top bar AnimatedVisibility(visible = showOverlay, enter = fadeIn(), exit = fadeOut()) { - Box( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - ) { - when (currentData) { - is MediaViewerPageData.MediaViewerData -> { - MediaViewerTopBar( - data = currentData, - canShowInfo = state.canShowInfo, - onBackClick = onBackClick, - onShareClick = { - state.eventSink(MediaViewerEvent.Share(currentData)) - }, - onSaveClick = { - state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) - }, - onInfoClick = { - state.eventSink(MediaViewerEvent.OpenInfo(currentData)) - }, - ) - } - else -> { - TopAppBar( - title = { - if (currentData is MediaViewerPageData.Loading) { - Text( - modifier = Modifier.semantics { - heading() - }, - text = stringResource(id = CommonStrings.common_loading_more), - style = ElementTheme.typography.fontBodyMdMedium, - color = ElementTheme.colors.textPrimary, - ) - } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = bgCanvasWithTransparency, - ), - navigationIcon = { BackButton(onClick = onBackClick) }, - ) - } + when (currentData) { + is MediaViewerPageData.MediaViewerData -> { + MediaViewerTopBar( + data = currentData, + canShowInfo = state.canShowInfo, + onBackClick = onBackClick, + onShareClick = { + state.eventSink(MediaViewerEvent.Share(currentData)) + }, + onSaveClick = { + state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) + }, + onInfoClick = { + state.eventSink(MediaViewerEvent.OpenInfo(currentData)) + }, + ) + } + else -> { + TopAppBar( + title = { + if (currentData is MediaViewerPageData.Loading) { + Text( + modifier = Modifier.semantics { + heading() + }, + text = stringResource(id = CommonStrings.common_loading_more), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = bgCanvasWithTransparency, + ), + navigationIcon = { BackButton(onClick = onBackClick) }, + ) } } } From dcd0a98c0c73c2d23a0be25ec5763d5f84b73893 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 23 Apr 2026 17:49:31 +0200 Subject: [PATCH 0304/1083] Declare Top bar first and use zIndex. --- .../impl/viewer/MediaViewerView.kt | 88 ++++++++++--------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 7149592a26..f22f326986 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -59,6 +59,7 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import coil3.compose.AsyncImage import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -130,6 +131,52 @@ fun MediaViewerView( state.eventSink(MediaViewerEvent.OnNavigateTo(page)) } } + // Top bar + AnimatedVisibility( + modifier = Modifier.zIndex(1f), + visible = showOverlay, + enter = fadeIn(), + exit = fadeOut(), + ) { + when (currentData) { + is MediaViewerPageData.MediaViewerData -> { + MediaViewerTopBar( + data = currentData, + canShowInfo = state.canShowInfo, + onBackClick = onBackClick, + onShareClick = { + state.eventSink(MediaViewerEvent.Share(currentData)) + }, + onSaveClick = { + state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) + }, + onInfoClick = { + state.eventSink(MediaViewerEvent.OpenInfo(currentData)) + }, + ) + } + else -> { + TopAppBar( + title = { + if (currentData is MediaViewerPageData.Loading) { + Text( + modifier = Modifier.semantics { + heading() + }, + text = stringResource(id = CommonStrings.common_loading_more), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = bgCanvasWithTransparency, + ), + navigationIcon = { BackButton(onClick = onBackClick) }, + ) + } + } + } HorizontalPager( state = pagerState, modifier = Modifier, @@ -202,47 +249,6 @@ fun MediaViewerView( } } } - // Top bar - AnimatedVisibility(visible = showOverlay, enter = fadeIn(), exit = fadeOut()) { - when (currentData) { - is MediaViewerPageData.MediaViewerData -> { - MediaViewerTopBar( - data = currentData, - canShowInfo = state.canShowInfo, - onBackClick = onBackClick, - onShareClick = { - state.eventSink(MediaViewerEvent.Share(currentData)) - }, - onSaveClick = { - state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) - }, - onInfoClick = { - state.eventSink(MediaViewerEvent.OpenInfo(currentData)) - }, - ) - } - else -> { - TopAppBar( - title = { - if (currentData is MediaViewerPageData.Loading) { - Text( - modifier = Modifier.semantics { - heading() - }, - text = stringResource(id = CommonStrings.common_loading_more), - style = ElementTheme.typography.fontBodyMdMedium, - color = ElementTheme.colors.textPrimary, - ) - } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = bgCanvasWithTransparency, - ), - navigationIcon = { BackButton(onClick = onBackClick) }, - ) - } - } - } } when (val bottomSheetState = state.mediaBottomSheetState) { From 5e963fc743b3a279db90006cb63ec2fe853f2176 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 10:08:37 +0200 Subject: [PATCH 0305/1083] a11y: do not use Overlay if screen reader is active, or external keyboard is connected. Related to #6399 --- .../messages/impl/MessagesFlowNode.kt | 29 +++++++++-- .../features/messages/impl/MessagesNode.kt | 9 ++-- .../pinned/list/PinnedMessagesListNode.kt | 9 +++- .../impl/threads/ThreadedMessagesNode.kt | 9 ++-- .../ui/utils/a11y/hasExternalKeyboard.kt | 49 +++++++++++++++++++ 5 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/hasExternalKeyboard.kt 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 36e94ec456..4079a540f6 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 @@ -143,6 +143,7 @@ class MessagesFlowNode( val mediaInfo: MediaInfo, val mediaSource: MediaSource, val thumbnailSource: MediaSource?, + val canUseOverlay: Boolean, ) : NavTarget @Parcelize @@ -227,10 +228,11 @@ class MessagesFlowNode( callback.navigateToRoomDetails() } - override fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event): Boolean { + override fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event, canUseOverlay: Boolean): Boolean { return processEventClick( timelineMode = timelineMode, event = event, + canUseOverlay = canUseOverlay, ) } @@ -320,7 +322,11 @@ class MessagesFlowNode( ) val callback = object : MediaViewerEntryPoint.Callback { override fun onDone() { - overlay.hide() + if (navTarget.canUseOverlay) { + overlay.hide() + } else { + backstack.pop() + } } override fun viewInTimeline(eventId: EventId) { @@ -414,10 +420,11 @@ class MessagesFlowNode( } NavTarget.PinnedMessagesList -> { val callback = object : PinnedMessagesListNode.Callback { - override fun handleEventClick(event: TimelineItem.Event) { + override fun handleEventClick(event: TimelineItem.Event, canUseOverlay: Boolean) { processEventClick( timelineMode = Timeline.Mode.PinnedEvents, event = event, + canUseOverlay = canUseOverlay, ) } @@ -456,10 +463,11 @@ class MessagesFlowNode( focusedEventId = navTarget.focusedEventId, ) val callback = object : ThreadedMessagesNode.Callback { - override fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event): Boolean { + override fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event, canUseOverlay: Boolean): Boolean { return processEventClick( timelineMode = timelineMode, event = event, + canUseOverlay = canUseOverlay, ) } @@ -547,6 +555,7 @@ class MessagesFlowNode( private fun processEventClick( timelineMode: Timeline.Mode, event: TimelineItem.Event, + canUseOverlay: Boolean, ): Boolean { val navTarget = when (event.content) { is TimelineItemImageContent -> { @@ -556,6 +565,7 @@ class MessagesFlowNode( content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, + canUseOverlay = canUseOverlay, ) } is TimelineItemVideoContent -> { @@ -565,6 +575,7 @@ class MessagesFlowNode( content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, + canUseOverlay = canUseOverlay, ) } is TimelineItemFileContent -> { @@ -574,6 +585,7 @@ class MessagesFlowNode( content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, + canUseOverlay = canUseOverlay, ) } is TimelineItemAudioContent -> { @@ -583,6 +595,7 @@ class MessagesFlowNode( content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = null, + canUseOverlay = canUseOverlay, ) } is TimelineItemLocationContent -> { @@ -603,7 +616,11 @@ class MessagesFlowNode( } return when (navTarget) { is NavTarget.MediaViewer -> { - overlay.show(navTarget) + if (canUseOverlay) { + overlay.show(navTarget) + } else { + backstack.push(navTarget) + } true } is NavTarget.LocationViewer -> { @@ -620,6 +637,7 @@ class MessagesFlowNode( content: TimelineItemEventContentWithAttachment, mediaSource: MediaSource, thumbnailSource: MediaSource?, + canUseOverlay: Boolean, ): NavTarget { return NavTarget.MediaViewer( mode = mode, @@ -647,6 +665,7 @@ class MessagesFlowNode( ), mediaSource = mediaSource, thumbnailSource = thumbnailSource, + canUseOverlay = canUseOverlay, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index a2cf4a3da0..f8c54d284e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -68,6 +68,8 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard +import io.element.android.libraries.ui.utils.time.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.LoadMessagesUi import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.finishLongRunningTransaction @@ -115,7 +117,7 @@ class MessagesNode( ) interface Callback : Plugin { - fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event): Boolean + fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event, canUseOverlay: Boolean): Boolean fun navigateToPreviewAttachments(attachments: ImmutableList, inReplyToEventId: EventId?) fun navigateToRoomMemberDetails(userId: UserId) fun handlePermalinkClick(data: PermalinkData) @@ -247,6 +249,7 @@ class MessagesNode( override fun View(modifier: Modifier) { val activity = requireNotNull(LocalActivity.current) val isDark = ElementTheme.isLightTheme.not() + val canUseOverlay = !isTalkbackActive() && !hasExternalKeyboard() CompositionLocalProvider( LocalTimelineItemPresenterFactories provides timelineItemPresenterFactories, ) { @@ -268,11 +271,11 @@ class MessagesNode( onRoomDetailsClick = callback::navigateToRoomDetails, onEventContentClick = { isLive, event -> if (isLive) { - callback.handleEventClick(timelineController.mainTimelineMode(), event) + callback.handleEventClick(timelineController.mainTimelineMode(), event, canUseOverlay) } else { val detachedTimelineMode = timelineController.detachedTimelineMode() if (detachedTimelineMode != null) { - callback.handleEventClick(detachedTimelineMode, event) + callback.handleEventClick(detachedTimelineMode, event, canUseOverlay) } else { false } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt index cddc1831db..9800f0296a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt @@ -38,6 +38,8 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard +import io.element.android.libraries.ui.utils.time.isTalkbackActive @ContributesNode(RoomScope::class) @AssistedInject @@ -50,7 +52,7 @@ class PinnedMessagesListNode( private val permalinkParser: PermalinkParser, ) : Node(buildContext, plugins = plugins), PinnedMessagesListNavigator { interface Callback : Plugin { - fun handleEventClick(event: TimelineItem.Event) + fun handleEventClick(event: TimelineItem.Event, canUseOverlay: Boolean) fun navigateToRoomMemberDetails(userId: UserId) fun viewInTimeline(eventId: EventId) fun handlePermalinkClick(data: PermalinkData.RoomLink) @@ -103,6 +105,7 @@ class PinnedMessagesListNode( @Composable override fun View(modifier: Modifier) { + val canUseOverlay = !isTalkbackActive() && !hasExternalKeyboard() CompositionLocalProvider( LocalTimelineItemPresenterFactories provides timelineItemPresenterFactories, ) { @@ -113,7 +116,9 @@ class PinnedMessagesListNode( PinnedMessagesListView( state = state, onBackClick = ::navigateUp, - onEventClick = callback::handleEventClick, + onEventClick = { + callback.handleEventClick(it, canUseOverlay) + }, onUserDataClick = { callback.navigateToRoomMemberDetails(it.userId) }, onLinkClick = { link -> onLinkClick(context, link.url) }, onLinkLongClick = { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 0949237862..c51c24c168 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -68,6 +68,8 @@ import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.mediaplayer.api.MediaPlayer +import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard +import io.element.android.libraries.ui.utils.time.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.appnavstate.api.AppNavigationStateService import kotlinx.collections.immutable.ImmutableList @@ -124,7 +126,7 @@ class ThreadedMessagesNode( } interface Callback : Plugin { - fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event): Boolean + fun handleEventClick(timelineMode: Timeline.Mode, event: TimelineItem.Event, canUseOverlay: Boolean): Boolean fun navigateToPreviewAttachments(attachments: ImmutableList, inReplyToEventId: EventId?) fun navigateToRoomMemberDetails(userId: UserId) fun handlePermalinkClick(data: PermalinkData) @@ -252,6 +254,7 @@ class ThreadedMessagesNode( override fun View(modifier: Modifier) { val activity = requireNotNull(LocalActivity.current) val isDark = ElementTheme.isLightTheme.not() + val canUseOverlay = !isTalkbackActive() && !hasExternalKeyboard() CompositionLocalProvider( LocalTimelineItemPresenterFactories provides timelineItemPresenterFactories, ) { @@ -271,11 +274,11 @@ class ThreadedMessagesNode( onEventContentClick = { isLive, event -> timelineController?.let { controller -> if (isLive) { - callback.handleEventClick(controller.mainTimelineMode(), event) + callback.handleEventClick(controller.mainTimelineMode(), event, canUseOverlay) } else { val detachedTimelineMode = controller.detachedTimelineMode() if (detachedTimelineMode != null) { - callback.handleEventClick(detachedTimelineMode, event) + callback.handleEventClick(detachedTimelineMode, event, canUseOverlay) } else { false } diff --git a/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/hasExternalKeyboard.kt b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/hasExternalKeyboard.kt new file mode 100644 index 0000000000..ed35cfbc3e --- /dev/null +++ b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/hasExternalKeyboard.kt @@ -0,0 +1,49 @@ +/* + * 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.ui.utils.a11y + +import android.app.Activity +import android.app.Application +import android.content.res.Configuration +import android.os.Build +import android.os.Bundle +import androidx.activity.compose.LocalActivity +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue + +@Composable +fun hasExternalKeyboard(): Boolean { + val activity = requireNotNull(LocalActivity.current) + var hasExternalKeyboard by remember { mutableStateOf(activity.resources.configuration.keyboard != Configuration.KEYBOARD_NOKEYS) } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + DisposableEffect(Unit) { + val callback = object : Application.ActivityLifecycleCallbacks { + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {} + override fun onActivityStarted(activity: Activity) {} + override fun onActivityResumed(activity: Activity) { + // We do not have access to onActivityConfigurationChanged, so update the value when tha Activity is resumed + hasExternalKeyboard = activity.resources.configuration.keyboard != Configuration.KEYBOARD_NOKEYS + } + + override fun onActivityPaused(activity: Activity) {} + override fun onActivityStopped(activity: Activity) {} + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {} + override fun onActivityDestroyed(activity: Activity) {} + } + activity.registerActivityLifecycleCallbacks(callback) + onDispose { + activity.unregisterActivityLifecycleCallbacks(callback) + } + } + } + return hasExternalKeyboard +} From 97cada743278217b137c960d9b25241564c5a6b1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 10:09:50 +0200 Subject: [PATCH 0306/1083] Move isTalkbackActive to a11y package. --- .../io/element/android/features/messages/impl/MessagesNode.kt | 2 +- .../messages/impl/pinned/list/PinnedMessagesListNode.kt | 2 +- .../features/messages/impl/threads/ThreadedMessagesNode.kt | 2 +- .../android/features/messages/impl/timeline/TimelineView.kt | 2 +- .../messages/impl/timeline/components/MessageEventBubble.kt | 2 +- .../messages/impl/timeline/components/TimelineItemEventRow.kt | 2 +- .../impl/timeline/components/TimelineItemGroupedEventsRow.kt | 2 +- .../messages/impl/timeline/components/TimelineItemRow.kt | 2 +- .../impl/timeline/components/event/TimelineItemImageView.kt | 2 +- .../impl/timeline/components/event/TimelineItemVideoView.kt | 2 +- .../impl/timeline/components/event/TimelineItemVoiceView.kt | 2 +- .../libraries/ui/utils/{time => a11y}/IsTalkbackEnabled.kt | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) rename libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/{time => a11y}/IsTalkbackEnabled.kt (96%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index f8c54d284e..308cda506e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -69,7 +69,7 @@ import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugIn import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction.LoadMessagesUi import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.finishLongRunningTransaction diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt index 9800f0296a..a618117950 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt @@ -39,7 +39,7 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive @ContributesNode(RoomScope::class) @AssistedInject diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index c51c24c168..0c58316b5e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -69,7 +69,7 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.appnavstate.api.AppNavigationStateService import kotlinx.collections.immutable.ImmutableList diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 2105cf9df7..41a828abb4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -77,7 +77,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.link.Link import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt index aa5aaa2075..80bd342d01 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt @@ -47,8 +47,8 @@ import io.element.android.libraries.designsystem.theme.messageFromMeBackground import io.element.android.libraries.designsystem.theme.messageFromOtherBackground import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.libraries.ui.utils.graphics.drawInLayer -import io.element.android.libraries.ui.utils.time.isTalkbackActive private val BUBBLE_RADIUS = 12.dp private val avatarRadius = AvatarSize.TimelineSender.dp / 2 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 976fa3c17e..f15d4d39a5 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 @@ -120,7 +120,7 @@ import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonPlurals import io.element.android.libraries.ui.strings.CommonStrings -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.link.Link import kotlinx.coroutines.launch import kotlin.math.abs diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt index 8316911843..df2b9d8691 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt @@ -34,7 +34,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.link.Link @Composable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index e75df2f89f..842b7a08f5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -47,7 +47,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.ui.strings.CommonStrings -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.link.Link import kotlin.time.DurationUnit diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt index a8cbb89e96..bef06bcd73 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt @@ -54,7 +54,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle import io.element.android.libraries.ui.strings.CommonStrings -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.compose.EditorStyledText import io.element.android.wysiwyg.link.Link diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt index f5e760736e..8d1ef18f39 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt @@ -64,7 +64,7 @@ import io.element.android.libraries.matrix.ui.media.MAX_THUMBNAIL_WIDTH import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle import io.element.android.libraries.ui.strings.CommonStrings -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.compose.EditorStyledText import io.element.android.wysiwyg.link.Link diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVoiceView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVoiceView.kt index 5dbd0c478f..86e3f1c849 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVoiceView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVoiceView.kt @@ -52,7 +52,7 @@ 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 -import io.element.android.libraries.ui.utils.time.isTalkbackActive +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.libraries.voiceplayer.api.VoiceMessageEvent import io.element.android.libraries.voiceplayer.api.VoiceMessageState import io.element.android.libraries.voiceplayer.api.VoiceMessageStateProvider diff --git a/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/time/IsTalkbackEnabled.kt b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/IsTalkbackEnabled.kt similarity index 96% rename from libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/time/IsTalkbackEnabled.kt rename to libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/IsTalkbackEnabled.kt index 60ac1887c6..938a774355 100644 --- a/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/time/IsTalkbackEnabled.kt +++ b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/IsTalkbackEnabled.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.ui.utils.time +package io.element.android.libraries.ui.utils.a11y import android.view.accessibility.AccessibilityManager import androidx.compose.runtime.Composable From 562e36b5eae3cae43344ea88c1d93c3bb9c21015 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 10:41:36 +0200 Subject: [PATCH 0307/1083] Improve how the ThumbnailView is added to the composition --- .../impl/viewer/MediaViewerView.kt | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index f22f326986..f767fdbde1 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -373,11 +373,12 @@ private fun MediaViewerPage( isUserSelected = isUserSelected, audioFocus = audioFocus, ) - ThumbnailView( - mediaInfo = data.mediaInfo, - thumbnailSource = data.thumbnailSource, - isVisible = showThumbnail, - ) + if (showThumbnail) { + ThumbnailView( + mediaInfo = data.mediaInfo, + thumbnailSource = data.thumbnailSource, + ) + } if (showError) { ErrorView( errorMessage = stringResource(id = CommonStrings.error_unknown), @@ -603,7 +604,6 @@ private val maxCaptionHeightLandscape = 128.dp @Composable private fun ThumbnailView( thumbnailSource: MediaSource?, - isVisible: Boolean, mediaInfo: MediaInfo, modifier: Modifier = Modifier, ) { @@ -611,21 +611,19 @@ private fun ThumbnailView( modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - if (isVisible) { - val mediaRequestData = MediaRequestData( - source = thumbnailSource, - kind = MediaRequestData.Kind.File(mediaInfo.filename, mediaInfo.mimeType) - ) - val alpha = if (LocalInspectionMode.current) 0.1f else 1f - AsyncImage( - modifier = Modifier - .fillMaxSize() - .alpha(alpha), - model = mediaRequestData, - contentScale = ContentScale.Fit, - contentDescription = null, - ) - } + val mediaRequestData = MediaRequestData( + source = thumbnailSource, + kind = MediaRequestData.Kind.File(mediaInfo.filename, mediaInfo.mimeType) + ) + val alpha = if (LocalInspectionMode.current) 0.1f else 1f + AsyncImage( + modifier = Modifier + .fillMaxSize() + .alpha(alpha), + model = mediaRequestData, + contentScale = ContentScale.Fit, + contentDescription = null, + ) } } From 8188ef1463701911daf441f8b498441abe87ede7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 11:31:32 +0200 Subject: [PATCH 0308/1083] Improve MediaViewerBottomBar usage. --- .../impl/viewer/MediaViewerView.kt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index f767fdbde1..c3c8aa8907 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -233,17 +233,17 @@ fun MediaViewerView( isUserSelected = (state.listData[page] as? MediaViewerPageData.MediaViewerData)?.eventId == state.initiallySelectedEventId, ) // Bottom bar - AnimatedVisibility(visible = showOverlay, enter = fadeIn(), exit = fadeOut()) { - Box( - modifier = Modifier.fillMaxSize() - ) { - MediaViewerBottomBar( - modifier = Modifier.align(Alignment.BottomCenter), - showDivider = dataForPage.mediaInfo.mimeType.isMimeTypeVideo(), - caption = dataForPage.mediaInfo.caption, - onHeightChange = { bottomPaddingInPixels = it }, - ) - } + AnimatedVisibility( + visible = showOverlay, + enter = fadeIn(), + exit = fadeOut(), + modifier = Modifier.align(Alignment.BottomCenter), + ) { + MediaViewerBottomBar( + showDivider = dataForPage.mediaInfo.mimeType.isMimeTypeVideo(), + caption = dataForPage.mediaInfo.caption, + onHeightChange = { bottomPaddingInPixels = it }, + ) } } } From b1890de26aa36097ea01eaeb1a1d819c2a5e0608 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 11:46:57 +0200 Subject: [PATCH 0309/1083] MediaViewerView: move TopBar to Scaffold topbar --- .../impl/viewer/MediaViewerView.kt | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index c3c8aa8907..5b10fbfe96 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -121,6 +121,52 @@ fun MediaViewerView( Scaffold( modifier, containerColor = Color.Transparent, + topBar = { + AnimatedVisibility( + visible = showOverlay, + enter = fadeIn(), + exit = fadeOut(), + ) { + when (currentData) { + is MediaViewerPageData.MediaViewerData -> { + MediaViewerTopBar( + data = currentData, + canShowInfo = state.canShowInfo, + onBackClick = onBackClick, + onShareClick = { + state.eventSink(MediaViewerEvent.Share(currentData)) + }, + onSaveClick = { + state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) + }, + onInfoClick = { + state.eventSink(MediaViewerEvent.OpenInfo(currentData)) + }, + ) + } + else -> { + TopAppBar( + title = { + if (currentData is MediaViewerPageData.Loading) { + Text( + modifier = Modifier.semantics { + heading() + }, + text = stringResource(id = CommonStrings.common_loading_more), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = bgCanvasWithTransparency, + ), + navigationIcon = { BackButton(onClick = onBackClick) }, + ) + } + } + } + }, snackbarHost = { SnackbarHost(snackbarHostState) }, ) { val pagerState = rememberPagerState(state.currentIndex, 0f) { @@ -131,52 +177,6 @@ fun MediaViewerView( state.eventSink(MediaViewerEvent.OnNavigateTo(page)) } } - // Top bar - AnimatedVisibility( - modifier = Modifier.zIndex(1f), - visible = showOverlay, - enter = fadeIn(), - exit = fadeOut(), - ) { - when (currentData) { - is MediaViewerPageData.MediaViewerData -> { - MediaViewerTopBar( - data = currentData, - canShowInfo = state.canShowInfo, - onBackClick = onBackClick, - onShareClick = { - state.eventSink(MediaViewerEvent.Share(currentData)) - }, - onSaveClick = { - state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) - }, - onInfoClick = { - state.eventSink(MediaViewerEvent.OpenInfo(currentData)) - }, - ) - } - else -> { - TopAppBar( - title = { - if (currentData is MediaViewerPageData.Loading) { - Text( - modifier = Modifier.semantics { - heading() - }, - text = stringResource(id = CommonStrings.common_loading_more), - style = ElementTheme.typography.fontBodyMdMedium, - color = ElementTheme.colors.textPrimary, - ) - } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = bgCanvasWithTransparency, - ), - navigationIcon = { BackButton(onClick = onBackClick) }, - ) - } - } - } HorizontalPager( state = pagerState, modifier = Modifier, From d6f8c13c3f1c9b0480c28778c0dccd86ef6ce0a0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 24 Apr 2026 12:08:19 +0200 Subject: [PATCH 0310/1083] MediaPlayerControllerView: Use IconButton instead of Box and remove the clipping. --- .../local/player/MediaPlayerControllerView.kt | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt index b83c598c10..b06b97f491 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt @@ -12,13 +12,12 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -28,7 +27,6 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter @@ -91,33 +89,31 @@ fun MediaPlayerControllerView( .widthIn(max = 480.dp), verticalAlignment = Alignment.CenterVertically, ) { - val bgColor = if (state.isPlaying) { - ElementTheme.colors.bgCanvasDefault + val colors = if (state.isPlaying) { + IconButtonDefaults.iconButtonColors( + containerColor = ElementTheme.colors.bgCanvasDefault, + contentColor = ElementTheme.colors.iconPrimary, + ) } else { - ElementTheme.colors.textPrimary + IconButtonDefaults.iconButtonColors( + containerColor = ElementTheme.colors.iconPrimary, + contentColor = ElementTheme.colors.iconOnSolidPrimary, + ) } - Box( + IconButton( modifier = Modifier - .size(36.dp) - .background( - color = bgColor, - shape = CircleShape, - ) - .clip(CircleShape) - .clickable { onTogglePlay() } - .padding(8.dp), - contentAlignment = Alignment.Center, + .size(36.dp), + onClick = onTogglePlay, + colors = colors, ) { if (state.isPlaying) { Icon( imageVector = CompoundIcons.PauseSolid(), - tint = ElementTheme.colors.iconPrimary, contentDescription = stringResource(CommonStrings.a11y_pause) ) } else { Icon( imageVector = CompoundIcons.PlaySolid(), - tint = ElementTheme.colors.iconOnSolidPrimary, contentDescription = stringResource(CommonStrings.a11y_play) ) } From 0b04dec85c88d76c412e1f53b4a9c3033e05ff88 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 30 Apr 2026 10:44:04 +0000 Subject: [PATCH 0311/1083] Update screenshots --- .../images/features.roomdetails.impl_RoomDetailsA11y_en.png | 4 ++-- ...s.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png | 4 ++-- ...s.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en.png | 4 ++-- ...mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png | 4 ++-- ...mediaviewer.impl.local.audio_MediaAudioView_Night_1_en.png | 4 ++-- ...r.impl.local.player_MediaPlayerControllerView_Day_0_en.png | 4 ++-- ...r.impl.local.player_MediaPlayerControllerView_Day_1_en.png | 4 ++-- ...r.impl.local.player_MediaPlayerControllerView_Day_2_en.png | 4 ++-- ...impl.local.player_MediaPlayerControllerView_Night_0_en.png | 4 ++-- ...impl.local.player_MediaPlayerControllerView_Night_1_en.png | 4 ++-- ...impl.local.player_MediaPlayerControllerView_Night_2_en.png | 4 ++-- ...s.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png | 4 ++-- ...mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png | 4 ++-- 21 files changed, 42 insertions(+), 42 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png index 8d8186f2d3..5f0cdd8eca 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2119838c9649710465dc1b8610550ce101f3016a1a6511c3f6dadc715fb75862 -size 82975 +oid sha256:33d583fac967f383a3d3535c4ac38aaccdcbf4a1d48323ff375a239dbce81838 +size 83494 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png index 8ca8df6e8e..3c218ccbbc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c7dea18de5eabe820fe8670cd09d7b68160a97f31e4f1c474c790d829854ef7 -size 25291 +oid sha256:b918ce7162d95c873f0029a657ee07fca2e34926e4c3cdb39eaeb10123a08721 +size 25340 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en.png index e7f7345c31..37ecdb10ac 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98b39ded83aac1bb5befba6749c08a328b6855bcbd491c1a2f669c848ce72c31 -size 22982 +oid sha256:478c8ee2d55bb2a9f99b8d83c6e0eb0b316237ff1a60a6a735b5eb06f7ca083e +size 23029 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png index 086f166d79..e6925f9f5b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f7aa184c28a4281a30a443b208bf3f64d9a0f85ad135ef50c999d40362c67d4 -size 24670 +oid sha256:d62cf7beeba92ee47193a871becad07f50d27e6f6fa0b85f6c620c3f1b04b6ce +size 24697 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en.png index 86ab39550c..e62cdf3ec4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e13b61fcb56fbd64064bc35628957cb68507efb7fdc25280d6dbf1e6477addc -size 22637 +oid sha256:d684c9ed8b2c38cdf7017194ca656ca8da161ab0a40ef3270c6e3988d8e7f144 +size 22664 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en.png index 67fbefb086..ad12fe8923 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbd0574dba895e157ff5b69ab23f3b389d280538810b457d2860ae5d77331705 -size 8256 +oid sha256:2b55fce1bf0d6b764aaed8eed0fbc1416c5aa1c5b6160775a641dfa10addb227 +size 8231 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en.png index 6b140844b0..db6b026090 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e87c0990dcaf2511a2a0573a04bf14c6a9a7d24e0291fed18aa3a9ea28da572 -size 7543 +oid sha256:4ca666990cb421602e21be0dbf4ec075e8d3e94f9835464923bd31d2414d9d57 +size 7594 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_2_en.png index de0bd78c7d..e40d0af8b2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ed14962b63afa972c68a53d2366b9f00906bab2f3436220bb28643fcb1d56cb -size 7668 +oid sha256:01726f688e5149a460cb1004dff0c7700302a3fe7179829603625dd369b20e78 +size 7659 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en.png index bded2caa96..65f3240329 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a50093fb47b3b17a2ccd1aeb2a10fb6b5d368add8f7d458e50f0cc8643128b7c -size 8053 +oid sha256:8c30a496415f6c00f5ce3a01c775c78994992efd68b2548ecbb5b5ffac054cc1 +size 8041 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en.png index 7030c0a8c4..039388acdc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a45336123e1eec5ea4b21c6932c1c11d6024685f736454e585a0fb6e6a85ccb2 -size 7701 +oid sha256:10f58df934f372a3b8c68c8e0c4ef61e5bfef242d65daa8f34f4999249bf9e8d +size 7799 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_2_en.png index 41449d52b8..f9f1b8195d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:174f9f97fbce115d36fc5124d3301bd148444acdf24bdc933b5a3fb0754c883d -size 7545 +oid sha256:6d452b48ef65df5257eb708553d667bee46b9d83b1c29a07119c54e342cf1bc2 +size 7527 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png index 9b62306041..12f6ba7c36 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed8342b56d749db4d862aaa82d5d312089494965c2879adf18e8fd0c94f8525f -size 13476 +oid sha256:f10ca2d461e4078e46455e007eca2d1e9c9a20dbb6bc24c681fa5164e5f50efd +size 13531 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png index 72bd9cfb6c..6273b591af 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04a62974dd81e0786127501b8778f9d302db38a27c984d1b403884942d43accd -size 13209 +oid sha256:da386980ce6a45e102727715b5d50f219e39dcb40a513abdfaab9fa725b8ea41 +size 13260 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png index d2231ed54c..9ca317cf9d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:041669475888f2f0c3b2d34502ae72098547340d8c2422ea2a674d38eb6a6241 -size 207620 +oid sha256:d265f0c3fe5bc7f5a6e6d6cfa022ba16ca770b65eeb9a742ba250ff55c4b066a +size 207625 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png index 8a6ebb2746..d404456119 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c56b22d79924d1f463f01428d5be1c69c8068b94a953160fae59a9f6faa112ad -size 206047 +oid sha256:f6870b9c1a5aad4257aa4bd7b13d0be5bea281778061d71c711495aadfaafdb8 +size 206057 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png index bbea97e0b3..77e9dad534 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e72ef42ad838837ce2427af5677931f5db68f876eccc297894c7a2cdd437cffa -size 210729 +oid sha256:094c1de97c33431390f3ff71d73019d9af9a62ed57ba98c94e53f1f9680851fa +size 210728 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png index 67bec8b0d3..c3caba08ff 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58a323c4f06745a877ea546870fbe69ec927aea50584001b3871cad833fca1d4 -size 211343 +oid sha256:2a17d0f4bc47305b9c8a3866f70cdddb16fcb5ba10c8007c8739a329025e846a +size 211342 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png index d5b81bb469..4734e4e6db 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55671428c52d37c3f63f8b3410817d4e893e2f4327b31b227bc7b7d9ff84b884 -size 134680 +oid sha256:b593f6827598052cbde0e580dcd43b92fb098f6755779b95a60bb691d9ad5003 +size 134711 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png index 26dcbe4099..c44162b0ff 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7bee65567cced59131d471b5c3795347a2ef52cf64ff74b47f1c983a0b4a36f -size 130718 +oid sha256:c0249f33aca3e50713c87a3826e71985991f0996998132c42a374c6169800023 +size 130728 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png index f2ff11333d..932ddfb632 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3cea16c42488306fe29fd22362a0d37c1eeb0fbb1db48f26ad7ff18f6b196ae -size 137605 +oid sha256:43ab4873fc5fc812bf18af50cbe620c83b273ee70305b5ea06a7aeabdf8dbc93 +size 137637 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png index 62de7a4953..924e24ba8a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58655e1846dbe73c287073ac909ee6c881a0ad800e8852653116fdbfd043b9a0 -size 137881 +oid sha256:33048dafab286cf0e5c84040c034d93a42d69c234edd53132d918a4a1c135ece +size 137908 From b8995e4356a85fdc1bb7438366fb7995b368c1d9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 14:09:07 +0200 Subject: [PATCH 0312/1083] Fix quality issues --- .../android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 1 - .../a11y/{hasExternalKeyboard.kt => HasExternalKeyboard.kt} | 0 2 files changed, 1 deletion(-) rename libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/{hasExternalKeyboard.kt => HasExternalKeyboard.kt} (100%) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 5b10fbfe96..738d940453 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -59,7 +59,6 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import androidx.compose.ui.zIndex import coil3.compose.AsyncImage import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons diff --git a/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/hasExternalKeyboard.kt b/libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/HasExternalKeyboard.kt similarity index 100% rename from libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/hasExternalKeyboard.kt rename to libraries/ui-utils/src/main/kotlin/io/element/android/libraries/ui/utils/a11y/HasExternalKeyboard.kt From 13775f4fbdf7af89603785e6072d2f902dd3d401 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 14:09:41 +0200 Subject: [PATCH 0313/1083] Update kotlin version --- .idea/kotlinc.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 76f6344777..f393d5cdd1 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,7 @@ - From 30fd90abb9450e267ba1f9addd69c9d778b2fbca Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 30 Apr 2026 16:01:24 +0200 Subject: [PATCH 0314/1083] Mitigate a deadlock when loading room timelines (#6674) This may be happening because we were not destroying focused event timelines used for the media viewer/gallery when necessary, and having several of those back paginating *may* have caused a deadlock in the event cache. --- .../impl/datasource/MediaGalleryDataSource.kt | 13 +++++++++---- .../impl/gallery/MediaGalleryPresenter.kt | 2 +- .../impl/viewer/MediaViewerDataSource.kt | 6 ++++-- .../mediaviewer/impl/viewer/MediaViewerPresenter.kt | 2 +- .../impl/viewer/SingleMediaGalleryDataSource.kt | 3 ++- .../impl/datasource/FakeMediaGalleryDataSource.kt | 3 ++- .../TimelineMediaGalleryDataSourceTest.kt | 12 ++++++------ .../impl/viewer/MediaViewerDataSourceTest.kt | 2 +- .../impl/viewer/SingleMediaGalleryDataSourceTest.kt | 4 ++-- 9 files changed, 28 insertions(+), 19 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt index 722e14a790..f5418c76c9 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow @@ -27,10 +28,11 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach +import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean interface MediaGalleryDataSource { - fun start() + fun start(coroutineScope: CoroutineScope) fun groupedMediaItemsFlow(): Flow> fun getLastData(): AsyncData suspend fun loadMore(direction: Timeline.PaginationDirection) @@ -58,7 +60,7 @@ class TimelineMediaGalleryDataSource( private val isStarted = AtomicBoolean(false) @OptIn(ExperimentalCoroutinesApi::class) - override fun start() { + override fun start(coroutineScope: CoroutineScope) { if (!isStarted.compareAndSet(false, true)) { return } @@ -96,9 +98,12 @@ class TimelineMediaGalleryDataSource( groupedMediaItemsFlow.emit(AsyncData.Success(groupedMediaItems)) } .onCompletion { - timeline?.close() + timeline?.let { + Timber.d("Timeline media gallery data source flow completed for room ${room.roomId}, closing timeline") + it.close() + } } - .launchIn(room.roomCoroutineScope) + .launchIn(coroutineScope) } override suspend fun loadMore(direction: Timeline.PaginationDirection) { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index ac9b365099..e7caa12f2e 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -78,7 +78,7 @@ class MediaGalleryPresenter( .collectAsState(AsyncData.Uninitialized) LaunchedEffect(Unit) { - mediaGalleryDataSource.start() + mediaGalleryDataSource.start(this) } val permissions by room.permissionsAsState(MediaPermissions.DEFAULT) { perms -> 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 a9fb5d645c..24e48531f0 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 @@ -35,6 +35,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext @@ -62,11 +63,12 @@ class MediaViewerDataSource( private val localMediaStates: MutableMap>> = mutableMapOf() - fun setup() { - galleryDataSource.start() + fun setup(coroutineScope: CoroutineScope) { + galleryDataSource.start(coroutineScope) } fun dispose() { + Timber.d("Disposing MediaViewerDataSource, closing ${mediaFiles.size} media files") mediaFiles.forEach { it.close() } mediaFiles.clear() localMediaStates.clear() 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 b7631a7039..60f03bb1e0 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 @@ -88,7 +88,7 @@ class MediaViewerPresenter( var mediaBottomSheetState by remember { mutableStateOf(MediaBottomSheetState.Hidden) } DisposableEffect(Unit) { - dataSource.setup() + dataSource.setup(coroutineScope) onDispose { dataSource.dispose() } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt index f243ac4fd7..7bbf397171 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt @@ -20,12 +20,13 @@ import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryData import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems import io.element.android.libraries.mediaviewer.impl.model.MediaItem import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flowOf class SingleMediaGalleryDataSource( private val data: GroupedMediaItems, ) : MediaGalleryDataSource { - override fun start() = Unit + override fun start(coroutineScope: CoroutineScope) = Unit override fun groupedMediaItemsFlow() = flowOf(AsyncData.Success(data)) override fun getLastData(): AsyncData = AsyncData.Success(data) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt index c612bba1bc..4a64f02a33 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems import io.element.android.tests.testutils.lambda.lambdaError +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow @@ -21,7 +22,7 @@ class FakeMediaGalleryDataSource( private val loadMoreLambda: (Timeline.PaginationDirection) -> Unit = { lambdaError() }, private val deleteItemLambda: (EventId) -> Unit = { lambdaError() }, ) : MediaGalleryDataSource { - override fun start() = startLambda() + override fun start(coroutineScope: CoroutineScope) = startLambda() private val groupedMediaItemsFlow = MutableSharedFlow>( replay = 1 diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt index bb8419dde5..528fc1da70 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt @@ -80,7 +80,7 @@ class TimelineMediaGalleryDataSourceTest { roomCoroutineScope = backgroundScope, ) ) - sut.start() + sut.start(backgroundScope) assertThat(sut.getLastData()).isEqualTo(AsyncData.Uninitialized) sut.groupedMediaItemsFlow().test { assertThat(awaitItem().isLoading()).isTrue() @@ -95,7 +95,7 @@ class TimelineMediaGalleryDataSourceTest { ) assertThat(sut.getLastData().isSuccess()).isTrue() // Also test that starting again should have no effect - sut.start() + sut.start(backgroundScope) } } // Ensure that the timeline has been closed on flow completion @@ -117,7 +117,7 @@ class TimelineMediaGalleryDataSourceTest { roomCoroutineScope = backgroundScope, ) ) - sut.start() + sut.start(backgroundScope) sut.groupedMediaItemsFlow().test { skipItems(2) sut.loadMore(Timeline.PaginationDirection.BACKWARDS) @@ -140,7 +140,7 @@ class TimelineMediaGalleryDataSourceTest { roomCoroutineScope = backgroundScope, ) ) - sut.start() + sut.start(backgroundScope) sut.groupedMediaItemsFlow().test { skipItems(2) sut.deleteItem(AN_EVENT_ID) @@ -159,7 +159,7 @@ class TimelineMediaGalleryDataSourceTest { roomCoroutineScope = backgroundScope, ) ) - sut.start() + sut.start(backgroundScope) sut.groupedMediaItemsFlow().test { assertThat(awaitItem().isLoading()).isTrue() assertThat(sut.getLastData().isLoading()).isTrue() @@ -181,7 +181,7 @@ class TimelineMediaGalleryDataSourceTest { roomCoroutineScope = backgroundScope, ) ) - sut.start() + sut.start(backgroundScope) sut.groupedMediaItemsFlow().test { assertThat(awaitItem().isLoading()).isTrue() assertThat(sut.getLastData().isLoading()).isTrue() diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt index 44eed2733f..c3f1ab9a0d 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt @@ -50,7 +50,7 @@ class MediaViewerDataSourceTest { val sut = createMediaViewerDataSource( galleryDataSource = galleryDataSource, ) - sut.setup() + sut.setup(backgroundScope) startLambda.assertions().isCalledOnce() } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt index c6460cb70a..8c0a7c05d0 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt @@ -37,9 +37,9 @@ class SingleMediaGalleryDataSourceTest { val warmUpRule = WarmUpRule() @Test - fun `function start is no op`() { + fun `function start is no op`() = runTest { val sut = SingleMediaGalleryDataSource(aGroupedMediaItems()) - sut.start() + sut.start(backgroundScope) } @Test From 11b9efa2c98ad73faa1e05c840e5c8b8fb45431f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 15:54:33 +0200 Subject: [PATCH 0315/1083] Migrate to v2 testing APIs --- .../FullscreenAnnouncementViewTest.kt | 25 ++- .../features/call/ui/CallScreenViewTest.kt | 32 ++- .../impl/AccountDeactivationViewTest.kt | 55 +++--- .../forward/impl/ForwardMessagesViewTest.kt | 23 ++- .../ChooseSessionVerificationModeViewTest.kt | 37 ++-- .../impl/filters/RoomListFiltersViewTest.kt | 20 +- .../impl/roomlist/RoomListContextMenuTest.kt | 48 ++--- .../roomlist/RoomListDeclineInviteMenuTest.kt | 33 ++-- .../home/impl/roomlist/RoomListViewTest.kt | 84 ++++---- .../impl/spacefilters/SpaceFiltersViewTest.kt | 34 ++-- .../DeclineAndBlockViewTest.kt | 49 +++-- .../joinroom/impl/JoinRoomViewTest.kt | 121 ++++++------ .../banner/KnockRequestsBannerViewTest.kt | 40 ++-- .../impl/list/KnockRequestsListViewTest.kt | 61 +++--- .../screens/desktop/DesktopNoticeViewTest.kt | 36 ++-- .../impl/screens/error/ErrorViewTest.kt | 32 ++- .../screens/number/EnterNumberViewTest.kt | 40 ++-- .../impl/screens/qrcode/ShowQrCodeViewTest.kt | 20 +- .../screens/root/LinkNewDeviceRootViewTest.kt | 38 ++-- .../impl/screens/scan/ScanQrCodeViewTest.kt | 26 ++- .../impl/share/ShareLocationViewTest.kt | 61 +++--- .../impl/show/ShowLocationViewTest.kt | 57 +++--- .../impl/unlock/keypad/PinKeypadTest.kt | 33 ++-- .../ChooseAccountProviderViewTest.kt | 32 ++- .../loginpassword/LoginPasswordViewTest.kt | 97 +++++---- .../screens/onboarding/OnboardingViewTest.kt | 100 +++++----- .../QrCodeConfirmationViewTest.kt | 26 ++- .../qrcode/error/QrCodeErrorViewTest.kt | 32 ++- .../qrcode/intro/QrCodeIntroViewTest.kt | 36 ++-- .../screens/qrcode/scan/QrCodeScanViewTest.kt | 24 ++- .../features/logout/impl/LogoutViewTest.kt | 49 +++-- .../direct/DefaultDirectLogoutViewTest.kt | 43 ++-- .../messages/impl/MessagesViewTest.kt | 173 ++++++++-------- .../identity/IdentityChangeStateViewTest.kt | 43 ++-- .../ResolveVerifiedUserSendFailureViewTest.kt | 25 ++- .../messages/impl/link/LinkViewTest.kt | 30 ++- .../banner/PinnedMessagesBannerViewTest.kt | 25 ++- .../pinned/list/PinnedMessagesListViewTest.kt | 32 ++- .../DefaultHtmlConverterProviderTest.kt | 12 +- .../impl/timeline/TimelineViewTest.kt | 65 +++--- .../event/TimelineItemPollViewTest.kt | 28 +-- .../components/event/TimelineTextViewTest.kt | 38 ++-- .../timeline/protection/ProtectedViewTest.kt | 27 ++- .../poll/impl/history/PollHistoryViewTest.kt | 56 +++--- .../preferences/impl/about/AboutViewTest.kt | 31 ++- .../impl/advanced/AdvancedSettingsViewTest.kt | 108 +++++----- .../impl/blockedusers/BlockedUserViewTest.kt | 38 ++-- .../developer/DeveloperSettingsViewTest.kt | 38 ++-- .../AppDeveloperSettingsPageTest.kt | 44 ++--- .../NotificationSettingsViewTest.kt | 86 ++++---- .../impl/root/PreferencesRootViewTest.kt | 187 +++++++++--------- .../editprofile/EditUserProfileViewTest.kt | 54 ++--- .../reportroom/impl/ReportRoomViewTest.kt | 43 ++-- .../ChangeRoomPermissionsViewTest.kt | 75 ++++--- .../impl/roles/ChangeRolesViewTest.kt | 111 ++++++----- .../impl/root/RolesAndPermissionsViewTest.kt | 86 ++++---- .../impl/RoomAliasHelperViewTest.kt | 29 ++- .../roomdetails/impl/RoomDetailsViewTest.kt | 149 +++++++------- .../impl/RoomDetailsEditViewTest.kt | 95 +++++---- .../impl/root/RoomDirectoryViewTest.kt | 29 ++- .../impl/RoomMemberModerationViewTest.kt | 85 ++++---- .../SecureBackupEnterRecoveryKeyViewTest.kt | 57 +++--- .../password/ResetIdentityPasswordViewTest.kt | 40 ++-- .../reset/root/ResetIdentityRootViewTest.kt | 44 ++--- .../EditRoomAddressViewTest.kt | 49 +++-- .../ManageAuthorizedSpacesViewTest.kt | 37 ++-- .../impl/root/SecurityAndPrivacyViewTest.kt | 102 +++++----- .../impl/addroom/AddRoomToSpaceViewTest.kt | 45 +++-- .../features/space/impl/root/SpaceViewTest.kt | 85 ++++---- .../JoinBaseRoomByAddressViewTest.kt | 28 ++- .../startchat/impl/root/StartChatViewTest.kt | 52 +++-- .../userprofile/UserProfileViewTest.kt | 98 +++++---- .../shared/blockuser/BlockUserDialogsTest.kt | 33 ++-- .../incoming/IncomingVerificationViewTest.kt | 85 ++++---- .../outgoing/OutgoingVerificationViewTest.kt | 67 ++++--- .../MediaDeleteConfirmationBottomSheetTest.kt | 28 ++- .../details/MediaDetailsBottomSheetTest.kt | 52 +++-- .../impl/viewer/MediaViewerViewTest.kt | 72 +++---- .../markdown/MarkdownTextInputTest.kt | 127 +++++------- .../impl/TroubleshootNotificationsViewTest.kt | 38 ++-- .../impl/history/PushHistoryViewTest.kt | 58 +++--- .../testutils/RobolectricDispatcherCleaner.kt | 8 +- ...nticsNodeInteractionsProviderExtensions.kt | 26 +-- 83 files changed, 2197 insertions(+), 2320 deletions(-) diff --git a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt index b69037e61a..b7932898a8 100644 --- a/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt +++ b/features/announcement/impl/src/test/kotlin/io/element/android/features/announcement/impl/fullscreen/FullscreenAnnouncementViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.announcement.impl.fullscreen import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.announcement.api.Announcement import io.element.android.features.announcement.impl.AnnouncementEvent @@ -20,43 +23,39 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class FullscreenAnnouncementViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back sends a AnnouncementEvent`() { + fun `clicking on back sends a AnnouncementEvent`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setFullscreenAnnouncementView( + setFullscreenAnnouncementView( anAnnouncementState( announcement = Announcement.Fullscreen.Space, eventSink = eventsRecorder, ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(AnnouncementEvent.Continue(Announcement.Fullscreen.Space)) } @Test - fun `clicking on Continue sends a AnnouncementEvent`() { + fun `clicking on Continue sends a AnnouncementEvent`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setFullscreenAnnouncementView( + setFullscreenAnnouncementView( anAnnouncementState( announcement = Announcement.Fullscreen.Space, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(AnnouncementEvent.Continue(Announcement.Fullscreen.Space)) } } -private fun AndroidComposeTestRule.setFullscreenAnnouncementView( +private fun AndroidComposeUiTest.setFullscreenAnnouncementView( state: AnnouncementState, ) { setContent { diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt index 35b90a6716..fed9f90de0 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt @@ -5,6 +5,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.call.ui import android.view.KeyEvent @@ -12,8 +14,9 @@ import android.webkit.WebView import androidx.activity.ComponentActivity import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.call.impl.pip.PictureInPictureEvents import io.element.android.features.call.impl.pip.aPictureInPictureState @@ -24,9 +27,7 @@ import io.element.android.features.call.impl.ui.aCallScreenState import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.pressBackKey import org.junit.Assert.assertEquals -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config import org.robolectric.annotation.Implementation @@ -36,32 +37,29 @@ import org.robolectric.shadows.ShadowWebView @RunWith(AndroidJUnit4::class) class CallScreenViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() { + fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() = runAndroidComposeUiTest { val callEvents = EventsRecorder() - rule.setCallScreenView( + setCallScreenView( state = aCallScreenState(eventSink = callEvents), useInspectionMode = true, ) - rule.pressBackKey() + pressBackKey() callEvents.assertEmpty() } @Config(shadows = [RecordingShadowWebView::class]) @Test - fun `pressing back key dispatches escape key events to web view when pip is unsupported`() { - rule.setCallScreenView( + fun `pressing back key dispatches escape key events to web view when pip is unsupported`() = runAndroidComposeUiTest { + setCallScreenView( state = aCallScreenState(), useInspectionMode = false, ) - rule.pressBackKey() + pressBackKey() val dispatchedEvents = RecordingShadowWebView.dispatchedEvents assertEquals(2, dispatchedEvents.size) @@ -73,10 +71,10 @@ class CallScreenViewTest { @Config(shadows = [RecordingShadowWebView::class]) @Test - fun `web view javascript back handler emits pip event when pip is supported`() { + fun `web view javascript back handler emits pip event when pip is supported`() = runAndroidComposeUiTest { val pipEvents = EventsRecorder() - rule.setCallScreenView( + setCallScreenView( state = aCallScreenState(), useInspectionMode = false, pipState = aPictureInPictureState( @@ -85,7 +83,7 @@ class CallScreenViewTest { ), ) - rule.runOnIdle { + runOnIdle { RecordingShadowWebView.invokeJavascriptBackHandler() } @@ -95,7 +93,7 @@ class CallScreenViewTest { } } -private fun AndroidComposeTestRule.setCallScreenView( +private fun AndroidComposeUiTest.setCallScreenView( state: io.element.android.features.call.impl.ui.CallScreenState, useInspectionMode: Boolean, pipState: io.element.android.features.call.impl.pip.PictureInPictureState = aPictureInPictureState(supportPip = false), diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt index 26c942da1f..c672fd666b 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.logout.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.deactivation.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -26,33 +29,29 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressTag -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class AccountDeactivationViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState(eventSink = eventsRecorder), onBackClick = it, ) - rule.pressBack() + pressBack() } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on Deactivate emits the expected Event`() { + fun `clicking on Deactivate emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState( deactivateFormState = aDeactivateFormState( password = A_PASSWORD, @@ -60,14 +59,14 @@ class AccountDeactivationViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_delete) + clickOn(CommonStrings.action_delete) eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) } @Test - fun `clicking on Deactivate on the confirmation dialog emits the expected Event`() { + fun `clicking on Deactivate on the confirmation dialog emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState( deactivateFormState = aDeactivateFormState( password = A_PASSWORD, @@ -76,14 +75,14 @@ class AccountDeactivationViewTest { eventSink = eventsRecorder, ), ) - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) } @Test - fun `clicking on retry on the confirmation dialog emits the expected Event`() { + fun `clicking on retry on the confirmation dialog emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState( deactivateFormState = aDeactivateFormState( password = A_PASSWORD, @@ -92,26 +91,26 @@ class AccountDeactivationViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_retry) + clickOn(CommonStrings.action_retry) eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(true)) } @Test - fun `switching on the erase all switch emits the expected Event`() { + fun `switching on the erase all switch emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState( eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_deactivate_account_delete_all_messages) + clickOn(R.string.screen_deactivate_account_delete_all_messages) eventsRecorder.assertSingle(AccountDeactivationEvents.SetEraseData(true)) } @Test - fun `switching off the erase all switch emits the expected Event`() { + fun `switching off the erase all switch emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState( deactivateFormState = aDeactivateFormState( eraseData = true, @@ -119,15 +118,15 @@ class AccountDeactivationViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_deactivate_account_delete_all_messages) + clickOn(R.string.screen_deactivate_account_delete_all_messages) eventsRecorder.assertSingle(AccountDeactivationEvents.SetEraseData(false)) } @Config(qualifiers = "h1024dp") @Test - fun `typing text in the password field emits the expected Event`() { + fun `typing text in the password field emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAccountDeactivationView( + setAccountDeactivationView( state = anAccountDeactivationState( deactivateFormState = aDeactivateFormState( password = A_PASSWORD, @@ -135,12 +134,12 @@ class AccountDeactivationViewTest { eventSink = eventsRecorder, ), ) - rule.onNodeWithTag(TestTags.loginPassword.value).performTextInput("A") + onNodeWithTag(TestTags.loginPassword.value).performTextInput("A") eventsRecorder.assertSingle(AccountDeactivationEvents.SetPassword("A$A_PASSWORD")) } } -private fun AndroidComposeTestRule.setAccountDeactivationView( +private fun AndroidComposeUiTest.setAccountDeactivationView( state: AccountDeactivationState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/forward/impl/src/test/kotlin/io/element/android/features/forward/impl/ForwardMessagesViewTest.kt b/features/forward/impl/src/test/kotlin/io/element/android/features/forward/impl/ForwardMessagesViewTest.kt index f1e9bd8fc6..57a9f65099 100644 --- a/features/forward/impl/src/test/kotlin/io/element/android/features/forward/impl/ForwardMessagesViewTest.kt +++ b/features/forward/impl/src/test/kotlin/io/element/android/features/forward/impl/ForwardMessagesViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.forward.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId @@ -21,34 +24,30 @@ import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.tests.testutils.pressTag -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ForwardMessagesViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `cancel error emits the expected event`() { + fun `cancel error emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setForwardMessagesView( + setForwardMessagesView( aForwardMessagesState( forwardAction = AsyncAction.Failure(AN_EXCEPTION), eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(ForwardMessagesEvents.ClearError) } @Test - fun `success invokes onForwardSuccess`() { + fun `success invokes onForwardSuccess`() = runAndroidComposeUiTest { val data = listOf(A_ROOM_ID) val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam?>(data) { callback -> - rule.setForwardMessagesView( + setForwardMessagesView( aForwardMessagesState( forwardAction = AsyncAction.Success(data), eventSink = eventsRecorder @@ -59,7 +58,7 @@ class ForwardMessagesViewTest { } } -private fun AndroidComposeTestRule.setForwardMessagesView( +private fun AndroidComposeUiTest.setForwardMessagesView( state: ForwardMessagesState, onForwardSuccess: (List) -> Unit = EnsureNeverCalledWithParam(), ) { diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSessionVerificationModeViewTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSessionVerificationModeViewTest.kt index 521bf91b37..6e74f58f66 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSessionVerificationModeViewTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/sessionverification/choosemode/ChooseSessionVerificationModeViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.ftue.impl.sessionverification.choosemode import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.ftue.impl.R import io.element.android.libraries.architecture.AsyncData @@ -18,65 +21,61 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class ChooseSessionVerificationModeViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Config(qualifiers = "h1024dp") @Test - fun `clicking on learn more invokes the expected callback`() { + fun `clicking on learn more invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setChooseSelfVerificationModeView( + setChooseSelfVerificationModeView( aChooseSelfVerificationModeState(), onLearnMoreClick = callback, ) - rule.clickOn(CommonStrings.action_learn_more) + clickOn(CommonStrings.action_learn_more) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on use another device calls the callback`() { + fun `clicking on use another device calls the callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setChooseSelfVerificationModeView( + setChooseSelfVerificationModeView( aChooseSelfVerificationModeState(AsyncData.Success(aButtonsState(canUseAnotherDevice = true))), onUseAnotherDevice = callback, ) - rule.clickOn(R.string.screen_identity_use_another_device) + clickOn(R.string.screen_identity_use_another_device) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on enter recovery key calls the callback`() { + fun `clicking on enter recovery key calls the callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setChooseSelfVerificationModeView( + setChooseSelfVerificationModeView( aChooseSelfVerificationModeState(AsyncData.Success(aButtonsState(canUseRecoveryKey = true))), onEnterRecoveryKey = callback, ) - rule.clickOn(R.string.screen_identity_confirmation_use_recovery_key) + clickOn(R.string.screen_identity_confirmation_use_recovery_key) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on cannot confirm calls the reset keys callback`() { + fun `clicking on cannot confirm calls the reset keys callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setChooseSelfVerificationModeView( + setChooseSelfVerificationModeView( aChooseSelfVerificationModeState(), onResetKey = callback, ) - rule.clickOn(R.string.screen_identity_confirmation_cannot_confirm) + clickOn(R.string.screen_identity_confirmation_cannot_confirm) } } - private fun AndroidComposeTestRule.setChooseSelfVerificationModeView( + private fun AndroidComposeUiTest.setChooseSelfVerificationModeView( state: ChooseSelfVerificationModeState, onLearnMoreClick: () -> Unit = EnsureNeverCalled(), onUseAnotherDevice: () -> Unit = EnsureNeverCalled(), diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersViewTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersViewTest.kt index 4c361b47f3..de5760c1bd 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersViewTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersViewTest.kt @@ -6,10 +6,13 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.home.impl.filters import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.home.impl.R import io.element.android.features.home.impl.filters.selection.FilterSelectionState @@ -17,23 +20,20 @@ import io.element.android.libraries.testtags.TestTags import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressTag -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class RoomListFiltersViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on filters generates expected Event`() { + fun `clicking on filters generates expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setContent { + setContent { RoomListFiltersView( state = aRoomListFiltersState(eventSink = eventsRecorder), ) } - rule.clickOn(R.string.screen_roomlist_filter_rooms) + clickOn(R.string.screen_roomlist_filter_rooms) eventsRecorder.assertList( listOf( RoomListFiltersEvent.ToggleFilter(RoomListFilter.Rooms), @@ -42,9 +42,9 @@ class RoomListFiltersViewTest { } @Test - fun `clicking on clear filters generates expected Event`() { + fun `clicking on clear filters generates expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setContent { + setContent { RoomListFiltersView( state = aRoomListFiltersState( filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) }, @@ -52,7 +52,7 @@ class RoomListFiltersViewTest { ), ) } - rule.pressTag(TestTags.homeScreenClearFilters.value) + pressTag(TestTags.homeScreenClearFilters.value) eventsRecorder.assertList( listOf( RoomListFiltersEvent.ClearSelectedFilters, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt index 6be5fe4c16..5fa2adf9d6 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.home.impl.roomlist import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.home.impl.R import io.element.android.libraries.matrix.api.core.RoomId @@ -20,23 +23,20 @@ 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.setSafeContent -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class RoomListContextMenuTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on Mark as read generates expected Events`() { + fun `clicking on Mark as read generates expected Events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val contextMenu = aContextMenuShown(hasNewContent = true) - rule.setRoomListContextMenu( + setRoomListContextMenu( contextMenu = contextMenu, eventSink = eventsRecorder, ) - rule.clickOn(R.string.screen_roomlist_mark_as_read) + clickOn(R.string.screen_roomlist_mark_as_read) eventsRecorder.assertList( listOf( RoomListEvent.HideContextMenu, @@ -46,14 +46,14 @@ class RoomListContextMenuTest { } @Test - fun `clicking on Mark as unread generates expected Events`() { + fun `clicking on Mark as unread generates expected Events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val contextMenu = aContextMenuShown(hasNewContent = false) - rule.setRoomListContextMenu( + setRoomListContextMenu( contextMenu = contextMenu, eventSink = eventsRecorder, ) - rule.clickOn(R.string.screen_roomlist_mark_as_unread) + clickOn(R.string.screen_roomlist_mark_as_unread) eventsRecorder.assertList( listOf( RoomListEvent.HideContextMenu, @@ -63,14 +63,14 @@ class RoomListContextMenuTest { } @Test - fun `clicking on Leave room generates expected Events`() { + fun `clicking on Leave room generates expected Events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val contextMenu = aContextMenuShown(isDm = false) - rule.setRoomListContextMenu( + setRoomListContextMenu( contextMenu = contextMenu, eventSink = eventsRecorder, ) - rule.clickOn(CommonStrings.action_leave_room) + clickOn(CommonStrings.action_leave_room) eventsRecorder.assertList( listOf( RoomListEvent.HideContextMenu, @@ -80,48 +80,48 @@ class RoomListContextMenuTest { } @Test - fun `clicking on Report room invokes the expected callback and generates expected Event`() { + fun `clicking on Report room invokes the expected callback and generates expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val contextMenu = aContextMenuShown() val callback = EnsureCalledOnceWithParam(contextMenu.roomId, Unit) - rule.setRoomListContextMenu( + setRoomListContextMenu( contextMenu = contextMenu, canReportRoom = true, eventSink = eventsRecorder, onRoomSettingsClick = EnsureNeverCalledWithParam(), onReportRoomClick = callback, ) - rule.clickOn(CommonStrings.action_report_room) + clickOn(CommonStrings.action_report_room) eventsRecorder.assertSingle(RoomListEvent.HideContextMenu) callback.assertSuccess() } @Test - fun `clicking on Settings invokes the expected callback and generates expected Event`() { + fun `clicking on Settings invokes the expected callback and generates expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val contextMenu = aContextMenuShown() val callback = EnsureCalledOnceWithParam(contextMenu.roomId, Unit) - rule.setRoomListContextMenu( + setRoomListContextMenu( contextMenu = contextMenu, eventSink = eventsRecorder, onRoomSettingsClick = callback, ) - rule.clickOn(CommonStrings.common_settings) + clickOn(CommonStrings.common_settings) eventsRecorder.assertSingle(RoomListEvent.HideContextMenu) callback.assertSuccess() } @Test - fun `clicking on Favourites generates expected Event`() { + fun `clicking on Favourites generates expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val contextMenu = aContextMenuShown(isDm = false, isFavorite = false) val callback = EnsureNeverCalledWithParam() - rule.setRoomListContextMenu( + setRoomListContextMenu( contextMenu = contextMenu, eventSink = eventsRecorder, onRoomSettingsClick = callback, ) - rule.clickOn(CommonStrings.common_favourite) + clickOn(CommonStrings.common_favourite) eventsRecorder.assertList( listOf( RoomListEvent.SetRoomIsFavorite(contextMenu.roomId, true), @@ -129,7 +129,7 @@ class RoomListContextMenuTest { ) } - private fun AndroidComposeTestRule<*, *>.setRoomListContextMenu( + private fun AndroidComposeUiTest.setRoomListContextMenu( contextMenu: RoomListState.ContextMenu.Shown, canReportRoom: Boolean = false, eventSink: (RoomListEvent) -> Unit, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenuTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenuTest.kt index d7f509fda4..c8bba05e52 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenuTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListDeclineInviteMenuTest.kt @@ -6,10 +6,12 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.home.impl.roomlist -import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.home.impl.model.aRoomListRoomSummary import io.element.android.libraries.ui.strings.CommonStrings @@ -18,19 +20,16 @@ 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.setSafeContent -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class RoomListDeclineInviteMenuTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on decline emits the expected Events`() { + fun `clicking on decline emits the expected Events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary()) - rule.setSafeContent { + setSafeContent { RoomListDeclineInviteMenu( menu = menu, canReportRoom = false, @@ -38,7 +37,7 @@ class RoomListDeclineInviteMenuTest { eventSink = eventsRecorder, ) } - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_decline) eventsRecorder.assertList( listOf( RoomListEvent.HideDeclineInviteMenu, @@ -48,10 +47,10 @@ class RoomListDeclineInviteMenuTest { } @Test - fun `clicking on decline and block when canReportRoom=true, it emits the expected Events and callback`() { + fun `clicking on decline and block when canReportRoom=true, it emits the expected Events and callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary()) - rule.setSafeContent { + setSafeContent { RoomListDeclineInviteMenu( menu = menu, canReportRoom = true, @@ -59,16 +58,16 @@ class RoomListDeclineInviteMenuTest { eventSink = eventsRecorder, ) } - rule.clickOn(CommonStrings.action_decline_and_block) + clickOn(CommonStrings.action_decline_and_block) val expectedEvents = listOf(RoomListEvent.HideDeclineInviteMenu) eventsRecorder.assertList(expectedEvents) } @Test - fun `clicking on decline and block when canReportRoom=false, it emits the expected Events`() { + fun `clicking on decline and block when canReportRoom=false, it emits the expected Events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary()) - rule.setSafeContent { + setSafeContent { RoomListDeclineInviteMenu( menu = menu, canReportRoom = false, @@ -76,7 +75,7 @@ class RoomListDeclineInviteMenuTest { eventSink = eventsRecorder, ) } - rule.clickOn(CommonStrings.action_decline_and_block) + clickOn(CommonStrings.action_decline_and_block) val expectedEvents = listOf( RoomListEvent.HideDeclineInviteMenu, RoomListEvent.DeclineInvite(menu.roomSummary, blockUser = true), @@ -85,10 +84,10 @@ class RoomListDeclineInviteMenuTest { } @Test - fun `clicking on cancel emits the expected Event`() { + fun `clicking on cancel emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val menu = RoomListState.DeclineInviteMenu.Shown(roomSummary = aRoomListRoomSummary()) - rule.setSafeContent { + setSafeContent { RoomListDeclineInviteMenu( menu = menu, canReportRoom = false, @@ -96,7 +95,7 @@ class RoomListDeclineInviteMenuTest { eventSink = eventsRecorder, ) } - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertList(listOf(RoomListEvent.HideDeclineInviteMenu)) } } diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt index 8402a921ca..b8d61994fa 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt @@ -6,16 +6,19 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.home.impl.roomlist import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.longClick import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.home.impl.HomeView import io.element.android.features.home.impl.R @@ -32,22 +35,17 @@ 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.setSafeContent -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class RoomListViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Config(qualifiers = "h1024dp") @Test - fun `displaying the view automatically sends a couple of UpdateVisibleRangeEvents`() { + fun `displaying the view automatically sends a couple of UpdateVisibleRangeEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomListView( + setRoomListView( state = aRoomListState( contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), eventSink = eventsRecorder, @@ -62,9 +60,9 @@ class RoomListViewTest { } @Test - fun `clicking on close recovery key banner emits the expected Event`() { + fun `clicking on close recovery key banner emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomListView( + setRoomListView( state = aRoomListState( contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), eventSink = eventsRecorder, @@ -74,15 +72,15 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - val close = rule.activity.getString(CommonStrings.action_close) - rule.onNodeWithContentDescription(close).performClick() + val close = activity!!.getString(CommonStrings.action_close) + onNodeWithContentDescription(close).performClick() eventsRecorder.assertSingle(RoomListEvent.DismissBanner) } @Test - fun `clicking on close setup key banner emits the expected Event`() { + fun `clicking on close setup key banner emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomListView( + setRoomListView( state = aRoomListState( contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery), eventSink = eventsRecorder, @@ -92,16 +90,16 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - val close = rule.activity.getString(CommonStrings.action_close) - rule.onNodeWithContentDescription(close).performClick() + val close = activity!!.getString(CommonStrings.action_close) + onNodeWithContentDescription(close).performClick() eventsRecorder.assertSingle(RoomListEvent.DismissBanner) } @Test - fun `clicking on continue recovery key banner invokes the expected callback`() { + fun `clicking on continue recovery key banner invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnce { callback -> - rule.setRoomListView( + setRoomListView( state = aRoomListState( contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), eventSink = eventsRecorder, @@ -112,17 +110,17 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertEmpty() } } @Test - fun `clicking on continue setup key banner invokes the expected callback`() { + fun `clicking on continue setup key banner invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnce { callback -> - rule.setRoomListView( + setRoomListView( state = aRoomListState( contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery), eventSink = eventsRecorder, @@ -131,28 +129,28 @@ class RoomListViewTest { ) // Remove automatic initial events eventsRecorder.clear() - rule.clickOn(R.string.banner_set_up_recovery_submit) + clickOn(R.string.banner_set_up_recovery_submit) eventsRecorder.assertEmpty() } } @Test - fun `clicking on start chat when the session has no room invokes the expected callback`() { + fun `clicking on start chat when the session has no room invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setRoomListView( + setRoomListView( state = aRoomListState( eventSink = eventsRecorder, contentState = anEmptyContentState(), ), onCreateRoomClick = callback, ) - rule.clickOn(CommonStrings.action_start_chat) + clickOn(CommonStrings.action_start_chat) } } @Test - fun `clicking on a room invokes the expected callback`() { + fun `clicking on a room invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomListState( eventSink = eventsRecorder, @@ -161,7 +159,7 @@ class RoomListViewTest { it.displayType == RoomSummaryDisplayType.ROOM } ensureCalledOnceWithParam(room0.roomId) { callback -> - rule.setRoomListView( + setRoomListView( state = state, onRoomClick = callback, ) @@ -169,14 +167,14 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - rule.onNodeWithText(room0.latestEvent.content().toString()).performClick() + onNodeWithText(room0.latestEvent.content().toString()).performClick() } eventsRecorder.assertEmpty() } @Test - fun `clicking on a room twice invokes the expected callback only once`() { + fun `clicking on a room twice invokes the expected callback only once`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomListState( eventSink = eventsRecorder, @@ -185,13 +183,13 @@ class RoomListViewTest { it.displayType == RoomSummaryDisplayType.ROOM } ensureCalledOnceWithParam(room0.roomId) { callback -> - rule.setRoomListView( + setRoomListView( state = state, onRoomClick = callback, ) // Remove automatic initial events eventsRecorder.clear() - rule.onNodeWithText(room0.latestEvent.content().toString()) + onNodeWithText(room0.latestEvent.content().toString()) .performClick() .performClick() } @@ -199,7 +197,7 @@ class RoomListViewTest { } @Test - fun `long clicking on a room emits the expected Event`() { + fun `long clicking on a room emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomListState( eventSink = eventsRecorder, @@ -207,18 +205,18 @@ class RoomListViewTest { val room0 = state.contentAsRooms().summaries.first { it.displayType == RoomSummaryDisplayType.ROOM } - rule.setRoomListView( + setRoomListView( state = state, ) // Remove automatic initial events eventsRecorder.clear() - rule.onNodeWithText(room0.latestEvent.content().toString()).performTouchInput { longClick() } + onNodeWithText(room0.latestEvent.content().toString()).performTouchInput { longClick() } eventsRecorder.assertSingle(RoomListEvent.ShowContextMenu(room0)) } @Test - fun `clicking on a room setting invokes the expected callback and emits expected Event`() { + fun `clicking on a room setting invokes the expected callback and emits expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomListState( contextMenu = aContextMenuShown(), @@ -226,7 +224,7 @@ class RoomListViewTest { ) val room0 = (state.contextMenu as RoomListState.ContextMenu.Shown).roomId ensureCalledOnceWithParam(room0) { callback -> - rule.setRoomListView( + setRoomListView( state = state, onRoomSettingsClick = callback, ) @@ -234,14 +232,14 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - rule.clickOn(CommonStrings.common_settings) + clickOn(CommonStrings.common_settings) } eventsRecorder.assertSingle(RoomListEvent.HideContextMenu) } @Test - fun `clicking on accept and decline invite emits the expected Events`() { + fun `clicking on accept and decline invite emits the expected Events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomListState( eventSink = eventsRecorder, @@ -249,13 +247,13 @@ class RoomListViewTest { val invitedRoom = state.contentAsRooms().summaries.first { it.displayType == RoomSummaryDisplayType.INVITE } - rule.setRoomListView(state = state) + setRoomListView(state = state) // Remove automatic initial events eventsRecorder.clear() - rule.clickOn(CommonStrings.action_accept) - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_accept) + clickOn(CommonStrings.action_decline) eventsRecorder.assertList( listOf( RoomListEvent.AcceptInvite(invitedRoom), @@ -265,7 +263,7 @@ class RoomListViewTest { } } -private fun AndroidComposeTestRule.setRoomListView( +private fun AndroidComposeUiTest.setRoomListView( state: RoomListState, onRoomClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(), onSettingsClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersViewTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersViewTest.kt index 5c1325b107..d612d765b6 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersViewTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersViewTest.kt @@ -5,34 +5,32 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.home.impl.spacefilters import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.tests.testutils.EventsRecorder -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class SpaceFiltersViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on a filter with alias shows display name and alias`() { + fun `clicking on a filter with alias shows display name and alias`() = runAndroidComposeUiTest { val filter = aSpaceServiceFilter( displayName = "Test Space", canonicalAlias = A_ROOM_ALIAS, ) val eventsRecorder = EventsRecorder() - rule.setSpaceFiltersView( + setSpaceFiltersView( state = aSelectingSpaceFiltersState( availableFilters = listOf(filter), eventSink = eventsRecorder, @@ -40,20 +38,20 @@ class SpaceFiltersViewTest { ) // Both display name and alias should be visible - rule.onNodeWithText(filter.spaceRoom.displayName).assertExists() - rule.onNodeWithText(A_ROOM_ALIAS.value).assertExists() + onNodeWithText(filter.spaceRoom.displayName).assertExists() + onNodeWithText(A_ROOM_ALIAS.value).assertExists() - rule.onNodeWithText(filter.spaceRoom.displayName).performClick() + onNodeWithText(filter.spaceRoom.displayName).performClick() eventsRecorder.assertSingle(SpaceFiltersEvent.Selecting.SelectFilter(filter)) } @Test - fun `multiple filters are displayed and clickable`() { + fun `multiple filters are displayed and clickable`() = runAndroidComposeUiTest { val filter1 = aSpaceServiceFilter(displayName = "Space One") val filter2 = aSpaceServiceFilter(displayName = "Space Two") val eventsRecorder = EventsRecorder() - rule.setSpaceFiltersView( + setSpaceFiltersView( state = aSelectingSpaceFiltersState( availableFilters = listOf(filter1, filter2), eventSink = eventsRecorder, @@ -61,17 +59,17 @@ class SpaceFiltersViewTest { ) // Both filters should be visible - rule.onNodeWithText(filter1.spaceRoom.displayName).assertExists() - rule.onNodeWithText(filter2.spaceRoom.displayName).assertExists() + onNodeWithText(filter1.spaceRoom.displayName).assertExists() + onNodeWithText(filter2.spaceRoom.displayName).assertExists() // Click on second filter - rule.onNodeWithText(filter2.spaceRoom.displayName).performClick() + onNodeWithText(filter2.spaceRoom.displayName).performClick() eventsRecorder.assertSingle(SpaceFiltersEvent.Selecting.SelectFilter(filter2)) } } -private fun AndroidComposeTestRule.setSpaceFiltersView( +private fun AndroidComposeUiTest.setSpaceFiltersView( state: SpaceFiltersState, ) { setContent { diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockViewTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockViewTest.kt index 299fec8565..e915696de4 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockViewTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.invite.impl.declineandblock import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.invite.impl.R import io.element.android.libraries.ui.strings.CommonStrings @@ -21,98 +24,94 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class DeclineAndBlockViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invoke the expected callback`() { + fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setDeclineAndBlockView( + setDeclineAndBlockView( aDeclineAndBlockState( eventSink = eventsRecorder, ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on decline when enabled emits the expected event`() { + fun `clicking on decline when enabled emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDeclineAndBlockView( + setDeclineAndBlockView( aDeclineAndBlockState( blockUser = true, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_decline) eventsRecorder.assertSingle(DeclineAndBlockEvents.Decline) } @Test - fun `clicking on decline when disabled does not emit event`() { + fun `clicking on decline when disabled does not emit event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setDeclineAndBlockView( + setDeclineAndBlockView( aDeclineAndBlockState( blockUser = false, reportRoom = false, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_decline) eventsRecorder.assertEmpty() } @Test - fun `clicking on block option emits the expected event`() { + fun `clicking on block option emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDeclineAndBlockView( + setDeclineAndBlockView( aDeclineAndBlockState( blockUser = true, eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_decline_and_block_block_user_option_title) + clickOn(R.string.screen_decline_and_block_block_user_option_title) eventsRecorder.assertSingle(DeclineAndBlockEvents.ToggleBlockUser) } @Test - fun `clicking on report room option emits the expected event`() { + fun `clicking on report room option emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDeclineAndBlockView( + setDeclineAndBlockView( aDeclineAndBlockState( reportRoom = true, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_report_room) + clickOn(CommonStrings.action_report_room) eventsRecorder.assertSingle(DeclineAndBlockEvents.ToggleReportRoom) } @Test - fun `typing text in the reason field emits the expected Event`() { + fun `typing text in the reason field emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDeclineAndBlockView( + setDeclineAndBlockView( aDeclineAndBlockState( reportRoom = true, reportReason = "", eventSink = eventsRecorder, ), ) - rule.onNodeWithText("").performTextInput("Spam!") + onNodeWithText("").performTextInput("Spam!") eventsRecorder.assertSingle(DeclineAndBlockEvents.UpdateReportReason("Spam!")) } } -private fun AndroidComposeTestRule.setDeclineAndBlockView( +private fun AndroidComposeUiTest.setDeclineAndBlockView( state: DeclineAndBlockState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt index 0a3b1ca3c6..e60d7da691 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.joinroom.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.test.anInviteData @@ -26,116 +29,112 @@ 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 JoinRoomViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invoke the expected callback`() { + fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( eventSink = eventsRecorder, ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on Join room on CanJoin room emits the expected Event`() { + fun `clicking on Join room on CanJoin room emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanJoin), eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_join_room_join_action) + clickOn(R.string.screen_join_room_join_action) eventsRecorder.assertSingle(JoinRoomEvents.JoinRoom) } @Test - fun `clicking on Knock room on CanKnock room emits the expected Event`() { + fun `clicking on Knock room on CanKnock room emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock), knockMessage = "Knock knock", eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_join_room_knock_action) + clickOn(R.string.screen_join_room_knock_action) eventsRecorder.assertSingle(JoinRoomEvents.KnockRoom) } @Test - fun `clicking on closing Knock error emits the expected Event`() { + fun `clicking on closing Knock error emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock), knockAction = AsyncAction.Failure(Exception("Error")), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates) } @Test - fun `clicking on cancel knock request emit the expected Event`() { + fun `clicking on cancel knock request emit the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked), eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_join_room_cancel_knock_action) + clickOn(R.string.screen_join_room_cancel_knock_action) eventsRecorder.assertSingle(JoinRoomEvents.CancelKnock(true)) } @Test - fun `clicking on closing Cancel Knock error emits the expected Event`() { + fun `clicking on closing Cancel Knock error emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked), cancelKnockAction = AsyncAction.Failure(Exception("Error")), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates) } @Test - fun `clicking on closing Join error emits the expected Event`() { + fun `clicking on closing Join error emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock), joinAction = AsyncAction.Failure(Exception("Error")), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates) } @Test - fun `when joining room is successful, the expected callback is invoked`() { + fun `when joining room is successful, the expected callback is invoked`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( joinAction = AsyncAction.Success(Unit), eventSink = eventsRecorder, @@ -146,53 +145,55 @@ class JoinRoomViewTest { } @Test - fun `clicking on Accept when JoinAuthorisationStatus is IsInvited emits the expected Event`() { + fun `clicking on Accept when JoinAuthorisationStatus is IsInvited emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val inviteData = anInviteData() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(inviteData, null)), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_accept) + clickOn(CommonStrings.action_accept) eventsRecorder.assertSingle(JoinRoomEvents.AcceptInvite(inviteData)) } @Test - fun `clicking on Decline when JoinAuthorisationStatus is IsInvited emits the expected Event`() { + fun `clicking on Decline when JoinAuthorisationStatus is IsInvited emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val inviteData = anInviteData() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(inviteData, null)), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_decline) eventsRecorder.assertSingle(JoinRoomEvents.DeclineInvite(inviteData, false)) } @Test fun `clicking on Decline and block when JoinAuthorisationStatus is IsInvited and can report room, the expected callback is invoked`() { - val eventsRecorder = EventsRecorder(expectEvents = false) - val inviteData = anInviteData() - val joinRoomState = aJoinRoomState( - contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(inviteData, aRoomMember().toInviteSender())), - canReportRoom = true, - eventSink = eventsRecorder, - ) - ensureCalledOnceWithParam(inviteData) { - rule.setJoinRoomView( - state = joinRoomState, - onDeclineInviteAndBlockUser = it, + runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder(expectEvents = false) + val inviteData = anInviteData() + val joinRoomState = aJoinRoomState( + contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsInvited(inviteData, aRoomMember().toInviteSender())), + canReportRoom = true, + eventSink = eventsRecorder, ) - rule.clickOn(R.string.screen_join_room_decline_and_block_button_title) + ensureCalledOnceWithParam(inviteData) { + setJoinRoomView( + state = joinRoomState, + onDeclineInviteAndBlockUser = it, + ) + clickOn(R.string.screen_join_room_decline_and_block_button_title) + } } } @Test - fun `clicking on Decline and block when JoinAuthorisationStatus is IsInvited and cant report room, emits the expected Event`() { + fun `clicking on Decline and block when JoinAuthorisationStatus is IsInvited and cant report room, emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val inviteData = anInviteData() val joinRoomState = aJoinRoomState( @@ -200,29 +201,29 @@ class JoinRoomViewTest { canReportRoom = false, eventSink = eventsRecorder, ) - rule.setJoinRoomView(state = joinRoomState) - rule.clickOn(R.string.screen_join_room_decline_and_block_button_title) + setJoinRoomView(state = joinRoomState) + clickOn(R.string.screen_join_room_decline_and_block_button_title) eventsRecorder.assertSingle(JoinRoomEvents.DeclineInvite(inviteData, true)) } @Test - fun `clicking on Retry when an error occurs emits the expected Event`() { + fun `clicking on Retry when an error occurs emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aFailureContentState(), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_retry) + clickOn(CommonStrings.action_retry) eventsRecorder.assertSingle(JoinRoomEvents.RetryFetchingContent) } @Test - fun `clicking on ok when user is unauthorized the expected callback`() { + fun `clicking on ok when user is unauthorized the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(), joinAction = AsyncAction.Failure(JoinRoom.Failures.UnauthorizedJoin), @@ -230,25 +231,25 @@ class JoinRoomViewTest { ), onBackClick = it ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) } } @Test - fun `clicking on forget when user is banned invokes the expected callback`() { + fun `clicking on forget when user is banned invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomView( + setJoinRoomView( aJoinRoomState( contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned(null, null)), eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_join_room_forget_action) + clickOn(R.string.screen_join_room_forget_action) eventsRecorder.assertSingle(JoinRoomEvents.ForgetRoom) } } -private fun AndroidComposeTestRule.setJoinRoomView( +private fun AndroidComposeUiTest.setJoinRoomView( state: JoinRoomState, onBackClick: () -> Unit = EnsureNeverCalled(), onJoinSuccess: () -> Unit = EnsureNeverCalled(), diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerViewTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerViewTest.kt index a9fea0905e..fc1600d8c8 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerViewTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.knockrequests.impl.banner import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.knockrequests.impl.R import io.element.android.features.knockrequests.impl.data.aKnockRequestPresentable @@ -21,35 +24,30 @@ import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class KnockRequestsBannerViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on view on single request invoke the expected callback`() { + fun `clicking on view on single request invoke the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setKnockRequestsBannerView( + setKnockRequestsBannerView( state = aKnockRequestsBannerState( eventSink = eventsRecorder, ), onViewRequestsClick = it ) - rule.clickOn(R.string.screen_room_single_knock_request_view_button_title) + clickOn(R.string.screen_room_single_knock_request_view_button_title) } } @Test - fun `clicking on view all when multiple requests invoke the expected callback`() { + fun `clicking on view all when multiple requests invoke the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setKnockRequestsBannerView( + setKnockRequestsBannerView( state = aKnockRequestsBannerState( knockRequests = listOf( aKnockRequestPresentable(displayName = "Alice"), @@ -60,37 +58,37 @@ class KnockRequestsBannerViewTest { ), onViewRequestsClick = it ) - rule.clickOn(R.string.screen_room_multiple_knock_requests_view_all_button_title) + clickOn(R.string.screen_room_multiple_knock_requests_view_all_button_title) } } @Test - fun `clicking on accept on a single request emit the expected event`() { + fun `clicking on accept on a single request emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setKnockRequestsBannerView( + setKnockRequestsBannerView( state = aKnockRequestsBannerState( eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_accept) + clickOn(CommonStrings.action_accept) eventsRecorder.assertSingle(KnockRequestsBannerEvents.AcceptSingleRequest) } @Test - fun `clicking on dismiss emit the expected event`() { + fun `clicking on dismiss emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setKnockRequestsBannerView( + setKnockRequestsBannerView( state = aKnockRequestsBannerState( eventSink = eventsRecorder, ), ) - val close = rule.activity.getString(CommonStrings.action_close) - rule.onNodeWithContentDescription(close).performClick() + val close = activity!!.getString(CommonStrings.action_close) + onNodeWithContentDescription(close).performClick() eventsRecorder.assertSingle(KnockRequestsBannerEvents.Dismiss) } } -private fun AndroidComposeTestRule.setKnockRequestsBannerView( +private fun AndroidComposeUiTest.setKnockRequestsBannerView( state: KnockRequestsBannerState, onViewRequestsClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListViewTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListViewTest.kt index 188dcc7e56..14cac7a9b7 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListViewTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.knockrequests.impl.list import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.knockrequests.impl.R import io.element.android.features.knockrequests.impl.data.aKnockRequestPresentable @@ -23,90 +26,86 @@ 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.persistentListOf -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class KnockRequestsListViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invoke the expected callback`() { + fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( eventSink = eventsRecorder, ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on accept emit the expected event`() { + fun `clicking on accept emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequest = aKnockRequestPresentable() - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(persistentListOf(knockRequest)), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_accept) + clickOn(CommonStrings.action_accept) eventsRecorder.assertSingle(KnockRequestsListEvents.Accept(knockRequest)) } @Test - fun `clicking on decline emit the expected event`() { + fun `clicking on decline emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequest = aKnockRequestPresentable() - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(persistentListOf(knockRequest)), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_decline) eventsRecorder.assertSingle(KnockRequestsListEvents.Decline(knockRequest)) } @Test - fun `clicking on decline and ban emit the expected event`() { + fun `clicking on decline and ban emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequest = aKnockRequestPresentable() - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(persistentListOf(knockRequest)), eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_knock_requests_list_decline_and_ban_action_title) + clickOn(R.string.screen_knock_requests_list_decline_and_ban_action_title) eventsRecorder.assertSingle(KnockRequestsListEvents.DeclineAndBan(knockRequest)) } @Test - fun `clicking on accept all emit the expected event`() { + fun `clicking on accept all emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequests = persistentListOf(aKnockRequestPresentable(), aKnockRequestPresentable()) - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(knockRequests), eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_knock_requests_list_accept_all_button_title) + clickOn(R.string.screen_knock_requests_list_accept_all_button_title) eventsRecorder.assertSingle(KnockRequestsListEvents.AcceptAll) } @Test - fun `retry on async view retry emit the expected event`() { + fun `retry on async view retry emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequests = persistentListOf(aKnockRequestPresentable(), aKnockRequestPresentable()) - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(knockRequests), asyncAction = AsyncAction.Failure(RuntimeException("Failed to accept all")), @@ -114,15 +113,15 @@ class KnockRequestsListViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_retry) + clickOn(CommonStrings.action_retry) eventsRecorder.assertSingle(KnockRequestsListEvents.RetryCurrentAction) } @Test - fun `canceling async view emit the expected event`() { + fun `canceling async view emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequests = persistentListOf(aKnockRequestPresentable(), aKnockRequestPresentable()) - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(knockRequests), asyncAction = AsyncAction.Failure(RuntimeException("Failed to accept all")), @@ -130,15 +129,15 @@ class KnockRequestsListViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(KnockRequestsListEvents.ResetCurrentAction) } @Test - fun `confirming async view emit the expected event`() { + fun `confirming async view emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val knockRequests = persistentListOf(aKnockRequestPresentable(), aKnockRequestPresentable()) - rule.setKnockRequestsListView( + setKnockRequestsListView( aKnockRequestsListState( knockRequests = AsyncData.Success(knockRequests), asyncAction = AsyncAction.ConfirmingNoParams, @@ -146,12 +145,12 @@ class KnockRequestsListViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_knock_requests_list_accept_all_alert_confirm_button_title) + clickOn(R.string.screen_knock_requests_list_accept_all_alert_confirm_button_title) eventsRecorder.assertSingle(KnockRequestsListEvents.ConfirmCurrentAction) } } -private fun AndroidComposeTestRule.setKnockRequestsListView( +private fun AndroidComposeUiTest.setKnockRequestsListView( state: KnockRequestsListState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeViewTest.kt index ac0a129f49..7609acf809 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeViewTest.kt @@ -5,11 +5,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.linknewdevice.impl.screens.desktop import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.linknewdevice.impl.R import io.element.android.tests.testutils.EnsureNeverCalled @@ -18,42 +21,37 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class DesktopNoticeViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setView( + setView( state = aDesktopNoticeState(), onBackClicked = callback, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on back button clicked - calls the expected callback`() { + fun `on back button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setView( + setView( state = aDesktopNoticeState(), onBackClicked = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `when can continue - calls the expected callback`() { + fun `when can continue - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setView( + setView( state = aDesktopNoticeState(canContinue = true), onReadyToScanClick = callback, ) @@ -61,16 +59,16 @@ class DesktopNoticeViewTest { } @Test - fun `on submit button clicked - emits the Continue event`() { + fun `on submit button clicked - emits the Continue event`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder() - rule.setView( + setView( state = aDesktopNoticeState(eventSink = eventRecorder), ) - rule.clickOn(R.string.screen_link_new_device_desktop_submit) + clickOn(R.string.screen_link_new_device_desktop_submit) eventRecorder.assertSingle(DesktopNoticeEvent.Continue) } - private fun AndroidComposeTestRule.setView( + private fun AndroidComposeUiTest.setView( state: DesktopNoticeState, onBackClicked: () -> Unit = EnsureNeverCalled(), onReadyToScanClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorViewTest.kt index aa52a70149..b63d7471ac 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorViewTest.kt @@ -5,58 +5,56 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.linknewdevice.impl.screens.error import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ErrorViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the onCancel callback`() { + fun `on back pressed - calls the onCancel callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setErrorView( + setErrorView( onCancel = callback, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on try again button clicked - calls the expected callback`() { + fun `on try again button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setErrorView( + setErrorView( onRetry = callback ) - rule.clickOn(CommonStrings.action_try_again) + clickOn(CommonStrings.action_try_again) } } @Test - fun `on cancel button clicked - calls the expected callback`() { + fun `on cancel button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setErrorView( + setErrorView( onCancel = callback ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) } } - private fun AndroidComposeTestRule.setErrorView( + private fun AndroidComposeUiTest.setErrorView( onRetry: () -> Unit = EnsureNeverCalled(), onCancel: () -> Unit = EnsureNeverCalled(), errorScreenType: ErrorScreenType = ErrorScreenType.UnknownError, diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/number/EnterNumberViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/number/EnterNumberViewTest.kt index 20e1d898dd..25dc9efa8a 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/number/EnterNumberViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/number/EnterNumberViewTest.kt @@ -5,13 +5,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.linknewdevice.impl.screens.number import androidx.activity.ComponentActivity +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assertIsNotEnabled -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.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -20,65 +23,60 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class EnterNumberViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setView( + setView( state = aEnterNumberState(), onBackClicked = callback, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on back button clicked - calls the expected callback`() { + fun `on back button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setView( + setView( state = aEnterNumberState(), onBackClicked = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `on continue button clicked - emits the Continue event`() { + fun `on continue button clicked - emits the Continue event`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder() - rule.setView( + setView( state = aEnterNumberState( number = "12", eventSink = eventRecorder, ), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventRecorder.assertSingle(EnterNumberEvent.Continue) } @Test - fun `when the number is not complete, continue button is disabled`() { + fun `when the number is not complete, continue button is disabled`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( state = aEnterNumberState( number = "1", eventSink = eventRecorder, ), ) - val continueStr = rule.activity.getString(CommonStrings.action_continue) - rule.onNodeWithText(continueStr).assertIsNotEnabled() + val continueStr = activity!!.getString(CommonStrings.action_continue) + onNodeWithText(continueStr).assertIsNotEnabled() } - private fun AndroidComposeTestRule.setView( + private fun AndroidComposeUiTest.setView( state: EnterNumberState, onBackClicked: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt index c6c89ba818..d552c2bff6 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt @@ -5,36 +5,34 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.linknewdevice.impl.screens.qrcode import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ShowQrCodeViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setView( + setView( onBackClick = callback ) - rule.pressBackKey() + pressBackKey() } } - private fun AndroidComposeTestRule.setView( + private fun AndroidComposeUiTest.setView( onBackClick: () -> Unit = EnsureNeverCalled(), ) { setContent { diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/root/LinkNewDeviceRootViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/root/LinkNewDeviceRootViewTest.kt index e352debfb0..bceb8753b2 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/root/LinkNewDeviceRootViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/root/LinkNewDeviceRootViewTest.kt @@ -5,11 +5,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.linknewdevice.impl.screens.root import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.linknewdevice.impl.R import io.element.android.libraries.architecture.AsyncData @@ -19,74 +22,69 @@ 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.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class LinkNewDeviceRootViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the onRetry callback`() { + fun `on back pressed - calls the onRetry callback`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setLinkNewDeviceRootView( + setLinkNewDeviceRootView( state = aLinkNewDeviceRootState( eventSink = eventRecorder, ), onBackClick = callback ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `link desktop button clicked - calls the expected callback`() { + fun `link desktop button clicked - calls the expected callback`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setLinkNewDeviceRootView( + setLinkNewDeviceRootView( state = aLinkNewDeviceRootState( isSupported = AsyncData.Success(true), eventSink = eventRecorder, ), onLinkDesktopDeviceClick = callback, ) - rule.clickOn(R.string.screen_link_new_device_root_desktop_computer) + clickOn(R.string.screen_link_new_device_root_desktop_computer) } } @Test - fun `link mobile button clicked - emits the expected event`() { + fun `link mobile button clicked - emits the expected event`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder() - rule.setLinkNewDeviceRootView( + setLinkNewDeviceRootView( state = aLinkNewDeviceRootState( isSupported = AsyncData.Success(true), eventSink = eventRecorder, ) ) - rule.clickOn(R.string.screen_link_new_device_root_mobile_device) + clickOn(R.string.screen_link_new_device_root_mobile_device) eventRecorder.assertSingle(LinkNewDeviceRootEvent.LinkMobileDevice) } @Test - fun `not supported - dismiss click - invokes the expected callback`() { + fun `not supported - dismiss click - invokes the expected callback`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setLinkNewDeviceRootView( + setLinkNewDeviceRootView( state = aLinkNewDeviceRootState( isSupported = AsyncData.Success(false), eventSink = eventRecorder, ), onBackClick = callback, ) - rule.clickOn(CommonStrings.action_dismiss) + clickOn(CommonStrings.action_dismiss) } } - private fun AndroidComposeTestRule.setLinkNewDeviceRootView( + private fun AndroidComposeUiTest.setLinkNewDeviceRootView( state: LinkNewDeviceRootState = aLinkNewDeviceRootState(), onBackClick: () -> Unit = EnsureNeverCalled(), onLinkDesktopDeviceClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/scan/ScanQrCodeViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/scan/ScanQrCodeViewTest.kt index fcc3afeb7d..1932718fef 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/scan/ScanQrCodeViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/scan/ScanQrCodeViewTest.kt @@ -5,11 +5,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.linknewdevice.impl.screens.scan import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.test.AN_EXCEPTION @@ -19,44 +22,39 @@ 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.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ScanQrCodeViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( state = aScanQrCodeState( eventSink = eventRecorder, ), onBackClick = callback ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `try again button clicked - emits the expected event`() { + fun `try again button clicked - emits the expected event`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder() - rule.setView( + setView( state = aScanQrCodeState( scanAction = AsyncAction.Failure(AN_EXCEPTION), eventSink = eventRecorder, ) ) - rule.clickOn(CommonStrings.action_try_again) + clickOn(CommonStrings.action_try_again) eventRecorder.assertSingle(ScanQrCodeEvent.TryAgain) } - private fun AndroidComposeTestRule.setView( + private fun AndroidComposeUiTest.setView( state: ScanQrCodeState = aScanQrCodeState(), onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt index 317fbf8fed..63c19ba913 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt @@ -5,15 +5,18 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.location.impl.share import androidx.activity.ComponentActivity import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.libraries.testtags.TestTags @@ -23,102 +26,98 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ShareLocationViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `test back action`() { + fun `test back action`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setShareLocationView( + setShareLocationView( state = aShareLocationState( eventSink = eventsRecorder ), navigateUp = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `test fab click`() { + fun `test fab click`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), ) - rule.onNodeWithTag(TestTags.floatingActionButton.value).performClick() + onNodeWithTag(TestTags.floatingActionButton.value).performClick() eventsRecorder.assertSingle(ShareLocationEvent.StartTrackingUserLocation) } @Test - fun `when permission denied is displayed user can open the settings`() { + fun `when permission denied is displayed user can open the settings`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionDenied), eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(ShareLocationEvent.OpenAppSettings) } @Test - fun `when permission denied is displayed user can close the dialog`() { + fun `when permission denied is displayed user can close the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionDenied), eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) } @Test - fun `when permission rationale is displayed user can request permissions`() { + fun `when permission rationale is displayed user can request permissions`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionRationale), eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(ShareLocationEvent.RequestPermissions) } @Test - fun `when permission rationale is displayed user can close the dialog`() { + fun `when permission rationale is displayed user can close the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionRationale), eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) } @Test - fun `when location service disabled is displayed user can open location settings`() { + fun `when location service disabled is displayed user can open location settings`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled), hasLocationPermission = true, @@ -126,14 +125,14 @@ class ShareLocationViewTest { ), navigateUp = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(ShareLocationEvent.OpenLocationSettings) } @Test - fun `when location service disabled is displayed user can close the dialog`() { + fun `when location service disabled is displayed user can close the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShareLocationView( + setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled), hasLocationPermission = true, @@ -141,12 +140,12 @@ class ShareLocationViewTest { ), navigateUp = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) } } -private fun AndroidComposeTestRule.setShareLocationView( +private fun AndroidComposeUiTest.setShareLocationView( state: ShareLocationState, navigateUp: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationViewTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationViewTest.kt index fecbbdbf89..45ed894f97 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationViewTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationViewTest.kt @@ -6,16 +6,19 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.location.impl.show import androidx.activity.ComponentActivity import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.location.api.Location import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState @@ -26,115 +29,111 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ShowLocationViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `test back action`() { + fun `test back action`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setShowLocationView( + setShowLocationView( state = aShowLocationState( eventSink = eventsRecorder ), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `test share action`() { + fun `test share action`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShowLocationView( + setShowLocationView( aShowLocationState( eventSink = eventsRecorder ), onBackClick = EnsureNeverCalled(), ) - val shareContentDescription = rule.activity.getString(CommonStrings.action_share) - rule.onNodeWithContentDescription(shareContentDescription).performClick() + val shareContentDescription = activity!!.getString(CommonStrings.action_share) + onNodeWithContentDescription(shareContentDescription).performClick() // The default aStaticLocationMode uses Location(1.23, 2.34, 4f) eventsRecorder.assertSingle(ShowLocationEvent.Share(Location(1.23, 2.34, 4f))) } @Test - fun `test fab click`() { + fun `test fab click`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShowLocationView( + setShowLocationView( aShowLocationState( eventSink = eventsRecorder ), onBackClick = EnsureNeverCalled(), ) - rule.onNodeWithTag(TestTags.floatingActionButton.value).performClick() + onNodeWithTag(TestTags.floatingActionButton.value).performClick() eventsRecorder.assertSingle(ShowLocationEvent.TrackMyLocation(true)) } @Test - fun `when permission denied is displayed user can open the settings`() { + fun `when permission denied is displayed user can open the settings`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShowLocationView( + setShowLocationView( aShowLocationState( constraintsDialogState = LocationConstraintsDialogState.PermissionDenied, eventSink = eventsRecorder ), onBackClick = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(ShowLocationEvent.OpenAppSettings) } @Test - fun `when permission denied is displayed user can close the dialog`() { + fun `when permission denied is displayed user can close the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShowLocationView( + setShowLocationView( aShowLocationState( constraintsDialogState = LocationConstraintsDialogState.PermissionDenied, eventSink = eventsRecorder ), onBackClick = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShowLocationEvent.DismissDialog) } @Test - fun `when permission rationale is displayed user can request permissions`() { + fun `when permission rationale is displayed user can request permissions`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShowLocationView( + setShowLocationView( aShowLocationState( constraintsDialogState = LocationConstraintsDialogState.PermissionRationale, eventSink = eventsRecorder ), onBackClick = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(ShowLocationEvent.RequestPermissions) } @Test - fun `when permission rationale is displayed user can close the dialog`() { + fun `when permission rationale is displayed user can close the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setShowLocationView( + setShowLocationView( aShowLocationState( constraintsDialogState = LocationConstraintsDialogState.PermissionRationale, eventSink = eventsRecorder ), onBackClick = EnsureNeverCalled(), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShowLocationEvent.DismissDialog) } } -private fun AndroidComposeTestRule.setShowLocationView( +private fun AndroidComposeUiTest.setShowLocationView( state: ShowLocationState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/keypad/PinKeypadTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/keypad/PinKeypadTest.kt index 1ecb79bd67..e6d1659778 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/keypad/PinKeypadTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/keypad/PinKeypadTest.kt @@ -6,60 +6,57 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.lockscreen.impl.unlock.keypad import android.view.KeyEvent import androidx.activity.ComponentActivity import androidx.compose.ui.input.key.Key +import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasText import androidx.compose.ui.test.isRoot -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.compose.ui.test.performKeyInput import androidx.compose.ui.test.pressKey import androidx.compose.ui.test.requestFocus +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.compose.ui.unit.dp import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EventsRecorder -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class PinKeypadTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on a number emits the expected event`() { + fun `clicking on a number emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPinKeyPad(onClick = eventsRecorder) - rule.onNode(hasText("1")).performClick() + setPinKeyPad(onClick = eventsRecorder) + onNode(hasText("1")).performClick() eventsRecorder.assertSingle(PinKeypadModel.Number('1')) } @Test - fun `clicking on the delete previous character button emits the expected event`() { + fun `clicking on the delete previous character button emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPinKeyPad(onClick = eventsRecorder) - rule.onNode(hasContentDescription(rule.activity.getString(CommonStrings.a11y_delete))).performClick() + setPinKeyPad(onClick = eventsRecorder) + onNode(hasContentDescription(activity!!.getString(CommonStrings.a11y_delete))).performClick() eventsRecorder.assertSingle(PinKeypadModel.Back) } @OptIn(ExperimentalTestApi::class) @Test - fun `typing using the hardware keyboard emits the expected events`() { + fun `typing using the hardware keyboard emits the expected events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPinKeyPad(onClick = eventsRecorder) - rule.onNodeWithText("1").requestFocus() - rule.onAllNodes(isRoot())[0].performKeyInput { + setPinKeyPad(onClick = eventsRecorder) + onNodeWithText("1").requestFocus() + onAllNodes(isRoot())[0].performKeyInput { val keys = listOf( Key.A, Key.NumPad1, @@ -118,7 +115,7 @@ class PinKeypadTest { ) } - private fun AndroidComposeTestRule.setPinKeyPad( + private fun AndroidComposeUiTest.setPinKeyPad( onClick: (PinKeypadModel) -> Unit = EnsureNeverCalledWithParam(), ) { setContent { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt index c6610b212c..61ec7cc698 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.chooseaccountprovider import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.login.impl.accountprovider.anAccountProvider import io.element.android.libraries.architecture.AsyncData @@ -25,36 +28,31 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class ChooseAccountProviderViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setChooseAccountProviderView( + setChooseAccountProviderView( state = aChooseAccountProviderState( eventSink = eventSink, ), onBackClick = it, ) - rule.pressBack() + pressBack() } } @Config(qualifiers = "h1024dp") @Test - fun `selecting an account provider emits the the expected event`() { + fun `selecting an account provider emits the the expected event`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() - rule.setChooseAccountProviderView( + setChooseAccountProviderView( state = aChooseAccountProviderState( accountProviders = listOf( ChooseAccountProviderPresenterTest.accountProvider1, @@ -64,24 +62,24 @@ class ChooseAccountProviderViewTest { eventSink = eventSink, ), ) - rule.onNodeWithText(ChooseAccountProviderPresenterTest.accountProvider1.title).performClick() + onNodeWithText(ChooseAccountProviderPresenterTest.accountProvider1.title).performClick() eventSink.assertSingle(ChooseAccountProviderEvents.SelectAccountProvider(ChooseAccountProviderPresenterTest.accountProvider1)) } @Test - fun `when error is displayed - closing the dialog emits the expected event`() { + fun `when error is displayed - closing the dialog emits the expected event`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() - rule.setChooseAccountProviderView( + setChooseAccountProviderView( state = aChooseAccountProviderState( loginMode = AsyncData.Failure(AN_EXCEPTION), eventSink = eventSink, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventSink.assertSingle(ChooseAccountProviderEvents.ClearError) } - private fun AndroidComposeTestRule.setChooseAccountProviderView( + private fun AndroidComposeUiTest.setChooseAccountProviderView( state: ChooseAccountProviderState, onBackClick: () -> Unit = EnsureNeverCalled(), onOAuthDetails: (OAuthDetails) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordViewTest.kt index 26da50da63..c0e7e5c378 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordViewTest.kt @@ -6,20 +6,23 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.loginpassword import androidx.activity.ComponentActivity +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assert import androidx.compose.ui.test.assertIsEnabled import androidx.compose.ui.test.assertIsNotEnabled import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.test.A_PASSWORD import io.element.android.libraries.matrix.test.A_USER_NAME @@ -30,158 +33,154 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class LoginPasswordViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invoke back callback`() { + fun `clicking on back invoke back callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( eventSink = eventsRecorder ), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `changing login invokes the expected event`() { + fun `changing login invokes the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( eventSink = eventsRecorder, ), ) - val userNameHint = rule.activity.getString(CommonStrings.common_username) - rule.onNodeWithText(userNameHint).performTextInput(A_USER_NAME) + val userNameHint = activity!!.getString(CommonStrings.common_username) + onNodeWithText(userNameHint).performTextInput(A_USER_NAME) eventsRecorder.assertSingle( LoginPasswordEvents.SetLogin(A_USER_NAME) ) } @Test - fun `changing login removes new lines the expected event`() { + fun `changing login removes new lines the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( eventSink = eventsRecorder, ), ) - val userNameHint = rule.activity.getString(CommonStrings.common_username) - rule.onNodeWithText(userNameHint).performTextInput("a\nb") + val userNameHint = activity!!.getString(CommonStrings.common_username) + onNodeWithText(userNameHint).performTextInput("a\nb") eventsRecorder.assertSingle( LoginPasswordEvents.SetLogin("ab") ) } @Test - fun `clearing login invokes the expected event`() { + fun `clearing login invokes the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( formState = aLoginFormState(A_USER_NAME), eventSink = eventsRecorder, ), ) - val a11yClear = rule.activity.getString(CommonStrings.action_clear) - rule.onNodeWithContentDescription(a11yClear).performClick() + val a11yClear = activity!!.getString(CommonStrings.action_clear) + onNodeWithContentDescription(a11yClear).performClick() eventsRecorder.assertSingle( LoginPasswordEvents.SetLogin("") ) } @Test - fun `changing password invokes the expected event`() { + fun `changing password invokes the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( eventSink = eventsRecorder, ), ) - val userNameHint = rule.activity.getString(CommonStrings.common_password) - rule.onNodeWithText(userNameHint).performTextInput(A_PASSWORD) + val userNameHint = activity!!.getString(CommonStrings.common_password) + onNodeWithText(userNameHint).performTextInput(A_PASSWORD) eventsRecorder.assertSingle( LoginPasswordEvents.SetPassword(A_PASSWORD) ) } @Test - fun `reveal password makes the password visible`() { + fun `reveal password makes the password visible`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( formState = aLoginFormState(password = A_PASSWORD), eventSink = eventsRecorder, ), ) - rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••")) + onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••")) + val resources = activity!!.resources // Show password - val a11yShowPassword = rule.activity.getString(CommonStrings.a11y_show_password) - rule.onNodeWithContentDescription(a11yShowPassword).performClick() - rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText(A_PASSWORD)) + val a11yShowPassword = resources.getString(CommonStrings.a11y_show_password) + onNodeWithContentDescription(a11yShowPassword).performClick() + onNodeWithTag(TestTags.loginPassword.value).assert(hasText(A_PASSWORD)) // Hide password - val a11yHidePassword = rule.activity.getString(CommonStrings.a11y_hide_password) - rule.onNodeWithContentDescription(a11yHidePassword).performClick() - rule.onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••")) + val a11yHidePassword = resources.getString(CommonStrings.a11y_hide_password) + onNodeWithContentDescription(a11yHidePassword).performClick() + onNodeWithTag(TestTags.loginPassword.value).assert(hasText("••••••••")) } @Test - fun `when login is empty, continue button is not enabled`() { + fun `when login is empty, continue button is not enabled`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( formState = aLoginFormState(password = A_PASSWORD), eventSink = eventsRecorder, ), ) - val continueStr = rule.activity.getString(CommonStrings.action_continue) - rule.onNodeWithText(continueStr).assertIsNotEnabled() + val continueStr = activity!!.getString(CommonStrings.action_continue) + onNodeWithText(continueStr).assertIsNotEnabled() } @Test - fun `when password is empty, continue button is not enabled`() { + fun `when password is empty, continue button is not enabled`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( formState = aLoginFormState(login = A_USER_NAME), eventSink = eventsRecorder, ), ) - val continueStr = rule.activity.getString(CommonStrings.action_continue) - rule.onNodeWithText(continueStr).assertIsNotEnabled() + val continueStr = activity!!.getString(CommonStrings.action_continue) + onNodeWithText(continueStr).assertIsNotEnabled() } @Config(qualifiers = "h1024dp") @Test - fun `clicking on Continue sends expected event`() { + fun `clicking on Continue sends expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLoginPasswordView( + setLoginPasswordView( aLoginPasswordState( formState = aLoginFormState(login = A_USER_NAME, password = A_PASSWORD), eventSink = eventsRecorder, ), ) - val continueStr = rule.activity.getString(CommonStrings.action_continue) - rule.onNodeWithText(continueStr).assertIsEnabled() - rule.clickOn(CommonStrings.action_continue) + val continueStr = activity!!.getString(CommonStrings.action_continue) + onNodeWithText(continueStr).assertIsEnabled() + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle( LoginPasswordEvents.Submit ) } } -private fun AndroidComposeTestRule.setLoginPasswordView( +private fun AndroidComposeUiTest.setLoginPasswordView( state: LoginPasswordState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt index a8f0ccbb5a..bcb62ea707 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt @@ -6,14 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.onboarding import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import com.google.testing.junit.testparameterinjector.KotlinTestParameters.namedTestValues import com.google.testing.junit.testparameterinjector.TestParameter import io.element.android.features.login.impl.R @@ -29,22 +32,17 @@ 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 import org.robolectric.RobolectricTestParameterInjector @RunWith(RobolectricTestParameterInjector::class) class OnboardingViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `when can create account - clicking on create account calls the expected callback`() { + fun `when can create account - clicking on create account calls the expected callback`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( canCreateAccount = true, showDeveloperSettings = false, @@ -52,40 +50,40 @@ class OnboardingViewTest { ), onCreateAccount = callback, ) - rule.clickOn(R.string.screen_onboarding_sign_up) + clickOn(R.string.screen_onboarding_sign_up) // Developer settings should not be shown - val developerSettingsText = rule.activity.getString(CommonStrings.common_developer_options) - rule.onNodeWithContentDescription(developerSettingsText).assertDoesNotExist() + val developerSettingsText = activity!!.getString(CommonStrings.common_developer_options) + onNodeWithContentDescription(developerSettingsText).assertDoesNotExist() } } @Test - fun `when can go back - clicking on back calls the expected callback`() { + fun `when can go back - clicking on back calls the expected callback`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( isAddingAccount = true, eventSink = eventSink, ), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `when can login with QR code - clicking on sign in with QR code calls the expected callback`() { + fun `when can login with QR code - clicking on sign in with QR code calls the expected callback`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( canLoginWithQrCode = true, eventSink = eventSink, ), onSignInWithQrCode = callback, ) - rule.clickOn(R.string.screen_onboarding_sign_in_with_qr_code) + clickOn(R.string.screen_onboarding_sign_in_with_qr_code) } } @@ -95,10 +93,10 @@ class OnboardingViewTest { "can search account provider" to false, "cannot search account provider" to true, ) - ) { + ) = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(mustChooseAccountProvider) { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( canLoginWithQrCode = true, mustChooseAccountProvider = mustChooseAccountProvider, @@ -106,7 +104,7 @@ class OnboardingViewTest { ), onSignIn = callback, ) - rule.clickOn(R.string.screen_onboarding_sign_in_manually) + clickOn(R.string.screen_onboarding_sign_in_manually) } } @@ -116,10 +114,10 @@ class OnboardingViewTest { "can search account provider" to false, "cannot search account provider" to true, ) - ) { + ) = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(mustChooseAccountProvider) { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( canLoginWithQrCode = false, canCreateAccount = false, @@ -128,89 +126,89 @@ class OnboardingViewTest { ), onSignIn = callback, ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) } } @Test - fun `when sign in to pre defined account provider - clicking on button emits the expected event`() { + fun `when sign in to pre defined account provider - clicking on button emits the expected event`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( defaultAccountProvider = "element.io", eventSink = eventSink, ), ) - val buttonText = rule.activity.getString(R.string.screen_onboarding_sign_in_to, "element.io") - rule.onNodeWithText(buttonText).performClick() + val buttonText = activity!!.getString(R.string.screen_onboarding_sign_in_to, "element.io") + onNodeWithText(buttonText).performClick() eventSink.assertSingle(OnBoardingEvents.OnSignIn("element.io")) } @Test - fun `when error is displayed - closing the dialog emits the expected event`() { + fun `when error is displayed - closing the dialog emits the expected event`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( defaultAccountProvider = "element.io", loginMode = AsyncData.Failure(AN_EXCEPTION), eventSink = eventSink, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventSink.assertSingle(OnBoardingEvents.ClearError) } @Test - fun `clicking on report a problem calls the sign in callback`() { + fun `clicking on report a problem calls the sign in callback`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( canReportBug = true, eventSink = eventSink, ), onReportProblem = callback, ) - val text = rule.activity.getString(CommonStrings.common_report_a_problem) - rule.onNodeWithText(text).assertExists() - rule.clickOn(CommonStrings.common_report_a_problem) + val text = activity!!.getString(CommonStrings.common_report_a_problem) + onNodeWithText(text).assertExists() + clickOn(CommonStrings.common_report_a_problem) } } @Test - fun `clicking on settings calls the developer settings callback`() { + fun `clicking on settings calls the developer settings callback`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( showDeveloperSettings = true, eventSink = eventSink, ), onDeveloperSettingsClick = callback, ) - val text = rule.activity.getString(CommonStrings.common_developer_options) - rule.onNodeWithContentDescription(text).performClick() + val text = activity!!.getString(CommonStrings.common_developer_options) + onNodeWithContentDescription(text).performClick() } } @Test - fun `cannot report a problem when the feature is disabled`() { + fun `cannot report a problem when the feature is disabled`() = runAndroidComposeUiTest { val eventSink = EventsRecorder(expectEvents = false) - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( canReportBug = false, eventSink = eventSink, ), ) - val text = rule.activity.getString(CommonStrings.common_report_a_problem) - rule.onNodeWithText(text).assertDoesNotExist() + val text = activity!!.getString(CommonStrings.common_report_a_problem) + onNodeWithText(text).assertDoesNotExist() } @Test - fun `when success PasswordLogin - the expected callback is invoked and the event is received`() { + fun `when success PasswordLogin - the expected callback is invoked and the event is received`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() ensureCalledOnce { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( loginMode = AsyncData.Success(LoginMode.PasswordLogin), eventSink = eventSink, @@ -222,11 +220,11 @@ class OnboardingViewTest { } @Test - fun `when success Oidc - the expected callback is invoked and the event is received`() { + fun `when success Oidc - the expected callback is invoked and the event is received`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() val oAuthDetails = OAuthDetails("aUrl") ensureCalledOnceWithParam(oAuthDetails) { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( loginMode = AsyncData.Success(LoginMode.OAuth(oAuthDetails)), eventSink = eventSink, @@ -238,11 +236,11 @@ class OnboardingViewTest { } @Test - fun `when success AccountCreation - the expected callback is invoked and the event is received`() { + fun `when success AccountCreation - the expected callback is invoked and the event is received`() = runAndroidComposeUiTest { val eventSink = EventsRecorder() val oAuthDetails = OAuthDetails("aUrl") ensureCalledOnceWithParam(oAuthDetails.url) { callback -> - rule.setOnboardingView( + setOnboardingView( state = anOnBoardingState( loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl")), eventSink = eventSink, @@ -253,7 +251,7 @@ class OnboardingViewTest { eventSink.assertSingle(OnBoardingEvents.ClearError) } - private fun AndroidComposeTestRule.setOnboardingView( + private fun AndroidComposeUiTest.setOnboardingView( state: OnBoardingState, onBackClick: () -> Unit = EnsureNeverCalled(), onDeveloperSettingsClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/confirmation/QrCodeConfirmationViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/confirmation/QrCodeConfirmationViewTest.kt index a0469a684e..79566625c5 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/confirmation/QrCodeConfirmationViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/confirmation/QrCodeConfirmationViewTest.kt @@ -6,49 +6,47 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.qrcode.confirmation import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class QrCodeConfirmationViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeConfirmationView( + setQrCodeConfirmationView( step = QrCodeConfirmationStep.DisplayCheckCode("12"), onCancel = callback ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on Cancel button clicked - calls the expected callback`() { + fun `on Cancel button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeConfirmationView( + setQrCodeConfirmationView( step = QrCodeConfirmationStep.DisplayVerificationCode("123456"), onCancel = callback ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) } } - private fun AndroidComposeTestRule.setQrCodeConfirmationView( + private fun AndroidComposeUiTest.setQrCodeConfirmationView( step: QrCodeConfirmationStep, onCancel: () -> Unit ) { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorViewTest.kt index de0f689220..2ae68c3485 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.qrcode.error import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.login.impl.qrcode.QrCodeErrorScreenType import io.element.android.libraries.ui.strings.CommonStrings @@ -18,47 +21,42 @@ import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class QrCodeErrorViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the onCancel callback`() { + fun `on back pressed - calls the onCancel callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeErrorView( + setQrCodeErrorView( onCancel = callback, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on try again button clicked - calls the expected callback`() { + fun `on try again button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeErrorView( + setQrCodeErrorView( onRetry = callback, ) - rule.clickOn(CommonStrings.action_try_again) + clickOn(CommonStrings.action_try_again) } } @Test - fun `on cancel button clicked - calls the expected callback`() { + fun `on cancel button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeErrorView( + setQrCodeErrorView( onCancel = callback, ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) } } - private fun AndroidComposeTestRule.setQrCodeErrorView( + private fun AndroidComposeUiTest.setQrCodeErrorView( onRetry: () -> Unit = EnsureNeverCalled(), onCancel: () -> Unit = EnsureNeverCalled(), errorScreenType: QrCodeErrorScreenType = QrCodeErrorScreenType.UnknownError, diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroViewTest.kt index cec67e5011..c6812d3759 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/intro/QrCodeIntroViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.qrcode.intro import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.login.impl.R import io.element.android.tests.testutils.EnsureNeverCalled @@ -19,42 +22,37 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class QrCodeIntroViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeIntroView( + setQrCodeIntroView( state = aQrCodeIntroState(), onBackClicked = callback ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on back button clicked - calls the expected callback`() { + fun `on back button clicked - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeIntroView( + setQrCodeIntroView( state = aQrCodeIntroState(), onBackClicked = callback ) - rule.pressBack() + pressBack() } } @Test - fun `when can continue - calls the expected callback`() { + fun `when can continue - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeIntroView( + setQrCodeIntroView( state = aQrCodeIntroState(canContinue = true), onContinue = callback ) @@ -62,16 +60,16 @@ class QrCodeIntroViewTest { } @Test - fun `on submit button clicked - emits the Continue event`() { + fun `on submit button clicked - emits the Continue event`() = runAndroidComposeUiTest { val eventRecorder = EventsRecorder() - rule.setQrCodeIntroView( + setQrCodeIntroView( state = aQrCodeIntroState(eventSink = eventRecorder), ) - rule.clickOn(R.string.screen_qr_code_login_initial_state_button_title) + clickOn(R.string.screen_qr_code_login_initial_state_button_title) eventRecorder.assertSingle(QrCodeIntroEvents.Continue) } - private fun AndroidComposeTestRule.setQrCodeIntroView( + private fun AndroidComposeUiTest.setQrCodeIntroView( state: QrCodeIntroState, onBackClicked: () -> Unit = EnsureNeverCalled(), onContinue: () -> Unit = EnsureNeverCalled(), diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanViewTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanViewTest.kt index b8becd545f..bde960ef1a 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanViewTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanViewTest.kt @@ -6,12 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.login.impl.screens.qrcode.scan import androidx.activity.ComponentActivity import androidx.camera.lifecycle.ProcessCameraProvider -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import io.element.android.libraries.architecture.AsyncAction @@ -24,16 +27,11 @@ import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.tests.testutils.pressBackKey import org.junit.After import org.junit.Before -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class QrCodeScanViewTest { - @get:Rule - val rule = createAndroidComposeRule() - private var provider: ProcessCameraProvider? = null @Before @@ -48,28 +46,28 @@ class QrCodeScanViewTest { } @Test - fun `on back pressed - calls the expected callback`() { + fun `on back pressed - calls the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setQrCodeScanView( + setQrCodeScanView( state = aQrCodeScanState(), onBackClick = callback ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `on QR code data ready - calls the expected callback`() { + fun `on QR code data ready - calls the expected callback`() = runAndroidComposeUiTest { val data = FakeMatrixQrCodeLoginData() ensureCalledOnceWithParam(data) { callback -> - rule.setQrCodeScanView( + setQrCodeScanView( state = aQrCodeScanState(authenticationAction = AsyncAction.Success(data)), onQrCodeDataReady = callback ) } } - private fun AndroidComposeTestRule.setQrCodeScanView( + private fun AndroidComposeUiTest.setQrCodeScanView( state: QrCodeScanState, onBackClick: () -> Unit = EnsureNeverCalled(), onQrCodeDataReady: (MatrixQrCodeLoginData) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt index 84ca038d7b..a42fd891d4 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.logout.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.testtags.TestTags @@ -21,97 +24,93 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressTag -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class LogoutViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on logout sends a LogoutEvents`() { + fun `clicking on logout sends a LogoutEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLogoutView( + setLogoutView( aLogoutState( eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_signout) + clickOn(CommonStrings.action_signout) eventsRecorder.assertSingle(LogoutEvents.Logout(false)) } @Test - fun `confirming logout sends a LogoutEvents`() { + fun `confirming logout sends a LogoutEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLogoutView( + setLogoutView( aLogoutState( logoutAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(LogoutEvents.Logout(false)) } @Test - fun `clicking on back invoke back callback`() { + fun `clicking on back invoke back callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setLogoutView( + setLogoutView( aLogoutState( eventSink = eventsRecorder ), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on confirm after error sends a LogoutEvents`() { + fun `clicking on confirm after error sends a LogoutEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLogoutView( + setLogoutView( aLogoutState( logoutAction = AsyncAction.Failure(Exception("Failed to logout")), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_signout_anyway) + clickOn(CommonStrings.action_signout_anyway) eventsRecorder.assertSingle(LogoutEvents.Logout(true)) } @Test - fun `clicking on cancel after error sends a LogoutEvents`() { + fun `clicking on cancel after error sends a LogoutEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLogoutView( + setLogoutView( aLogoutState( logoutAction = AsyncAction.Failure(Exception("Failed to logout")), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(LogoutEvents.CloseDialogs) } @Test - fun `last session setting button invoke onChangeRecoveryKeyClicked`() { + fun `last session setting button invoke onChangeRecoveryKeyClicked`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setLogoutView( + setLogoutView( aLogoutState( isLastDevice = true, eventSink = eventsRecorder ), onChangeRecoveryKeyClick = callback, ) - rule.clickOn(CommonStrings.common_settings) + clickOn(CommonStrings.common_settings) } } } -private fun AndroidComposeTestRule.setLogoutView( +private fun AndroidComposeUiTest.setLogoutView( state: LogoutState, onChangeRecoveryKeyClick: () -> Unit = EnsureNeverCalled(), onBackClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutViewTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutViewTest.kt index 8eae534740..99860259c4 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutViewTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.logout.impl.direct import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.logout.api.direct.DirectLogoutEvents import io.element.android.features.logout.api.direct.DirectLogoutState @@ -21,83 +24,79 @@ import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressBackKey import org.junit.Ignore -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class DefaultDirectLogoutViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on confirm logout sends expected Event`() { + fun `clicking on confirm logout sends expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDefaultDirectLogoutView( + setDefaultDirectLogoutView( state = aDirectLogoutState( logoutAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder, ) ) - rule.clickOn(CommonStrings.action_signout) + clickOn(CommonStrings.action_signout) eventsRecorder.assertSingle(DirectLogoutEvents.Logout(false)) } @Test - fun `clicking on cancel logout sends expected Event`() { + fun `clicking on cancel logout sends expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDefaultDirectLogoutView( + setDefaultDirectLogoutView( state = aDirectLogoutState( logoutAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder, ) ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(DirectLogoutEvents.CloseDialogs) } @Ignore("Pressing back key should dismiss the dialog, and so generate the expected event, but it's not the case.") @Test - fun `clicking on back invoke back callback`() { + fun `clicking on back invoke back callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDefaultDirectLogoutView( + setDefaultDirectLogoutView( state = aDirectLogoutState( logoutAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder, ) ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(DirectLogoutEvents.CloseDialogs) } @Test - fun `clicking on confirm after error sends expected Event`() { + fun `clicking on confirm after error sends expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDefaultDirectLogoutView( + setDefaultDirectLogoutView( state = aDirectLogoutState( logoutAction = AsyncAction.Failure(Exception("Error")), eventSink = eventsRecorder, ) ) - rule.clickOn(CommonStrings.action_signout_anyway) + clickOn(CommonStrings.action_signout_anyway) eventsRecorder.assertSingle(DirectLogoutEvents.Logout(true)) } @Test - fun `clicking on cancel after error sends expected Event`() { + fun `clicking on cancel after error sends expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDefaultDirectLogoutView( + setDefaultDirectLogoutView( state = aDirectLogoutState( logoutAction = AsyncAction.Failure(Exception("Error")), eventSink = eventsRecorder, ) ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(DirectLogoutEvents.CloseDialogs) } } -private fun AndroidComposeTestRule.setDefaultDirectLogoutView( +private fun AndroidComposeUiTest.setDefaultDirectLogoutView( state: DirectLogoutState, ) { setContent { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 62b9eac68d..70ef70325e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -6,13 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl import androidx.activity.ComponentActivity import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.longClick import androidx.compose.ui.test.onAllNodesWithContentDescription import androidx.compose.ui.test.onAllNodesWithTag @@ -25,6 +27,7 @@ import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipeRight +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.compose.ui.text.AnnotatedString import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.emojibasebindings.Emoji @@ -78,82 +81,78 @@ import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.setSafeContent import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentMapOf -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config import kotlin.time.Duration.Companion.milliseconds @RunWith(AndroidJUnit4::class) class MessagesViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invoke expected callback`() { + fun `clicking on back invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setMessagesView( + setMessagesView( state = state, onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on room name invoke expected callback`() { + fun `clicking on room name invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setMessagesView( + setMessagesView( state = state, onRoomDetailsClick = callback, ) - rule.onNodeWithText(state.roomName.orEmpty(), useUnmergedTree = true).performClick() + onNodeWithText(state.roomName.orEmpty(), useUnmergedTree = true).performClick() } } @Test - fun `clicking on join call invoke expected callback`() { + fun `clicking on join call invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder ) ensureCalledOnceWithParam(false) { callback -> - rule.setMessagesView( + setMessagesView( state = state, onJoinCallClick = callback, ) - val joinCallContentDescription = rule.activity.getString(CommonStrings.a11y_start_call) - rule.onNodeWithContentDescription(joinCallContentDescription).performClick() + val joinCallContentDescription = activity!!.getString(CommonStrings.a11y_start_call) + onNodeWithContentDescription(joinCallContentDescription).performClick() } } @Test - fun `clicking on join voice call invoke expected callback`() { + fun `clicking on join voice call invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder, roomCallState = aStandByCallState(isDM = true) ) ensureCalledOnceWithParam(true) { callback -> - rule.setMessagesView( + setMessagesView( state = state, onJoinCallClick = callback, ) - val joinVoiceCallContentDescription = rule.activity.getString(CommonStrings.a11y_start_voice_call) - rule.onNodeWithContentDescription(joinVoiceCallContentDescription).performClick() + val joinVoiceCallContentDescription = activity!!.getString(CommonStrings.a11y_start_voice_call) + onNodeWithContentDescription(joinVoiceCallContentDescription).performClick() } } @Test - fun `clicking on an Event invoke expected callback`() { + fun `clicking on an Event invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( timelineState = aTimelineState( @@ -167,12 +166,12 @@ class MessagesViewTest { expectedParam2 = timelineItem, result = true, ) - rule.setMessagesView( + setMessagesView( state = state, onEventClick = callback, ) // Cannot perform click on "Text", it's not detected. Use tag instead - rule.onAllNodesWithTag(TestTags.messageBubble.value).onFirst().performClick() + onAllNodesWithTag(TestTags.messageBubble.value).onFirst().performClick() callback.assertSuccess() } @@ -202,7 +201,7 @@ class MessagesViewTest { userHasPermissionToRedactOther: Boolean = false, userHasPermissionToSendReaction: Boolean = false, userCanPinEvent: Boolean = false, - ) { + ) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( actionListState = anActionListState( @@ -220,11 +219,11 @@ class MessagesViewTest { ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event - rule.setMessagesView( + setMessagesView( state = state, ) // Cannot perform click on "Text", it's not detected. Use tag instead - rule.onAllNodesWithTag(TestTags.messageBubble.value).onFirst().performTouchInput { longClick() } + onAllNodesWithTag(TestTags.messageBubble.value).onFirst().performTouchInput { longClick() } eventsRecorder.assertSingle( ActionListEvent.ComputeForMessage( event = timelineItem, @@ -235,7 +234,7 @@ class MessagesViewTest { @Test @Config(qualifiers = "h1024dp") - fun `clicking on a read receipt list emits the expected Event`() { + fun `clicking on a read receipt list emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( @@ -255,10 +254,10 @@ class MessagesViewTest { ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event - rule.setMessagesView( + setMessagesView( state = state, ) - rule.onNodeWithTag(TestTags.messageReadReceipts.value, useUnmergedTree = true).performClick() + onNodeWithTag(TestTags.messageReadReceipts.value, useUnmergedTree = true).performClick() eventsRecorder.assertSingle(ReadReceiptBottomSheetEvent.EventSelected(timelineItem)) } @@ -272,7 +271,7 @@ class MessagesViewTest { swipeTest(userHasPermissionToSendMessage = false) } - private fun swipeTest(userHasPermissionToSendMessage: Boolean) { + private fun swipeTest(userHasPermissionToSendMessage: Boolean) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val canBeRepliedEvent = aTimelineItemEvent(canBeRepliedTo = true) val cannotBeRepliedEvent = aTimelineItemEvent(canBeRepliedTo = false) @@ -285,10 +284,10 @@ class MessagesViewTest { ), eventSink = eventsRecorder, ) - rule.setMessagesView( + setMessagesView( state = state, ) - rule.onAllNodesWithTag(TestTags.messageBubble.value).apply { + onAllNodesWithTag(TestTags.messageBubble.value).apply { onFirst().performTouchInput { swipeRight(endX = 200f) } onLast().performTouchInput { swipeRight(endX = 200f) } } @@ -300,7 +299,7 @@ class MessagesViewTest { } @Test - fun `clicking on send location invoke expected callback`() { + fun `clicking on send location invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( composerState = aMessageComposerState( @@ -309,16 +308,16 @@ class MessagesViewTest { eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setMessagesView( + setMessagesView( state = state, onSendLocationClick = callback, ) - rule.clickOn(R.string.screen_room_attachment_source_location) + clickOn(R.string.screen_room_attachment_source_location) } } @Test - fun `clicking on create poll invoke expected callback`() { + fun `clicking on create poll invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( composerState = aMessageComposerState( @@ -327,25 +326,25 @@ class MessagesViewTest { eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setMessagesView( + setMessagesView( state = state, onCreatePollClick = callback, ) // Then click on the poll action - rule.clickOn(R.string.screen_room_attachment_source_poll) + clickOn(R.string.screen_room_attachment_source_poll) } } @Test @Config(qualifiers = "h1024dp") - fun `clicking on the avatar of the sender of an Event emits the expected event`() { + fun `clicking on the avatar of the sender of an Event emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( eventSink = eventsRecorder ) val timelineEvent = state.timelineState.timelineItems.filterIsInstance().first() - rule.setMessagesView(state = state) - rule.onNodeWithTag(TestTags.timelineItemSenderAvatar.value, useUnmergedTree = true).performClick() + setMessagesView(state = state) + onNodeWithTag(TestTags.timelineItemSenderAvatar.value, useUnmergedTree = true).performClick() eventsRecorder.assertSingle( MessagesEvent.OnUserClicked( MatrixUser( @@ -359,12 +358,12 @@ class MessagesViewTest { @Test @Config(qualifiers = "h1024dp") - fun `clicking on the display name of the sender of an Event emits expected event`() { + fun `clicking on the display name of the sender of an Event emits expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState(eventSink = eventsRecorder) val timelineEvent = state.timelineState.timelineItems.filterIsInstance().first() - rule.setMessagesView(state = state) - rule.onNodeWithTag(TestTags.timelineItemSenderAvatar.value, useUnmergedTree = true).performClick() + setMessagesView(state = state) + onNodeWithTag(TestTags.timelineItemSenderAvatar.value, useUnmergedTree = true).performClick() eventsRecorder.assertSingle( MessagesEvent.OnUserClicked( MatrixUser( @@ -377,7 +376,7 @@ class MessagesViewTest { } @Test - fun `selecting a action on a message emits the expected Event`() { + fun `selecting a action on a message emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( eventSink = eventsRecorder @@ -395,17 +394,17 @@ class MessagesViewTest { ) ), ) - rule.setMessagesView( + setMessagesView( state = stateWithMessageAction, ) - rule.clickOn(CommonStrings.action_edit) + clickOn(CommonStrings.action_edit) // Give time for the close animation to complete - rule.mainClock.advanceTimeBy(milliseconds = 1_000) + mainClock.advanceTimeBy(milliseconds = 1_000) eventsRecorder.assertSingle(MessagesEvent.HandleAction(TimelineItemAction.Edit, timelineItem)) } @Test - fun `clicking on a reaction emits the expected Event`() { + fun `clicking on a reaction emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( @@ -414,10 +413,10 @@ class MessagesViewTest { eventSink = eventsRecorder, ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event - rule.setMessagesView( + setMessagesView( state = state, ) - rule.onAllNodesWithText( + onAllNodesWithText( text = "👍️", useUnmergedTree = true, ).onFirst().performClick() @@ -425,7 +424,7 @@ class MessagesViewTest { } @Test - fun `long clicking on a reaction emits the expected Event`() { + fun `long clicking on a reaction emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( @@ -437,10 +436,10 @@ class MessagesViewTest { ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event - rule.setMessagesView( + setMessagesView( state = state, ) - rule.onAllNodesWithText( + onAllNodesWithText( text = "👍️", useUnmergedTree = true, ).onFirst().performTouchInput { longClick() } @@ -448,7 +447,7 @@ class MessagesViewTest { } @Test - fun `clicking on more reaction emits the expected Event`() { + fun `clicking on more reaction emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( @@ -459,16 +458,16 @@ class MessagesViewTest { ), ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event - rule.setMessagesView( + setMessagesView( state = state, ) - val moreReactionContentDescription = rule.activity.getString(R.string.screen_room_timeline_add_reaction) - rule.onAllNodesWithContentDescription(moreReactionContentDescription).onFirst().performClick() + val moreReactionContentDescription = activity!!.getString(R.string.screen_room_timeline_add_reaction) + onAllNodesWithContentDescription(moreReactionContentDescription).onFirst().performClick() eventsRecorder.assertSingle(CustomReactionEvent.ShowCustomReactionSheet(timelineItem)) } @Test - fun `clicking on more reaction from action list emits the expected Event`() { + fun `clicking on more reaction from action list emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( @@ -491,18 +490,18 @@ class MessagesViewTest { eventSink = eventsRecorder ), ) - rule.setMessagesView( + setMessagesView( state = stateWithActionListState, ) - val moreReactionContentDescription = rule.activity.getString(CommonStrings.a11y_react_with_other_emojis) - rule.onNodeWithContentDescription(moreReactionContentDescription).performClick() + val moreReactionContentDescription = activity!!.getString(CommonStrings.a11y_react_with_other_emojis) + onNodeWithContentDescription(moreReactionContentDescription).performClick() // Give time for the close animation to complete - rule.mainClock.advanceTimeBy(milliseconds = 1_000) + mainClock.advanceTimeBy(milliseconds = 1_000) eventsRecorder.assertSingle(CustomReactionEvent.ShowCustomReactionSheet(timelineItem)) } @Test - fun `clicking on verified user send failure from action list emits the expected Event`() { + fun `clicking on verified user send failure from action list emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState() val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event @@ -519,21 +518,21 @@ class MessagesViewTest { ), timelineState = aTimelineState(eventSink = eventsRecorder) ) - rule.setMessagesView( + setMessagesView( state = stateWithActionListState, ) // Clear initial 'LoadMore' event emitted when setting the state eventsRecorder.clear() - val verifiedUserSendFailure = rule.activity.getString(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, "Alice") - rule.onNodeWithText(verifiedUserSendFailure).performClick() + val verifiedUserSendFailure = activity!!.getString(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, "Alice") + onNodeWithText(verifiedUserSendFailure).performClick() // Give time for the close animation to complete - rule.mainClock.advanceTimeBy(milliseconds = 1_000) + mainClock.advanceTimeBy(milliseconds = 1_000) eventsRecorder.assertSingle(TimelineEvent.ComputeVerifiedUserSendFailure(timelineItem)) } @Test - fun `clicking on a custom emoji emits the expected Events`() { + fun `clicking on a custom emoji emits the expected Events`() = runAndroidComposeUiTest { val aUnicode = "🙈" val customReactionStateEventsRecorder = EventsRecorder() val eventsRecorder = EventsRecorder() @@ -563,18 +562,18 @@ class MessagesViewTest { eventSink = customReactionStateEventsRecorder ), ) - rule.setMessagesView( + setMessagesView( state = stateWithCustomReactionState, ) - rule.onNodeWithText(aUnicode, useUnmergedTree = true).performClick() + onNodeWithText(aUnicode, useUnmergedTree = true).performClick() // Give time for the close animation to complete - rule.mainClock.advanceTimeBy(milliseconds = 1_000) + mainClock.advanceTimeBy(milliseconds = 1_000) customReactionStateEventsRecorder.assertSingle(CustomReactionEvent.DismissCustomReactionSheet) eventsRecorder.assertSingle(MessagesEvent.ToggleReaction(aUnicode, timelineItem.eventOrTransactionId)) } @Test - fun `clicking on pinned messages banner emits the expected Event`() { + fun `clicking on pinned messages banner emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState(eventSink = eventsRecorder), @@ -587,16 +586,16 @@ class MessagesViewTest { ), ), ) - rule.setMessagesView(state = state) + setMessagesView(state = state) // Clear initial 'LoadMore' event emitted when setting the state eventsRecorder.clear() - rule.onNodeWithText("This is a pinned message").performClick() + onNodeWithText("This is a pinned message").performClick() eventsRecorder.assertSingle(TimelineEvent.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)) } @Test - fun `clicking on successor room button emits expected event`() { + fun `clicking on successor room button emits expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val successorRoomId = RoomId("!successor:server.org") val state = aMessagesState( @@ -606,18 +605,18 @@ class MessagesViewTest { ), timelineState = aTimelineState(eventSink = eventsRecorder) ) - rule.setMessagesView(state = state) + setMessagesView(state = state) // Clear initial 'LoadMore' event emitted when setting the state eventsRecorder.clear() - val text = rule.activity.getString(R.string.screen_room_timeline_tombstoned_room_action) + val text = activity!!.getString(R.string.screen_room_timeline_tombstoned_room_action) // The bottomsheet subcompose seems to make the node to appear twice - rule.onAllNodesWithText(text).onFirst().performClick() + onAllNodesWithText(text).onFirst().performClick() eventsRecorder.assertSingle(TimelineEvent.NavigateToPredecessorOrSuccessorRoom(successorRoomId)) } @Test - fun `clicking on threads list button calls the expected function`() { + fun `clicking on threads list button calls the expected function`() = runAndroidComposeUiTest { val state = aMessagesState( threads = MessagesState.Threads( hasThreads = true, @@ -625,28 +624,28 @@ class MessagesViewTest { ) ) val onThreadsListClicked = lambdaRecorder {} - rule.setMessagesView( + setMessagesView( state = state, onThreadsListClicked = onThreadsListClicked, ) - rule.onNodeWithContentDescription("Threads").performClick() + onNodeWithContentDescription("Threads").performClick() onThreadsListClicked.assertions().isCalledOnce() } @Test - fun `no banner shown when there is no successor room`() { + fun `no banner shown when there is no successor room`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( successorRoom = null, eventSink = eventsRecorder ) - rule.setMessagesView(state = state) - rule.assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_message) - rule.assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_action) + setMessagesView(state = state) + assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_message) + assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_action) } } -private fun AndroidComposeTestRule.setMessagesView( +private fun AndroidComposeUiTest.setMessagesView( state: MessagesState, onBackClick: () -> Unit = EnsureNeverCalled(), onRoomDetailsClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateViewTest.kt index 24779ba78a..0ee342513a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateViewTest.kt @@ -6,12 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.crypto.identity import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.matrix.api.core.UserId @@ -21,19 +24,15 @@ import io.element.android.libraries.matrix.ui.room.RoomMemberIdentityStateChange import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class IdentityChangeStateViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `show and resolve pin violation`() { + fun `show and resolve pin violation`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIdentityChangeStateView( + setIdentityChangeStateView( state = anIdentityChangeState( listOf( RoomMemberIdentityStateChange( @@ -45,18 +44,18 @@ class IdentityChangeStateViewTest { ), ) - rule.onNodeWithText("identity was reset", substring = true).assertExists("should display pin violation warning") - rule.onNodeWithText("@alice:localhost", substring = true).assertExists("should display user mxid") - rule.onNodeWithText("Alice", substring = true).assertExists("should display user displayname") + onNodeWithText("identity was reset", substring = true).assertExists("should display pin violation warning") + onNodeWithText("@alice:localhost", substring = true).assertExists("should display user mxid") + onNodeWithText("Alice", substring = true).assertExists("should display user displayname") - rule.clickOn(res = CommonStrings.action_dismiss) + clickOn(res = CommonStrings.action_dismiss) eventsRecorder.assertSingle(IdentityChangeEvent.PinIdentity(UserId("@alice:localhost"))) } @Test - fun `show and resolve verification violation`() { + fun `show and resolve verification violation`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIdentityChangeStateView( + setIdentityChangeStateView( state = anIdentityChangeState( listOf( RoomMemberIdentityStateChange( @@ -68,17 +67,17 @@ class IdentityChangeStateViewTest { ), ) - rule.onNodeWithText("identity was reset", substring = true).assertExists("should display verification violation warning") - rule.onNodeWithText("@alice:localhost", substring = true).assertExists("should display user mxid") - rule.onNodeWithText("Alice", substring = true).assertExists("should display user displayname") + onNodeWithText("identity was reset", substring = true).assertExists("should display verification violation warning") + onNodeWithText("@alice:localhost", substring = true).assertExists("should display user mxid") + onNodeWithText("Alice", substring = true).assertExists("should display user displayname") - rule.clickOn(res = CommonStrings.crypto_identity_change_withdraw_verification_action) + clickOn(res = CommonStrings.crypto_identity_change_withdraw_verification_action) eventsRecorder.assertSingle(IdentityChangeEvent.WithdrawVerification(UserId("@alice:localhost"))) } @Test - fun `Should not show any banner if no violations`() { - rule.setIdentityChangeStateView( + fun `Should not show any banner if no violations`() = runAndroidComposeUiTest { + setIdentityChangeStateView( state = anIdentityChangeState( listOf( RoomMemberIdentityStateChange( @@ -93,10 +92,10 @@ class IdentityChangeStateViewTest { ), ) - rule.onNodeWithText("identity was reset", substring = true).assertDoesNotExist() + onNodeWithText("identity was reset", substring = true).assertDoesNotExist() } - private fun AndroidComposeTestRule.setIdentityChangeStateView( + private fun AndroidComposeUiTest.setIdentityChangeStateView( state: IdentityChangeState, ) { setContent { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt index 02767fbeb9..07a0fd5f94 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt @@ -6,54 +6,53 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.crypto.sendfailure.resolve import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.setSafeContent -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ResolveVerifiedUserSendFailureViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on resolve and resend emit the expected event`() { + fun `clicking on resolve and resend emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setResolveVerifiedUserSendFailureView( + setResolveVerifiedUserSendFailureView( state = aResolveVerifiedUserSendFailureState( verifiedUserSendFailure = aChangedIdentitySendFailure(), eventSink = eventsRecorder, ), ) - rule.clickOn(res = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) + clickOn(res = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } @Test - fun `clicking on retry emit the expected event`() { + fun `clicking on retry emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setResolveVerifiedUserSendFailureView( + setResolveVerifiedUserSendFailureView( state = aResolveVerifiedUserSendFailureState( verifiedUserSendFailure = aChangedIdentitySendFailure(), eventSink = eventsRecorder, ), ) - rule.clickOn(res = CommonStrings.action_retry) + clickOn(res = CommonStrings.action_retry) eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvent.Retry) } - private fun AndroidComposeTestRule.setResolveVerifiedUserSendFailureView( + private fun AndroidComposeUiTest.setResolveVerifiedUserSendFailureView( state: ResolveVerifiedUserSendFailureState, ) { setSafeContent { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt index e198ea9043..b656430466 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.link import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.ui.strings.CommonStrings @@ -19,51 +22,46 @@ import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.wysiwyg.link.Link -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class LinkViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on cancel emits the expected event`() { + fun `clicking on cancel emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLinkView( + setLinkView( aLinkState( linkClick = ConfirmingLinkClick(aLink), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle( LinkEvent.Cancel ) } @Test - fun `clicking on continue emits the expected event`() { + fun `clicking on continue emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setLinkView( + setLinkView( aLinkState( linkClick = ConfirmingLinkClick(aLink), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle( LinkEvent.Confirm ) } @Test - fun `success state invokes the callback and emits the expected event`() { + fun `success state invokes the callback and emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnceWithParam(aLink) { callback -> - rule.setLinkView( + setLinkView( aLinkState( linkClick = AsyncAction.Success(aLink), eventSink = eventsRecorder, @@ -77,7 +75,7 @@ class LinkViewTest { } } -private fun AndroidComposeTestRule.setLinkView( +private fun AndroidComposeUiTest.setLinkView( state: LinkState, onLinkValid: (Link) -> Unit = EnsureNeverCalledWithParam(), ) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt index 2c33e348c0..546731ff87 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.pinned.banner import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.ui.strings.CommonStrings @@ -22,49 +25,45 @@ 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 org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class PinnedMessagesBannerViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on the banner invoke expected callback`() { + fun `clicking on the banner invoke expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aLoadedPinnedMessagesBannerState( eventSink = eventsRecorder ) val pinnedEventId = state.currentPinnedMessage.eventId ensureCalledOnceWithParam(pinnedEventId) { callback -> - rule.setPinnedMessagesBannerView( + setPinnedMessagesBannerView( state = state, onClick = callback ) - rule.onRoot().performClick() + onRoot().performClick() eventsRecorder.assertSingle(PinnedMessagesBannerEvent.MoveToNextPinned) } } @Test - fun `clicking on view all emit the expected event`() { + fun `clicking on view all emit the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = true) val state = aLoadedPinnedMessagesBannerState( eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setPinnedMessagesBannerView( + setPinnedMessagesBannerView( state = state, onViewAllClick = callback ) - rule.clickOn(CommonStrings.screen_room_pinned_banner_view_all_button_title) + clickOn(CommonStrings.screen_room_pinned_banner_view_all_button_title) } } } -private fun AndroidComposeTestRule.setPinnedMessagesBannerView( +private fun AndroidComposeUiTest.setPinnedMessagesBannerView( state: PinnedMessagesBannerState, onClick: (EventId) -> Unit = EnsureNeverCalledWithParam(), onViewAllClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt index 41671b71c1..9c10abb631 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt @@ -6,16 +6,19 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.pinned.list import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.longClick import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.anActionListState @@ -31,33 +34,28 @@ import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.setSafeContent import io.element.android.wysiwyg.link.Link -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class PinnedMessagesListViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back calls the expected callback`() { + fun `clicking on back calls the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aLoadedPinnedMessagesListState( eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setPinnedMessagesListView( + setPinnedMessagesListView( state = state, onBackClick = callback ) - rule.pressBack() + pressBack() } } @Test - fun `click on an event calls the expected callback`() { + fun `click on an event calls the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val content = aTimelineItemFileContent() val state = aLoadedPinnedMessagesListState( @@ -67,16 +65,16 @@ class PinnedMessagesListViewTest { val event = state.timelineItems.first() as TimelineItem.Event ensureCalledOnceWithParam(event) { callback -> - rule.setPinnedMessagesListView( + setPinnedMessagesListView( state = state, onEventClick = callback ) - rule.onAllNodesWithText(content.filename).onFirst().performClick() + onAllNodesWithText(content.filename).onFirst().performClick() } } @Test - fun `long click on an event emits the expected event`() { + fun `long click on an event emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = true) val content = aTimelineItemFileContent() val state = aLoadedPinnedMessagesListState( @@ -84,10 +82,10 @@ class PinnedMessagesListViewTest { actionListState = anActionListState(eventSink = eventsRecorder) ) - rule.setPinnedMessagesListView( + setPinnedMessagesListView( state = state, ) - rule.onAllNodesWithText(content.filename).onFirst() + onAllNodesWithText(content.filename).onFirst() .performTouchInput { longClick() } @@ -96,7 +94,7 @@ class PinnedMessagesListViewTest { } } -private fun AndroidComposeTestRule.setPinnedMessagesListView( +private fun AndroidComposeUiTest.setPinnedMessagesListView( state: PinnedMessagesListState, onBackClick: () -> Unit = EnsureNeverCalled(), onEventClick: (event: TimelineItem.Event) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProviderTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProviderTest.kt index 315d9c459c..9e98f0fa49 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProviderTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/DefaultHtmlConverterProviderTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.timeline import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runComposeUiTest import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter import io.element.android.libraries.core.extensions.runCatchingExceptions @@ -18,15 +21,12 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider import io.element.android.libraries.textcomposer.mentions.MentionSpanTheme -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class DefaultHtmlConverterProviderTest { - @get:Rule val composeTestRule = createComposeRule() - private val provider = DefaultHtmlConverterProvider( mentionSpanProvider = MentionSpanProvider( permalinkParser = FakePermalinkParser(), @@ -43,8 +43,8 @@ class DefaultHtmlConverterProviderTest { } @Test - fun `calling provide after calling Update first should return an HtmlConverter`() { - composeTestRule.setContent { + fun `calling provide after calling Update first should return an HtmlConverter`() = runComposeUiTest { + setContent { CompositionLocalProvider(LocalInspectionMode provides true) { provider.Update() } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt index 3a0b0e1224..2138d4ced2 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt @@ -6,15 +6,18 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.timeline import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollToIndex +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.components.aCriticalShield @@ -39,19 +42,15 @@ import io.element.android.wysiwyg.link.Link import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import org.junit.Ignore -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class TimelineViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `reaching the end of the timeline with more events to load emits a LoadMore event`() { + fun `reaching the end of the timeline with more events to load emits a LoadMore event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf( TimelineItem.Virtual( @@ -66,9 +65,9 @@ class TimelineViewTest { } @Test - fun `reaching the end of the timeline does not send a LoadMore event`() { + fun `reaching the end of the timeline does not send a LoadMore event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), eventSink = eventsRecorder, @@ -78,9 +77,9 @@ class TimelineViewTest { } @Test - fun `scroll to bottom on live timeline does not emit the Event`() { + fun `scroll to bottom on live timeline does not emit the Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), isLive = true, @@ -92,14 +91,14 @@ class TimelineViewTest { eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) eventsRecorder.clear() - val contentDescription = rule.activity.getString(CommonStrings.a11y_jump_to_bottom) - rule.onNodeWithContentDescription(contentDescription).performClick() + val contentDescription = activity!!.getString(CommonStrings.a11y_jump_to_bottom) + onNodeWithContentDescription(contentDescription).performClick() } @Test - fun `scroll to bottom on detached timeline emits the expected Event`() { + fun `scroll to bottom on detached timeline emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), isLive = false, @@ -110,15 +109,15 @@ class TimelineViewTest { eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) eventsRecorder.clear() - val contentDescription = rule.activity.getString(CommonStrings.a11y_jump_to_bottom) - rule.onNodeWithContentDescription(contentDescription).performClick() + val contentDescription = activity!!.getString(CommonStrings.a11y_jump_to_bottom) + onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertSingle(TimelineEvent.JumpToLive) } @Test - fun `an empty timeline triggers a prefetch`() { + fun `an empty timeline triggers a prefetch`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf(), eventSink = eventsRecorder, @@ -129,9 +128,9 @@ class TimelineViewTest { } @Test - fun `show shield dialog`() { + fun `show shield dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf( aTimelineItemEvent( @@ -143,8 +142,8 @@ class TimelineViewTest { eventSink = eventsRecorder, ), ) - val contentDescription = rule.activity.getString(CommonStrings.a11y_encryption_details) - rule.onNodeWithContentDescription(contentDescription).performClick() + val contentDescription = activity!!.getString(CommonStrings.a11y_encryption_details) + onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertList( listOf( TimelineEvent.OnScrollFinished(0), @@ -154,9 +153,9 @@ class TimelineViewTest { } @Test - fun `hide shield dialog`() { + fun `hide shield dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), isLive = false, @@ -167,16 +166,16 @@ class TimelineViewTest { eventsRecorder.assertSingle(TimelineEvent.OnScrollFinished(firstIndex = 0)) eventsRecorder.clear() - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(TimelineEvent.HideShieldDialog) } @Ignore( "performScrollToIndex in compose tests no longer sets LazyListState.isScrollInProgress to true, so the LoadMore event is not emitted." + - "This needs to be reworked to use a different approach to check the LoadMore event was emitted." + "This needs to be reworked to use a different approach to check the LoadMore event was emitted." ) @Test - fun `scrolling near to the start of the loaded items triggers a pre-fetch`() { + fun `scrolling near to the start of the loaded items triggers a pre-fetch`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val items = List(200) { aTimelineItemEvent( @@ -185,7 +184,7 @@ class TimelineViewTest { ) }.toImmutableList() - rule.setTimelineView( + setTimelineView( state = aTimelineState( timelineItems = items, eventSink = eventsRecorder, @@ -194,9 +193,9 @@ class TimelineViewTest { ), ) - rule.onNodeWithTag("timeline").performScrollToIndex(180) + onNodeWithTag("timeline").performScrollToIndex(180) - rule.mainClock.advanceTimeBy(1000) + mainClock.advanceTimeBy(1000) eventsRecorder.assertList( listOf( @@ -207,7 +206,7 @@ class TimelineViewTest { } } -private fun AndroidComposeTestRule.setTimelineView( +private fun AndroidComposeUiTest.setTimelineView( state: TimelineState, timelineProtectionState: TimelineProtectionState = aTimelineProtectionState(), onUserDataClick: (MatrixUser) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt index 64b5216d2e..40671e4bf8 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt @@ -6,12 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.timeline.components.event import androidx.activity.ComponentActivity +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent @@ -20,14 +23,11 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressTag -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class TimelineItemPollViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test fun `answering a poll with first answer should emit a PollAnswerSelected event`() { testAnswer(answerIndex = 0) @@ -38,17 +38,17 @@ class TimelineItemPollViewTest { testAnswer(answerIndex = 1) } - private fun testAnswer(answerIndex: Int) { + private fun testAnswer(answerIndex: Int) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val content = aTimelineItemPollContent() - rule.setContent { + setContent { TimelineItemPollView( content = content, eventSink = eventsRecorder ) } val answer = content.answerItems[answerIndex].answer - rule.onNode( + onNode( matcher = hasText(answer.text), useUnmergedTree = true, ).performClick() @@ -56,38 +56,38 @@ class TimelineItemPollViewTest { } @Test - fun `editing a poll should emit a PollEditClicked event`() { + fun `editing a poll should emit a PollEditClicked event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val content = aTimelineItemPollContent( isMine = true, isEditable = true, ) - rule.setContent { + setContent { TimelineItemPollView( content = content, eventSink = eventsRecorder ) } - rule.clickOn(CommonStrings.action_edit_poll) + clickOn(CommonStrings.action_edit_poll) eventsRecorder.assertSingle(TimelineEvent.EditPoll(content.eventId!!)) } @Test - fun `closing a poll should emit a PollEndClicked event`() { + fun `closing a poll should emit a PollEndClicked event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val content = aTimelineItemPollContent( isMine = true, ) - rule.setContent { + setContent { TimelineItemPollView( content = content, eventSink = eventsRecorder ) } - rule.clickOn(CommonStrings.action_end_poll) + clickOn(CommonStrings.action_end_poll) // A confirmation dialog should be shown eventsRecorder.assertEmpty() - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(TimelineEvent.EndPoll(content.eventId!!)) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineTextViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineTextViewTest.kt index 154225aa7a..7b8597f05a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineTextViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineTextViewTest.kt @@ -6,14 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.timeline.components.event import android.text.SpannableString import android.text.SpannedString 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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.core.text.buildSpannedString import androidx.core.text.inSpans import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -38,45 +41,40 @@ import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.wysiwyg.view.spans.CustomMentionSpan import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.test.runTest -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class TimelineTextViewTest { - @get:Rule val rule = createAndroidComposeRule() - private val mentionSpanTheme = MentionSpanTheme(currentUserId = A_USER_ID) private val formatLambda = lambdaRecorder { mentionType -> mentionType.toString() } private val mentionSpanFormatter = FakeMentionSpanFormatter(formatLambda) @Test - fun `getTextWithResolvedMentions - does nothing for a non spannable CharSequence`() = runTest { + fun `getTextWithResolvedMentions - does nothing for a non spannable CharSequence`() = runAndroidComposeUiTest { val charSequence = "Hello @alice:example.com" val mentionSpanUpdater = aMentionSpanUpdater() - val result = rule.getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) + val result = getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) assertThat(result.getMentionSpans()).isEmpty() assert(formatLambda).isNeverCalled() } @Test - fun `getTextWithResolvedMentions - does nothing if there are no mentions`() = runTest { + fun `getTextWithResolvedMentions - does nothing if there are no mentions`() = runAndroidComposeUiTest { val charSequence = SpannableString("Hello @alice:example.com") val mentionSpanUpdater = aMentionSpanUpdater() - val result = rule.getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) + val result = getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) assertThat(result.getMentionSpans()).isEmpty() assert(formatLambda).isNeverCalled() } @Test - fun `getTextWithResolvedMentions - just returns the body if there is no formattedBody`() = runTest { + fun `getTextWithResolvedMentions - just returns the body if there is no formattedBody`() = runAndroidComposeUiTest { val charSequence = "Hello @alice:example.com" val mentionSpanUpdater = aMentionSpanUpdater() - val result = rule.getText(mentionSpanUpdater, aTextContentWithFormattedBody(body = charSequence, formattedBody = null)) + val result = getText(mentionSpanUpdater, aTextContentWithFormattedBody(body = charSequence, formattedBody = null)) assertThat(result.getMentionSpans()).isEmpty() assertThat(result.toString()).isEqualTo(charSequence) @@ -84,7 +82,7 @@ class TimelineTextViewTest { } @Test - fun `getTextWithResolvedMentions - with Room mention format correctly`() = runTest { + fun `getTextWithResolvedMentions - with Room mention format correctly`() = runAndroidComposeUiTest { val mentionType = MentionType.Room(roomIdOrAlias = A_ROOM_ID_2.toRoomIdOrAlias()) val charSequence = buildSpannedString { append("Hello ") @@ -93,7 +91,7 @@ class TimelineTextViewTest { } } val mentionSpanUpdater = aMentionSpanUpdater() - val result = rule.getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) + val result = getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) val expectedDisplayText = mentionType.toString() assertThat(result.getMentionSpans().firstOrNull()?.displayText.toString()).isEqualTo(expectedDisplayText) @@ -102,7 +100,7 @@ class TimelineTextViewTest { } @Test - fun `getTextWithResolvedMentions - replaces MentionSpan's text`() = runTest { + fun `getTextWithResolvedMentions - replaces MentionSpan's text`() = runAndroidComposeUiTest { val mentionType = MentionType.User(userId = A_USER_ID) val charSequence = buildSpannedString { append("Hello ") @@ -111,7 +109,7 @@ class TimelineTextViewTest { } } val mentionSpanUpdater = aMentionSpanUpdater() - val result = rule.getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) + val result = getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) val expectedDisplayText = mentionType.toString() assertThat(result.getMentionSpans().firstOrNull()?.displayText.toString()).isEqualTo(expectedDisplayText) @@ -119,7 +117,7 @@ class TimelineTextViewTest { } @Test - fun `getTextWithResolvedMentions - replaces MentionSpan's text inside CustomMentionSpan`() = runTest { + fun `getTextWithResolvedMentions - replaces MentionSpan's text inside CustomMentionSpan`() = runAndroidComposeUiTest { val mentionType = MentionType.User(userId = A_USER_ID) val charSequence = buildSpannedString { append("Hello ") @@ -129,12 +127,12 @@ class TimelineTextViewTest { } val mentionSpanUpdater = aMentionSpanUpdater() val expectedDisplayText = mentionType.toString() - val result = rule.getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) + val result = getText(mentionSpanUpdater, aTextContentWithFormattedBody(charSequence)) assertThat(result.getMentionSpans().firstOrNull()?.displayText.toString()).isEqualTo(expectedDisplayText) assert(formatLambda).isCalledOnce() } - private suspend fun AndroidComposeTestRule.getText( + private suspend fun AndroidComposeUiTest.getText( mentionSpanUpdater: MentionSpanUpdater, content: TimelineItemTextBasedContent, ): CharSequence { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedViewTest.kt index af3acee6a2..8050278fb2 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedViewTest.kt @@ -6,56 +6,55 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.messages.impl.timeline.protection import androidx.activity.ComponentActivity import androidx.compose.runtime.Composable -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.lambda.lambdaError -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ProtectedViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `when hideContent is false, the content is rendered`() { - rule.setProtectedView( + fun `when hideContent is false, the content is rendered`() = runAndroidComposeUiTest { + setProtectedView( hideContent = false, content = { Text("Hello") } ) - rule.onNodeWithText("Hello").assertExists() + onNodeWithText("Hello").assertExists() } @Test - fun `when hideContent is true, the content is not rendered, and user can reveal it`() { + fun `when hideContent is true, the content is not rendered, and user can reveal it`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setProtectedView( + setProtectedView( hideContent = true, onShowClick = it, content = { Text("Hello") } ) - rule.onNodeWithText("Hello").assertDoesNotExist() - rule.clickOn(CommonStrings.action_show) + onNodeWithText("Hello").assertDoesNotExist() + clickOn(CommonStrings.action_show) } } } -private fun AndroidComposeTestRule.setProtectedView( +private fun AndroidComposeUiTest.setProtectedView( hideContent: Boolean = false, onShowClick: () -> Unit = { lambdaError() }, content: @Composable () -> Unit = {}, diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryViewTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryViewTest.kt index 1ff25a0a81..a6b97c554c 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryViewTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.poll.impl.history import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.poll.api.pollcontent.aPollContentState import io.element.android.features.poll.impl.R @@ -26,34 +29,29 @@ 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 import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class PollHistoryViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setPollHistoryViewView( + setPollHistoryViewView( aPollHistoryState( eventSink = eventsRecorder ), goBack = it ) - rule.pressBack() + pressBack() } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on edit poll invokes the expected callback`() { + fun `clicking on edit poll invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val eventId = EventId("\$anEventId") val state = aPollHistoryState( @@ -69,17 +67,17 @@ class PollHistoryViewTest { eventSink = eventsRecorder ) ensureCalledOnceWithParam(eventId) { - rule.setPollHistoryViewView( + setPollHistoryViewView( state = state, onEditPoll = it ) - rule.clickOn(CommonStrings.action_edit_poll) + clickOn(CommonStrings.action_edit_poll) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on poll end emits the expected Event`() { + fun `clicking on poll end emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val eventId = EventId("\$anEventId") val state = aPollHistoryState( @@ -95,16 +93,16 @@ class PollHistoryViewTest { ), eventSink = eventsRecorder ) - rule.setPollHistoryViewView( + setPollHistoryViewView( state = state, ) - rule.clickOn(CommonStrings.action_end_poll) + clickOn(CommonStrings.action_end_poll) // Cancel the dialog - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) // Do it again, and confirm the dialog - rule.clickOn(CommonStrings.action_end_poll) + clickOn(CommonStrings.action_end_poll) eventsRecorder.assertEmpty() - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle( PollHistoryEvents.EndPoll(eventId) ) @@ -112,7 +110,7 @@ class PollHistoryViewTest { @Config(qualifiers = "h1024dp") @Test - fun `clicking on poll answer emits the expected Event`() { + fun `clicking on poll answer emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val eventId = EventId("\$anEventId") val state = aPollHistoryState( @@ -129,10 +127,10 @@ class PollHistoryViewTest { eventSink = eventsRecorder ) val answer = state.pollHistoryItems.ongoing.first().state.answerItems.first().answer - rule.setPollHistoryViewView( + setPollHistoryViewView( state = state, ) - rule.onNodeWithText( + onNodeWithText( text = answer.text, useUnmergedTree = true, ).performClick() @@ -142,14 +140,14 @@ class PollHistoryViewTest { } @Test - fun `clicking on past tab emits the expected Event`() { + fun `clicking on past tab emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPollHistoryViewView( + setPollHistoryViewView( aPollHistoryState( eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_polls_history_filter_past) + clickOn(R.string.screen_polls_history_filter_past) eventsRecorder.assertSingle( PollHistoryEvents.SelectFilter(filter = PollHistoryFilter.PAST) ) @@ -157,22 +155,22 @@ class PollHistoryViewTest { @Config(qualifiers = "h1024dp") @Test - fun `clicking on load more emits the expected Event`() { + fun `clicking on load more emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPollHistoryViewView( + setPollHistoryViewView( aPollHistoryState( hasMoreToLoad = true, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_load_more) + clickOn(CommonStrings.action_load_more) eventsRecorder.assertSingle( PollHistoryEvents.LoadMore ) } } -private fun AndroidComposeTestRule.setPollHistoryViewView( +private fun AndroidComposeUiTest.setPollHistoryViewView( state: PollHistoryState, onEditPoll: (EventId) -> Unit = EnsureNeverCalledWithParam(), goBack: () -> Unit = EnsureNeverCalled(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutViewTest.kt index 258e9855de..e7ce526843 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.about import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -19,51 +22,47 @@ 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 AboutViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes back callback`() { + fun `clicking on back invokes back callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setAboutView( + setAboutView( anAboutState(), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on an item invokes the expected callback`() { + fun `clicking on an item invokes the expected callback`() = runAndroidComposeUiTest { val state = anAboutState() ensureCalledOnceWithParam(state.elementLegals.first()) { callback -> - rule.setAboutView( + setAboutView( state, onElementLegalClick = callback, ) - rule.clickOn(state.elementLegals.first().titleRes) + clickOn(state.elementLegals.first().titleRes) } } @Test - fun `clicking on the open source licenses invokes the expected callback`() { + fun `clicking on the open source licenses invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setAboutView( + setAboutView( anAboutState(), onOpenSourceLicensesClick = callback, ) - rule.clickOn(CommonStrings.common_open_source_licenses) + clickOn(CommonStrings.common_open_source_licenses) } } } -private fun AndroidComposeTestRule.setAboutView( +private fun AndroidComposeUiTest.setAboutView( state: AboutState, onElementLegalClick: (ElementLegal) -> Unit = EnsureNeverCalledWithParam(), onOpenSourceLicensesClick: () -> Unit = EnsureNeverCalled(), 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 e46e350415..b6fe5c3d0b 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 @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.advanced 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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.Interaction @@ -30,104 +33,99 @@ 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 import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class AdvancedSettingsViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on other theme emits the expected event`() { + fun `clicking on other theme emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.common_appearance) - rule.clickOn(CommonStrings.common_dark) + clickOn(CommonStrings.common_appearance) + clickOn(CommonStrings.common_dark) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTheme(ThemeOption.Dark)) } @Test - fun `black theme is shown when available`() { - rule.setAdvancedSettingsView( + fun `black theme is shown when available`() = runAndroidComposeUiTest { + setAdvancedSettingsView( state = aAdvancedSettingsState( availableThemeOptions = ThemeOption.entries.toImmutableList(), ), ) - rule.clickOn(CommonStrings.common_appearance) - rule.run { - val text = activity.getString(CommonStrings.common_black) + clickOn(CommonStrings.common_appearance) + run { + val text = activity!!.getString(CommonStrings.common_black) onNodeWithText(text).assertExists() } } @Test - fun `black theme is hidden when unavailable`() { - rule.setAdvancedSettingsView( + fun `black theme is hidden when unavailable`() = runAndroidComposeUiTest { + setAdvancedSettingsView( state = aAdvancedSettingsState( availableThemeOptions = ThemeOption.entries.filterNot { it == ThemeOption.Black }.toImmutableList(), ), ) - rule.clickOn(CommonStrings.common_appearance) - rule.assertNoNodeWithText(CommonStrings.common_black) + clickOn(CommonStrings.common_appearance) + assertNoNodeWithText(CommonStrings.common_black) } @Test - fun `clicking on View source emits the expected event`() { + fun `clicking on View source emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_view_source) + clickOn(CommonStrings.action_view_source) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetDeveloperModeEnabled(true)) } @Test - fun `clicking on Share presence emits the expected event`() { + fun `clicking on Share presence emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_advanced_settings_share_presence) + clickOn(R.string.screen_advanced_settings_share_presence) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetSharePresenceEnabled(true)) } @Test - fun `clicking on media to enable compression emits the expected event`() { + fun `clicking on media to enable compression emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val analyticsService = FakeAnalyticsService() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, ), analyticsService = analyticsService ) - rule.clickOn(R.string.screen_advanced_settings_media_compression_description) + clickOn(R.string.screen_advanced_settings_media_compression_description) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetCompressMedia(true)) assertThat(analyticsService.capturedEvents).isEqualTo( listOf( @@ -139,17 +137,17 @@ class AdvancedSettingsViewTest { } @Test - fun `clicking on media to disable compression emits the expected event`() { + fun `clicking on media to disable compression emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val analyticsService = FakeAnalyticsService() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( mediaOptimizationState = MediaOptimizationState.AllMedia(isEnabled = true), eventSink = eventsRecorder, ), analyticsService = analyticsService ) - rule.clickOn(R.string.screen_advanced_settings_media_compression_description) + clickOn(R.string.screen_advanced_settings_media_compression_description) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetCompressMedia(false)) assertThat(analyticsService.capturedEvents).isEqualTo( listOf( @@ -162,65 +160,65 @@ class AdvancedSettingsViewTest { @Test @Config(qualifiers = "h1080dp") - fun `clicking on hide invite avatars emits the expected event`() { + fun `clicking on hide invite avatars emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, hideInviteAvatars = false ), ) - rule.clickOn(R.string.screen_advanced_settings_hide_invite_avatars_toggle_title) + clickOn(R.string.screen_advanced_settings_hide_invite_avatars_toggle_title) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetHideInviteAvatars(true)) } @Test @Config(qualifiers = "h1080dp") - fun `clicking on timeline media preview always hide emits the expected event`() { + fun `clicking on timeline media preview always hide emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, timelineMediaPreviewValue = MediaPreviewValue.On ), ) - rule.clickOn(R.string.screen_advanced_settings_show_media_timeline_always_hide) + clickOn(R.string.screen_advanced_settings_show_media_timeline_always_hide) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTimelineMediaPreviewValue(MediaPreviewValue.Off)) } @Test @Config(qualifiers = "h1080dp") - fun `clicking on timeline media preview private rooms emits the expected event`() { + fun `clicking on timeline media preview private rooms emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, timelineMediaPreviewValue = MediaPreviewValue.On ), ) - rule.clickOn(R.string.screen_advanced_settings_show_media_timeline_private_rooms) + clickOn(R.string.screen_advanced_settings_show_media_timeline_private_rooms) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTimelineMediaPreviewValue(MediaPreviewValue.Private)) } @Test @Config(qualifiers = "h1080dp") - fun `clicking on timeline media preview always show emits the expected event`() { + fun `clicking on timeline media preview always show emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, timelineMediaPreviewValue = MediaPreviewValue.Off ), ) - rule.clickOn(R.string.screen_advanced_settings_show_media_timeline_always_show) + clickOn(R.string.screen_advanced_settings_show_media_timeline_always_show) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTimelineMediaPreviewValue(MediaPreviewValue.On)) } @Test @Config(qualifiers = "h1080dp") - fun `hide invite avatars toggle is disabled when action is loading`() { + fun `hide invite avatars toggle is disabled when action is loading`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, hideInviteAvatars = false, @@ -228,14 +226,14 @@ class AdvancedSettingsViewTest { ), ) // The toggle should be disabled, so clicking should not emit any events - rule.clickOn(R.string.screen_advanced_settings_hide_invite_avatars_toggle_title) + clickOn(R.string.screen_advanced_settings_hide_invite_avatars_toggle_title) } @Test @Config(qualifiers = "h1080dp") - fun `timeline media preview options are disabled when action is loading`() { + fun `timeline media preview options are disabled when action is loading`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setAdvancedSettingsView( + setAdvancedSettingsView( state = aAdvancedSettingsState( eventSink = eventsRecorder, timelineMediaPreviewValue = MediaPreviewValue.On, @@ -243,12 +241,12 @@ class AdvancedSettingsViewTest { ), ) // The options should be disabled, so clicking should not emit any events - rule.clickOn(R.string.screen_advanced_settings_show_media_timeline_always_hide) - rule.clickOn(R.string.screen_advanced_settings_show_media_timeline_private_rooms) + clickOn(R.string.screen_advanced_settings_show_media_timeline_always_hide) + clickOn(R.string.screen_advanced_settings_show_media_timeline_private_rooms) } } -private fun AndroidComposeTestRule.setAdvancedSettingsView( +private fun AndroidComposeUiTest.setAdvancedSettingsView( state: AdvancedSettingsState, analyticsService: AnalyticsService = FakeAnalyticsService(), onBackClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/blockedusers/BlockedUserViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/blockedusers/BlockedUserViewTest.kt index b3549762ab..993d14caab 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/blockedusers/BlockedUserViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/blockedusers/BlockedUserViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.blockedusers import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.preferences.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -23,72 +26,67 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class BlockedUserViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes back callback`() { + fun `clicking on back invokes back callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setBlockedUsersView( + setBlockedUsersView( aBlockedUsersState( eventSink = eventsRecorder ), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on a user emits the expected Event`() { + fun `clicking on a user emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val userList = aMatrixUserList() - rule.setBlockedUsersView( + setBlockedUsersView( aBlockedUsersState( blockedUsers = userList, eventSink = eventsRecorder ), ) - rule.onNodeWithText(userList.first().displayName.orEmpty()).performClick() + onNodeWithText(userList.first().displayName.orEmpty()).performClick() eventsRecorder.assertSingle(BlockedUsersEvents.Unblock(userList.first().userId)) } @Test - fun `clicking on cancel sends a BlockedUsersEvents`() { + fun `clicking on cancel sends a BlockedUsersEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setBlockedUsersView( + setBlockedUsersView( aBlockedUsersState( unblockUserAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(BlockedUsersEvents.Cancel) } @Test - fun `clicking on confirm sends a BlockedUsersEvents`() { + fun `clicking on confirm sends a BlockedUsersEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setBlockedUsersView( + setBlockedUsersView( aBlockedUsersState( unblockUserAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_blocked_users_unblock_alert_action) + clickOn(R.string.screen_blocked_users_unblock_alert_action) eventsRecorder.assertSingle(BlockedUsersEvents.ConfirmUnblock) } } -private fun AndroidComposeTestRule.setBlockedUsersView( +private fun AndroidComposeUiTest.setBlockedUsersView( state: BlockedUsersState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt index d4d02d7de9..61d7278a8a 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.developer import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.preferences.impl.R import io.element.android.tests.testutils.EnsureNeverCalled @@ -20,76 +23,71 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class DeveloperSettingsViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setDeveloperSettingsView( + setDeveloperSettingsView( state = aDeveloperSettingsState( eventSink = eventsRecorder ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Config(qualifiers = "h2000dp") @Test - fun `clicking on push history notification invokes the expected callback`() { + fun `clicking on push history notification invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setDeveloperSettingsView( + setDeveloperSettingsView( state = aDeveloperSettingsState( eventSink = eventsRecorder ), onPushHistoryClick = it ) - rule.clickOn(R.string.troubleshoot_notifications_entry_point_push_history_title) + clickOn(R.string.troubleshoot_notifications_entry_point_push_history_title) } } @Config(qualifiers = "h2000dp") @Test - fun `clicking on open showkase invokes the expected callback`() { + fun `clicking on open showkase invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setDeveloperSettingsView( + setDeveloperSettingsView( state = aDeveloperSettingsState( eventSink = eventsRecorder ), onOpenShowkase = it ) - rule.onNodeWithText("Open Showkase browser").performClick() + onNodeWithText("Open Showkase browser").performClick() } } @Config(qualifiers = "h2200dp") @Test - fun `clicking on clear cache emits the expected event`() { + fun `clicking on clear cache emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setDeveloperSettingsView( + setDeveloperSettingsView( state = aDeveloperSettingsState( eventSink = eventsRecorder ), ) - rule.onNodeWithText("Clear cache").performClick() + onNodeWithText("Clear cache").performClick() eventsRecorder.assertSingle(DeveloperSettingsEvents.ClearCache) } } -private fun AndroidComposeTestRule.setDeveloperSettingsView( +private fun AndroidComposeUiTest.setDeveloperSettingsView( state: DeveloperSettingsState, onOpenShowkase: () -> Unit = EnsureNeverCalled(), onPushHistoryClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt index 123f31ae8e..17218c6ab5 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPageTest.kt @@ -5,19 +5,22 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.developer.appsettings import androidx.activity.ComponentActivity +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.filterToOne import androidx.compose.ui.test.hasAnyAncestor import androidx.compose.ui.test.isDialog import androidx.compose.ui.test.isEditable import androidx.compose.ui.test.isFocusable -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.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.preferences.impl.R import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem @@ -27,78 +30,73 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class AppDeveloperSettingsPageTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setAppDeveloperSettingsView( + setAppDeveloperSettingsView( state = anAppDeveloperSettingsState( eventSink = eventsRecorder ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Config(qualifiers = "h1500dp") @Test - fun `clicking on element call url open the dialogs and submit emits the expected event`() { + fun `clicking on element call url open the dialogs and submit emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAppDeveloperSettingsView( + setAppDeveloperSettingsView( state = anAppDeveloperSettingsState( eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_advanced_settings_element_call_base_url) - val textInputNode = rule.onAllNodes(isEditable().and(isFocusable())).filterToOne(hasAnyAncestor(isDialog())) + clickOn(R.string.screen_advanced_settings_element_call_base_url) + val textInputNode = onAllNodes(isEditable().and(isFocusable())).filterToOne(hasAnyAncestor(isDialog())) textInputNode.performTextInput("https://call.element.dev") - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(AppDeveloperSettingsEvent.SetCustomElementCallBaseUrl("https://call.element.dev")) } @Config(qualifiers = "h2000dp") @Test - fun `clicking on open showkase invokes the expected callback`() { + fun `clicking on open showkase invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setAppDeveloperSettingsView( + setAppDeveloperSettingsView( state = anAppDeveloperSettingsState( eventSink = eventsRecorder ), onOpenShowkase = it ) - rule.onNodeWithText("Open Showkase browser").performClick() + onNodeWithText("Open Showkase browser").performClick() } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on log level emits the expected event`() { + fun `clicking on log level emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAppDeveloperSettingsView( + setAppDeveloperSettingsView( state = anAppDeveloperSettingsState( eventSink = eventsRecorder ), ) - rule.onNodeWithText("Tracing log level").performClick() - rule.onNodeWithText("Debug").performClick() + onNodeWithText("Tracing log level").performClick() + onNodeWithText("Debug").performClick() eventsRecorder.assertSingle(AppDeveloperSettingsEvent.SetTracingLogLevel(LogLevelItem.DEBUG)) } } -private fun AndroidComposeTestRule.setAppDeveloperSettingsView( +private fun AndroidComposeUiTest.setAppDeveloperSettingsView( state: AppDeveloperSettingsState, onOpenShowkase: () -> Unit = EnsureNeverCalled(), onBackClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt index ea140abbd7..66ed0339a3 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.notifications import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.preferences.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -25,76 +28,71 @@ 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 import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class NotificationSettingsViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnce { - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( eventSink = eventsRecorder ), onBackClick = it ) - rule.pressBack() + pressBack() } eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on troubleshoot notification invokes the expected callback`() { + fun `clicking on troubleshoot notification invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnce { - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( eventSink = eventsRecorder ), onTroubleshootNotificationsClick = it ) - rule.clickOn(R.string.troubleshoot_notifications_entry_point_title) + clickOn(R.string.troubleshoot_notifications_entry_point_title) } eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on group chats invokes the expected callback`() { + fun `clicking on group chats invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnceWithParam(false) { - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( eventSink = eventsRecorder ), onOpenEditDefault = it ) - rule.clickOn(R.string.screen_notification_settings_group_chats) + clickOn(R.string.screen_notification_settings_group_chats) } eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on direct chats invokes the expected callback`() { + fun `clicking on direct chats invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnceWithParam(true) { - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( eventSink = eventsRecorder ), onOpenEditDefault = it ) - rule.clickOn(R.string.screen_notification_settings_direct_chats) + clickOn(R.string.screen_notification_settings_direct_chats) } eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled) } @@ -111,15 +109,15 @@ class NotificationSettingsViewTest { testNotificationToggle(false) } - private fun testNotificationToggle(initialState: Boolean) { + private fun testNotificationToggle(initialState: Boolean) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( appNotificationEnabled = initialState, eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_notification_settings_enable_notifications) + clickOn(R.string.screen_notification_settings_enable_notifications) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -140,15 +138,15 @@ class NotificationSettingsViewTest { testAtRoomToggle(false) } - private fun testAtRoomToggle(initialState: Boolean) { + private fun testAtRoomToggle(initialState: Boolean) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( atRoomNotificationsEnabled = initialState, eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_notification_settings_room_mention_label) + clickOn(R.string.screen_notification_settings_room_mention_label) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -169,15 +167,15 @@ class NotificationSettingsViewTest { testInvitationToggle(false) } - private fun testInvitationToggle(initialState: Boolean) { + private fun testInvitationToggle(initialState: Boolean) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( inviteForMeNotificationsEnabled = initialState, eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_notification_settings_invite_for_me_label) + clickOn(R.string.screen_notification_settings_invite_for_me_label) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -188,15 +186,15 @@ class NotificationSettingsViewTest { @Config(qualifiers = "h1024dp") @Test - fun `with an error configuration, clicking on continue emits the expected events`() { + fun `with an error configuration, clicking on continue emits the expected events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( changeNotificationSettingAction = AsyncAction.Failure(AN_EXCEPTION), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -207,15 +205,15 @@ class NotificationSettingsViewTest { @Config(qualifiers = "h1024dp") @Test - fun `with invalid configuration, clicking on continue emits the expected events`() { + fun `with invalid configuration, clicking on continue emits the expected events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aInvalidNotificationSettingsState( fixFailed = false, eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -226,15 +224,15 @@ class NotificationSettingsViewTest { @Config(qualifiers = "h1024dp") @Test - fun `with invalid configuration and error, clicking on OK emits the expected events`() { + fun `with invalid configuration and error, clicking on OK emits the expected events`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aInvalidNotificationSettingsState( fixFailed = true, eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -245,14 +243,14 @@ class NotificationSettingsViewTest { @Config(qualifiers = "h1024dp") @Test - fun `clicking on Push notification provider emits the expected event`() { + fun `clicking on Push notification provider emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_advanced_settings_push_provider_android) + clickOn(R.string.screen_advanced_settings_push_provider_android) eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -262,16 +260,16 @@ class NotificationSettingsViewTest { } @Test - fun `clicking on a push provider emits the expected event`() { + fun `clicking on a push provider emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setNotificationSettingsView( + setNotificationSettingsView( state = aValidNotificationSettingsState( eventSink = eventsRecorder, showChangePushProviderDialog = true, availablePushDistributors = listOf(aDistributor("P1"), aDistributor("P2")) ), ) - rule.onNodeWithText("P2").performClick() + onNodeWithText("P2").performClick() eventsRecorder.assertList( listOf( NotificationSettingsEvents.RefreshSystemNotificationsEnabled, @@ -281,7 +279,7 @@ class NotificationSettingsViewTest { } } -private fun AndroidComposeTestRule.setNotificationSettingsView( +private fun AndroidComposeUiTest.setNotificationSettingsView( state: NotificationSettingsState, onOpenEditDefault: (isOneToOne: Boolean) -> Unit = EnsureNeverCalledWithParam(), onTroubleshootNotificationsClick: () -> Unit = EnsureNeverCalled(), 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 index da91bdbf86..88ebbf64a1 100644 --- 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 @@ -5,13 +5,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + 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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.preferences.impl.R import io.element.android.libraries.matrix.api.user.MatrixUser @@ -25,49 +28,45 @@ 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`() { + fun `clicking on back invokes back callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( eventSink = eventsRecorder ), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `click on User profile invokes the expected callback`() { + fun `click on User profile invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val user = aMatrixUser() ensureCalledOnceWithParam(user) { callback -> - rule.setView( + setView( aPreferencesRootState( myUser = user, eventSink = eventsRecorder, ), onOpenUserProfile = callback, ) - rule.onNodeWithText("Alice").performClick() + onNodeWithText("Alice").performClick() } } @Test - fun `clicking on other session sends a SwitchToSession`() { + fun `clicking on other session sends a SwitchToSession`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setView( + setView( aPreferencesRootState( isMultiAccountEnabled = true, otherSessions = listOf( @@ -79,366 +78,366 @@ class PreferencesRootViewTest { eventSink = eventsRecorder, ), ) - rule.onNodeWithText("Bob").performClick() + onNodeWithText("Bob").performClick() eventsRecorder.assertSingle(PreferencesRootEvent.SwitchToSession(A_USER_ID_2)) } @Test - fun `click on Add account invokes the expected callback`() { + fun `click on Add account invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( isMultiAccountEnabled = true, eventSink = eventsRecorder, ), onAddAccountClick = callback, ) - rule.clickOn(CommonStrings.common_add_another_account) + clickOn(CommonStrings.common_add_another_account) } } @Test - fun `when multi account is not enabled, item is not shown`() { + fun `when multi account is not enabled, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( isMultiAccountEnabled = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_add_another_account)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_add_another_account)).assertDoesNotExist() } @Test - fun `click on Encryption invokes the expected callback`() { + fun `click on Encryption invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( showSecureBackup = true, eventSink = eventsRecorder, ), onSecureBackupClick = callback, ) - rule.clickOn(CommonStrings.common_encryption) + clickOn(CommonStrings.common_encryption) } } @Test - fun `when showSecureBackup is false, item is not shown`() { + fun `when showSecureBackup is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( showSecureBackup = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_encryption)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_encryption)).assertDoesNotExist() } @Test - fun `click on Manage account invokes the expected callback`() { + fun `click on Manage account invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam("aUrl") { callback -> - rule.setView( + setView( aPreferencesRootState( accountManagementUrl = "aUrl", eventSink = eventsRecorder, ), onManageAccountClick = callback, ) - rule.clickOn(CommonStrings.action_manage_account_and_devices) + clickOn(CommonStrings.action_manage_account_and_devices) } } @Test - fun `when accountManagementUrl is null, item is not shown`() { + fun `when accountManagementUrl is null, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( accountManagementUrl = null, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_manage_account_and_devices)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.action_manage_account_and_devices)).assertDoesNotExist() } @Test - fun `click on Link new devices invokes the expected callback`() { + fun `click on Link new devices invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( showLinkNewDevice = true, eventSink = eventsRecorder, ), onLinkNewDeviceClick = callback, ) - rule.clickOn(CommonStrings.common_link_new_device) + clickOn(CommonStrings.common_link_new_device) } } @Test - fun `when showLinkNewDevice is false, item is not shown`() { + fun `when showLinkNewDevice is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( showLinkNewDevice = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_link_new_device)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_link_new_device)).assertDoesNotExist() } @Test - fun `click on Analytics invokes the expected callback`() { + fun `click on Analytics invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( showAnalyticsSettings = true, eventSink = eventsRecorder, ), onOpenAnalytics = callback, ) - rule.clickOn(CommonStrings.common_analytics) + clickOn(CommonStrings.common_analytics) } } @Test - fun `when showAnalyticsSettings is false, item is not shown`() { + fun `when showAnalyticsSettings is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( showAnalyticsSettings = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_analytics)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_analytics)).assertDoesNotExist() } @Test - fun `click on Report a problem invokes the expected callback`() { + fun `click on Report a problem invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( canReportBug = true, eventSink = eventsRecorder, ), onOpenRageShake = callback, ) - rule.clickOn(CommonStrings.common_report_a_problem) + clickOn(CommonStrings.common_report_a_problem) } } @Test - fun `when canReportBug is false, item is not shown`() { + fun `when canReportBug is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( canReportBug = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_report_a_problem)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_report_a_problem)).assertDoesNotExist() } @Test - fun `click on Screen lock invokes the expected callback`() { + fun `click on Screen lock invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( eventSink = eventsRecorder, ), onOpenLockScreenSettings = callback, ) - rule.clickOn(CommonStrings.common_screen_lock) + clickOn(CommonStrings.common_screen_lock) } } @Test - fun `click on About invokes the expected callback`() { + fun `click on About invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( eventSink = eventsRecorder, ), onOpenAbout = callback, ) - rule.clickOn(CommonStrings.common_about) + clickOn(CommonStrings.common_about) } } @Test - fun `click on Developer settings invokes the expected callback`() { + fun `click on Developer settings invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( showDeveloperSettings = true, eventSink = eventsRecorder, ), onOpenDeveloperSettings = callback, ) - rule.clickOn(CommonStrings.common_developer_options) + clickOn(CommonStrings.common_developer_options) } } @Test - fun `when showDeveloperSettings is false, item is not shown`() { + fun `when showDeveloperSettings is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( showDeveloperSettings = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_developer_options)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_developer_options)).assertDoesNotExist() } @Test - fun `click on Advanced settings invokes the expected callback`() { + fun `click on Advanced settings invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( eventSink = eventsRecorder, ), onOpenAdvancedSettings = callback, ) - rule.clickOn(CommonStrings.common_advanced_settings) + clickOn(CommonStrings.common_advanced_settings) } } @Test - fun `click on Labs invokes the expected callback`() { + fun `click on Labs invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( showLabsItem = true, eventSink = eventsRecorder, ), onOpenLabs = callback, ) - rule.clickOn(R.string.screen_labs_title) + clickOn(R.string.screen_labs_title) } } @Test - fun `when showLabsItem is false, item is not shown`() { + fun `when showLabsItem is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( showLabsItem = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(R.string.screen_labs_title)).assertDoesNotExist() + onNodeWithText(activity!!.getString(R.string.screen_labs_title)).assertDoesNotExist() } @Test - fun `click on Notification invokes the expected callback`() { + fun `click on Notification invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( eventSink = eventsRecorder, ), onOpenNotificationSettings = callback, ) - rule.clickOn(R.string.screen_notification_settings_title) + clickOn(R.string.screen_notification_settings_title) } } @Test - fun `click on Blocked users invokes the expected callback`() { + fun `click on Blocked users invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( nbOfBlockedUsers = 1, eventSink = eventsRecorder, ), onOpenBlockedUsers = callback, ) - rule.clickOn(CommonStrings.common_blocked_users) + clickOn(CommonStrings.common_blocked_users) } } @Test - fun `when nbOfBlockedUsers is 0, item is not shown`() { + fun `when nbOfBlockedUsers is 0, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( nbOfBlockedUsers = 0, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.common_blocked_users)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.common_blocked_users)).assertDoesNotExist() } @Test - fun `click on Remove this device invokes the expected callback`() { + fun `click on Remove this device invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( eventSink = eventsRecorder, ), onSignOutClick = callback, ) - rule.clickOn(CommonStrings.action_signout) + clickOn(CommonStrings.action_signout) } } @Test - fun `click on Deactivate invokes the expected callback`() { + fun `click on Deactivate invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setView( + setView( aPreferencesRootState( canDeactivateAccount = true, eventSink = eventsRecorder, ), onDeactivateClick = callback, ) - rule.clickOn(CommonStrings.action_delete_account) + clickOn(CommonStrings.action_delete_account) } } @Test - fun `when canDeactivateAccount is false, item is not shown`() { + fun `when canDeactivateAccount is false, item is not shown`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setView( + setView( aPreferencesRootState( canDeactivateAccount = false, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_delete_account)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.action_delete_account)).assertDoesNotExist() } @Test - fun `clicking on version sends a PreferencesRootEvents`() { + fun `clicking on version sends a PreferencesRootEvents`() = runAndroidComposeUiTest { val version = "VERSION" val eventsRecorder = EventsRecorder() - rule.setView( + setView( aPreferencesRootState( version = version, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(version).performClick() + onNodeWithText(version).performClick() eventsRecorder.assertSingle(PreferencesRootEvent.OnVersionInfoClick) } } -private fun AndroidComposeTestRule.setView( +private fun AndroidComposeUiTest.setView( state: PreferencesRootState, onBackClick: () -> Unit = EnsureNeverCalled(), onAddAccountClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileViewTest.kt index 728e05ee7e..20db955955 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileViewTest.kt @@ -6,14 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.preferences.impl.user.editprofile import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.ui.media.AvatarAction @@ -23,96 +26,93 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class EditUserProfileViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back emits the expected event`() { + fun `clicking on back emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setEditUserProfileView( + setEditUserProfileView( aEditUserProfileState( eventSink = eventsRecorder, ), ) - rule.pressBack() + pressBack() eventsRecorder.assertSingle(EditUserProfileEvent.Exit) } @Test - fun `clicking on save from the exit confirmation dialog emits the expected event`() { + fun `clicking on save from the exit confirmation dialog emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setEditUserProfileView( + setEditUserProfileView( aEditUserProfileState( saveAction = AsyncAction.ConfirmingCancellation, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save, inDialog = true) + clickOn(CommonStrings.action_save, inDialog = true) eventsRecorder.assertSingle(EditUserProfileEvent.Save) } @Test - fun `clicking on discard exit emits the expected event`() { + fun `clicking on discard exit emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setEditUserProfileView( + setEditUserProfileView( aEditUserProfileState( saveAction = AsyncAction.ConfirmingCancellation, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_discard) + clickOn(CommonStrings.action_discard) eventsRecorder.assertSingle(EditUserProfileEvent.Exit) } @Test - fun `clicking on save emits the expected event`() { + fun `clicking on save emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setEditUserProfileView( + setEditUserProfileView( aEditUserProfileState( saveButtonEnabled = true, saveAction = AsyncAction.Uninitialized, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) eventsRecorder.assertSingle(EditUserProfileEvent.Save) } @Test - fun `clicking on avatar opens the bottom sheet dialog`() { + fun `clicking on avatar opens the bottom sheet dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val actions = listOf( AvatarAction.TakePhoto, AvatarAction.ChoosePhoto, AvatarAction.Remove, ) - rule.setEditUserProfileView( + setEditUserProfileView( aEditUserProfileState( saveAction = AsyncAction.Uninitialized, avatarActions = actions, eventSink = eventsRecorder, ), ) - val contentDescription = rule.activity.getString(CommonStrings.a11y_avatar) - rule.onNodeWithContentDescription(contentDescription).performClick() + val resources = activity!!.resources + val contentDescription = resources.getString(CommonStrings.a11y_avatar) + onNodeWithContentDescription(contentDescription).performClick() // Assert that the actions are displayed actions.forEach { action -> - val text = rule.activity.getString(action.titleResId) - rule.onNodeWithText(text).assertExists() + val text = resources.getString(action.titleResId) + onNodeWithText(text).assertExists() } } @Test - fun `success invokes the expected callback`() { + fun `success invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setEditUserProfileView( + setEditUserProfileView( aEditUserProfileState( saveAction = AsyncAction.Success(Unit), eventSink = eventsRecorder, @@ -123,7 +123,7 @@ class EditUserProfileViewTest { } } -private fun AndroidComposeTestRule.setEditUserProfileView( +private fun AndroidComposeUiTest.setEditUserProfileView( state: EditUserProfileState, onEditProfileSuccess: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomViewTest.kt b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomViewTest.kt index 59d9507571..a18c82b275 100644 --- a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomViewTest.kt +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.reportroom.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -20,76 +23,72 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ReportRoomViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invoke the expected callback`() { + fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setReportRoomView( + setReportRoomView( aReportRoomState( eventSink = eventsRecorder, ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on report when enabled emits the expected event`() { + fun `clicking on report when enabled emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setReportRoomView( + setReportRoomView( aReportRoomState( reason = "Spam", eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_report) + clickOn(CommonStrings.action_report) eventsRecorder.assertSingle(ReportRoomEvents.Report) } @Test - fun `clicking on decline when disabled does not emit event`() { + fun `clicking on decline when disabled does not emit event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setReportRoomView( + setReportRoomView( aReportRoomState(eventSink = eventsRecorder), ) - rule.clickOn(CommonStrings.action_report) + clickOn(CommonStrings.action_report) } @Test - fun `clicking on leave room option emits the expected event`() { + fun `clicking on leave room option emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setReportRoomView( + setReportRoomView( aReportRoomState(eventSink = eventsRecorder), ) - rule.clickOn(CommonStrings.action_leave_room) + clickOn(CommonStrings.action_leave_room) eventsRecorder.assertSingle(ReportRoomEvents.ToggleLeaveRoom) } @Test - fun `typing text in the reason field emits the expected Event`() { + fun `typing text in the reason field emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setReportRoomView( + setReportRoomView( aReportRoomState( eventSink = eventsRecorder, reason = "" ), ) - rule.onNodeWithText("").performTextInput("Spam!") + onNodeWithText("").performTextInput("Spam!") eventsRecorder.assertSingle(ReportRoomEvents.UpdateReason("Spam!")) } } -private fun AndroidComposeTestRule.setReportRoomView( +private fun AndroidComposeUiTest.setReportRoomView( state: ReportRoomState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsViewTest.kt b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsViewTest.kt index f28c9c150f..668c6bb221 100644 --- a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsViewTest.kt +++ b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.rolesandpermissions.impl.permissions import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.rolesandpermissions.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -23,84 +26,80 @@ import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentMapOf -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ChangeRoomPermissionsViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `click on back icon invokes Exit`() { + fun `click on back icon invokes Exit`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( eventSink = recorder ) ) - rule.pressBack() + pressBack() recorder.assertSingle(ChangeRoomPermissionsEvent.Exit) } @Test - fun `click on back key invokes Exit`() { + fun `click on back key invokes Exit`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( eventSink = recorder ) ) - rule.pressBackKey() + pressBackKey() recorder.assertSingle(ChangeRoomPermissionsEvent.Exit) } @Test - fun `when confirming exit with pending changes, using the back key actually exits`() { + fun `when confirming exit with pending changes, using the back key actually exits`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, eventSink = recorder, ), ) - rule.pressBackKey() + pressBackKey() recorder.assertSingle(ChangeRoomPermissionsEvent.Exit) } @Test - fun `when confirming exit with pending changes, clicking on 'discard' button in the dialog actually exits`() { + fun `when confirming exit with pending changes, clicking on 'discard' button in the dialog actually exits`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, saveAction = AsyncAction.ConfirmingCancellation, eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_discard) + clickOn(CommonStrings.action_discard) recorder.assertSingle(ChangeRoomPermissionsEvent.Exit) } @Test - fun `when confirming exit with pending changes, clicking on 'save' button in the dialog saves the changes`() { + fun `when confirming exit with pending changes, clicking on 'save' button in the dialog saves the changes`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, saveAction = AsyncAction.ConfirmingCancellation, eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_save, inDialog = true) + clickOn(CommonStrings.action_save, inDialog = true) recorder.assertSingle(ChangeRoomPermissionsEvent.Save) } @Test - fun `click on a role item triggers ChangeRole event`() { + fun `click on a role item triggers ChangeRole event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( itemsBySection = persistentMapOf( // Makes sure there is only one item to click on @@ -109,70 +108,70 @@ class ChangeRoomPermissionsViewTest { eventSink = recorder, ) ) - rule.clickOn(R.string.screen_room_change_permissions_room_name) - rule.clickOn(R.string.screen_room_change_permissions_everyone) + clickOn(R.string.screen_room_change_permissions_room_name) + clickOn(R.string.screen_room_change_permissions_everyone) recorder.assertSingle( ChangeRoomPermissionsEvent.ChangeMinimumRoleForAction(RoomPermissionType.ROOM_NAME, SelectableRole.Everyone), ) } @Test - fun `click on the Save menu item triggers Save event`() { + fun `click on the Save menu item triggers Save event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) recorder.assertSingle(ChangeRoomPermissionsEvent.Save) } @Test - fun `a successful save exits the screen`() { + fun `a successful save exits the screen`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(true) { callback -> - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, saveAction = AsyncAction.Success(true), ), onComplete = callback, ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) } } @Test - fun `a cancellation exits the screen`() { + fun `a cancellation exits the screen`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(false) { callback -> - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, saveAction = AsyncAction.Success(false), ), onComplete = callback, ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) } } @Test - fun `click on the Ok option in save error dialog triggers ResetPendingAction event`() { + fun `click on the Ok option in save error dialog triggers ResetPendingAction event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setChangeRoomPermissionsRule( + setChangeRoomPermissionsRule( state = aChangeRoomPermissionsState( hasChanges = true, saveAction = AsyncAction.Failure(IllegalStateException("Failed to set room power levels")), eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) recorder.assertSingle(ChangeRoomPermissionsEvent.ResetPendingActions) } } -private fun AndroidComposeTestRule.setChangeRoomPermissionsRule( +private fun AndroidComposeUiTest.setChangeRoomPermissionsRule( state: ChangeRoomPermissionsState = aChangeRoomPermissionsState(), onComplete: (Boolean) -> Unit = EnsureNeverCalledWithParam(), ) { diff --git a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesViewTest.kt b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesViewTest.kt index 09bef49cbd..62d0608f26 100644 --- a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesViewTest.kt +++ b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesViewTest.kt @@ -6,15 +6,18 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.rolesandpermissions.impl.roles import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import io.element.android.libraries.architecture.AsyncAction @@ -30,20 +33,16 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey import kotlinx.collections.immutable.toImmutableList -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class ChangeRolesViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `passing a 'User' role throws an exception`() { + fun `passing a 'User' role throws an exception`() = runAndroidComposeUiTest { val exception = runCatchingExceptions { - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( role = RoomMember.Role.User, eventSink = EnsureNeverCalledWithParam(), @@ -54,106 +53,106 @@ class ChangeRolesViewTest { } @Test - fun `back key - with search active toggles the search`() { + fun `back key - with search active toggles the search`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( isSearchActive = true, eventSink = eventsRecorder, ), ) - rule.pressBackKey() + pressBackKey() // Advance time to let the event be processed, as the search toggle might have some delay (e.g. for the animation) - rule.mainClock.advanceTimeBy(1) + mainClock.advanceTimeBy(1) eventsRecorder.assertSingle(ChangeRolesEvent.ToggleSearchActive) } @Test - fun `back key - with search inactive exits the screen`() { + fun `back key - with search inactive exits the screen`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( isSearchActive = false, eventSink = eventsRecorder, ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(ChangeRolesEvent.Exit) } @Test - fun `back button - exits the screen`() { + fun `back button - exits the screen`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( isSearchActive = false, eventSink = eventsRecorder, ), ) - rule.pressBack() + pressBack() eventsRecorder.assertSingle(ChangeRolesEvent.Exit) } @Test - fun `save button - with changes, it saves them`() { + fun `save button - with changes, it saves them`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( hasPendingChanges = true, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) eventsRecorder.assertSingle(ChangeRolesEvent.Save) } @Test - fun `save button - with no changes, does nothing`() { + fun `save button - with no changes, does nothing`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( hasPendingChanges = false, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) eventsRecorder.assertEmpty() } @Test - fun `exit confirmation dialog - discard exits the screen`() { + fun `exit confirmation dialog - discard exits the screen`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( isSearchActive = true, savingState = AsyncAction.ConfirmingCancellation, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_discard) + clickOn(CommonStrings.action_discard) eventsRecorder.assertSingle(ChangeRolesEvent.Exit) } @Test - fun `exit confirmation dialog - save emits the save event`() { + fun `exit confirmation dialog - save emits the save event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( isSearchActive = true, savingState = AsyncAction.ConfirmingCancellation, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) eventsRecorder.assertSingle(ChangeRolesEvent.Save) } @Test - fun `save admins confirmation dialog - submit saves the changes`() { + fun `save admins confirmation dialog - submit saves the changes`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( role = RoomMember.Role.Admin, isSearchActive = true, @@ -161,14 +160,14 @@ class ChangeRolesViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(ChangeRolesEvent.Save) } @Test - fun `save owners confirmation dialog - continue saves the changes`() { + fun `save owners confirmation dialog - continue saves the changes`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( role = RoomMember.Role.Owner(isCreator = false), isSearchActive = true, @@ -176,14 +175,14 @@ class ChangeRolesViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(ChangeRolesEvent.Save) } @Test - fun `save admins confirmation dialog - cancel removes the dialog`() { + fun `save admins confirmation dialog - cancel removes the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( role = RoomMember.Role.Admin, isSearchActive = true, @@ -191,14 +190,14 @@ class ChangeRolesViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ChangeRolesEvent.CloseDialog) } @Test - fun `save owners confirmation dialog - cancel removes the dialog`() { + fun `save owners confirmation dialog - cancel removes the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( role = RoomMember.Role.Owner(isCreator = false), isSearchActive = true, @@ -206,39 +205,39 @@ class ChangeRolesViewTest { eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ChangeRolesEvent.CloseDialog) } @Test - fun `error dialog - dismissing removes the dialog`() { + fun `error dialog - dismissing removes the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesState( isSearchActive = true, savingState = AsyncAction.Failure(IllegalStateException("boom")), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(ChangeRolesEvent.CloseDialog) } @Test - fun `testing removing user from selected list emits the expected event`() { + fun `testing removing user from selected list emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val selectedUsers = aMatrixUserList().take(2) val userToDeselect = selectedUsers[1] assertThat(userToDeselect.displayName).isEqualTo("Bob") - rule.setChangeRolesContent( + setChangeRolesContent( state = aChangeRolesStateWithSelectedUsers().copy( selectedUsers = selectedUsers.toImmutableList(), eventSink = eventsRecorder, ), ) // Unselect the user from the row list - val contentDescription = rule.activity.getString(CommonStrings.action_remove) - rule.onNodeWithContentDescription( + val contentDescription = activity!!.getString(CommonStrings.action_remove) + onNodeWithContentDescription( label = contentDescription, useUnmergedTree = true, ).performClick() @@ -247,7 +246,7 @@ class ChangeRolesViewTest { @Test @Config(qualifiers = "h1000dp") - fun `testing adding user to the selected list emits the expected event`() { + fun `testing adding user to the selected list emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val selectedUsers = aMatrixUserList().take(2) val state = aChangeRolesStateWithSelectedUsers().copy( @@ -256,16 +255,16 @@ class ChangeRolesViewTest { ) val userToSelect = (state.searchResults as SearchBarResultState.Results).results.members.first().toMatrixUser() assertThat(userToSelect.displayName).isEqualTo("Carol") - rule.setChangeRolesContent( + setChangeRolesContent( state = state, ) // Select the user from the user list - rule.onNodeWithText("Carol").performClick() + onNodeWithText("Carol").performClick() eventsRecorder.assertSingle(ChangeRolesEvent.UserSelectionToggled(userToSelect)) } @Test - fun `testing removing user to the selected list emits the expected event`() { + fun `testing removing user to the selected list emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val selectedUsers = aMatrixUserList().take(2) val state = aChangeRolesStateWithSelectedUsers().copy( @@ -274,18 +273,18 @@ class ChangeRolesViewTest { ) val userToSelect = (state.searchResults as SearchBarResultState.Results).results.moderators.first().toMatrixUser() assertThat(userToSelect.displayName).isEqualTo("Bob") - rule.setChangeRolesContent( + setChangeRolesContent( state = state, ) // Unselect the user from the user list - rule.onAllNodesWithText( + onAllNodesWithText( text = "Bob", useUnmergedTree = true, )[1].performClick() eventsRecorder.assertSingle(ChangeRolesEvent.UserSelectionToggled(userToSelect)) } - private fun AndroidComposeTestRule.setChangeRolesContent( + private fun AndroidComposeUiTest.setChangeRolesContent( state: ChangeRolesState, ) { setContent { diff --git a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsViewTest.kt b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsViewTest.kt index e08ae205b7..d8908c405d 100644 --- a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsViewTest.kt +++ b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.rolesandpermissions.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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.rolesandpermissions.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -23,159 +26,154 @@ import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.ensureCalledTimes import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.setSafeContent -import kotlinx.coroutines.test.runTest -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class RolesAndPermissionsViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `click on back invokes expected callback`() { + fun `click on back invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( goBack = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `tapping on Admins opens admin list`() { + fun `tapping on Admins opens admin list`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( aRolesAndPermissionsState( roomSupportsOwners = false, eventSink = EventsRecorder(expectEvents = false) ), openAdminList = callback, ) - rule.clickOn(R.string.screen_room_roles_and_permissions_admins) + clickOn(R.string.screen_room_roles_and_permissions_admins) } } @Test - fun `tapping on Admins and Owners opens admin list`() { + fun `tapping on Admins and Owners opens admin list`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( aRolesAndPermissionsState( roomSupportsOwners = true, eventSink = EventsRecorder(expectEvents = false) ), openAdminList = callback, ) - rule.clickOn(R.string.screen_room_roles_and_permissions_admins_and_owners) + clickOn(R.string.screen_room_roles_and_permissions_admins_and_owners) } } @Test - fun `tapping on Moderators opens moderators list`() { + fun `tapping on Moderators opens moderators list`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( openModeratorList = callback, ) - rule.clickOn(R.string.screen_room_roles_and_permissions_moderators) + clickOn(R.string.screen_room_roles_and_permissions_moderators) } } @Test @Config(qualifiers = "h640dp") - fun `tapping permission item open the change permissions screen`() { + fun `tapping permission item open the change permissions screen`() = runAndroidComposeUiTest { ensureCalledTimes(1) { callback -> - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( openEditPermissions = callback, ) - rule.clickOn(R.string.screen_room_roles_and_permissions_permissions_header) + clickOn(R.string.screen_room_roles_and_permissions_permissions_header) } } @Test @Config(qualifiers = "h640dp") - fun `tapping on reset permissions triggers ResetPermissions event`() { + fun `tapping on reset permissions triggers ResetPermissions event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( state = aRolesAndPermissionsState( eventSink = recorder, ), ) - rule.clickOn(R.string.screen_room_roles_and_permissions_reset) + clickOn(R.string.screen_room_roles_and_permissions_reset) recorder.assertSingle(RolesAndPermissionsEvents.ResetPermissions) } @Test - fun `tapping on Reset in the reset permissions confirmation dialog triggers ResetPermissions event`() { + fun `tapping on Reset in the reset permissions confirmation dialog triggers ResetPermissions event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( state = aRolesAndPermissionsState( resetPermissionsAction = AsyncAction.ConfirmingNoParams, eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_reset) + clickOn(CommonStrings.action_reset) recorder.assertSingle(RolesAndPermissionsEvents.ResetPermissions) } @Test - fun `tapping on Cancel in the reset permissions confirmation dialog triggers CancelPendingAction event`() { + fun `tapping on Cancel in the reset permissions confirmation dialog triggers CancelPendingAction event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( state = aRolesAndPermissionsState( resetPermissionsAction = AsyncAction.ConfirmingNoParams, eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) recorder.assertSingle(RolesAndPermissionsEvents.CancelPendingAction) } @Test - fun `tapping on 'Demote to moderator' in the demote self bottom sheet triggers the right event`() { + fun `tapping on 'Demote to moderator' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( state = aRolesAndPermissionsState( changeOwnRoleAction = AsyncAction.ConfirmingNoParams, eventSink = recorder, ), ) - rule.clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_moderator) - rule.mainClock.advanceTimeBy(1_000L) + clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_moderator) + mainClock.advanceTimeBy(1_000L) recorder.assertSingle(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.Moderator)) } @Test - fun `tapping on 'Demote to member' in the demote self bottom sheet triggers the right event`() = runTest { + fun `tapping on 'Demote to member' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( state = aRolesAndPermissionsState( changeOwnRoleAction = AsyncAction.ConfirmingNoParams, eventSink = recorder, ), ) - rule.clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_member) - rule.mainClock.advanceTimeBy(1_000L) + clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_member) + mainClock.advanceTimeBy(1_000L) recorder.assertSingle(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.User)) } @Test - fun `tapping on 'Cancel' in the demote self bottom sheet triggers the right event`() { + fun `tapping on 'Cancel' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setRolesAndPermissionsView( + setRolesAndPermissionsView( state = aRolesAndPermissionsState( changeOwnRoleAction = AsyncAction.ConfirmingNoParams, eventSink = recorder, ), ) - rule.clickOn(CommonStrings.action_cancel) - rule.mainClock.advanceTimeBy(1_000L) + clickOn(CommonStrings.action_cancel) + mainClock.advanceTimeBy(1_000L) recorder.assertSingle(RolesAndPermissionsEvents.CancelPendingAction) } } -private fun AndroidComposeTestRule.setRolesAndPermissionsView( +private fun AndroidComposeUiTest.setRolesAndPermissionsView( state: RolesAndPermissionsState = aRolesAndPermissionsState( roomSupportsOwners = false, eventSink = EventsRecorder(expectEvents = false), diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperViewTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperViewTest.kt index 4b37f993f9..5f871183d6 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperViewTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.roomaliasresolver.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias @@ -22,48 +25,44 @@ 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 RoomAliasHelperViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setRoomAliasResolverView( + setRoomAliasResolverView( aRoomAliasResolverState( eventSink = eventsRecorder, ), onBackClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on Retry emits the expected Event`() { + fun `clicking on Retry emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomAliasResolverView( + setRoomAliasResolverView( aRoomAliasResolverState( resolveState = AsyncData.Failure(Exception("Error")), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_retry) + clickOn(CommonStrings.action_retry) eventsRecorder.assertSingle(RoomAliasResolverEvents.Retry) } @Test - fun `success state invokes the expected Callback`() { + fun `success state invokes the expected Callback`() = runAndroidComposeUiTest { val result = aResolvedRoomAlias() val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(result) { - rule.setRoomAliasResolverView( + setRoomAliasResolverView( aRoomAliasResolverState( resolveState = AsyncData.Success(result), eventSink = eventsRecorder, @@ -74,7 +73,7 @@ class RoomAliasHelperViewTest { } } -private fun AndroidComposeTestRule.setRoomAliasResolverView( +private fun AndroidComposeUiTest.setRoomAliasResolverView( state: RoomAliasResolverState, onBackClick: () -> Unit = EnsureNeverCalled(), onAliasResolved: (ResolvedRoomAlias) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 588a10a218..50139e0149 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -6,14 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.roomdetails.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.roomdetails.impl.members.aRoomMember import io.element.android.features.userprofile.shared.aUserProfileState @@ -32,98 +35,94 @@ 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 import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class RoomDetailsViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `click on back invokes expected callback`() { + fun `click on back invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( goBack = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `click on share invokes expected callback`() { + fun `click on share invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( onShareRoom = callback, ) - rule.clickOn(CommonStrings.action_share) + clickOn(CommonStrings.action_share) } } @Config(qualifiers = "h1024dp") @Test - fun `click on room members invokes expected callback`() { + fun `click on room members invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( openRoomMemberList = callback, ) - rule.clickOn(CommonStrings.common_people) + clickOn(CommonStrings.common_people) } } @Config(qualifiers = "h1024dp") @Test - fun `click on polls invokes expected callback`() { + fun `click on polls invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( openPollHistory = callback, ) - rule.clickOn(R.string.screen_polls_history_title) + clickOn(R.string.screen_polls_history_title) } } @Config(qualifiers = "h1024dp") @Test - fun `click on media gallery invokes expected callback`() { + fun `click on media gallery invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( openMediaGallery = callback, ) - rule.clickOn(R.string.screen_room_details_media_gallery_title) + clickOn(R.string.screen_room_details_media_gallery_title) } } @Config(qualifiers = "h1024dp") @Test - fun `click on notification invokes expected callback`() { + fun `click on notification invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( openRoomNotificationSettings = callback, ) - rule.clickOn(R.string.screen_room_details_notification_title) + clickOn(R.string.screen_room_details_notification_title) } } @Test - fun `click on invite invokes expected callback`() { + fun `click on invite invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canInvite = true, ), invitePeople = callback, ) - rule.clickOn(CommonStrings.action_invite) + clickOn(CommonStrings.action_invite) } } @Test - fun `click on call invokes expected callback`() { + fun `click on call invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(CallIntent.AUDIO) { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canInvite = true, @@ -134,103 +133,103 @@ class RoomDetailsViewTest { ), onJoinCallClick = callback, ) - rule.clickOn(CommonStrings.action_call) + clickOn(CommonStrings.action_call) } } @Test - fun `click on video call invokes expected callback`() { + fun `click on video call invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(CallIntent.VIDEO) { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canInvite = true, ), onJoinCallClick = callback, ) - rule.clickOn(CommonStrings.common_video) + clickOn(CommonStrings.common_video) } } @Config(qualifiers = "h1024dp") @Test - fun `click on pinned messages invokes expected callback`() { + fun `click on pinned messages invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canInvite = true, ), onPinnedMessagesClick = callback, ) - rule.clickOn(R.string.screen_room_details_pinned_events_row_title) + clickOn(R.string.screen_room_details_pinned_events_row_title) } } @Config(qualifiers = "h1024dp") @Test - fun `click on security and privacy invokes expected callback`() { + fun `click on security and privacy invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canShowSecurityAndPrivacy = true, ), onSecurityAndPrivacyClick = callback, ) - rule.clickOn(R.string.screen_room_details_security_and_privacy_title) + clickOn(R.string.screen_room_details_security_and_privacy_title) } } @Config(qualifiers = "h1024dp") @Test - fun `click on add topic emit expected event`() { + fun `click on add topic emit expected event`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(RoomDetailsAction.AddTopic) { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), roomTopic = RoomTopicState.CanAddTopic, ), onActionClick = callback, ) - rule.clickOn(R.string.screen_room_details_add_topic_title) + clickOn(R.string.screen_room_details_add_topic_title) } } @Test - fun `click on menu edit emit expected event`() { + fun `click on menu edit emit expected event`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(RoomDetailsAction.Edit) { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canEdit = true, ), onActionClick = callback, ) - val menuContentDescription = rule.activity.getString(CommonStrings.a11y_user_menu) - rule.onNodeWithContentDescription(menuContentDescription).performClick() - rule.clickOn(CommonStrings.action_edit) + val menuContentDescription = activity!!.getString(CommonStrings.a11y_user_menu) + onNodeWithContentDescription(menuContentDescription).performClick() + clickOn(CommonStrings.action_edit) } } @Test - fun `click on avatar test`() { + fun `click on avatar test`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aRoomDetailsState( eventSink = eventsRecorder, roomAvatarUrl = "an_avatar_url", ) val callback = EnsureCalledOnceWithTwoParams(state.roomName, "an_avatar_url") - rule.setRoomDetailView( + setRoomDetailView( state = state, openAvatarPreview = callback, ) - rule.onNodeWithTag(TestTags.roomDetailAvatar.value).performClick() + onNodeWithTag(TestTags.roomDetailAvatar.value).performClick() callback.assertSuccess() } @Test - fun `click on avatar test on DM`() { + fun `click on avatar test on DM`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aRoomDetailsState( roomType = RoomDetailsType.Dm( @@ -241,114 +240,114 @@ class RoomDetailsViewTest { eventSink = eventsRecorder, ) val callback = EnsureCalledOnceWithTwoParams("Daniel", "an_avatar_url") - rule.setRoomDetailView( + setRoomDetailView( state = state, openAvatarPreview = callback, ) - rule.onNodeWithTag(TestTags.memberDetailAvatar.value).performClick() + onNodeWithTag(TestTags.memberDetailAvatar.value).performClick() callback.assertSuccess() } @Test - fun `click on mute emit expected event`() { + fun `click on mute emit expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomDetailsState( eventSink = eventsRecorder, roomNotificationSettings = aRoomNotificationSettings(mode = RoomNotificationMode.ALL_MESSAGES), ) - rule.setRoomDetailView( + setRoomDetailView( state = state, ) - rule.clickOn(CommonStrings.common_mute) + clickOn(CommonStrings.common_mute) eventsRecorder.assertSingle(RoomDetailsEvent.MuteNotification) } @Test - fun `click on unmute emit expected event`() { + fun `click on unmute emit expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomDetailsState( eventSink = eventsRecorder, roomNotificationSettings = aRoomNotificationSettings(mode = RoomNotificationMode.MUTE), ) - rule.setRoomDetailView( + setRoomDetailView( state = state, ) - rule.clickOn(CommonStrings.common_unmute) + clickOn(CommonStrings.common_unmute) eventsRecorder.assertSingle(RoomDetailsEvent.UnmuteNotification) } @Config(qualifiers = "h1024dp") @Test - fun `click on favorite emit expected Event`() { + fun `click on favorite emit expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.common_favourite) + clickOn(CommonStrings.common_favourite) eventsRecorder.assertSingle(RoomDetailsEvent.SetFavorite(true)) } @Config(qualifiers = "h1500dp") @Test - fun `click on leave emit expected Event`() { + fun `click on leave emit expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_room_details_leave_room_title) + clickOn(R.string.screen_room_details_leave_room_title) eventsRecorder.assertSingle(RoomDetailsEvent.LeaveRoom(needsConfirmation = true)) } @Config(qualifiers = "h1500dp") @Test - fun `click on report room invokes expected callback`() { + fun `click on report room invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), ), onReportRoomClick = callback, ) - rule.clickOn(CommonStrings.action_report_room) + clickOn(CommonStrings.action_report_room) } } @Config(qualifiers = "h1024dp") @Test - fun `click on knock requests invokes expected callback`() { + fun `click on knock requests invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canShowKnockRequests = true, ), onKnockRequestsClick = callback, ) - rule.clickOn(R.string.screen_room_details_requests_to_join_title) + clickOn(R.string.screen_room_details_requests_to_join_title) } } @Config(qualifiers = "h1024dp") @Test - fun `click on profile invokes the expected callback`() { + fun `click on profile invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(A_USER_ID) { callback -> - rule.setRoomDetailView( + setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), roomMemberDetailsState = aUserProfileState(userId = A_USER_ID), ), onProfileClick = callback, ) - rule.clickOn(R.string.screen_room_details_profile_row_title) + clickOn(R.string.screen_room_details_profile_row_title) } } } -private fun AndroidComposeTestRule.setRoomDetailView( +private fun AndroidComposeUiTest.setRoomDetailView( state: RoomDetailsState = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), ), diff --git a/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditViewTest.kt b/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditViewTest.kt index 71fb143074..686794d641 100644 --- a/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditViewTest.kt +++ b/features/roomdetailsedit/impl/src/test/kotlin/io/element/android/features/roomdetailsedit/impl/RoomDetailsEditViewTest.kt @@ -5,18 +5,21 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.roomdetailsedit.impl import androidx.activity.ComponentActivity import androidx.annotation.StringRes +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assert import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.isEditable -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.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.ui.media.AvatarAction @@ -28,58 +31,54 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import org.junit.Ignore -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class RoomDetailsEditViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back emits the expected Event`() { + fun `clicking on back emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder ), ) - rule.pressBack() + pressBack() eventsRecorder.assertSingle(RoomDetailsEditEvent.OnBackPress) } @Test - fun `clicking on discard when confirming exit emits the expected Event`() { + fun `clicking on discard when confirming exit emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( saveAction = AsyncAction.ConfirmingCancellation, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_discard) + clickOn(CommonStrings.action_discard) eventsRecorder.assertSingle(RoomDetailsEditEvent.OnBackPress) } @Test - fun `clicking on save when confirming exit emits the expected Event`() { + fun `clicking on save when confirming exit emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( saveAction = AsyncAction.ConfirmingCancellation, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save, inDialog = true) + clickOn(CommonStrings.action_save, inDialog = true) eventsRecorder.assertSingle(RoomDetailsEditEvent.Save) } @Test - fun `when edition is successful, the expected callback is invoked`() { + fun `when edition is successful, the expected callback is invoked`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, saveAction = AsyncAction.Success(Unit) @@ -90,55 +89,55 @@ class RoomDetailsEditViewTest { } @Test - fun `when name is changed, the expected Event is emitted`() { + fun `when name is changed, the expected Event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, roomRawName = "Marketing", ), ) - rule.onNodeWithText("Marketing").performTextInput("A") + onNodeWithText("Marketing").performTextInput("A") eventsRecorder.assertSingle(RoomDetailsEditEvent.UpdateRoomName("AMarketing")) } @Test - fun `when user cannot change name, nothing happen`() { + fun `when user cannot change name, nothing happen`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, roomRawName = "Marketing", canChangeName = false, ), ) - rule.onNodeWithText("Marketing").assert(!isEditable()) + onNodeWithText("Marketing").assert(!isEditable()) } @Test - fun `when topic is changed, the expected Event is emitted`() { + fun `when topic is changed, the expected Event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, roomTopic = "My Topic", ), ) - rule.onNodeWithText("My Topic").performTextInput("A") + onNodeWithText("My Topic").performTextInput("A") eventsRecorder.assertSingle(RoomDetailsEditEvent.UpdateRoomTopic("AMy Topic")) } @Test - fun `when user cannot change topic, nothing happen`() { + fun `when user cannot change topic, nothing happen`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, roomTopic = "My Topic", canChangeTopic = false, ), ) - rule.onNodeWithText("My Topic").assert(!isEditable()) + onNodeWithText("My Topic").assert(!isEditable()) } @Ignore("This test is failing because the bottom sheet does not open") @@ -171,73 +170,73 @@ class RoomDetailsEditViewTest { private fun testAvatarChange( @StringRes stringActionRes: Int, expectedEvent: RoomDetailsEditEvent.HandleAvatarAction, - ) { + ) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, ), ) // Open the bottom sheet - rule.onNode(hasTestTag(TestTags.editAvatar.value)).performClick() - rule.onNodeWithText(rule.activity.getString(stringActionRes)).assertExists() - rule.clickOn(stringActionRes) + onNode(hasTestTag(TestTags.editAvatar.value)).performClick() + onNodeWithText(activity!!.getString(stringActionRes)).assertExists() + clickOn(stringActionRes) eventsRecorder.assertSingle(expectedEvent) } @Test - fun `when user cannot change avatar, nothing happen`() { + fun `when user cannot change avatar, nothing happen`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, canChangeAvatar = false, ), ) - rule.onNode(hasTestTag(TestTags.editAvatar.value)).performClick() - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_take_photo)).assertDoesNotExist() + onNode(hasTestTag(TestTags.editAvatar.value)).performClick() + onNodeWithText(activity!!.getString(CommonStrings.action_take_photo)).assertDoesNotExist() } @Test - fun `when save is clicked, the expected Event is emitted`() { + fun `when save is clicked, the expected Event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, saveButtonEnabled = true, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) eventsRecorder.assertSingle(RoomDetailsEditEvent.Save) } @Test - fun `when save is clicked, but nothing need to be saved, nothing happens`() { + fun `when save is clicked, but nothing need to be saved, nothing happens`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, saveButtonEnabled = false, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) } @Test - fun `when error is shown, closing the dialog emit the expected Event`() { + fun `when error is shown, closing the dialog emit the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDetailsEditView( + setRoomDetailsEditView( aRoomDetailsEditState( eventSink = eventsRecorder, saveAction = AsyncAction.Failure(RuntimeException("Whelp")), ), ) - rule.clickOn(CommonStrings.action_ok) + clickOn(CommonStrings.action_ok) eventsRecorder.assertSingle(RoomDetailsEditEvent.CloseDialog) } } -private fun AndroidComposeTestRule.setRoomDetailsEditView( +private fun AndroidComposeUiTest.setRoomDetailsEditView( state: RoomDetailsEditState, onDone: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt index a50ad6a22c..f9d60f87da 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryViewTest.kt @@ -6,15 +6,18 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.roomdirectory.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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.libraries.testtags.TestTags @@ -22,31 +25,27 @@ 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.ensureCalledOnceWithParam -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class RoomDirectoryViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `typing text in search field emits the expected Event`() { + fun `typing text in search field emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomDirectoryView( + setRoomDirectoryView( state = aRoomDirectoryState( eventSink = eventsRecorder, ) ) - rule.onNodeWithTag(TestTags.searchTextField.value).performTextInput( + onNodeWithTag(TestTags.searchTextField.value).performTextInput( text = "Test" ) eventsRecorder.assertSingle(RoomDirectoryEvents.Search("Test")) } @Test - fun `clicking on room item then onResultClick lambda is called once`() { + fun `clicking on room item then onResultClick lambda is called once`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomDirectoryState( roomDescriptions = aRoomDescriptionList(), @@ -54,27 +53,27 @@ class RoomDirectoryViewTest { ) val clickedRoom = state.roomDescriptions.first() ensureCalledOnceWithParam(clickedRoom) { callback -> - rule.setRoomDirectoryView( + setRoomDirectoryView( state = state, onResultClick = callback, ) - rule.onNodeWithText(clickedRoom.computedName).performClick() + onNodeWithText(clickedRoom.computedName).performClick() } } @Test - fun `composing load more indicator emits expected Event`() { + fun `composing load more indicator emits expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aRoomDirectoryState( displayLoadMoreIndicator = true, eventSink = eventsRecorder, ) - rule.setRoomDirectoryView(state = state) + setRoomDirectoryView(state = state) eventsRecorder.assertSingle(RoomDirectoryEvents.LoadMore) } } -private fun AndroidComposeTestRule.setRoomDirectoryView( +private fun AndroidComposeUiTest.setRoomDirectoryView( state: RoomDirectoryState, onBackClick: () -> Unit = EnsureNeverCalled(), onResultClick: (RoomDescription) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationViewTest.kt b/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationViewTest.kt index 6508b28053..646481715a 100644 --- a/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationViewTest.kt +++ b/features/roommembermoderation/impl/src/test/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.roommembermoderation.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.roommembermoderation.api.ModerationAction import io.element.android.features.roommembermoderation.api.ModerationActionState @@ -24,21 +27,17 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnceWithTwoParams import io.element.android.tests.testutils.pressTag import io.element.android.tests.testutils.setSafeContent -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class RoomMemberModerationViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on display profile action calls onSelectAction`() { + fun `clicking on display profile action calls onSelectAction`() = runAndroidComposeUiTest { val user = anAlice() val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithTwoParams(ModerationAction.DisplayProfile, user) { callback -> - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = user, actions = listOf( @@ -48,16 +47,16 @@ class RoomMemberModerationViewTest { ), onSelectAction = callback ) - rule.clickOn(R.string.screen_bottom_sheet_manage_room_member_member_user_info) + clickOn(R.string.screen_bottom_sheet_manage_room_member_member_user_info) } } @Test - fun `clicking on kick user action calls onSelectAction`() { + fun `clicking on kick user action calls onSelectAction`() = runAndroidComposeUiTest { val user = anAlice() val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithTwoParams(ModerationAction.KickUser, user) { callback -> - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = user, actions = listOf( @@ -67,18 +66,18 @@ class RoomMemberModerationViewTest { ), onSelectAction = callback ) - rule.clickOn(R.string.screen_bottom_sheet_manage_room_member_remove) + clickOn(R.string.screen_bottom_sheet_manage_room_member_remove) // Gives time for bottomsheet to hide - rule.mainClock.advanceTimeBy(1_000) + mainClock.advanceTimeBy(1_000) } } @Test - fun `clicking on ban user action calls onSelectAction`() { + fun `clicking on ban user action calls onSelectAction`() = runAndroidComposeUiTest { val user = anAlice() val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithTwoParams(ModerationAction.BanUser, user) { callback -> - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = user, actions = listOf( @@ -88,18 +87,18 @@ class RoomMemberModerationViewTest { ), onSelectAction = callback ) - rule.clickOn(R.string.screen_bottom_sheet_manage_room_member_ban) + clickOn(R.string.screen_bottom_sheet_manage_room_member_ban) // Gives time for bottomsheet to hide - rule.mainClock.advanceTimeBy(1_000) + mainClock.advanceTimeBy(1_000) } } @Test - fun `clicking on unban user action calls onSelectAction`() { + fun `clicking on unban user action calls onSelectAction`() = runAndroidComposeUiTest { val user = anAlice() val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithTwoParams(ModerationAction.UnbanUser, user) { callback -> - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = user, actions = listOf( @@ -109,100 +108,100 @@ class RoomMemberModerationViewTest { ), onSelectAction = callback ) - rule.clickOn(R.string.screen_bottom_sheet_manage_room_member_unban) + clickOn(R.string.screen_bottom_sheet_manage_room_member_unban) // Gives time for bottomsheet to hide - rule.mainClock.advanceTimeBy(1_000) + mainClock.advanceTimeBy(1_000) } } @Test - fun `clicking submit on kick confirmation dialog sends DoKickUser event`() { + fun `clicking submit on kick confirmation dialog sends DoKickUser event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), kickUserAsyncAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(InternalRoomMemberModerationEvents.DoKickUser(reason = "")) } @Test - fun `clicking dismiss on kick confirmation dialog sends Reset event`() { + fun `clicking dismiss on kick confirmation dialog sends Reset event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), kickUserAsyncAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogNegative.value) + pressTag(TestTags.dialogNegative.value) eventsRecorder.assertSingle(InternalRoomMemberModerationEvents.Reset) } @Test - fun `clicking submit on ban confirmation dialog sends DoBanUser event`() { + fun `clicking submit on ban confirmation dialog sends DoBanUser event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), banUserAsyncAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(InternalRoomMemberModerationEvents.DoBanUser(reason = "")) } @Test - fun `clicking dismiss on ban confirmation dialog sends Reset event`() { + fun `clicking dismiss on ban confirmation dialog sends Reset event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), banUserAsyncAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogNegative.value) + pressTag(TestTags.dialogNegative.value) eventsRecorder.assertSingle(InternalRoomMemberModerationEvents.Reset) } @Test - fun `clicking confirm on unban confirmation dialog sends DoUnbanUser event`() { + fun `clicking confirm on unban confirmation dialog sends DoUnbanUser event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), unbanUserAsyncAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogPositive.value) + pressTag(TestTags.dialogPositive.value) eventsRecorder.assertSingle(InternalRoomMemberModerationEvents.DoUnbanUser("")) } @Test - fun `clicking dismiss on unban confirmation dialog sends Reset event`() { + fun `clicking dismiss on unban confirmation dialog sends Reset event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), unbanUserAsyncAction = AsyncAction.ConfirmingNoParams, eventSink = eventsRecorder ), ) - rule.pressTag(TestTags.dialogNegative.value) + pressTag(TestTags.dialogNegative.value) eventsRecorder.assertSingle(InternalRoomMemberModerationEvents.Reset) } @Test - fun `disabled actions are not clickable`() { + fun `disabled actions are not clickable`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setRoomMemberModerationView( + setRoomMemberModerationView( aRoomMembersModerationState( selectedUser = anAlice(), actions = listOf( @@ -211,11 +210,11 @@ class RoomMemberModerationViewTest { eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_bottom_sheet_manage_room_member_remove) + clickOn(R.string.screen_bottom_sheet_manage_room_member_remove) } } -private fun AndroidComposeTestRule.setRoomMemberModerationView( +private fun AndroidComposeUiTest.setRoomMemberModerationView( state: InternalRoomMemberModerationState, onSelectAction: (ModerationAction, MatrixUser) -> Unit = EnsureNeverCalledWithTwoParams(), ) { diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyViewTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyViewTest.kt index d9324fdb91..f9729f74f0 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyViewTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyViewTest.kt @@ -6,16 +6,19 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.securebackup.impl.enter import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performImeAction import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.securebackup.impl.setup.views.aFormattedRecoveryKey import io.element.android.libraries.architecture.AsyncAction @@ -26,58 +29,54 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class SecureBackupEnterRecoveryKeyViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `back key pressed - calls onBackClick`() { + fun `back key pressed - calls onBackClick`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setSecureBackupEnterRecoveryKeyView( + setSecureBackupEnterRecoveryKeyView( aSecureBackupEnterRecoveryKeyState(), onBackClick = callback, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `back button clicked - calls onBackClick`() { + fun `back button clicked - calls onBackClick`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setSecureBackupEnterRecoveryKeyView( + setSecureBackupEnterRecoveryKeyView( aSecureBackupEnterRecoveryKeyState(), onBackClick = callback, ) - rule.pressBack() + pressBack() } } @Test @Config(qualifiers = "h1024dp") - fun `tapping on Continue when key is valid - calls expected action`() { + fun `tapping on Continue when key is valid - calls expected action`() = runAndroidComposeUiTest { val recorder = EventsRecorder() - rule.setSecureBackupEnterRecoveryKeyView( + setSecureBackupEnterRecoveryKeyView( aSecureBackupEnterRecoveryKeyState(isSubmitEnabled = true, eventSink = recorder), ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) recorder.assertSingle(SecureBackupEnterRecoveryKeyEvents.Submit) } @Test - fun `entering a char emits the expected event`() { + fun `entering a char emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val keyValue = aFormattedRecoveryKey() - rule.setSecureBackupEnterRecoveryKeyView( + setSecureBackupEnterRecoveryKeyView( aSecureBackupEnterRecoveryKeyState(isSubmitEnabled = true, eventSink = recorder), ) - rule.onNodeWithText(keyValue).performTextInput("X") + onNodeWithText(keyValue).performTextInput("X") recorder.assertSingle( SecureBackupEnterRecoveryKeyEvents.OnRecoveryKeyChange("X$keyValue") ) @@ -85,43 +84,43 @@ class SecureBackupEnterRecoveryKeyViewTest { @Test @Config(qualifiers = "h1024dp") - fun `toggling the visibility of the textfield changes it`() { + fun `toggling the visibility of the textfield changes it`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val keyValue = aFormattedRecoveryKey() - rule.setSecureBackupEnterRecoveryKeyView(aSecureBackupEnterRecoveryKeyState(isSubmitEnabled = true, eventSink = recorder)) + setSecureBackupEnterRecoveryKeyView(aSecureBackupEnterRecoveryKeyState(isSubmitEnabled = true, eventSink = recorder)) // Initially, the text field should be visible - rule.onNodeWithText(keyValue).assertExists() + onNodeWithText(keyValue).assertExists() - rule.onNodeWithContentDescription(rule.activity.getString(CommonStrings.a11y_hide_password)).performClick() + onNodeWithContentDescription(activity!!.getString(CommonStrings.a11y_hide_password)).performClick() - rule.waitForIdle() + waitForIdle() recorder.assertSingle(SecureBackupEnterRecoveryKeyEvents.ChangeRecoveryKeyFieldContentsVisibility(false)) } @Test - fun `validating from keyboard emits the expected event`() { + fun `validating from keyboard emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val keyValue = aFormattedRecoveryKey() - rule.setSecureBackupEnterRecoveryKeyView( + setSecureBackupEnterRecoveryKeyView( aSecureBackupEnterRecoveryKeyState(isSubmitEnabled = true, eventSink = recorder), ) - rule.onNodeWithText(keyValue).performImeAction() + onNodeWithText(keyValue).performImeAction() recorder.assertSingle(SecureBackupEnterRecoveryKeyEvents.Submit) } @Test - fun `when submit action succeeds - calls onDone`() { + fun `when submit action succeeds - calls onDone`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setSecureBackupEnterRecoveryKeyView( + setSecureBackupEnterRecoveryKeyView( aSecureBackupEnterRecoveryKeyState(submitAction = AsyncAction.Success(Unit)), onDone = callback, ) } } - private fun AndroidComposeTestRule.setSecureBackupEnterRecoveryKeyView( + private fun AndroidComposeUiTest.setSecureBackupEnterRecoveryKeyView( state: SecureBackupEnterRecoveryKeyState, onDone: () -> Unit = EnsureNeverCalled(), onBackClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt index 6cfd061103..ce5972f66b 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.securebackup.impl.reset.password import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.ui.strings.CommonStrings @@ -22,64 +25,59 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ResetIdentityPasswordViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `pressing the back HW button invokes the expected callback`() { + fun `pressing the back HW button invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setResetPasswordView( + setResetPasswordView( ResetIdentityPasswordState(resetAction = AsyncAction.Uninitialized, eventSink = {}), onBack = it, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `clicking on the back navigation button invokes the expected callback`() { + fun `clicking on the back navigation button invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setResetPasswordView( + setResetPasswordView( ResetIdentityPasswordState(resetAction = AsyncAction.Uninitialized, eventSink = {}), onBack = it, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking 'Reset identity' confirms the reset`() { + fun `clicking 'Reset identity' confirms the reset`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setResetPasswordView( + setResetPasswordView( ResetIdentityPasswordState(resetAction = AsyncAction.Uninitialized, eventSink = eventsRecorder), ) - rule.onNodeWithText("Password").performTextInput("A password") + onNodeWithText("Password").performTextInput("A password") - rule.clickOn(CommonStrings.action_reset_identity) + clickOn(CommonStrings.action_reset_identity) eventsRecorder.assertSingle(ResetIdentityPasswordEvent.Reset("A password")) } @Test - fun `modifying the password dismisses the error state`() { + fun `modifying the password dismisses the error state`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setResetPasswordView( + setResetPasswordView( ResetIdentityPasswordState(resetAction = AsyncAction.Failure(IllegalStateException("A failure")), eventSink = eventsRecorder), ) - rule.onNodeWithText("Password").performTextInput("A password") + onNodeWithText("Password").performTextInput("A password") eventsRecorder.assertSingle(ResetIdentityPasswordEvent.DismissError) } } -private fun AndroidComposeTestRule.setResetPasswordView( +private fun AndroidComposeUiTest.setResetPasswordView( state: ResetIdentityPasswordState, onBack: () -> Unit = EnsureNeverCalled(), ) { diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt index a913a9af27..0126d0d879 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/reset/root/ResetIdentityRootViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.securebackup.impl.reset.root import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.securebackup.impl.R import io.element.android.libraries.ui.strings.CommonStrings @@ -20,76 +23,71 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class ResetIdentityRootViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `pressing the back HW button invokes the expected callback`() { + fun `pressing the back HW button invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setResetRootView( + setResetRootView( ResetIdentityRootState(displayConfirmationDialog = false, eventSink = {}), onBack = it, ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `clicking on the back navigation button invokes the expected callback`() { + fun `clicking on the back navigation button invokes the expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setResetRootView( + setResetRootView( ResetIdentityRootState(displayConfirmationDialog = false, eventSink = {}), onBack = it, ) - rule.pressBack() + pressBack() } } @Test @Config(qualifiers = "h720dp") - fun `clicking Continue displays the confirmation dialog`() { + fun `clicking Continue displays the confirmation dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setResetRootView( + setResetRootView( ResetIdentityRootState(displayConfirmationDialog = false, eventSink = eventsRecorder), ) - rule.clickOn(R.string.screen_encryption_reset_action_continue_reset) + clickOn(R.string.screen_encryption_reset_action_continue_reset) eventsRecorder.assertSingle(ResetIdentityRootEvent.Continue) } @Test - fun `clicking 'Yes, reset now' confirms the reset`() { + fun `clicking 'Yes, reset now' confirms the reset`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setResetRootView( + setResetRootView( ResetIdentityRootState(displayConfirmationDialog = true, eventSink = {}), onContinue = it, ) - rule.clickOn(R.string.screen_reset_encryption_confirmation_alert_action) + clickOn(R.string.screen_reset_encryption_confirmation_alert_action) } } @Test - fun `clicking Cancel dismisses the dialog`() { + fun `clicking Cancel dismisses the dialog`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setResetRootView( + setResetRootView( ResetIdentityRootState(displayConfirmationDialog = true, eventSink = eventsRecorder), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ResetIdentityRootEvent.DismissDialog) } } -private fun AndroidComposeTestRule.setResetRootView( +private fun AndroidComposeUiTest.setResetRootView( state: ResetIdentityRootState, onBack: () -> Unit = EnsureNeverCalled(), onContinue: () -> Unit = EnsureNeverCalled(), diff --git a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/editroomaddress/EditRoomAddressViewTest.kt b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/editroomaddress/EditRoomAddressViewTest.kt index 17d6f3a88d..2c0a6c9acb 100644 --- a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/editroomaddress/EditRoomAddressViewTest.kt +++ b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/editroomaddress/EditRoomAddressViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.securityandprivacy.impl.editroomaddress import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity @@ -23,86 +26,82 @@ 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.pressBack -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class EditRoomAddressViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `click on back invokes expected callback`() { + fun `click on back invokes expected callback`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setEditRoomAddressView(onBackClick = callback) - rule.pressBack() + setEditRoomAddressView(onBackClick = callback) + pressBack() } } @Test - fun `click on disabled save doesn't emit event`() { + fun `click on disabled save doesn't emit event`() = runAndroidComposeUiTest { val recorder = EventsRecorder(expectEvents = false) val state = anEditRoomAddressState(eventSink = recorder) - rule.setEditRoomAddressView(state) - rule.clickOn(CommonStrings.action_save) + setEditRoomAddressView(state) + clickOn(CommonStrings.action_save) recorder.assertEmpty() } @Test - fun `click on enabled save emits the expected event`() { + fun `click on enabled save emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = anEditRoomAddressState( roomAddress = "room", roomAddressValidity = RoomAddressValidity.Valid, eventSink = recorder ) - rule.setEditRoomAddressView(state) - rule.clickOn(CommonStrings.action_save) + setEditRoomAddressView(state) + clickOn(CommonStrings.action_save) recorder.assertSingle(EditRoomAddressEvents.Save) } @Test - fun `text changes on text field emits the expected event`() { + fun `text changes on text field emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = anEditRoomAddressState( roomAddress = "", eventSink = recorder ) - rule.setEditRoomAddressView(state) + setEditRoomAddressView(state) - rule.onNodeWithTag(TestTags.roomAddressField.value).performTextInput("alias") + onNodeWithTag(TestTags.roomAddressField.value).performTextInput("alias") recorder.assertSingle(EditRoomAddressEvents.RoomAddressChanged("alias")) } @Test - fun `click on dismiss error emits the expected event`() { + fun `click on dismiss error emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = anEditRoomAddressState( roomAddress = "", saveAction = AsyncAction.Failure(IllegalStateException()), eventSink = recorder ) - rule.setEditRoomAddressView(state) - rule.clickOn(CommonStrings.action_cancel) + setEditRoomAddressView(state) + clickOn(CommonStrings.action_cancel) recorder.assertSingle(EditRoomAddressEvents.DismissError) } @Test - fun `click on retry error emits the expected event`() { + fun `click on retry error emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = anEditRoomAddressState( roomAddress = "", saveAction = AsyncAction.Failure(IllegalStateException()), eventSink = recorder ) - rule.setEditRoomAddressView(state) - rule.clickOn(CommonStrings.action_retry) + setEditRoomAddressView(state) + clickOn(CommonStrings.action_retry) recorder.assertSingle(EditRoomAddressEvents.Save) } } -private fun AndroidComposeTestRule.setEditRoomAddressView( +private fun AndroidComposeUiTest.setEditRoomAddressView( state: EditRoomAddressState = anEditRoomAddressState( eventSink = EventsRecorder(expectEvents = false), ), diff --git a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesViewTest.kt b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesViewTest.kt index c732df6df0..de6da41823 100644 --- a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesViewTest.kt +++ b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.securityandprivacy.impl.manageauthorizedspaces import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.spaces.SpaceRoom @@ -24,26 +27,22 @@ import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressBack import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableSet -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ManageAuthorizedSpacesViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking back emits Cancel event`() { + fun `clicking back emits Cancel event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aManageAuthorizedSpacesState(eventSink = recorder) - rule.setManageAuthorizedSpacesView(state) - rule.pressBack() + setManageAuthorizedSpacesView(state) + pressBack() recorder.assertSingle(ManageAuthorizedSpacesEvent.Cancel) } @Test - fun `clicking space checkbox emits ToggleSpace event`() { + fun `clicking space checkbox emits ToggleSpace event`() = runAndroidComposeUiTest { val roomId = A_ROOM_ID val space = aSpaceRoom(roomId = roomId, displayName = "Test Space") val recorder = EventsRecorder() @@ -51,37 +50,37 @@ class ManageAuthorizedSpacesViewTest { selectableSpaces = listOf(space), eventSink = recorder ) - rule.setManageAuthorizedSpacesView(state) - rule.onNodeWithText("Test Space").performClick() + setManageAuthorizedSpacesView(state) + onNodeWithText("Test Space").performClick() recorder.assertSingle(ManageAuthorizedSpacesEvent.ToggleSpace(roomId)) } @Test - fun `clicking done button emits Done event`() { + fun `clicking done button emits Done event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aManageAuthorizedSpacesState( selectedIds = listOf(A_ROOM_ID), eventSink = recorder ) - rule.setManageAuthorizedSpacesView(state) - rule.clickOn(CommonStrings.action_done) + setManageAuthorizedSpacesView(state) + clickOn(CommonStrings.action_done) recorder.assertSingle(ManageAuthorizedSpacesEvent.Done) } @Test - fun `done button is disabled when no spaces selected`() { + fun `done button is disabled when no spaces selected`() = runAndroidComposeUiTest { val recorder = EventsRecorder(expectEvents = false) val state = aManageAuthorizedSpacesState( selectedIds = emptyList(), eventSink = recorder ) - rule.setManageAuthorizedSpacesView(state) - rule.clickOn(CommonStrings.action_done) + setManageAuthorizedSpacesView(state) + clickOn(CommonStrings.action_done) recorder.assertEmpty() } } -private fun AndroidComposeTestRule.setManageAuthorizedSpacesView( +private fun AndroidComposeUiTest.setManageAuthorizedSpacesView( state: ManageAuthorizedSpacesState = aManageAuthorizedSpacesState( eventSink = EventsRecorder(expectEvents = false) ), diff --git a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyViewTest.kt b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyViewTest.kt index a1f46b2938..c46accbc91 100644 --- a/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyViewTest.kt +++ b/features/securityandprivacy/impl/src/test/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyViewTest.kt @@ -5,13 +5,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.securityandprivacy.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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.securityandprivacy.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -23,73 +26,69 @@ import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressBack import kotlinx.collections.immutable.persistentListOf -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class SecurityAndPrivacyViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `click on back invokes emits the expected event`() { + fun `click on back invokes emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, ) - rule.setSecurityAndPrivacyView(state) - rule.pressBack() + setSecurityAndPrivacyView(state) + pressBack() recorder.assertSingle(SecurityAndPrivacyEvent.Exit) } @Test - fun `discard cancellation emits the expected event`() { + fun `discard cancellation emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( saveAction = AsyncAction.ConfirmingCancellation, eventSink = recorder, ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(CommonStrings.action_discard) + setSecurityAndPrivacyView(state) + clickOn(CommonStrings.action_discard) recorder.assertSingle(SecurityAndPrivacyEvent.Exit) } @Test - fun `save cancellation confirmation emits the expected event`() { + fun `save cancellation confirmation emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( saveAction = AsyncAction.ConfirmingCancellation, eventSink = recorder, ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(CommonStrings.action_save, inDialog = true) + setSecurityAndPrivacyView(state) + clickOn(CommonStrings.action_save, inDialog = true) recorder.assertSingle(SecurityAndPrivacyEvent.Save) } @Test - fun `click on room access item emits the expected event`() { + fun `click on room access item emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_room_access_invite_only_option_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_room_access_invite_only_option_title) recorder.assertSingle(SecurityAndPrivacyEvent.ChangeRoomAccess(SecurityAndPrivacyRoomAccess.InviteOnly)) } @Test - fun `click on disabled save doesn't emit event`() { + fun `click on disabled save doesn't emit event`() = runAndroidComposeUiTest { val recorder = EventsRecorder(expectEvents = false) val state = aSecurityAndPrivacyState(eventSink = recorder) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(CommonStrings.action_save) + setSecurityAndPrivacyView(state) + clickOn(CommonStrings.action_save) recorder.assertEmpty() } @Test - fun `click on enabled save emits the expected event`() { + fun `click on enabled save emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, @@ -97,14 +96,14 @@ class SecurityAndPrivacyViewTest { roomAccess = SecurityAndPrivacyRoomAccess.Anyone, ) ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(CommonStrings.action_save) + setSecurityAndPrivacyView(state) + clickOn(CommonStrings.action_save) recorder.assertSingle(SecurityAndPrivacyEvent.Save) } @Test @Config(qualifiers = "h640dp") - fun `click on room address item emits the expected event`() { + fun `click on room address item emits the expected event`() = runAndroidComposeUiTest { val address = "@alias:matrix.org" val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( @@ -114,14 +113,14 @@ class SecurityAndPrivacyViewTest { roomAccess = SecurityAndPrivacyRoomAccess.Anyone, ), ) - rule.setSecurityAndPrivacyView(state) - rule.onNodeWithText(address).performClick() + setSecurityAndPrivacyView(state) + onNodeWithText(address).performClick() recorder.assertSingle(SecurityAndPrivacyEvent.EditRoomAddress) } @Test @Config(qualifiers = "h1024dp") - fun `click on room visibility item emits the expected event`() { + fun `click on room visibility item emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, @@ -130,14 +129,14 @@ class SecurityAndPrivacyViewTest { isVisibleInRoomDirectory = AsyncData.Success(false), ), ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_room_directory_visibility_toggle_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_room_directory_visibility_toggle_title) recorder.assertSingle(SecurityAndPrivacyEvent.ToggleRoomVisibility) } @Test @Config(qualifiers = "h1024dp") - fun `click on history visibility item emits the expected event`() { + fun `click on history visibility item emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, @@ -145,65 +144,65 @@ class SecurityAndPrivacyViewTest { historyVisibility = SecurityAndPrivacyHistoryVisibility.Invited, ), ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_room_history_since_invite_option_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_room_history_since_invite_option_title) recorder.assertSingle(SecurityAndPrivacyEvent.ChangeHistoryVisibility(SecurityAndPrivacyHistoryVisibility.Invited)) } @Test @Config(qualifiers = "h1024dp") - fun `click on encryption item emits the expected event`() { + fun `click on encryption item emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, savedSettings = aSecurityAndPrivacySettings(isEncrypted = false), ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_encryption_toggle_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_encryption_toggle_title) recorder.assertSingle(SecurityAndPrivacyEvent.ToggleEncryptionState) } @Test - fun `click on encryption confirm emits the expected event`() { + fun `click on encryption confirm emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, showEncryptionConfirmation = true, ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_enable_encryption_alert_confirm_button_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_enable_encryption_alert_confirm_button_title) recorder.assertSingle(SecurityAndPrivacyEvent.ConfirmEnableEncryption) } @Test @Config(qualifiers = "h1024dp") - fun `click on space member access emits the expected event`() { + fun `click on space member access emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, spaceSelectionMode = SpaceSelectionMode.Single(A_ROOM_ID, null), ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_room_access_space_members_option_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_room_access_space_members_option_title) recorder.assertSingle(SecurityAndPrivacyEvent.SelectSpaceMemberAccess) } @Test @Config(qualifiers = "h1024dp") - fun `click on ask to join with space members emits the expected event`() { + fun `click on ask to join with space members emits the expected event`() = runAndroidComposeUiTest { val recorder = EventsRecorder() val state = aSecurityAndPrivacyState( eventSink = recorder, spaceSelectionMode = SpaceSelectionMode.Single(A_ROOM_ID, null), ) - rule.setSecurityAndPrivacyView(state) - rule.clickOn(R.string.screen_security_and_privacy_ask_to_join_option_title) + setSecurityAndPrivacyView(state) + clickOn(R.string.screen_security_and_privacy_ask_to_join_option_title) recorder.assertSingle(SecurityAndPrivacyEvent.SelectAskToJoinWithSpaceMembersAccess) } @Test @Config(qualifiers = "h1024dp") - fun `manage spaces footer is shown when space member access is selected`() { + fun `manage spaces footer is shown when space member access is selected`() = runAndroidComposeUiTest { val recorder = EventsRecorder(expectEvents = false) val state = aSecurityAndPrivacyState( eventSink = recorder, @@ -212,15 +211,16 @@ class SecurityAndPrivacyViewTest { roomAccess = SecurityAndPrivacyRoomAccess.SpaceMember(persistentListOf(A_ROOM_ID)), ), ) - rule.setSecurityAndPrivacyView(state) + setSecurityAndPrivacyView(state) // The footer text uses AnnotatedString with a link. Verify the footer text is displayed. - val actionFooterText = rule.activity.getString(R.string.screen_security_and_privacy_room_access_footer_manage_spaces_action) - val footerText = rule.activity.getString(R.string.screen_security_and_privacy_room_access_footer, actionFooterText) - rule.onNodeWithText(footerText).assertExists() + val resources = activity!!.resources + val actionFooterText = resources.getString(R.string.screen_security_and_privacy_room_access_footer_manage_spaces_action) + val footerText = resources.getString(R.string.screen_security_and_privacy_room_access_footer, actionFooterText) + onNodeWithText(footerText).assertExists() } } -private fun AndroidComposeTestRule.setSecurityAndPrivacyView( +private fun AndroidComposeUiTest.setSecurityAndPrivacyView( state: SecurityAndPrivacyState = aSecurityAndPrivacyState( eventSink = EventsRecorder(expectEvents = false), ), diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt index d75fecd05a..6fc10f1e82 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt @@ -5,13 +5,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.space.impl.addroom import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.theme.components.SearchBarResultState @@ -22,77 +25,73 @@ 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 import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class AddRoomToSpaceViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking back when search inactive emits Dismiss and invokes onBackClick`() { + fun `clicking back when search inactive emits Dismiss and invokes onBackClick`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() ensureCalledOnce { - rule.setAddRoomToSpaceView( + setAddRoomToSpaceView( anAddRoomToSpaceState( isSearchActive = false, eventSink = eventsRecorder, ), onBackClick = it, ) - rule.pressBack() + pressBack() } eventsRecorder.assertSingle(AddRoomToSpaceEvent.Dismiss) } @Test - fun `clicking back when search active emits CloseSearch event`() { + fun `clicking back when search active emits CloseSearch event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAddRoomToSpaceView( + setAddRoomToSpaceView( anAddRoomToSpaceState( isSearchActive = true, eventSink = eventsRecorder, ), ) - rule.pressBack() + pressBack() eventsRecorder.assertSingle(AddRoomToSpaceEvent.OnSearchActiveChanged(false)) } @Test - fun `clicking save emits Save event`() { + fun `clicking save emits Save event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setAddRoomToSpaceView( + setAddRoomToSpaceView( anAddRoomToSpaceState( selectedRooms = aSelectRoomInfoList().take(1).toImmutableList(), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_save) + clickOn(CommonStrings.action_save) eventsRecorder.assertSingle(AddRoomToSpaceEvent.Save) } @Config(qualifiers = "h1024dp") @Test - fun `clicking room in suggestions emits ToggleRoom event`() { + fun `clicking room in suggestions emits ToggleRoom event`() = runAndroidComposeUiTest { val suggestions = aSelectRoomInfoList() val eventsRecorder = EventsRecorder() - rule.setAddRoomToSpaceView( + setAddRoomToSpaceView( anAddRoomToSpaceState( suggestions = suggestions, eventSink = eventsRecorder, ), ) - rule.onNodeWithText(suggestions.first().name!!).performClick() + onNodeWithText(suggestions.first().name!!).performClick() eventsRecorder.assertSingle(AddRoomToSpaceEvent.ToggleRoom(suggestions.first())) } @Test - fun `onRoomsAdded called when saveAction is Success`() { + fun `onRoomsAdded called when saveAction is Success`() = runAndroidComposeUiTest { ensureCalledOnce { - rule.setAddRoomToSpaceView( + setAddRoomToSpaceView( anAddRoomToSpaceState( saveAction = AsyncAction.Success(Unit), ), @@ -103,10 +102,10 @@ class AddRoomToSpaceViewTest { @Config(qualifiers = "h1024dp") @Test - fun `displaying search results sends UpdateSearchVisibleRange event`() { + fun `displaying search results sends UpdateSearchVisibleRange event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val rooms = aSelectRoomInfoList() - rule.setAddRoomToSpaceView( + setAddRoomToSpaceView( anAddRoomToSpaceState( isSearchActive = true, searchResults = SearchBarResultState.Results(rooms), @@ -117,7 +116,7 @@ class AddRoomToSpaceViewTest { } } -private fun AndroidComposeTestRule.setAddRoomToSpaceView( +private fun AndroidComposeUiTest.setAddRoomToSpaceView( state: AddRoomToSpaceState, onBackClick: () -> Unit = EnsureNeverCalled(), onRoomsAdded: () -> Unit = EnsureNeverCalled(), diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt index 87343b6e34..6632c7f4f8 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/root/SpaceViewTest.kt @@ -6,14 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.space.impl.root import androidx.activity.ComponentActivity import androidx.compose.runtime.Composable -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.room.CurrentUserMembership @@ -33,37 +36,33 @@ import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class SpaceViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setSpaceView( + setSpaceView( aSpaceState( hasMoreToLoad = false, eventSink = eventsRecorder, ), onBackClick = it, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on a room name invokes the expected callback`() { + fun `clicking on a room name invokes the expected callback`() = runAndroidComposeUiTest { val aSpaceRoom = aSpaceRoom(roomId = A_ROOM_ID, displayName = A_ROOM_NAME) val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(aSpaceRoom) { - rule.setSpaceView( + setSpaceView( aSpaceState( children = listOf(aSpaceRoom), hasMoreToLoad = false, @@ -71,91 +70,91 @@ class SpaceViewTest { ), onRoomClick = it, ) - rule.onNodeWithText(A_ROOM_NAME).performClick() + onNodeWithText(A_ROOM_NAME).performClick() } } @Test - fun `clicking on Join room emits the expected Event`() { + fun `clicking on Join room emits the expected Event`() = runAndroidComposeUiTest { val aSpaceRoom = aSpaceRoom(roomId = A_ROOM_ID, state = null) val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( children = listOf(aSpaceRoom), hasMoreToLoad = false, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_join) + clickOn(CommonStrings.action_join) eventsRecorder.assertSingle(SpaceEvents.Join(aSpaceRoom)) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on accept invite emits the expected Event`() { + fun `clicking on accept invite emits the expected Event`() = runAndroidComposeUiTest { val aSpaceRoom = aSpaceRoom(roomId = A_ROOM_ID, state = CurrentUserMembership.INVITED) val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( hasMoreToLoad = false, children = listOf(aSpaceRoom), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_accept) + clickOn(CommonStrings.action_accept) eventsRecorder.assertSingle(SpaceEvents.AcceptInvite(aSpaceRoom)) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on decline invite emits the expected Event`() { + fun `clicking on decline invite emits the expected Event`() = runAndroidComposeUiTest { val aSpaceRoom = aSpaceRoom(roomId = A_ROOM_ID, state = CurrentUserMembership.INVITED) val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( hasMoreToLoad = false, children = listOf(aSpaceRoom), eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_decline) + clickOn(CommonStrings.action_decline) eventsRecorder.assertSingle(SpaceEvents.DeclineInvite(aSpaceRoom)) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on topic emits the expected Event`() { + fun `clicking on topic emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( spaceInfo = aRoomInfo(topic = A_ROOM_TOPIC), hasMoreToLoad = false, eventSink = eventsRecorder, ) ) - rule.onNodeWithText(A_ROOM_TOPIC).performClick() + onNodeWithText(A_ROOM_TOPIC).performClick() eventsRecorder.assertSingle(SpaceEvents.ShowTopicViewer(A_ROOM_TOPIC)) } @Test - fun `clicking back in manage mode emits ExitManageMode event`() { + fun `clicking back in manage mode emits ExitManageMode event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( hasMoreToLoad = false, isManageMode = true, eventSink = eventsRecorder, ) ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(SpaceEvents.ExitManageMode) } @Test - fun `clicking on room in manage mode emits ToggleRoomSelection event`() { + fun `clicking on room in manage mode emits ToggleRoomSelection event`() = runAndroidComposeUiTest { val aSpaceRoom = aSpaceRoom(roomId = A_ROOM_ID, displayName = A_ROOM_NAME) val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( children = listOf(aSpaceRoom), hasMoreToLoad = false, @@ -163,14 +162,14 @@ class SpaceViewTest { eventSink = eventsRecorder, ) ) - rule.onNodeWithText(A_ROOM_NAME).performClick() + onNodeWithText(A_ROOM_NAME).performClick() eventsRecorder.assertSingle(SpaceEvents.ToggleRoomSelection(A_ROOM_ID)) } @Test - fun `clicking remove button emits RemoveSelectedRooms event`() { + fun `clicking remove button emits RemoveSelectedRooms event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( children = listOf(aSpaceRoom(roomId = A_ROOM_ID)), hasMoreToLoad = false, @@ -179,15 +178,15 @@ class SpaceViewTest { eventSink = eventsRecorder, ) ) - rule.clickOn(CommonStrings.action_remove) + clickOn(CommonStrings.action_remove) eventsRecorder.assertSingle(SpaceEvents.RemoveSelectedRooms) } @Config(qualifiers = "h1024dp") @Test - fun `clicking confirm in removal dialog emits ConfirmRoomRemoval event`() { + fun `clicking confirm in removal dialog emits ConfirmRoomRemoval event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setSpaceView( + setSpaceView( aSpaceState( children = listOf(aSpaceRoom(roomId = A_ROOM_ID)), hasMoreToLoad = false, @@ -198,14 +197,14 @@ class SpaceViewTest { ) ) // Click on the Remove button in the confirmation dialog - rule.clickOn(CommonStrings.action_remove, inDialog = true) + clickOn(CommonStrings.action_remove, inDialog = true) eventsRecorder.assertSingle(SpaceEvents.ConfirmRoomRemoval) } @Test - fun `clicking create room button calls the expected callback`() { + fun `clicking create room button calls the expected callback`() = runAndroidComposeUiTest { val onCreateRoomClick = lambdaRecorder { } - rule.setSpaceView( + setSpaceView( aSpaceState( children = emptyList(), hasMoreToLoad = false, @@ -214,14 +213,14 @@ class SpaceViewTest { ), onCreateRoomClick = onCreateRoomClick, ) - rule.clickOn(CommonStrings.action_create_room) + clickOn(CommonStrings.action_create_room) onCreateRoomClick.assertions().isCalledOnce() } @Test - fun `clicking add existing room button calls the expected callback`() { + fun `clicking add existing room button calls the expected callback`() = runAndroidComposeUiTest { val onAddRoomClick = lambdaRecorder { } - rule.setSpaceView( + setSpaceView( aSpaceState( children = emptyList(), hasMoreToLoad = false, @@ -230,12 +229,12 @@ class SpaceViewTest { ), onAddRoomClick = onAddRoomClick, ) - rule.clickOn(CommonStrings.action_add_existing_rooms) + clickOn(CommonStrings.action_add_existing_rooms) onAddRoomClick.assertions().isCalledOnce() } } -private fun AndroidComposeTestRule.setSpaceView( +private fun AndroidComposeUiTest.setSpaceView( state: SpaceState, onBackClick: () -> Unit = EnsureNeverCalled(), onRoomClick: (SpaceRoom) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt index 92162ca82c..dd992a9d2f 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt @@ -6,56 +6,54 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.startchat.impl.joinbyaddress import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.startchat.impl.R import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.setSafeContent -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class JoinBaseRoomByAddressViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `entering text emits the expected event`() { + fun `entering text emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomByAddressView( + setJoinRoomByAddressView( aJoinRoomByAddressState( eventSink = eventsRecorder, ) ) - val text = rule.activity.getString(R.string.screen_start_chat_join_room_by_address_action) - rule.onNodeWithText(text).performTextInput("#address:matrix.org") + val text = activity!!.getString(R.string.screen_start_chat_join_room_by_address_action) + onNodeWithText(text).performTextInput("#address:matrix.org") eventsRecorder.assertSingle(JoinRoomByAddressEvent.UpdateAddress("#address:matrix.org")) } @Test - fun `clicking on continue emits the expected event`() { + fun `clicking on continue emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setJoinRoomByAddressView( + setJoinRoomByAddressView( aJoinRoomByAddressState( eventSink = eventsRecorder, ) ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle(JoinRoomByAddressEvent.Continue) } } -private fun AndroidComposeTestRule.setJoinRoomByAddressView( +private fun AndroidComposeUiTest.setJoinRoomByAddressView( state: JoinRoomByAddressState, ) { setSafeContent { diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt index 9237f3433c..abcb70113b 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.startchat.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.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.startchat.impl.R import io.element.android.features.startchat.impl.userlist.aRecentDirectRoomList @@ -27,70 +30,65 @@ 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 import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class StartChatViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on back invokes the expected callback`() { + fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setStartChatView( + setStartChatView( aCreateRoomRootState( eventSink = eventsRecorder, ), onCloseClick = it ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on New room invokes the expected callback`() { + fun `clicking on New room invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setStartChatView( + setStartChatView( aCreateRoomRootState( eventSink = eventsRecorder, ), onNewRoomClick = it ) - rule.clickOn(R.string.screen_create_room_action_create_room) + clickOn(R.string.screen_create_room_action_create_room) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on Invite people invokes the expected callback`() { + fun `clicking on Invite people invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setStartChatView( + setStartChatView( aCreateRoomRootState( applicationName = "test", eventSink = eventsRecorder, ), onInviteFriendsClick = it ) - val text = rule.activity.getString(CommonStrings.action_invite_friends_to_app, "test") - rule.onNodeWithText(text).performClick() + val text = activity!!.getString(CommonStrings.action_invite_friends_to_app, "test") + onNodeWithText(text).performClick() } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on a user suggestion invokes the expected callback`() { + fun `clicking on a user suggestion invokes the expected callback`() = runAndroidComposeUiTest { val recentDirectRoomList = aRecentDirectRoomList() val firstRoom = recentDirectRoomList[0] val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(firstRoom.roomId) { - rule.setStartChatView( + setStartChatView( aCreateRoomRootState( userListState = aUserListState( recentDirectRooms = recentDirectRoomList @@ -99,42 +97,42 @@ class StartChatViewTest { ), onOpenDM = it ) - rule.onNodeWithText(firstRoom.matrixUser.getBestName()).performClick() + onNodeWithText(firstRoom.matrixUser.getBestName()).performClick() } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on Join room by address invokes the expected callback`() { + fun `clicking on Join room by address invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setStartChatView( + setStartChatView( aCreateRoomRootState( eventSink = eventsRecorder, ), onJoinRoomByAddressClick = it ) - rule.clickOn(R.string.screen_start_chat_join_room_by_address_action) + clickOn(R.string.screen_start_chat_join_room_by_address_action) } } @Test - fun `clicking on room directory invokes the expected callback`() { + fun `clicking on room directory invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setStartChatView( + setStartChatView( aCreateRoomRootState( eventSink = eventsRecorder, isRoomDirectorySearchEnabled = true ), onRoomDirectorySearchClick = it ) - rule.clickOn(R.string.screen_room_directory_search_title) + clickOn(R.string.screen_room_directory_search_title) } } } -private fun AndroidComposeTestRule.setStartChatView( +private fun AndroidComposeUiTest.setStartChatView( state: StartChatState, onCloseClick: () -> Unit = EnsureNeverCalled(), onNewRoomClick: () -> Unit = EnsureNeverCalled(), diff --git a/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/UserProfileViewTest.kt b/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/UserProfileViewTest.kt index 83b10e2a53..b1d81f374c 100644 --- a/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/UserProfileViewTest.kt +++ b/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/UserProfileViewTest.kt @@ -6,13 +6,16 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.userprofile import androidx.activity.ComponentActivity +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasTestTag -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileState @@ -39,193 +42,188 @@ import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.tests.testutils.ensureCalledOnceWithTwoParams import io.element.android.tests.testutils.pressBack -import kotlinx.coroutines.test.runTest -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class UserProfileViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `on back button click - the expected callback is called`() = runTest { + fun `on back button click - the expected callback is called`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setUserProfileView( + setUserProfileView( goBack = callback, ) - rule.pressBack() + pressBack() } } @Test - fun `on avatar clicked - the expected callback is called`() = runTest { + fun `on avatar clicked - the expected callback is called`() = runAndroidComposeUiTest { ensureCalledOnceWithTwoParams(A_USER_NAME, AN_AVATAR_URL) { callback -> - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState(userName = A_USER_NAME, avatarUrl = AN_AVATAR_URL), openAvatarPreview = callback, ) - rule.onNode(hasTestTag(TestTags.memberDetailAvatar.value)).performClick() + onNode(hasTestTag(TestTags.memberDetailAvatar.value)).performClick() } } @Test - fun `on avatar clicked with no avatar - nothing happens`() = runTest { + fun `on avatar clicked with no avatar - nothing happens`() = runAndroidComposeUiTest { val callback = EnsureNeverCalledWithTwoParams() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState(userName = A_USER_NAME, avatarUrl = null), openAvatarPreview = callback, ) - rule.onNode(hasTestTag(TestTags.memberDetailAvatar.value)).performClick() + onNode(hasTestTag(TestTags.memberDetailAvatar.value)).performClick() } @Test - fun `on Share clicked - the expected callback is called`() = runTest { + fun `on Share clicked - the expected callback is called`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setUserProfileView( + setUserProfileView( onShareUser = callback, ) - rule.clickOn(CommonStrings.action_share) + clickOn(CommonStrings.action_share) } } @Test - fun `on Message clicked - the StartDm event is emitted`() = runTest { + fun `on Message clicked - the StartDm event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( dmRoomId = A_ROOM_ID, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_message) + clickOn(CommonStrings.action_message) eventsRecorder.assertSingle(UserProfileEvents.StartDM) } @Test - fun `on Call clicked - the expected callback is called`() = runTest { + fun `on Call clicked - the expected callback is called`() = runAndroidComposeUiTest { ensureCalledOnceWithTwoParams(A_ROOM_ID, CallIntent.AUDIO) { callback -> - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( dmRoomId = A_ROOM_ID, canCall = true, ), onStartCall = callback, ) - rule.clickOn(CommonStrings.action_call) + clickOn(CommonStrings.action_call) } } @Test - fun `on Video Call clicked - the expected callback is called`() = runTest { + fun `on Video Call clicked - the expected callback is called`() = runAndroidComposeUiTest { ensureCalledOnceWithTwoParams(A_ROOM_ID, CallIntent.VIDEO) { callback -> - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( dmRoomId = A_ROOM_ID, canCall = true, ), onStartCall = callback, ) - rule.clickOn(CommonStrings.common_video) + clickOn(CommonStrings.common_video) } } @Config(qualifiers = "h1024dp") @Test - fun `on Block user clicked - a BlockUser event is emitted with needsConfirmation`() = runTest { + fun `on Block user clicked - a BlockUser event is emitted with needsConfirmation`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_dm_details_block_user) + clickOn(R.string.screen_dm_details_block_user) eventsRecorder.assertSingle(UserProfileEvents.BlockUser(needsConfirmation = true)) } @Test - fun `on confirming block user - a BlockUser event is emitted without needsConfirmation`() = runTest { + fun `on confirming block user - a BlockUser event is emitted without needsConfirmation`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( displayConfirmationDialog = UserProfileState.ConfirmationDialog.Block, eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_dm_details_block_alert_action) + clickOn(R.string.screen_dm_details_block_alert_action) eventsRecorder.assertSingle(UserProfileEvents.BlockUser(needsConfirmation = false)) } @Test - fun `on canceling blocking a user - a ClearConfirmationDialog event is emitted`() = runTest { + fun `on canceling blocking a user - a ClearConfirmationDialog event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( displayConfirmationDialog = UserProfileState.ConfirmationDialog.Block, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(UserProfileEvents.ClearConfirmationDialog) } @Config(qualifiers = "h1024dp") @Test - fun `on Unblock user clicked - an UnblockUser event is emitted with needsConfirmation`() = runTest { + fun `on Unblock user clicked - an UnblockUser event is emitted with needsConfirmation`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( isBlocked = AsyncData.Success(true), eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_dm_details_unblock_user) + clickOn(R.string.screen_dm_details_unblock_user) eventsRecorder.assertSingle(UserProfileEvents.UnblockUser(needsConfirmation = true)) } @Test - fun `on confirming Unblock user - an UnblockUser event is emitted without needsConfirmation`() = runTest { + fun `on confirming Unblock user - an UnblockUser event is emitted without needsConfirmation`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( isBlocked = AsyncData.Success(true), displayConfirmationDialog = UserProfileState.ConfirmationDialog.Unblock, eventSink = eventsRecorder, ), ) - rule.clickOn(R.string.screen_dm_details_unblock_alert_action) + clickOn(R.string.screen_dm_details_unblock_alert_action) eventsRecorder.assertSingle(UserProfileEvents.UnblockUser(needsConfirmation = false)) } @Test - fun `on canceling unblocking a user - a ClearConfirmationDialog event is emitted`() = runTest { + fun `on canceling unblocking a user - a ClearConfirmationDialog event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState( isBlocked = AsyncData.Success(true), displayConfirmationDialog = UserProfileState.ConfirmationDialog.Unblock, eventSink = eventsRecorder, ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(UserProfileEvents.ClearConfirmationDialog) } @Test - fun `on verify user clicked - the right callback is called`() = runTest { + fun `on verify user clicked - the right callback is called`() = runAndroidComposeUiTest { ensureCalledOnceWithParam(A_USER_ID) { callback -> - rule.setUserProfileView( + setUserProfileView( state = aUserProfileState(userId = A_USER_ID, verificationState = UserProfileVerificationState.UNVERIFIED), onVerifyClick = callback, ) - rule.clickOn(CommonStrings.common_verify_user) + clickOn(CommonStrings.common_verify_user) } } } -private fun AndroidComposeTestRule.setUserProfileView( +private fun AndroidComposeUiTest.setUserProfileView( state: UserProfileState = aUserProfileState( eventSink = EventsRecorder(expectEvents = false), ), diff --git a/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserDialogsTest.kt b/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserDialogsTest.kt index 3219658796..3498ad7714 100644 --- a/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserDialogsTest.kt +++ b/features/userprofile/shared/src/test/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserDialogsTest.kt @@ -6,10 +6,12 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.userprofile.shared.blockuser -import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileState @@ -18,18 +20,15 @@ import io.element.android.features.userprofile.shared.aUserProfileState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class BlockUserDialogsTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `confirm block user emit expected Event`() { + fun `confirm block user emit expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setContent { + setContent { BlockUserDialogs( state = aUserProfileState( displayConfirmationDialog = UserProfileState.ConfirmationDialog.Block, @@ -37,14 +36,14 @@ class BlockUserDialogsTest { ) ) } - rule.clickOn(R.string.screen_dm_details_block_alert_action) + clickOn(R.string.screen_dm_details_block_alert_action) eventsRecorder.assertSingle(UserProfileEvents.BlockUser(false)) } @Test - fun `cancel block user emit expected Event`() { + fun `cancel block user emit expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setContent { + setContent { BlockUserDialogs( state = aUserProfileState( displayConfirmationDialog = UserProfileState.ConfirmationDialog.Block, @@ -52,14 +51,14 @@ class BlockUserDialogsTest { ) ) } - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(UserProfileEvents.ClearConfirmationDialog) } @Test - fun `confirm unblock user emit expected Event`() { + fun `confirm unblock user emit expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setContent { + setContent { BlockUserDialogs( state = aUserProfileState( displayConfirmationDialog = UserProfileState.ConfirmationDialog.Unblock, @@ -67,14 +66,14 @@ class BlockUserDialogsTest { ) ) } - rule.clickOn(R.string.screen_dm_details_unblock_alert_action) + clickOn(R.string.screen_dm_details_unblock_alert_action) eventsRecorder.assertSingle(UserProfileEvents.UnblockUser(false)) } @Test - fun `cancel unblock user emit expected Event`() { + fun `cancel unblock user emit expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setContent { + setContent { BlockUserDialogs( state = aUserProfileState( displayConfirmationDialog = UserProfileState.ConfirmationDialog.Unblock, @@ -82,7 +81,7 @@ class BlockUserDialogsTest { ) ) } - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(UserProfileEvents.ClearConfirmationDialog) } } diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationViewTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationViewTest.kt index 4aa63f3ab8..afab77ad76 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationViewTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.verifysession.impl.incoming import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.verifysession.impl.R import io.element.android.features.verifysession.impl.ui.aEmojisSessionVerificationData @@ -18,59 +21,55 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class IncomingVerificationViewTest { - @get:Rule val rule = createAndroidComposeRule() - // region step Initial @Test - fun `back key pressed - ignore the verification`() { + fun `back key pressed - ignore the verification`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = aStepInitial(), eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } @Test - fun `ignore incoming verification emits the expected event`() { + fun `ignore incoming verification emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = aStepInitial(), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_ignore) + clickOn(CommonStrings.action_ignore) eventsRecorder.assertSingle(IncomingVerificationViewEvents.IgnoreVerification) } @Test - fun `start incoming verification emits the expected event`() { + fun `start incoming verification emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = aStepInitial(), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_start_verification) + clickOn(CommonStrings.action_start_verification) eventsRecorder.assertSingle(IncomingVerificationViewEvents.StartVerification) } @Test - fun `back key pressed - when awaiting response cancels the verification`() { + fun `back key pressed - when awaiting response cancels the verification`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = aStepInitial( isWaiting = true, @@ -78,16 +77,16 @@ class IncomingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } // endregion step Initial // region step Verifying @Test - fun `back key pressed - when ready to verify cancels the verification`() { + fun `back key pressed - when ready to verify cancels the verification`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -96,14 +95,14 @@ class IncomingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } @Test - fun `back key pressed - when verifying and loading emits the expected event`() { + fun `back key pressed - when verifying and loading emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -112,14 +111,14 @@ class IncomingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } @Test - fun `clicking on they do not match emits the expected event`() { + fun `clicking on they do not match emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -128,14 +127,14 @@ class IncomingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_session_verification_they_dont_match) + clickOn(R.string.screen_session_verification_they_dont_match) eventsRecorder.assertSingle(IncomingVerificationViewEvents.DeclineVerification) } @Test - fun `clicking on they match emits the expected event`() { + fun `clicking on they match emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -144,35 +143,35 @@ class IncomingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_session_verification_they_match) + clickOn(R.string.screen_session_verification_they_match) eventsRecorder.assertSingle(IncomingVerificationViewEvents.ConfirmVerification) } // endregion // region step Failure @Test - fun `back key pressed - when failure resets the flow`() { + fun `back key pressed - when failure resets the flow`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Failure, eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } @Test - fun `click on done - when failure resets the flow`() { + fun `click on done - when failure resets the flow`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Failure, eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_done) + clickOn(CommonStrings.action_done) eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } @@ -180,33 +179,33 @@ class IncomingVerificationViewTest { // region step Completed @Test - fun `back key pressed - on Completed step emits the expected event`() { + fun `back key pressed - on Completed step emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Completed, eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } @Test - fun `when flow is completed and the user clicks on the done button, the expected event is emitted`() { + fun `when flow is completed and the user clicks on the done button, the expected event is emitted`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setIncomingVerificationView( + setIncomingVerificationView( anIncomingVerificationState( step = IncomingVerificationState.Step.Completed, eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_done) + clickOn(CommonStrings.action_done) eventsRecorder.assertSingle(IncomingVerificationViewEvents.GoBack) } // endregion - private fun AndroidComposeTestRule.setIncomingVerificationView( + private fun AndroidComposeUiTest.setIncomingVerificationView( state: IncomingVerificationState, ) { setContent { diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationViewTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationViewTest.kt index 71b55fac10..1c96c5c2af 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationViewTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationViewTest.kt @@ -6,11 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.features.verifysession.impl.outgoing import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.verifysession.impl.R import io.element.android.features.verifysession.impl.ui.aEmojisSessionVerificationData @@ -21,58 +24,54 @@ 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.pressBackKey -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class OutgoingVerificationViewTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `back key pressed - when canceled resets the flow`() { + fun `back key pressed - when canceled resets the flow`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Canceled, eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(OutgoingVerificationViewEvents.Reset) } @Test - fun `back key pressed - when awaiting response cancels the verification`() { + fun `back key pressed - when awaiting response cancels the verification`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.AwaitingOtherDeviceResponse, eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(OutgoingVerificationViewEvents.Cancel) } @Test - fun `back key pressed - when ready to verify cancels the verification`() { + fun `back key pressed - when ready to verify cancels the verification`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Ready, eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(OutgoingVerificationViewEvents.Cancel) } @Test - fun `back key pressed - when verifying and not loading declines the verification`() { + fun `back key pressed - when verifying and not loading declines the verification`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -81,14 +80,14 @@ class OutgoingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertSingle(OutgoingVerificationViewEvents.DeclineVerification) } @Test - fun `back key pressed - when verifying and loading does nothing`() { + fun `back key pressed - when verifying and loading does nothing`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -97,42 +96,42 @@ class OutgoingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.pressBackKey() + pressBackKey() eventsRecorder.assertEmpty() } @Test - fun `back key pressed - on Completed exits the flow`() { + fun `back key pressed - on Completed exits the flow`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> - rule.setOutgoingVerificationView( + setOutgoingVerificationView( onBack = callback, state = anOutgoingVerificationState( step = OutgoingVerificationState.Step.Completed, ), ) - rule.pressBackKey() + pressBackKey() } } @Test - fun `when flow is completed and the user clicks on the continue button, the expected callback is invoked`() { + fun `when flow is completed and the user clicks on the continue button, the expected callback is invoked`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Completed, eventSink = eventsRecorder ), onFinished = callback, ) - rule.clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_continue) } } @Test - fun `clicking on they match emits the expected event`() { + fun `clicking on they match emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -141,14 +140,14 @@ class OutgoingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_session_verification_they_match) + clickOn(R.string.screen_session_verification_they_match) eventsRecorder.assertSingle(OutgoingVerificationViewEvents.ConfirmVerification) } @Test - fun `clicking on they do not match emits the expected event`() { + fun `clicking on they do not match emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setOutgoingVerificationView( + setOutgoingVerificationView( anOutgoingVerificationState( step = OutgoingVerificationState.Step.Verifying( data = aEmojisSessionVerificationData(), @@ -157,11 +156,11 @@ class OutgoingVerificationViewTest { eventSink = eventsRecorder ), ) - rule.clickOn(R.string.screen_session_verification_they_dont_match) + clickOn(R.string.screen_session_verification_they_dont_match) eventsRecorder.assertSingle(OutgoingVerificationViewEvents.DeclineVerification) } - private fun AndroidComposeTestRule.setOutgoingVerificationView( + private fun AndroidComposeUiTest.setOutgoingVerificationView( state: OutgoingVerificationState, onLearnMoreClick: () -> Unit = EnsureNeverCalled(), onFinished: () -> Unit = EnsureNeverCalled(), diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt index 4cbb35a85e..3f4c3aa6c3 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDeleteConfirmationBottomSheetTest.kt @@ -6,12 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.libraries.mediaviewer.impl.details import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.ui.strings.CommonStrings @@ -21,43 +24,38 @@ 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.setSafeContent -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class MediaDeleteConfirmationBottomSheetTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on Cancel invokes expected callback`() { + fun `clicking on Cancel invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDeleteConfirmation() ensureCalledOnce { callback -> - rule.setMediaDeleteConfirmationBottomSheet( + setMediaDeleteConfirmationBottomSheet( state = state, onDismiss = callback, ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) } } @Test - fun `clicking on Remove invokes expected callback`() { + fun `clicking on Remove invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDeleteConfirmation() ensureCalledOnceWithParam(state.eventId) { callback -> - rule.setMediaDeleteConfirmationBottomSheet( + setMediaDeleteConfirmationBottomSheet( state = state, onDelete = callback, ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_remove)).assertExists() - rule.clickOn(CommonStrings.action_remove) + onNodeWithText(activity!!.getString(CommonStrings.action_remove)).assertExists() + clickOn(CommonStrings.action_remove) } } } -private fun AndroidComposeTestRule.setMediaDeleteConfirmationBottomSheet( +private fun AndroidComposeUiTest.setMediaDeleteConfirmationBottomSheet( state: MediaBottomSheetState.DeleteConfirmation, onDelete: (EventId) -> Unit = EnsureNeverCalledWithParam(), onDismiss: () -> Unit = EnsureNeverCalled(), diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt index 21a06f9568..5b0f105aea 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt @@ -6,12 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.libraries.mediaviewer.impl.details import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.ui.strings.CommonStrings @@ -20,97 +23,92 @@ import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnceWithParam import io.element.android.tests.testutils.setSafeContent -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class MediaDetailsBottomSheetTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test @Config(qualifiers = "h1024dp") - fun `clicking on View in timeline invokes expected callback`() { + fun `clicking on View in timeline invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> - rule.setMediaDetailsBottomSheet( + setMediaDetailsBottomSheet( state = state, onViewInTimeline = callback, ) - rule.clickOn(CommonStrings.action_view_in_timeline) + clickOn(CommonStrings.action_view_in_timeline) } } @Test @Config(qualifiers = "h1024dp") - fun `clicking on Share invokes expected callback`() { + fun `clicking on Share invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> - rule.setMediaDetailsBottomSheet( + setMediaDetailsBottomSheet( state = state, onShare = callback, ) - rule.clickOn(CommonStrings.action_share) + clickOn(CommonStrings.action_share) } } @Test @Config(qualifiers = "h1024dp") - fun `clicking on Forward invokes expected callback`() { + fun `clicking on Forward invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> - rule.setMediaDetailsBottomSheet( + setMediaDetailsBottomSheet( state = state, onForward = callback, ) - rule.clickOn(CommonStrings.action_forward) + clickOn(CommonStrings.action_forward) } } @Test @Config(qualifiers = "h1024dp") - fun `clicking on Download invokes expected callback`() { + fun `clicking on Download invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> - rule.setMediaDetailsBottomSheet( + setMediaDetailsBottomSheet( state = state, onDownload = callback, ) - rule.clickOn(CommonStrings.action_download) + clickOn(CommonStrings.action_download) } } @Config(qualifiers = "h1024dp") @Test - fun `clicking on Delete invokes expected callback`() { + fun `clicking on Delete invokes expected callback`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDetails() ensureCalledOnceWithParam(state.eventId) { callback -> - rule.setMediaDetailsBottomSheet( + setMediaDetailsBottomSheet( state = state, onDelete = callback, ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_delete)).assertExists() - rule.clickOn(CommonStrings.action_delete) + onNodeWithText(activity!!.getString(CommonStrings.action_delete)).assertExists() + clickOn(CommonStrings.action_delete) } } @Config(qualifiers = "h1024dp") @Test - fun `Remove is not present if canDelete is false`() { + fun `Remove is not present if canDelete is false`() = runAndroidComposeUiTest { val state = aMediaBottomSheetStateDetails( canDelete = false, ) - rule.setMediaDetailsBottomSheet( + setMediaDetailsBottomSheet( state = state, ) - rule.onNodeWithText(rule.activity.getString(CommonStrings.action_remove)).assertDoesNotExist() + onNodeWithText(activity!!.getString(CommonStrings.action_remove)).assertDoesNotExist() } } -private fun AndroidComposeTestRule.setMediaDetailsBottomSheet( +private fun AndroidComposeUiTest.setMediaDetailsBottomSheet( state: MediaBottomSheetState.Details, onViewInTimeline: (EventId) -> Unit = EnsureNeverCalledWithParam(), onShare: (EventId) -> Unit = EnsureNeverCalledWithParam(), diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index 9eded788aa..fdd447c4a6 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -6,18 +6,21 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.libraries.mediaviewer.impl.viewer import android.net.Uri import androidx.activity.ComponentActivity import androidx.annotation.StringRes +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assertHasClickAction -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipeDown +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails @@ -30,30 +33,26 @@ import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.setSafeContent import io.mockk.mockk -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class MediaViewerViewTest { - @get:Rule val rule = createAndroidComposeRule() - private val mockMediaUrl: Uri = mockk("localMediaUri") @Test - fun `clicking on back invokes expected callback`() { + fun `clicking on back invokes expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMediaViewerState( eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setMediaViewerView( + setMediaViewerView( state = state, onBackClick = callback, ) - rule.pressBack() + pressBack() } eventsRecorder.assertList( listOf( @@ -103,16 +102,16 @@ class MediaViewerViewTest { data: MediaViewerPageData.MediaViewerData, @StringRes contentDescriptionRes: Int, expectedEvent: MediaViewerEvent, - ) { + ) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setMediaViewerView( + setMediaViewerView( aMediaViewerState( listData = listOf(data), eventSink = eventsRecorder ), ) - val contentDescription = rule.activity.getString(contentDescriptionRes) - rule.onNodeWithContentDescription(contentDescription).performClick() + val contentDescription = activity!!.getString(contentDescriptionRes) + onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertList( listOf( MediaViewerEvent.OnNavigateTo(0), @@ -159,16 +158,16 @@ class MediaViewerViewTest { data: MediaViewerPageData.MediaViewerData, @StringRes textRes: Int, expectedEvent: MediaViewerEvent, - ) { + ) = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setMediaViewerView( + setMediaViewerView( aMediaViewerState( listData = listOf(data), mediaBottomSheetState = aMediaBottomSheetStateDetails(), eventSink = eventsRecorder ), ) - rule.clickOn(textRes) + clickOn(textRes) eventsRecorder.assertList( listOf( MediaViewerEvent.OnNavigateTo(0), @@ -179,24 +178,25 @@ class MediaViewerViewTest { } @Test - fun `clicking on image hides the overlay`() { + fun `clicking on image hides the overlay`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMediaViewerState( eventSink = eventsRecorder ) - rule.setMediaViewerView( + setMediaViewerView( state = state, ) // Ensure that the action are visible - val contentDescription = rule.activity.getString(CommonStrings.action_share) - rule.onNodeWithContentDescription(contentDescription) + val resources = activity!!.resources + val contentDescription = resources.getString(CommonStrings.action_share) + onNodeWithContentDescription(contentDescription) .assertExists() .assertHasClickAction() - val imageContentDescription = rule.activity.getString(CommonStrings.common_image) - rule.onNodeWithContentDescription(imageContentDescription).performClick() + val imageContentDescription = resources.getString(CommonStrings.common_image) + onNodeWithContentDescription(imageContentDescription).performClick() // Give time for the animation (? since even by removing AnimatedVisibility it still fails) - rule.mainClock.advanceTimeBy(1_000) - rule.onNodeWithContentDescription(contentDescription) + mainClock.advanceTimeBy(1_000) + onNodeWithContentDescription(contentDescription) .assertDoesNotExist() eventsRecorder.assertList( listOf( @@ -207,19 +207,19 @@ class MediaViewerViewTest { } @Test - fun `clicking swipe on the image invokes the expected callback`() { + fun `clicking swipe on the image invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val state = aMediaViewerState( eventSink = eventsRecorder ) ensureCalledOnce { callback -> - rule.setMediaViewerView( + setMediaViewerView( state = state, onBackClick = callback, ) - val imageContentDescription = rule.activity.getString(CommonStrings.common_image) - rule.onNodeWithContentDescription(imageContentDescription).performTouchInput { swipeDown(startY = centerY) } - rule.mainClock.advanceTimeBy(1_000) + val imageContentDescription = activity!!.getString(CommonStrings.common_image) + onNodeWithContentDescription(imageContentDescription).performTouchInput { swipeDown(startY = centerY) } + mainClock.advanceTimeBy(1_000) } eventsRecorder.assertList( listOf( @@ -230,18 +230,18 @@ class MediaViewerViewTest { } @Test - fun `error case, click on retry emits the expected Event`() { + fun `error case, click on retry emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val data = aMediaViewerPageData( downloadedMedia = AsyncData.Failure(IllegalStateException("error")), ) - rule.setMediaViewerView( + setMediaViewerView( aMediaViewerState( listData = listOf(data), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_retry) + clickOn(CommonStrings.action_retry) eventsRecorder.assertList( listOf( MediaViewerEvent.OnNavigateTo(0), @@ -252,18 +252,18 @@ class MediaViewerViewTest { } @Test - fun `error case, click on cancel emits the expected Event`() { + fun `error case, click on cancel emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() val data = aMediaViewerPageData( downloadedMedia = AsyncData.Failure(IllegalStateException("error")), ) - rule.setMediaViewerView( + setMediaViewerView( aMediaViewerState( listData = listOf(data), eventSink = eventsRecorder ), ) - rule.clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertList( listOf( MediaViewerEvent.OnNavigateTo(0), @@ -274,7 +274,7 @@ class MediaViewerViewTest { } } -private fun AndroidComposeTestRule.setMediaViewerView( +private fun AndroidComposeUiTest.setMediaViewerView( state: MediaViewerState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt index 9a65ca0ad5..4840569c0e 100644 --- a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/impl/components/markdown/MarkdownTextInputTest.kt @@ -6,12 +6,15 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.libraries.textcomposer.impl.components.markdown import android.widget.EditText import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.core.text.getSpans import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat @@ -32,66 +35,54 @@ import io.element.android.libraries.textcomposer.model.SuggestionType import io.element.android.libraries.textcomposer.model.aMarkdownTextEditorState import io.element.android.tests.testutils.EnsureCalledOnceWithParam import io.element.android.tests.testutils.EventsRecorder -import kotlinx.coroutines.test.runTest -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class MarkdownTextInputTest { - @get:Rule val rule = createAndroidComposeRule() - @Test - fun `when user types onTyping is triggered with value 'true'`() = runTest { + fun `when user types onTyping is triggered with value 'true'`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialFocus = true) val onTyping = EnsureCalledOnceWithParam(expectedParam = true, result = Unit) - rule.setMarkdownTextInput(state = state, onTyping = onTyping) - rule.activityRule.scenario.onActivity { - it.findEditor().setText("Test") - } - rule.awaitIdle() + setMarkdownTextInput(state = state, onTyping = onTyping) + activity!!.findEditor().setText("Test") + awaitIdle() onTyping.assertSuccess() } @Test - fun `when user removes text onTyping is triggered with value 'false'`() = runTest { + fun `when user removes text onTyping is triggered with value 'false'`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialFocus = true) val onTyping = EventsRecorder() - rule.setMarkdownTextInput(state = state, onTyping = onTyping) - rule.activityRule.scenario.onActivity { - val editText = it.findEditor() - editText.setText("Test") - editText.setText("") - editText.setText(null) - } - rule.awaitIdle() + setMarkdownTextInput(state = state, onTyping = onTyping) + val editText = activity!!.findEditor() + editText.setText("Test") + editText.setText("") + editText.setText(null) + awaitIdle() onTyping.assertList(listOf(true, false, false)) } @Test - fun `when user types something that's not a mention onSuggestionReceived is triggered with 'null'`() = runTest { + fun `when user types something that's not a mention onSuggestionReceived is triggered with 'null'`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialFocus = true) val onSuggestionReceived = EventsRecorder() - rule.setMarkdownTextInput(state = state, onSuggestionReceived = onSuggestionReceived) - rule.activityRule.scenario.onActivity { - it.findEditor().setText("Test") - } - rule.awaitIdle() + setMarkdownTextInput(state = state, onSuggestionReceived = onSuggestionReceived) + activity!!.findEditor().setText("Test") + awaitIdle() onSuggestionReceived.assertSingle(null) } @Test - fun `when user types something that's a mention onSuggestionReceived is triggered a real value`() = runTest { + fun `when user types something that's a mention onSuggestionReceived is triggered a real value`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialFocus = true) val onSuggestionReceived = EventsRecorder() - rule.setMarkdownTextInput(state = state, onSuggestionReceived = onSuggestionReceived) - rule.activityRule.scenario.onActivity { - it.findEditor().setText("@") - it.findEditor().setText("#") - it.findEditor().setText("/") - } - rule.awaitIdle() + setMarkdownTextInput(state = state, onSuggestionReceived = onSuggestionReceived) + val editor = activity!!.findEditor() + editor.setText("@") + editor.setText("#") + editor.setText("/") + awaitIdle() onSuggestionReceived.assertList( listOf( // User mention suggestion @@ -105,69 +96,59 @@ class MarkdownTextInputTest { } @Test - fun `when the selection changes in the UI the state is updated`() = runTest { + fun `when the selection changes in the UI the state is updated`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialText = "Test", initialFocus = true) - rule.setMarkdownTextInput(state = state) - rule.activityRule.scenario.onActivity { - val editor = it.findEditor() - editor.setSelection(2) - } - rule.awaitIdle() + setMarkdownTextInput(state = state) + val editor = activity!!.findEditor() + editor.setSelection(2) + awaitIdle() // Selection is updated assertThat(state.selection).isEqualTo(2..2) } @Test - fun `when the selection state changes in the view is updated`() = runTest { + fun `when the selection state changes in the view is updated`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialText = "Test", initialFocus = true) - rule.setMarkdownTextInput(state = state) - var editor: EditText? = null - rule.activityRule.scenario.onActivity { - editor = it.findEditor() - state.selection = 2..2 - } - rule.awaitIdle() + setMarkdownTextInput(state = state) + val editor = activity!!.findEditor() + state.selection = 2..2 + awaitIdle() // Selection state is updated - assertThat(editor?.selectionStart).isEqualTo(2) - assertThat(editor?.selectionEnd).isEqualTo(2) + assertThat(editor.selectionStart).isEqualTo(2) + assertThat(editor.selectionEnd).isEqualTo(2) } @Test - fun `when the view focus changes the state is updated`() = runTest { + fun `when the view focus changes the state is updated`() = runAndroidComposeUiTest { val state = aMarkdownTextEditorState(initialText = "Test", initialFocus = false) - rule.setMarkdownTextInput(state = state) - rule.activityRule.scenario.onActivity { - val editor = it.findEditor() - editor.requestFocus() - } + setMarkdownTextInput(state = state) + val editor = activity!!.findEditor() + editor.requestFocus() // Focus state is updated assertThat(state.hasFocus).isTrue() } @Test - fun `inserting a mention replaces the existing text with a span`() = runTest { + fun `inserting a mention replaces the existing text with a span`() = runAndroidComposeUiTest { val permalinkParser = FakePermalinkParser(result = { PermalinkData.UserLink(A_SESSION_ID) }) val state = aMarkdownTextEditorState(initialText = "@", initialFocus = true) state.currentSuggestion = Suggestion(0, 1, SuggestionType.Mention, "") - rule.setMarkdownTextInput(state = state) - var editor: EditText? = null - rule.activityRule.scenario.onActivity { - editor = it.findEditor() - state.insertSuggestion( - ResolvedSuggestion.Member(roomMember = aRoomMember()), - aMentionSpanProvider(permalinkParser), - ) - } - rule.awaitIdle() + setMarkdownTextInput(state = state) + val editor = activity!!.findEditor() + state.insertSuggestion( + ResolvedSuggestion.Member(roomMember = aRoomMember()), + aMentionSpanProvider(permalinkParser), + ) + awaitIdle() // Text is replaced with a placeholder - assertThat(editor?.editableText.toString()).isEqualTo("@ ") + assertThat(editor.editableText.toString()).isEqualTo("@ ") // The placeholder contains a MentionSpan - val mentionSpans = editor?.editableText?.getSpans(0, 2).orEmpty() + val mentionSpans = editor.editableText?.getSpans(0, 2).orEmpty() assertThat(mentionSpans).isNotEmpty() } - private fun AndroidComposeTestRule.setMarkdownTextInput( + private fun AndroidComposeUiTest.setMarkdownTextInput( state: MarkdownTextEditorState = aMarkdownTextEditorState(), onTyping: (Boolean) -> Unit = {}, onSuggestionReceived: (Suggestion?) -> Unit = {}, diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsViewTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsViewTest.kt index 0ba6c22710..0244673ea5 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsViewTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsViewTest.kt @@ -6,60 +6,58 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.libraries.troubleshoot.impl import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.ensureCalledOnce 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 import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class TroubleshootNotificationsViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `press menu back invokes the expected callback`() { + fun `press menu back invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { - rule.setTroubleshootNotificationsView( + setTroubleshootNotificationsView( state = aTroubleshootNotificationsState( eventSink = eventsRecorder ), onBackClick = it, ) - rule.pressBack() + pressBack() } } @Test - fun `clicking on run test emits the expected Event`() { + fun `clicking on run test emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTroubleshootNotificationsView( + setTroubleshootNotificationsView( aTroubleshootNotificationsState( eventSink = eventsRecorder ), ) - rule.onNodeWithText("Run tests").performClick() + onNodeWithText("Run tests").performClick() eventsRecorder.assertSingle(TroubleshootNotificationsEvents.StartTests) } @Config(qualifiers = "h1024dp") @Test - fun `clicking on run test again emits the expected Event`() { + fun `clicking on run test again emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTroubleshootNotificationsView( + setTroubleshootNotificationsView( aTroubleshootNotificationsState( tests = listOf( aTroubleshootTestStateFailure( @@ -69,7 +67,7 @@ class TroubleshootNotificationsViewTest { eventSink = eventsRecorder ), ) - rule.onNodeWithText("Run tests again").performClick() + onNodeWithText("Run tests again").performClick() eventsRecorder.assertList( listOf( TroubleshootNotificationsEvents.RetryFailedTests, @@ -80,9 +78,9 @@ class TroubleshootNotificationsViewTest { @Config(qualifiers = "h1024dp") @Test - fun `clicking on quick fix emits the expected Event`() { + fun `clicking on quick fix emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setTroubleshootNotificationsView( + setTroubleshootNotificationsView( aTroubleshootNotificationsState( tests = listOf( aTroubleshootTestStateFailure( @@ -92,7 +90,7 @@ class TroubleshootNotificationsViewTest { eventSink = eventsRecorder ), ) - rule.onNodeWithText("Attempt to fix").performClick() + onNodeWithText("Attempt to fix").performClick() eventsRecorder.assertList( listOf( TroubleshootNotificationsEvents.RetryFailedTests, @@ -102,7 +100,7 @@ class TroubleshootNotificationsViewTest { } } -private fun AndroidComposeTestRule.setTroubleshootNotificationsView( +private fun AndroidComposeUiTest.setTroubleshootNotificationsView( state: TroubleshootNotificationsState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryViewTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryViewTest.kt index fa4e65ad9a..94cde37452 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryViewTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryViewTest.kt @@ -6,14 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.libraries.troubleshoot.impl.history import androidx.activity.ComponentActivity -import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_FORMATTED_DATE @@ -23,67 +26,62 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn -import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class PushHistoryViewTest { - @get:Rule - val rule = createAndroidComposeRule() - @Test - fun `clicking on Reset sends a PushHistoryEvents`() { + fun `clicking on Reset sends a PushHistoryEvents`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPushHistoryView( + setPushHistoryView( aPushHistoryState( pushCounter = 123, eventSink = eventsRecorder, ), ) - val menuContentDescription = rule.activity.getString(CommonStrings.a11y_user_menu) - rule.onNodeWithContentDescription(menuContentDescription).performClick() - rule.clickOn(CommonStrings.action_reset) + val menuContentDescription = activity!!.getString(CommonStrings.a11y_user_menu) + onNodeWithContentDescription(menuContentDescription).performClick() + clickOn(CommonStrings.action_reset) eventsRecorder.assertSingle(PushHistoryEvents.Reset(requiresConfirmation = true)) // Also check that the push counter is rendered - rule.onNodeWithText("123").assertExists() + onNodeWithText("123").assertExists() } @Test - fun `clicking on show only errors sends a PushHistoryEvents(true)`() { + fun `clicking on show only errors sends a PushHistoryEvents(true)`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPushHistoryView( + setPushHistoryView( aPushHistoryState( showOnlyErrors = false, eventSink = eventsRecorder, ), ) - val menuContentDescription = rule.activity.getString(CommonStrings.a11y_user_menu) - rule.onNodeWithContentDescription(menuContentDescription).performClick() - rule.onNodeWithText("Show only errors").performClick() + val menuContentDescription = activity!!.getString(CommonStrings.a11y_user_menu) + onNodeWithContentDescription(menuContentDescription).performClick() + onNodeWithText("Show only errors").performClick() eventsRecorder.assertSingle(PushHistoryEvents.SetShowOnlyErrors(showOnlyErrors = true)) } @Test - fun `clicking on show only errors sends a PushHistoryEvents(false)`() { + fun `clicking on show only errors sends a PushHistoryEvents(false)`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPushHistoryView( + setPushHistoryView( aPushHistoryState( showOnlyErrors = true, eventSink = eventsRecorder, ), ) - val menuContentDescription = rule.activity.getString(CommonStrings.a11y_user_menu) - rule.onNodeWithContentDescription(menuContentDescription).performClick() - rule.onNodeWithText("Show only errors").performClick() + val menuContentDescription = activity!!.getString(CommonStrings.a11y_user_menu) + onNodeWithContentDescription(menuContentDescription).performClick() + onNodeWithText("Show only errors").performClick() eventsRecorder.assertSingle(PushHistoryEvents.SetShowOnlyErrors(showOnlyErrors = false)) } @Test - fun `clicking on an invalid event has no effect`() { + fun `clicking on an invalid event has no effect`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) - rule.setPushHistoryView( + setPushHistoryView( aPushHistoryState( pushHistoryItems = listOf( aPushHistoryItem( @@ -93,14 +91,14 @@ class PushHistoryViewTest { eventSink = eventsRecorder, ), ) - rule.onNodeWithText(A_FORMATTED_DATE).performClick() + onNodeWithText(A_FORMATTED_DATE).performClick() // No callback invoked } @Test - fun `clicking on a valid event emits the expected Event`() { + fun `clicking on a valid event emits the expected Event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() - rule.setPushHistoryView( + setPushHistoryView( aPushHistoryState( pushHistoryItems = listOf( aPushHistoryItem( @@ -113,7 +111,7 @@ class PushHistoryViewTest { eventSink = eventsRecorder, ), ) - rule.onNodeWithText(A_FORMATTED_DATE).performClick() + onNodeWithText(A_FORMATTED_DATE).performClick() eventsRecorder.assertSingle( PushHistoryEvents.NavigateTo( sessionId = A_SESSION_ID, @@ -124,7 +122,7 @@ class PushHistoryViewTest { } } -private fun AndroidComposeTestRule.setPushHistoryView( +private fun AndroidComposeUiTest.setPushHistoryView( state: PushHistoryState, onBackClick: () -> Unit = EnsureNeverCalled(), ) { diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RobolectricDispatcherCleaner.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RobolectricDispatcherCleaner.kt index 12cfe44b44..d7ce9e2d28 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RobolectricDispatcherCleaner.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RobolectricDispatcherCleaner.kt @@ -6,15 +6,17 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.tests.testutils import androidx.activity.ComponentActivity import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import io.element.android.libraries.designsystem.utils.LocalUiTestMode import org.junit.Assert.assertFalse -import org.junit.rules.TestRule import kotlin.coroutines.CoroutineContext object RobolectricDispatcherCleaner { @@ -52,7 +54,7 @@ object RobolectricDispatcherCleaner { } } -fun AndroidComposeTestRule.setSafeContent( +fun AndroidComposeUiTest.setSafeContent( clearAndroidUiDispatcher: Boolean = false, content: @Composable () -> Unit, ) { 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 d78f570a31..a473e6bd22 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 @@ -6,10 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTestApi::class) + package io.element.android.tests.testutils import androidx.activity.ComponentActivity import androidx.annotation.StringRes +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.SemanticsNodeInteractionsProvider import androidx.compose.ui.test.assertIsDisplayed @@ -19,19 +23,17 @@ import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasText import androidx.compose.ui.test.isDialog -import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import io.element.android.libraries.ui.strings.CommonStrings -import org.junit.rules.TestRule val trueMatcher = SemanticsMatcher("true matcher") { true } -fun AndroidComposeTestRule.clickOn( +fun AndroidComposeUiTest.clickOn( @StringRes res: Int, inDialog: Boolean = false, ) { - val text = activity.getString(res) + val text = activity!!.getString(res) onNode( hasText(text) and hasClickAction() and if (inDialog) hasAnyAncestor(isDialog()) else trueMatcher ) @@ -41,28 +43,28 @@ fun AndroidComposeTestRule.clickOn( /** * Press the back button in the app bar. */ -fun AndroidComposeTestRule.pressBack() { - val text = activity.getString(CommonStrings.action_back) +fun AndroidComposeUiTest.pressBack() { + val text = activity!!.getString(CommonStrings.action_back) onNode(hasContentDescription(text)).performClick() } /** * Press the back key. */ -fun AndroidComposeTestRule.pressBackKey() { - activity.onBackPressedDispatcher.onBackPressed() +fun AndroidComposeUiTest.pressBackKey() { + activity!!.onBackPressedDispatcher.onBackPressed() } fun SemanticsNodeInteractionsProvider.pressTag(tag: String) { onNode(hasTestTag(tag)).performClick() } -fun AndroidComposeTestRule.assertNoNodeWithText(@StringRes res: Int) { - val text = activity.getString(res) +fun AndroidComposeUiTest.assertNoNodeWithText(@StringRes res: Int) { + val text = activity!!.getString(res) onNodeWithText(text).assertDoesNotExist() } -fun AndroidComposeTestRule.assertNodeWithTextIsDisplayed(@StringRes res: Int) { - val text = activity.getString(res) +fun AndroidComposeUiTest.assertNodeWithTextIsDisplayed(@StringRes res: Int) { + val text = activity!!.getString(res) onNodeWithText(text).assertIsDisplayed() } From 6c7c48da698afb7daf5a6f7b23849110e8a5d9b0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 16:59:14 +0200 Subject: [PATCH 0316/1083] Fix compilation issue --- .../android/features/call/ui/CallScreenViewTest.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt index fed9f90de0..e4f9c10a3c 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt @@ -18,9 +18,9 @@ import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.call.impl.pip.PictureInPictureEvents +import io.element.android.features.call.impl.pip.PictureInPictureEvent import io.element.android.features.call.impl.pip.aPictureInPictureState -import io.element.android.features.call.impl.ui.CallScreenEvents +import io.element.android.features.call.impl.ui.CallScreenEvent import io.element.android.features.call.impl.ui.CallScreenView import io.element.android.features.call.impl.ui.JavascriptBackHandler import io.element.android.features.call.impl.ui.aCallScreenState @@ -39,7 +39,7 @@ import org.robolectric.shadows.ShadowWebView class CallScreenViewTest { @Test fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() = runAndroidComposeUiTest { - val callEvents = EventsRecorder() + val callEvents = EventsRecorder() setCallScreenView( state = aCallScreenState(eventSink = callEvents), @@ -72,7 +72,7 @@ class CallScreenViewTest { @Config(shadows = [RecordingShadowWebView::class]) @Test fun `web view javascript back handler emits pip event when pip is supported`() = runAndroidComposeUiTest { - val pipEvents = EventsRecorder() + val pipEvents = EventsRecorder() setCallScreenView( state = aCallScreenState(), @@ -88,8 +88,8 @@ class CallScreenViewTest { } pipEvents.assertSize(2) - pipEvents.assertTrue(0) { it is PictureInPictureEvents.SetPipController } - pipEvents.assertTrue(1) { it is PictureInPictureEvents.EnterPictureInPicture } + pipEvents.assertTrue(0) { it is PictureInPictureEvent.SetPipController } + pipEvents.assertTrue(1) { it is PictureInPictureEvent.EnterPictureInPicture } } } From 194945c49e9d43489cca172e566715b24703460d Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 1 May 2026 12:19:17 +0000 Subject: [PATCH 0317/1083] Add `.clickable` to `RoomMemberModerationView` avatar --- .../roommembermoderation/impl/RoomMemberModerationView.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt index ac6c5bc4cb..1a6a14d3f3 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt @@ -8,6 +8,7 @@ package io.element.android.features.roommembermoderation.impl +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -234,6 +235,12 @@ private fun RoomMemberActionsBottomSheet( modifier = Modifier .padding(bottom = 24.dp) .align(Alignment.CenterHorizontally) + .clickable { + coroutineScope.launch { + onSelectAction(ModerationAction.DisplayProfile, user) + bottomSheetState.hide() + } + } ) val bestName = user.getBestName() Text( From 78aa500d23eaf00fabfa47c30b902c327848a6a7 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Fri, 1 May 2026 08:16:35 -0700 Subject: [PATCH 0318/1083] Fold newMessagesCount into NewEventState.FromOther --- .../impl/timeline/TimelinePresenter.kt | 29 +++------ .../messages/impl/timeline/TimelineState.kt | 1 - .../impl/timeline/TimelineStateProvider.kt | 5 +- .../messages/impl/timeline/TimelineView.kt | 13 ++-- .../impl/timeline/model/NewEventState.kt | 16 +++-- .../impl/timeline/TimelinePresenterTest.kt | 62 +++++++++---------- 6 files changed, 61 insertions(+), 65 deletions(-) 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 5462112fd4..fe45796428 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 @@ -10,7 +10,6 @@ package io.element.android.features.messages.impl.timeline import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.MutableIntState import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf @@ -137,8 +136,7 @@ class TimelinePresenter( val prevMostRecentItemId = rememberSaveable { mutableStateOf(null) } - val newEventState = remember { mutableStateOf(NewEventState.None) } - val newMessagesCount = remember { mutableIntStateOf(0) } + val newEventState = remember { mutableStateOf(NewEventState.None) } val messageShieldDialogData: MutableState = remember { mutableStateOf(null) } val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() @@ -177,7 +175,6 @@ class TimelinePresenter( if (isLive) { if (event.firstIndex == 0) { newEventState.value = NewEventState.None - newMessagesCount.intValue = 0 } Timber.tag(tag).d("## sendReadReceiptIfNeeded firstVisibleIndex: ${event.firstIndex}") sessionCoroutineScope.sendReadReceiptIfNeeded( @@ -278,7 +275,7 @@ class TimelinePresenter( } LaunchedEffect(timelineItems.size) { - computeNewItemState(timelineItems, prevMostRecentItemId, newEventState, newMessagesCount) + computeNewItemState(timelineItems, prevMostRecentItemId, newEventState) } // Read marker position + unread count, scanned off the main thread. The UI gates display via @@ -361,7 +358,6 @@ class TimelinePresenter( displayJumpToUnread = displayJumpToUnread, readMarkerIndex = readMarkerIndex.intValue, unreadMessagesCount = unreadMessagesCount.intValue, - newMessagesCount = newMessagesCount.intValue, eventSink = ::handleEvent, ) } @@ -420,16 +416,14 @@ class TimelinePresenter( * Basically, if we got new timeline event from sync or local, either from us or another user, we update the state so we tell we have new items. * The state never goes back to None from this method, but need to be reset from somewhere else. * - * It also maintains [newMessagesCount], counting how many incoming messages from other users have arrived in - * each batch since [prevMostRecentItemId] — this drives the badge on the scroll-to-bottom button. The count is - * reset to zero when the most recent event is from the local user (they're back to active engagement); the - * scroll-finish handler resets it when the user returns to the bottom of the timeline. + * The [NewEventState.FromOther] variant carries the running count of incoming messages from other users + * since [prevMostRecentItemId] last advanced to a local-user event or the timeline returned to the bottom + * — this drives the badge on the scroll-to-bottom button. */ private suspend fun computeNewItemState( timelineItems: ImmutableList, prevMostRecentItemId: MutableState, newEventState: MutableState, - newMessagesCount: MutableIntState, ) = withContext(dispatchers.computation) { // FromMe is prioritized over FromOther, so skip if we already have a FromMe if (newEventState.value == NewEventState.FromMe) { @@ -448,14 +442,8 @@ class TimelinePresenter( if (hasNewEvent) { // Scroll to bottom if the new event is from me, even if sent from another device - val fromMe = newMostRecentItem.isMine - newEventState.value = if (fromMe) { - NewEventState.FromMe - } else { - NewEventState.FromOther - } - if (fromMe) { - newMessagesCount.intValue = 0 + if (newMostRecentItem.isMine) { + newEventState.value = NewEventState.FromMe } else { var delta = 0 for (item in timelineItems) { @@ -464,7 +452,8 @@ class TimelinePresenter( delta++ } } - newMessagesCount.intValue += delta + val previousCount = (newEventState.value as? NewEventState.FromOther)?.messageCount ?: 0 + newEventState.value = NewEventState.FromOther(previousCount + delta) } } prevMostRecentItemId.value = newMostRecentItemId diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index ccd4d44ea8..12dd01d57a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -38,7 +38,6 @@ data class TimelineState( val displayJumpToUnread: Boolean, val readMarkerIndex: Int, val unreadMessagesCount: Int, - val newMessagesCount: Int, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 08ddf56c8c..7fc3386ca7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -60,7 +60,7 @@ fun aTimelineState( displayJumpToUnread: Boolean = true, readMarkerIndex: Int = -1, unreadMessagesCount: Int = 0, - newMessagesCount: Int = 0, + newEventState: NewEventState = NewEventState.None, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId @@ -74,7 +74,7 @@ fun aTimelineState( timelineMode = timelineMode, timelineRoomInfo = timelineRoomInfo, renderReadReceipts = renderReadReceipts, - newEventState = NewEventState.None, + newEventState = newEventState, isLive = isLive, focusRequestState = focusRequestState, messageShieldDialogData = messageShield?.let { MessageShieldData(it) }, @@ -84,7 +84,6 @@ fun aTimelineState( displayJumpToUnread = displayJumpToUnread, readMarkerIndex = readMarkerIndex, unreadMessagesCount = unreadMessagesCount, - newMessagesCount = newMessagesCount, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index ce62f1ef9f..54930a2f2b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -222,7 +222,6 @@ fun TimelineView( focusRequestState = state.focusRequestState, readMarkerIndex = state.readMarkerIndex, unreadMessagesCount = state.unreadMessagesCount, - newMessagesCount = state.newMessagesCount, displayJumpToUnread = state.displayJumpToUnread, topInset = floatingDateTopOffset, onScrollFinishAt = ::onScrollFinishAt, @@ -310,7 +309,6 @@ private fun BoxScope.TimelineScrollHelper( focusRequestState: FocusRequestState, readMarkerIndex: Int, unreadMessagesCount: Int, - newMessagesCount: Int, displayJumpToUnread: Boolean, topInset: Dp, onScrollFinishAt: (Int) -> Unit, @@ -386,8 +384,11 @@ private fun BoxScope.TimelineScrollHelper( } LaunchedEffect(canAutoScroll, newEventState) { - val shouldScrollToBottom = isScrollFinished && - (canAutoScroll && newEventState == NewEventState.FromOther || newEventState == NewEventState.FromMe) + val shouldScrollToBottom = isScrollFinished && when (newEventState) { + is NewEventState.FromOther -> canAutoScroll + NewEventState.FromMe -> true + NewEventState.None -> false + } if (shouldScrollToBottom) { scrollToBottom(force = true) } @@ -406,7 +407,7 @@ private fun BoxScope.TimelineScrollHelper( contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), isVisible = isJumpToBottomVisible, // Hide the badge entirely when the feature is off, regardless of the count value. - count = if (displayJumpToUnread) newMessagesCount else 0, + count = if (displayJumpToUnread) newEventState.messageCount else 0, modifier = Modifier .align(Alignment.BottomEnd) .padding(end = 24.dp, bottom = 12.dp), @@ -565,7 +566,7 @@ private fun TimelineViewWithReadMarker( // view. The actual scroll target doesn't matter for a static preview. readMarkerIndex = timelineItems.size, unreadMessagesCount = unreadMessagesCount, - newMessagesCount = newMessagesCount, + newEventState = if (newMessagesCount > 0) NewEventState.FromOther(newMessagesCount) else NewEventState.None, ), timelineProtectionState = aTimelineProtectionState(), onUserDataClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt index cac2798fdd..eb60d6780f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt @@ -8,12 +8,20 @@ package io.element.android.features.messages.impl.timeline.model +import androidx.compose.runtime.Immutable + /** * Model if there is a new event in the timeline and if it is from me or from other. * This can be used to scroll to the bottom of the list when a new event is added. + * + * [FromOther] also carries the running count of incoming messages from other users since the + * timeline was last at the bottom — used to drive the badge on the scroll-to-bottom button. */ -enum class NewEventState { - None, - FromMe, - FromOther +@Immutable +sealed interface NewEventState { + val messageCount: Int get() = 0 + + data object None : NewEventState + data object FromMe : NewEventState + data class FromOther(override val messageCount: Int) : NewEventState } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index e4ddbf6c82..502308cfe7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -362,7 +362,10 @@ class TimelinePresenterTest { } consumeItemsUntilPredicate { it.timelineItems.size == 4 } awaitLastSequentialItem().also { state -> - assertThat(state.newEventState).isEqualTo(NewEventState.FromOther) + // Both events received during the FromMe window are counted now that the timeline + // has progressed past it: prevMostRecentItemId points at the local user's "1", + // so "2" and "3" are both new countable messages. + assertThat(state.newEventState).isEqualTo(NewEventState.FromOther(2)) } cancelAndIgnoreRemainingEvents() } @@ -450,13 +453,13 @@ class TimelinePresenterTest { } @Test - fun `present - newMessagesCount increments by N when N events from others arrive in one batch`() = runTest { + fun `present - FromOther count increments by N when N events from others arrive in one batch`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) presenter.test { val initialState = awaitFirstItem() - assertThat(initialState.newMessagesCount).isEqualTo(0) + assertThat(initialState.newEventState).isEqualTo(NewEventState.None) // Seed prevMostRecentItemId so subsequent emissions count as new events. timelineItems.emit( listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) @@ -470,16 +473,15 @@ class TimelinePresenterTest { MatrixTimelineItem.Event(UniqueId("3"), anEventTimelineItem(content = aMessageContent())), ) } - consumeItemsUntilPredicate { it.newMessagesCount == 3 }.last().also { state -> - assertThat(state.newMessagesCount).isEqualTo(3) - assertThat(state.newEventState).isEqualTo(NewEventState.FromOther) + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(3) }.last().also { state -> + assertThat(state.newEventState).isEqualTo(NewEventState.FromOther(3)) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - newMessagesCount resets to 0 on OnScrollFinished firstIndex 0`() = runTest { + fun `present - newEventState resets to None on OnScrollFinished firstIndex 0`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline( timelineItems = timelineItems, @@ -495,18 +497,18 @@ class TimelinePresenterTest { timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - val countedState = consumeItemsUntilPredicate { it.newMessagesCount == 1 }.last() - assertThat(countedState.newMessagesCount).isEqualTo(1) + val countedState = consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) }.last() + assertThat(countedState.newEventState).isEqualTo(NewEventState.FromOther(1)) initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(0)) - consumeItemsUntilPredicate { it.newMessagesCount == 0 }.last().also { state -> - assertThat(state.newMessagesCount).isEqualTo(0) + consumeItemsUntilPredicate { it.newEventState == NewEventState.None }.last().also { state -> + assertThat(state.newEventState).isEqualTo(NewEventState.None) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - newMessagesCount resets to 0 when latest event is from me`() = runTest { + fun `present - newEventState transitions to FromMe when latest event is from me, dropping the count`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -520,25 +522,23 @@ class TimelinePresenterTest { timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newMessagesCount == 1 } - // Then the local user sends a message: count should reset. + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) } + // Then the local user sends a message: state moves to FromMe (which carries no count). timelineItems.getAndUpdate { items -> items + listOf( MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent(), isOwn = true)), ) } - consumeItemsUntilPredicate { - it.newEventState == NewEventState.FromMe && it.newMessagesCount == 0 - }.last().also { state -> - assertThat(state.newMessagesCount).isEqualTo(0) + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromMe }.last().also { state -> assertThat(state.newEventState).isEqualTo(NewEventState.FromMe) + assertThat(state.newEventState.messageCount).isEqualTo(0) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - newMessagesCount does not reset on OnScrollFinished firstIndex other than 0`() = runTest { + fun `present - FromOther count does not reset on OnScrollFinished firstIndex other than 0`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -551,19 +551,19 @@ class TimelinePresenterTest { timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newMessagesCount == 1 } + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) } // Scrolling stops above the bottom: the count must NOT reset. initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(5)) advanceUntilIdle() - // No state should emit with newMessagesCount == 0. + // No state should emit with the count back at 0. val drained = consumeItemsUntilTimeout() - assertThat(drained.any { it.newMessagesCount == 0 }).isFalse() + assertThat(drained.any { it.newEventState.messageCount == 0 }).isFalse() cancelAndIgnoreRemainingEvents() } } @Test - fun `present - newMessagesCount does not increment for events with PAGINATION origin`() = runTest { + fun `present - FromOther count does not increment for events with PAGINATION origin`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -583,14 +583,14 @@ class TimelinePresenterTest { ) } consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> - assertThat(state.newMessagesCount).isEqualTo(0) + assertThat(state.newEventState.messageCount).isEqualTo(0) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - newMessagesCount does not increment for state events`() = runTest { + fun `present - FromOther count does not increment for state events`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -607,7 +607,7 @@ class TimelinePresenterTest { ) } consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> - assertThat(state.newMessagesCount).isEqualTo(0) + assertThat(state.newEventState.messageCount).isEqualTo(0) } cancelAndIgnoreRemainingEvents() } @@ -632,7 +632,7 @@ class TimelinePresenterTest { } @Test - fun `present - newMessagesCount accumulates across multiple batches as prevMostRecentItemId advances`() = runTest { + fun `present - FromOther count accumulates across multiple batches as prevMostRecentItemId advances`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -647,7 +647,7 @@ class TimelinePresenterTest { timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("b1-1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newMessagesCount == 1 } + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) } // Batch 2: 2 more new events → count = 3. timelineItems.getAndUpdate { items -> items + listOf( @@ -655,13 +655,13 @@ class TimelinePresenterTest { MatrixTimelineItem.Event(UniqueId("b2-2"), anEventTimelineItem(content = aMessageContent())), ) } - consumeItemsUntilPredicate { it.newMessagesCount == 3 } + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(3) } // Batch 3: 1 more new event → count = 4. timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("b3-1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newMessagesCount == 4 }.last().also { state -> - assertThat(state.newMessagesCount).isEqualTo(4) + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(4) }.last().also { state -> + assertThat(state.newEventState).isEqualTo(NewEventState.FromOther(4)) } cancelAndIgnoreRemainingEvents() } From 7148f2f28f6d012c1eca395233396a4199ae9140 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Fri, 1 May 2026 09:01:32 -0700 Subject: [PATCH 0319/1083] Semantic fixes: clearer naming conventions, when statements --- .../impl/timeline/TimelinePresenter.kt | 7 ++-- .../messages/impl/timeline/TimelineView.kt | 35 +++++++++---------- .../tests/konsist/KonsistPreviewTest.kt | 1 + 3 files changed, 22 insertions(+), 21 deletions(-) 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 fe45796428..dbb23b774e 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 @@ -278,9 +278,10 @@ class TimelinePresenter( computeNewItemState(timelineItems, prevMostRecentItemId, newEventState) } - // Read marker position + unread count, scanned off the main thread. The UI gates display via - // [displayJumpToUnread]; the values are always computed so the state stays up to date if the - // feature flag flips at runtime. + // Keyed on the full [timelineItems] reference (not just .size) so we re-scan when the + // read marker advances in place — the SDK swaps the marker virtual item to a new position + // without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the + // bottom of the room. val readMarkerIndex = remember { mutableIntStateOf(-1) } val unreadMessagesCount = remember { mutableIntStateOf(0) } LaunchedEffect(timelineItems) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 54930a2f2b..9a324afd2f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -322,15 +322,15 @@ private fun BoxScope.TimelineScrollHelper( lazyListState.firstVisibleItemIndex < 3 && isLive } } - val isReadMarkerOffTop by remember { + val isJumpToUnreadVisible by remember { derivedStateOf { - if (!displayJumpToUnread || readMarkerIndex < 0) { - false - } else if (forceJumpToReadMarkerVisibility) { - true - } else { - val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false - readMarkerIndex > lastVisibleIndex + when { + forceJumpToReadMarkerVisibility -> true + !displayJumpToUnread || readMarkerIndex < 0 -> false + else -> { + val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false + readMarkerIndex > lastVisibleIndex + } } } } @@ -402,7 +402,7 @@ private fun BoxScope.TimelineScrollHelper( } } - TimelineFab( + JumpToPositionButton( icon = CompoundIcons.ChevronDown(), contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), isVisible = isJumpToBottomVisible, @@ -418,10 +418,10 @@ private fun BoxScope.TimelineScrollHelper( } else { stringResource(id = CommonStrings.a11y_jump_to_unread_messages) } - TimelineFab( + JumpToPositionButton( icon = CompoundIcons.ChevronUp(), contentDescription = jumpToUnreadDescription, - isVisible = isReadMarkerOffTop, + isVisible = isJumpToUnreadVisible, count = unreadMessagesCount, // Top padding includes [topInset] so the FAB sits below any pinned-events banner. modifier = Modifier @@ -432,7 +432,7 @@ private fun BoxScope.TimelineScrollHelper( } @Composable -private fun TimelineFab( +private fun JumpToPositionButton( icon: ImageVector, contentDescription: String, isVisible: Boolean, @@ -480,9 +480,9 @@ private fun TimelineCountBadge( count: Int, modifier: Modifier = Modifier, ) { - if (count <= 0) return - if (count <= 9) { - Box( + when { + count <= 0 -> return + count <= 9 -> Box( modifier = modifier .defaultMinSize(minWidth = 16.dp, minHeight = 16.dp) .background(color = ElementTheme.colors.bgActionPrimaryRest, shape = CircleShape) @@ -497,8 +497,7 @@ private fun TimelineCountBadge( textAlign = TextAlign.Center, ) } - } else { - Box( + else -> Box( modifier = modifier .size(12.dp) .background(color = ElementTheme.colors.bgActionPrimaryRest, shape = CircleShape) @@ -592,7 +591,7 @@ internal fun TimelineViewWithReadMarkerNoBadgesPreview() = ElementPreview { @PreviewsDayNight @Composable -internal fun TimelineViewWithReadMarkerPreview() = ElementPreview { +internal fun TimelineViewWithReadMarkerNumericBadgePreview() = ElementPreview { TimelineViewWithReadMarker(unreadMessagesCount = 3, newMessagesCount = 0) } 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 cbe4b674cc..23a91fda00 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 @@ -163,6 +163,7 @@ class KonsistPreviewTest { "TimelineViewWithReadMarkerBothCountsPreview", "TimelineViewWithReadMarkerDotBadgesPreview", "TimelineViewWithReadMarkerNoBadgesPreview", + "TimelineViewWithReadMarkerNumericBadgePreview", "UserAvatarColorsPreview", "UserProfileHeaderSectionWithVerificationViolationPreview", "VoiceItemViewPlayPreview", From 200b98b72b2b8ae106dd246613a5369536780b58 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Fri, 1 May 2026 09:13:40 -0700 Subject: [PATCH 0320/1083] Consolidate JumpToUnreadState --- .../impl/timeline/TimelinePresenter.kt | 25 ++++---- .../messages/impl/timeline/TimelineState.kt | 5 +- .../impl/timeline/TimelineStateProvider.kt | 9 +-- .../messages/impl/timeline/TimelineView.kt | 29 ++++----- .../impl/timeline/model/JumpToUnreadState.kt | 32 ++++++++++ .../impl/timeline/TimelinePresenterTest.kt | 60 +++++++++++-------- 6 files changed, 94 insertions(+), 66 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt 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 dbb23b774e..6e0145f742 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 @@ -14,14 +14,12 @@ import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshots.Snapshot import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject @@ -32,6 +30,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.resolve.Reso import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactoryConfig +import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.isMessageContent @@ -282,11 +281,14 @@ class TimelinePresenter( // read marker advances in place — the SDK swaps the marker virtual item to a new position // without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the // bottom of the room. - val readMarkerIndex = remember { mutableIntStateOf(-1) } - val unreadMessagesCount = remember { mutableIntStateOf(0) } - LaunchedEffect(timelineItems) { + val jumpToUnreadState = remember { mutableStateOf(JumpToUnreadState.Disabled) } + LaunchedEffect(timelineItems, displayJumpToUnread) { + if (!displayJumpToUnread) { + jumpToUnreadState.value = JumpToUnreadState.Disabled + return@LaunchedEffect + } val items = timelineItems - withContext(dispatchers.computation) { + jumpToUnreadState.value = withContext(dispatchers.computation) { var markerIdx = -1 var unread = 0 for ((i, item) in items.withIndex()) { @@ -298,12 +300,7 @@ class TimelinePresenter( unread++ } } - // Apply both writes atomically so consumers never see a half-updated pair - // (e.g. a non-negative markerIdx with the previous unread count). - Snapshot.withMutableSnapshot { - readMarkerIndex.intValue = markerIdx - unreadMessagesCount.intValue = if (markerIdx < 0) 0 else unread - } + if (markerIdx < 0) JumpToUnreadState.NoMarker else JumpToUnreadState.Loaded(markerIdx, unread) } } @@ -356,9 +353,7 @@ class TimelinePresenter( resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, - displayJumpToUnread = displayJumpToUnread, - readMarkerIndex = readMarkerIndex.intValue, - unreadMessagesCount = unreadMessagesCount.intValue, + jumpToUnreadState = jumpToUnreadState.value, eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 12dd01d57a..6f48a8d9fc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -11,6 +11,7 @@ package io.element.android.features.messages.impl.timeline import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.components.MessageShieldData +import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.typing.TypingNotificationState @@ -35,9 +36,7 @@ data class TimelineState( val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val displayThreadSummaries: Boolean, val displayFloatingDateBadge: Boolean, - val displayJumpToUnread: Boolean, - val readMarkerIndex: Int, - val unreadMessagesCount: Int, + val jumpToUnreadState: JumpToUnreadState, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 7fc3386ca7..0ea48c3c35 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -12,6 +12,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.resolve.Reso import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData +import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.ReadReceiptData import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -57,9 +58,7 @@ fun aTimelineState( resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), displayThreadSummaries: Boolean = false, displayFloatingDateBadge: Boolean = false, - displayJumpToUnread: Boolean = true, - readMarkerIndex: Int = -1, - unreadMessagesCount: Int = 0, + jumpToUnreadState: JumpToUnreadState = JumpToUnreadState.NoMarker, newEventState: NewEventState = NewEventState.None, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { @@ -81,9 +80,7 @@ fun aTimelineState( resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, - displayJumpToUnread = displayJumpToUnread, - readMarkerIndex = readMarkerIndex, - unreadMessagesCount = unreadMessagesCount, + jumpToUnreadState = jumpToUnreadState, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 9a324afd2f..b93f9e950d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -65,6 +65,7 @@ import io.element.android.features.messages.impl.timeline.components.toText import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.aFakeTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.focus.FocusRequestStateView +import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent @@ -220,9 +221,7 @@ fun TimelineView( newEventState = state.newEventState, isLive = state.isLive, focusRequestState = state.focusRequestState, - readMarkerIndex = state.readMarkerIndex, - unreadMessagesCount = state.unreadMessagesCount, - displayJumpToUnread = state.displayJumpToUnread, + jumpToUnreadState = state.jumpToUnreadState, topInset = floatingDateTopOffset, onScrollFinishAt = ::onScrollFinishAt, onJumpToLive = ::onJumpToLive, @@ -307,9 +306,7 @@ private fun BoxScope.TimelineScrollHelper( forceJumpToBottomVisibility: Boolean, forceJumpToReadMarkerVisibility: Boolean, focusRequestState: FocusRequestState, - readMarkerIndex: Int, - unreadMessagesCount: Int, - displayJumpToUnread: Boolean, + jumpToUnreadState: JumpToUnreadState, topInset: Dp, onScrollFinishAt: (Int) -> Unit, onJumpToLive: () -> Unit, @@ -326,10 +323,10 @@ private fun BoxScope.TimelineScrollHelper( derivedStateOf { when { forceJumpToReadMarkerVisibility -> true - !displayJumpToUnread || readMarkerIndex < 0 -> false + jumpToUnreadState !is JumpToUnreadState.Loaded -> false else -> { val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false - readMarkerIndex > lastVisibleIndex + jumpToUnreadState.markerIndex > lastVisibleIndex } } } @@ -362,9 +359,9 @@ private fun BoxScope.TimelineScrollHelper( } fun jumpToReadMarker() { - if (readMarkerIndex < 0) return + val loaded = jumpToUnreadState as? JumpToUnreadState.Loaded ?: return coroutineScope.launch { - lazyListState.animateScrollToItemCenter(readMarkerIndex) + lazyListState.animateScrollToItemCenter(loaded.markerIndex) } } @@ -407,14 +404,15 @@ private fun BoxScope.TimelineScrollHelper( contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), isVisible = isJumpToBottomVisible, // Hide the badge entirely when the feature is off, regardless of the count value. - count = if (displayJumpToUnread) newEventState.messageCount else 0, + count = if (jumpToUnreadState is JumpToUnreadState.Disabled) 0 else newEventState.messageCount, modifier = Modifier .align(Alignment.BottomEnd) .padding(end = 24.dp, bottom = 12.dp), onClick = ::jumpToBottom, ) - val jumpToUnreadDescription = if (unreadMessagesCount > 0) { - pluralStringResource(CommonPlurals.a11y_jump_to_unread_messages_count, unreadMessagesCount, unreadMessagesCount) + val unreadCount = (jumpToUnreadState as? JumpToUnreadState.Loaded)?.unreadCount ?: 0 + val jumpToUnreadDescription = if (unreadCount > 0) { + pluralStringResource(CommonPlurals.a11y_jump_to_unread_messages_count, unreadCount, unreadCount) } else { stringResource(id = CommonStrings.a11y_jump_to_unread_messages) } @@ -422,7 +420,7 @@ private fun BoxScope.TimelineScrollHelper( icon = CompoundIcons.ChevronUp(), contentDescription = jumpToUnreadDescription, isVisible = isJumpToUnreadVisible, - count = unreadMessagesCount, + count = unreadCount, // Top padding includes [topInset] so the FAB sits below any pinned-events banner. modifier = Modifier .align(Alignment.TopEnd) @@ -563,8 +561,7 @@ private fun TimelineViewWithReadMarker( // Index points past the loaded items, mirroring the real-world state the FAB // represents: the user has scrolled past the read marker, so it's no longer in // view. The actual scroll target doesn't matter for a static preview. - readMarkerIndex = timelineItems.size, - unreadMessagesCount = unreadMessagesCount, + jumpToUnreadState = JumpToUnreadState.Loaded(markerIndex = timelineItems.size, unreadCount = unreadMessagesCount), newEventState = if (newMessagesCount > 0) NewEventState.FromOther(newMessagesCount) else NewEventState.None, ), timelineProtectionState = aTimelineProtectionState(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt new file mode 100644 index 0000000000..8154445015 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt @@ -0,0 +1,32 @@ +/* + * 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.features.messages.impl.timeline.model + +import androidx.compose.runtime.Immutable + +/** + * Drives the jump-to-unread FAB and the count badge on the scroll-to-bottom FAB. + * + * The two affordances share state because they're both gated on the same feature flag and both + * use counts derived from the same timeline scan. + */ +@Immutable +sealed interface JumpToUnreadState { + /** Feature flag is off — neither the FAB nor the new-message badge is shown. */ + data object Disabled : JumpToUnreadState + + /** Feature flag is on, but no read marker is present in the current timeline window. */ + data object NoMarker : JumpToUnreadState + + /** + * Feature flag is on and the read marker is loaded at [markerIndex]. The FAB shows when the + * marker is above the viewport; the badge displays [unreadCount] when greater than zero. + */ + data class Loaded(val markerIndex: Int, val unreadCount: Int) : JumpToUnreadState +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 502308cfe7..bec7895c63 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -16,6 +16,7 @@ import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactoryCreator import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.components.aCriticalShield +import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.typing.aTypingNotificationState @@ -27,6 +28,7 @@ import io.element.android.features.poll.api.actions.SendPollResponseAction import io.element.android.features.poll.test.actions.FakeEndPollAction import io.element.android.features.poll.test.actions.FakeSendPollResponseAction import io.element.android.features.roomcall.api.aStandByCallState +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -372,14 +374,15 @@ class TimelinePresenterTest { } @Test - fun `present - unreadMessagesCount counts message-content items between newest and read marker, excluding state events`() = runTest { + fun `present - jumpToUnreadState reports loaded marker and unread count, excluding state events`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter(timeline) + val presenter = createTimelinePresenter( + timeline = timeline, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) presenter.test { - val initialState = awaitFirstItem() - assertThat(initialState.readMarkerIndex).isEqualTo(-1) - assertThat(initialState.unreadMessagesCount).isEqualTo(0) + awaitFirstItem() // SDK delivers items oldest-first; the factory reverses so output index 0 is the newest. // After processing: [msg-newest, membership, msg-2, read-marker, msg-old] timelineItems.emit( @@ -391,20 +394,22 @@ class TimelinePresenterTest { MatrixTimelineItem.Event(UniqueId("msg-newest"), anEventTimelineItem(content = aMessageContent())), ) ) - consumeItemsUntilPredicate { it.readMarkerIndex >= 0 }.last().also { state -> + consumeItemsUntilPredicate { it.jumpToUnreadState is JumpToUnreadState.Loaded }.last().also { state -> // 2 message items above the marker; the membership state event is skipped. - assertThat(state.readMarkerIndex).isEqualTo(3) - assertThat(state.unreadMessagesCount).isEqualTo(2) + assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.Loaded(markerIndex = 3, unreadCount = 2)) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - unreadMessagesCount excludes own messages and PAGINATION-origin events`() = runTest { + fun `present - jumpToUnreadState count excludes own messages and PAGINATION-origin events`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter(timeline) + val presenter = createTimelinePresenter( + timeline = timeline, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) presenter.test { awaitFirstItem() // After processing (factory reverses): [other-newest, own-msg, paginated, read-marker, msg-old] @@ -420,33 +425,34 @@ class TimelinePresenterTest { MatrixTimelineItem.Event(UniqueId("other-newest"), anEventTimelineItem(content = aMessageContent())), ) ) - consumeItemsUntilPredicate { it.readMarkerIndex >= 0 }.last().also { state -> - assertThat(state.readMarkerIndex).isEqualTo(3) + consumeItemsUntilPredicate { it.jumpToUnreadState is JumpToUnreadState.Loaded }.last().also { state -> // Only `other-newest` counts: own-msg and paginated are filtered out. - assertThat(state.unreadMessagesCount).isEqualTo(1) + assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.Loaded(markerIndex = 3, unreadCount = 1)) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - readMarkerIndex is -1 when no read marker present`() = runTest { + fun `present - jumpToUnreadState is NoMarker when no read marker present`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter(timeline) + val presenter = createTimelinePresenter( + timeline = timeline, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) presenter.test { - val initialState = awaitFirstItem() - assertThat(initialState.readMarkerIndex).isEqualTo(-1) - assertThat(initialState.unreadMessagesCount).isEqualTo(0) + awaitFirstItem() timelineItems.emit( listOf( MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent())), MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent())), ) ) - consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> - assertThat(state.readMarkerIndex).isEqualTo(-1) - assertThat(state.unreadMessagesCount).isEqualTo(0) + consumeItemsUntilPredicate { + it.timelineItems.size == 2 && it.jumpToUnreadState == JumpToUnreadState.NoMarker + }.last().also { state -> + assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.NoMarker) } cancelAndIgnoreRemainingEvents() } @@ -614,18 +620,20 @@ class TimelinePresenterTest { } @Test - fun `present - readMarkerIndex is 0 when the read marker is the only item`() = runTest { + fun `present - jumpToUnreadState markerIndex is 0 when the read marker is the only item`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter(timeline) + val presenter = createTimelinePresenter( + timeline = timeline, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) presenter.test { awaitFirstItem() timelineItems.emit( listOf(MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker)) ) - consumeItemsUntilPredicate { it.readMarkerIndex >= 0 }.last().also { state -> - assertThat(state.readMarkerIndex).isEqualTo(0) - assertThat(state.unreadMessagesCount).isEqualTo(0) + consumeItemsUntilPredicate { it.jumpToUnreadState is JumpToUnreadState.Loaded }.last().also { state -> + assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.Loaded(markerIndex = 0, unreadCount = 0)) } cancelAndIgnoreRemainingEvents() } From 715402d1788ef0f6ff7c2546a7cc4008b00e5c4d Mon Sep 17 00:00:00 2001 From: Strac Consulting Engineers Pty Ltd Date: Sat, 2 May 2026 09:40:23 +1000 Subject: [PATCH 0321/1083] Update AppDeveloperSettingsView.kt Fix 2 x Crash the app Fixes #6707 --- .../developer/appsettings/AppDeveloperSettingsView.kt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt index 71051cf829..f60eb2ac85 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt @@ -87,14 +87,7 @@ fun AppDeveloperSettingsView( onClick = onOpenShowkase ) } - PreferenceCategory(title = "Crash") { - ListItem( - headlineContent = { - Text("Crash the app 💥") - }, - onClick = { error("This crash is a test.") } - ) - } + RageshakePreferencesView( state = state.rageshakeState, ) From 0d2f71643aca180a7544de8c4958e5ff2ada6d62 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 4 May 2026 00:54:27 +0000 Subject: [PATCH 0322/1083] Sync Strings from Localazy --- .../src/main/res/values-ja/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-da/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 3 +- .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-da/translations.xml | 5 +- .../src/main/res/values-de/translations.xml | 6 +- .../src/main/res/values-fr/translations.xml | 6 +- .../src/main/res/values-hr/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 6 +- .../src/main/res/values-ja/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-da/translations.xml | 4 + .../src/main/res/values-hr/translations.xml | 4 + .../src/main/res/values-hu/translations.xml | 4 + .../src/main/res/values-be/translations.xml | 3 + .../src/main/res/values-cs/translations.xml | 3 + .../src/main/res/values-cy/translations.xml | 3 + .../src/main/res/values-da/translations.xml | 3 + .../src/main/res/values-de/translations.xml | 3 + .../src/main/res/values-el/translations.xml | 3 + .../src/main/res/values-es/translations.xml | 3 + .../src/main/res/values-et/translations.xml | 3 + .../src/main/res/values-eu/translations.xml | 3 + .../src/main/res/values-fa/translations.xml | 3 + .../src/main/res/values-fi/translations.xml | 3 + .../src/main/res/values-fr/translations.xml | 3 + .../src/main/res/values-hr/translations.xml | 3 + .../src/main/res/values-hu/translations.xml | 3 + .../src/main/res/values-in/translations.xml | 3 + .../src/main/res/values-it/translations.xml | 3 + .../src/main/res/values-ja/translations.xml | 5 +- .../src/main/res/values-ko/translations.xml | 3 + .../src/main/res/values-nb/translations.xml | 3 + .../src/main/res/values-nl/translations.xml | 3 + .../src/main/res/values-pl/translations.xml | 3 + .../main/res/values-pt-rBR/translations.xml | 3 + .../src/main/res/values-pt/translations.xml | 3 + .../src/main/res/values-ro/translations.xml | 3 + .../src/main/res/values-ru/translations.xml | 3 + .../src/main/res/values-sk/translations.xml | 3 + .../src/main/res/values-sv/translations.xml | 3 + .../src/main/res/values-tr/translations.xml | 3 + .../src/main/res/values-uk/translations.xml | 3 + .../src/main/res/values-ur/translations.xml | 3 + .../src/main/res/values-uz/translations.xml | 3 + .../main/res/values-zh-rTW/translations.xml | 3 + .../src/main/res/values-zh/translations.xml | 3 + .../src/main/res/values-da/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-in/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-be/translations.xml | 2 +- .../src/main/res/values-bg/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 2 +- .../src/main/res/values-cy/translations.xml | 2 +- .../src/main/res/values-da/translations.xml | 12 +- .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-el/translations.xml | 2 +- .../src/main/res/values-es/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-eu/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 4 +- .../src/main/res/values-fi/translations.xml | 2 +- .../src/main/res/values-fr/translations.xml | 4 +- .../src/main/res/values-hr/translations.xml | 2 +- .../src/main/res/values-hu/translations.xml | 4 +- .../src/main/res/values-in/translations.xml | 2 +- .../src/main/res/values-it/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 30 +- .../src/main/res/values-ka/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 2 +- .../src/main/res/values-lt/translations.xml | 2 +- .../src/main/res/values-nb/translations.xml | 2 +- .../src/main/res/values-nl/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 2 +- .../main/res/values-pt-rBR/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 4 +- .../src/main/res/values-ro/translations.xml | 2 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-sv/translations.xml | 2 +- .../src/main/res/values-tr/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 2 +- .../src/main/res/values-ur/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 2 +- .../main/res/values-zh-rTW/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 8 +- .../impl/src/main/res/values/localazy.xml | 2 +- .../src/main/res/values-de/translations.xml | 10 +- .../src/main/res/values-fa/translations.xml | 10 +- .../src/main/res/values-in/translations.xml | 10 +- .../src/main/res/values-pt/translations.xml | 26 +- .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-da/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-in/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 8 + .../src/main/res/values-hr/translations.xml | 9 + .../src/main/res/values-hu/translations.xml | 8 + .../src/main/res/values-ja/translations.xml | 10 +- .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 8 +- .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 12 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 14 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-da/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 6 +- .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-in/translations.xml | 2 +- .../src/main/res/values-pt/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 6 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 2 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-da/translations.xml | 1 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-hr/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-da/translations.xml | 28 +- .../src/main/res/values-de/translations.xml | 7 +- .../src/main/res/values-fa/translations.xml | 4 +- .../src/main/res/values-fr/translations.xml | 5 + .../src/main/res/values-hr/translations.xml | 15 + .../src/main/res/values-hu/translations.xml | 7 + .../src/main/res/values-in/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 8 +- .../src/main/res/values-pt/translations.xml | 8 +- .../src/main/res/values-zh/translations.xml | 28 +- .../src/main/res/values/localazy.xml | 1 + ...nfigureroom_ConfigureRoomViewDark_7_de.png | 4 +- ...figureroom_ConfigureRoomViewLight_7_de.png | 4 +- ..._SelectParentSpaceBottomSheet_Day_0_de.png | 4 +- ...hooseSelfVerificationModeView_Day_0_de.png | 4 +- ...hooseSelfVerificationModeView_Day_1_de.png | 4 +- ...hooseSelfVerificationModeView_Day_2_de.png | 4 +- ...hooseSelfVerificationModeView_Day_3_de.png | 4 +- ...hooseSelfVerificationModeView_Day_4_de.png | 4 +- ....roomlist_RoomListContextMenu_Day_0_de.png | 3 + ....roomlist_RoomListContextMenu_Day_1_de.png | 3 + ....roomlist_RoomListContextMenu_Day_2_de.png | 3 + ...mListDeclineInviteMenuContent_Day_0_de.png | 3 - ...ist_RoomListDeclineInviteMenu_Day_0_de.png | 3 + ...ist_RoomListDeclineInviteMenu_Day_1_de.png | 3 + ...ist_RoomListDeclineInviteMenu_Day_2_de.png | 3 + ...omListModalBottomSheetContent_Day_0_de.png | 3 - ...omListModalBottomSheetContent_Day_1_de.png | 3 - ...omListModalBottomSheetContent_Day_2_de.png | 3 - ...irmation_CodeConfirmationView_Day_0_de.png | 3 + ....impl.screens.error_ErrorView_Day_2_de.png | 4 +- ....impl.screens.error_ErrorView_Day_3_de.png | 4 +- ....impl.screens.error_ErrorView_Day_4_de.png | 4 +- ....impl.screens.error_ErrorView_Day_8_de.png | 3 + ...ns.root_LinkNewDeviceRootView_Day_0_de.png | 4 +- ...ns.root_LinkNewDeviceRootView_Day_1_de.png | 4 +- ...ns.root_LinkNewDeviceRootView_Day_2_de.png | 4 +- ...ns.root_LinkNewDeviceRootView_Day_3_de.png | 4 +- ...ns.root_LinkNewDeviceRootView_Day_4_de.png | 4 +- ...ns.root_LinkNewDeviceRootView_Day_5_de.png | 4 +- ....impl.share_ShareLocationView_Day_3_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_5_de.png | 4 +- ...changeserver_ChangeServerView_Day_5_de.png | 4 +- ...ogin.impl.login_LoginModeView_Day_5_de.png | 4 +- ...mation_QrCodeConfirmationView_Day_0_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_2_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_3_de.png | 4 +- ....qrcode.error_QrCodeErrorView_Day_5_de.png | 4 +- ....qrcode.intro_QrCodeIntroView_Day_0_de.png | 4 +- ....impl_AccountDeactivationView_Day_0_de.png | 4 +- ....impl_AccountDeactivationView_Day_1_de.png | 4 +- ....impl_AccountDeactivationView_Day_2_de.png | 4 +- ....impl_AccountDeactivationView_Day_3_de.png | 4 +- ....impl_AccountDeactivationView_Day_4_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_1_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_3_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_7_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_8_de.png | 4 +- ...atures.logout.impl_LogoutView_Day_9_de.png | 4 +- ...ent_TimelineItemEncryptedView_Day_6_de.png | 4 +- ...sable_SecureBackupDisableView_Day_0_de.png | 4 +- ...sable_SecureBackupDisableView_Day_1_de.png | 4 +- ...sable_SecureBackupDisableView_Day_2_de.png | 4 +- ...sable_SecureBackupDisableView_Day_3_de.png | 4 +- ...ureBackupEnterRecoveryKeyView_Day_0_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_0_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_10_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_11_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_12_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_13_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_14_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_15_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_16_de.png | 4 +- ...pl.root_SecureBackupRootView_Day_17_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_1_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_2_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_3_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_4_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_5_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_6_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_7_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_8_de.png | 4 +- ...mpl.root_SecureBackupRootView_Day_9_de.png | 4 +- ...p_SecureBackupSetupViewChange_Day_0_de.png | 4 +- ...p_SecureBackupSetupViewChange_Day_1_de.png | 4 +- ...p_SecureBackupSetupViewChange_Day_5_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_0_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_1_de.png | 4 +- ...l.setup_SecureBackupSetupView_Day_5_de.png | 4 +- ...ing_IncomingVerificationView_Day_11_de.png | 4 +- ...ming_IncomingVerificationView_Day_2_de.png | 4 +- ...ming_IncomingVerificationView_Day_4_de.png | 4 +- ...ing_OutgoingVerificationView_Day_11_de.png | 4 +- screenshots/html/data.js | 2112 +++++++++-------- ...changeserver_ChangeServerView_Day_5_en.png | 4 +- ...angeserver_ChangeServerView_Night_5_en.png | 4 +- ...ogin.impl.login_LoginModeView_Day_5_en.png | 4 +- ...in.impl.login_LoginModeView_Night_5_en.png | 4 +- 245 files changed, 1664 insertions(+), 1442 deletions(-) create mode 100644 screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png create mode 100644 screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png create mode 100644 screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png delete mode 100644 screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_de.png create mode 100644 screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_de.png create mode 100644 screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_de.png create mode 100644 screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_de.png delete mode 100644 screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_de.png delete mode 100644 screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_de.png delete mode 100644 screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_de.png create mode 100644 screenshots/de/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_de.png create mode 100644 screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_8_de.png diff --git a/features/analytics/api/src/main/res/values-ja/translations.xml b/features/analytics/api/src/main/res/values-ja/translations.xml index 5554ee162f..e1495271d3 100644 --- a/features/analytics/api/src/main/res/values-ja/translations.xml +++ b/features/analytics/api/src/main/res/values-ja/translations.xml @@ -1,7 +1,7 @@ - "問題発見のため、匿名の使用データの共有にご協力ください。" - "利用規約の全文を%1$sから確認することができます。" + "改善のため、匿名の使用データの共有にご協力ください。" + "規約の全文は%1$sから確認することができます。" "こちら" "使用データを共有" diff --git a/features/analytics/api/src/main/res/values-zh/translations.xml b/features/analytics/api/src/main/res/values-zh/translations.xml index e8f0fcb434..8f1c1699d9 100644 --- a/features/analytics/api/src/main/res/values-zh/translations.xml +++ b/features/analytics/api/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ "共享匿名使用数据以帮助我们排查问题。" - "你可以阅读我们的所有条款 %1$s。" + "你可以点击 %1$s 阅读我们的所有条款。" "此处" "共享分析数据" diff --git a/features/analytics/impl/src/main/res/values-ja/translations.xml b/features/analytics/impl/src/main/res/values-ja/translations.xml index 2cee69962c..162e01ecb0 100644 --- a/features/analytics/impl/src/main/res/values-ja/translations.xml +++ b/features/analytics/impl/src/main/res/values-ja/translations.xml @@ -1,8 +1,8 @@ "いかなる個人情報も記録, 分析されることはありません" - "問題発見のため、匿名の使用データの共有にご協力ください。" - "利用規約の全文を%1$sから確認することができます。" + "改善のため、匿名の使用データの共有にご協力ください。" + "規約の全文は%1$sから確認することができます。" "こちら" "いつでも設定は変更できます" "情報が第三者に共有されることはありません" diff --git a/features/analytics/impl/src/main/res/values-zh/translations.xml b/features/analytics/impl/src/main/res/values-zh/translations.xml index 8393e45e81..678d506287 100644 --- a/features/analytics/impl/src/main/res/values-zh/translations.xml +++ b/features/analytics/impl/src/main/res/values-zh/translations.xml @@ -2,7 +2,7 @@ "我们不会记录或分析任何个人数据" "共享匿名使用数据以帮助我们排查问题。" - "你可以阅读我们的所有条款 %1$s。" + "你可以点击 %1$s 阅读我们的所有条款。" "此处" "可以随时关闭此功能" "我们不会与第三方共享你的数据" diff --git a/features/createroom/impl/src/main/res/values-da/translations.xml b/features/createroom/impl/src/main/res/values-da/translations.xml index 66c4f08b70..ab72755dcf 100644 --- a/features/createroom/impl/src/main/res/values-da/translations.xml +++ b/features/createroom/impl/src/main/res/values-da/translations.xml @@ -19,7 +19,7 @@ Du kan ændre dette når som helst i rummets indstillinger." "Anmod om at deltage" "Kun inviterede brugere kan deltage." "Privat" - "Alle kan deltage i dette rum" + "Alle kan deltage." "Offentlig" "Alle i %1$s kan deltage." "Standard" 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 4408bf66a3..c3f42ca287 100644 --- a/features/createroom/impl/src/main/res/values-de/translations.xml +++ b/features/createroom/impl/src/main/res/values-de/translations.xml @@ -28,7 +28,8 @@ Du kannst dies jederzeit in den Einstellungen des Chats ändern." "Adresse" " Sichtbarkeit des Chats" "(kein Space)" - "Home" + "Nicht zu einem Space hinzufügen" + "Kein Space ausgewählt" "Space hinzufügen" "Thema (optional)" "Beschreibung hinzufügen…" diff --git a/features/createroom/impl/src/main/res/values-fa/translations.xml b/features/createroom/impl/src/main/res/values-fa/translations.xml index 27542ccc19..821d55af67 100644 --- a/features/createroom/impl/src/main/res/values-fa/translations.xml +++ b/features/createroom/impl/src/main/res/values-fa/translations.xml @@ -3,7 +3,7 @@ "اتاق جدید" "دعوت افراد" "هنگام ایجاد اتاق خطایی رخ داد" - "تنها افراد دعوت شده می‌توانند به این اتاق دسترسی داشته باشند. همهٔ پیام‌ها رمزنگاری سرتاسری شده‌اند." + "تنها افراد دعوت شده می‌توانند بپیوندند." "هرکسی می‌تواند اتاق را بیابد. می‌توانید بعداً در تظیمات اتاق عوضش کنید." "درخواست دعوت" diff --git a/features/createroom/impl/src/main/res/values-zh/translations.xml b/features/createroom/impl/src/main/res/values-zh/translations.xml index 8d898fe5f0..1ba1036634 100644 --- a/features/createroom/impl/src/main/res/values-zh/translations.xml +++ b/features/createroom/impl/src/main/res/values-zh/translations.xml @@ -1,13 +1,13 @@ "新房间" - "邀请朋友" + "邀请人员" "创建房间时出错" "由于未知错误,空间创建失败。请稍后再试。" "添加名称…" "新房间" "新空间" - "仅限受邀者加入。" + "仅限受邀人员加入。" "私密" "任何人都能找到此房间。 你可以随时在房间设置中更改。" @@ -17,11 +17,11 @@ "申请加入" "%1$s 中的任何人都可以加入,但其他人必须申请访问。" "申请加入" - "仅限受邀者加入。" + "仅限受邀人员加入。" "私密" "任何人都可以加入。" "公共" - "%1$s 中的任何人可加入。" + "%1$s 中的任何人都可以加入。" "标准" "谁有权访问此房间" "要使该房间在公共目录中可见,你需要一个地址。" diff --git a/features/deactivation/impl/src/main/res/values-da/translations.xml b/features/deactivation/impl/src/main/res/values-da/translations.xml index dfbf00a1c6..f434547b8a 100644 --- a/features/deactivation/impl/src/main/res/values-da/translations.xml +++ b/features/deactivation/impl/src/main/res/values-da/translations.xml @@ -1,13 +1,14 @@ - "Bekræft venligst, at du vil deaktivere din konto. Denne handling kan ikke fortrydes." + "Bekræft venligst, at du ønsker at slette din konto. Denne handling kan ikke fortrydes." "Slet alle mine beskeder" "Advarsel: Fremtidige brugere kan muligvis se ufuldstændige samtaler." - "Deaktivering af din konto er %1$s, det vil:" + "Sletning af din konto er %1$s, det vil:" "irreversibel" "%1$s din konto (du kan ikke logge ind igen, og dit ID kan ikke genbruges)." "Permanent deaktivere" "Fjerne dig fra alle samtaler" "Slette dine kontooplysninger fra vores identitetsserver." "Dine beskeder vil stadig være synlige for registrerede brugere, men vil ikke være tilgængelige for nye eller uregistrerede brugere, hvis du vælger at slette dem." + "Slet konto" diff --git a/features/deactivation/impl/src/main/res/values-de/translations.xml b/features/deactivation/impl/src/main/res/values-de/translations.xml index e03d53bbce..8430134d00 100644 --- a/features/deactivation/impl/src/main/res/values-de/translations.xml +++ b/features/deactivation/impl/src/main/res/values-de/translations.xml @@ -1,14 +1,14 @@ - "Bitte bestätige, dass du dein Konto deaktivieren möchtest. Dies kann nicht rückgängig gemacht werden." + "Bitte bestätige, dass du dein Konto löschen möchtest. Diese Aktion kann nicht rückgängig gemacht werden." "Lösche alle meine Nachrichten" "Warnung: Künftigen Nutzern werden möglicherweise unvollständige Konversationen angezeigt." - "Dein Konto zu deaktivieren ist %1$s. Folgendes wird passieren:" + "Das Löschen deines Kontos ist %1$s. Es wird:" "irreversibel" "%1$s dein Konto (du kannst dich nicht erneut anmelden und deine ID kann nicht wiederverwendet werden)." "Dauerhaft deaktivieren" "Du wirst aus allen Chats entfernt." "Lösche deine Kontoinformationen von unserem Identitätsserver." "Deine Nachrichten werden für bereits registrierte Nutzer weiterhin sichtbar sein. Für neue oder unregistrierte Nutzer sind sie nicht verfügbar, wenn du sie löschen solltest." - "Benutzerkonto deaktivieren" + "Konto löschen" diff --git a/features/deactivation/impl/src/main/res/values-fr/translations.xml b/features/deactivation/impl/src/main/res/values-fr/translations.xml index 875142bc01..cf69cb3275 100644 --- a/features/deactivation/impl/src/main/res/values-fr/translations.xml +++ b/features/deactivation/impl/src/main/res/values-fr/translations.xml @@ -1,14 +1,14 @@ - "Veuillez confirmer que vous souhaitez désactiver votre compte. Cette action ne peut pas être annulée." + "Veuillez confirmer que vous souhaitez supprimer votre compte. Cette action ne peut pas être annulée." "Supprimer tous mes messages" "Attention : les futurs utilisateurs pourraient voir des conversations incomplètes." - "La désactivation de votre compte est %1$s, cela va :" + "La suppression de votre compte est %1$s, cela va :" "irréversible" "%1$s votre compte (vous ne pourrez plus vous reconnecter et votre identifiant ne pourra pas être réutilisé)." "Désactiver définitivement" "Vous retirer de tous les salons et toutes les discussions." "Supprimer les informations de votre compte du serveur d’identité." "Rendre vos messages invisibles aux futurs membres des salons si vous choisissez de les supprimer. Vos messages seront toujours visibles pour les utilisateurs qui les ont déjà récupérés." - "Désactiver votre compte" + "Supprimer le compte" diff --git a/features/deactivation/impl/src/main/res/values-hr/translations.xml b/features/deactivation/impl/src/main/res/values-hr/translations.xml index 9273254886..1d8a02a08c 100644 --- a/features/deactivation/impl/src/main/res/values-hr/translations.xml +++ b/features/deactivation/impl/src/main/res/values-hr/translations.xml @@ -10,4 +10,5 @@ "Ukloniti vas iz svih soba za razgovore." "Izbrisati podatke o vašem računu s našeg poslužitelja identiteta." "Vaše će poruke i dalje biti vidljive registriranim korisnicima, ali neće biti dostupne novim ili neregistriranim korisnicima ako ih odlučite izbrisati." + "Izbriši račun" diff --git a/features/deactivation/impl/src/main/res/values-hu/translations.xml b/features/deactivation/impl/src/main/res/values-hu/translations.xml index 3d3722b8ef..2c3f51ed7a 100644 --- a/features/deactivation/impl/src/main/res/values-hu/translations.xml +++ b/features/deactivation/impl/src/main/res/values-hu/translations.xml @@ -1,14 +1,14 @@ - "Erősítse meg, hogy deaktiválja a fiókját. Ez a művelet nem vonható vissza." + "Erősítse meg a fiókja törlését. Ez a művelet nem vonható vissza." "Összes saját üzenet törlése" "Figyelmeztetés: A jövőbeli felhasználók hiányos beszélgetéseket láthatnak." - "A fiók deaktiválása %1$s, a következőket okozza:" + "Fiókjának törlése: %1$s, ez a következőket eredményezi:" "visszafordíthatatlan" "%1$s a fiókját (nem fog tudni újra bejelentkezni, és az azonosítója nem használható újra)." "Véglegesen letiltja" "Eltávolításra kerül az összes csevegőszobából." "Törlésre kerülnek a fiókadatai az azonosítási kiszolgálónkról." "Üzenetei továbbra is láthatóak maradnak a regisztrált felhasználók számára, de nem lesznek elérhetőek az új vagy nem regisztrált felhasználók számára, ha úgy dönt, hogy törli őket." - "Fiók deaktiválása" + "Fiók törlése" diff --git a/features/deactivation/impl/src/main/res/values-ja/translations.xml b/features/deactivation/impl/src/main/res/values-ja/translations.xml index f41dd1d282..53893a594f 100644 --- a/features/deactivation/impl/src/main/res/values-ja/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ja/translations.xml @@ -1,9 +1,9 @@ - "アカウントを無効化することを再度確認します。この操作は元に戻せません。" + "アカウントを削除しようとしていることを確認しています。この操作は元に戻せません。" "メッセージをすべて削除" "注意: 新しいユーザーには断片的な会話が表示されます" - "アカウントを無効化することは %1$s であり、次の変化が生じます:" + "アカウントを削除することは %1$s であり、次の変化が生じます:" "不可逆" "アカウントを %1$s (再度ログイン不可, 同一のIDを再利用不可)" "恒久的に無効化する" 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 241f73516e..0e83b29e35 100644 --- a/features/ftue/impl/src/main/res/values-de/translations.xml +++ b/features/ftue/impl/src/main/res/values-de/translations.xml @@ -3,7 +3,7 @@ "Bestätigung unmöglich?" "Erstelle einen neuen Wiederherstellungsschlüssel" "Wähle eine Verifizierungsmethode, um den sicheren Nachrichtenversand einzurichten." - "Bestätige deine Identität" + "Bestätige deine digitale Identität" "Ein anderes Gerät verwenden" "Wiederherstellungsschlüssel verwenden" "Du kannst jetzt verschlüsselte Nachrichten lesen und versenden. Dein Chatpartner vertraut nun diesem Gerät." diff --git a/features/ftue/impl/src/main/res/values-ja/translations.xml b/features/ftue/impl/src/main/res/values-ja/translations.xml index 68b69079ef..9a87a3dcfa 100644 --- a/features/ftue/impl/src/main/res/values-ja/translations.xml +++ b/features/ftue/impl/src/main/res/values-ja/translations.xml @@ -11,5 +11,5 @@ "他の端末を使用" "一方の端末を待機中…" "設定は後で変更することができます。" - "メッセージを見逃さないため通知を許可" + "メッセージを見逃さないために通知を許可しましょう" diff --git a/features/ftue/impl/src/main/res/values-pt/translations.xml b/features/ftue/impl/src/main/res/values-pt/translations.xml index 5b6729f04e..34f39c7bdb 100644 --- a/features/ftue/impl/src/main/res/values-pt/translations.xml +++ b/features/ftue/impl/src/main/res/values-pt/translations.xml @@ -3,7 +3,7 @@ "Não é possível confirmar?" "Criar uma nova chave de recuperação" "Verifica este dispositivo para configurar o envio seguro de mensagens." - "Confirma que és tu" + "Confirma a tua identidade digital" "Utilizar outro dispositivo" "Utilizar chave de recuperação" "Agora podes ler ou enviar mensagens de forma segura, e qualquer pessoa com quem converses também pode confiar neste dispositivo." diff --git a/features/ftue/impl/src/main/res/values-zh/translations.xml b/features/ftue/impl/src/main/res/values-zh/translations.xml index c111aecaa9..f9171c9879 100644 --- a/features/ftue/impl/src/main/res/values-zh/translations.xml +++ b/features/ftue/impl/src/main/res/values-zh/translations.xml @@ -9,7 +9,7 @@ "现在你可以安全地读取或发送消息,并且与你聊天的任何人也可以信任此设备。" "设备已验证" "使用其它设备" - "正在等待其它设备……" + "正在等待其它设备…" "你可以稍后更改设置。" "允许通知,绝不错过任何消息" diff --git a/features/home/impl/src/main/res/values-pt/translations.xml b/features/home/impl/src/main/res/values-pt/translations.xml index 9870014904..6c6a72930e 100644 --- a/features/home/impl/src/main/res/values-pt/translations.xml +++ b/features/home/impl/src/main/res/values-pt/translations.xml @@ -6,7 +6,7 @@ "O toque de notificação foi atualizado — mais claro, mais rápido e menos perturbador." "Atualizámos os seus sons" "Recupera a tua identidade criptográfica e o histórico de mensagens com uma chave de recuperação se tiveres perdido todos os teus dispositivos existentes." - "Configurar recuperação" + "Chave de recuperação" "Configurar a recuperação" "Confirma a tua chave de recuperação para manteres o acesso ao teu armazenamento de chaves e ao histórico de mensagens." "Introduz a tua chave de recuperação" 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 4bc15b08cf..39900a6f0b 100644 --- a/features/home/impl/src/main/res/values-zh/translations.xml +++ b/features/home/impl/src/main/res/values-zh/translations.xml @@ -21,14 +21,14 @@ "你确定要拒绝与 %1$s 私聊?" "拒绝聊天" "没有邀请" - "%1$s (%2$s)邀请了你" + "%1$s(%2$s)邀请了你" "此为一次性流程,感谢等待。" "设置账户。" "创建新的对话或房间" "清除筛选条件" "通过向某人发送消息来开始。" "暂无聊天。" - "收藏夹" + "收藏" "可以在聊天设置里将聊天添加到收藏夹。 现在可以取消选择筛选器以查看其它对话。" "你尚未收藏任何聊天" @@ -38,7 +38,7 @@ "你暂无任何低优先级聊天" "你可以取消选择筛选器以查看其它对话" "你暂无适用于此选项的聊天" - "用户" + "人员" "你暂无任何私聊" "房间" "你尚未进入任何房间" diff --git a/features/invite/impl/src/main/res/values-zh/translations.xml b/features/invite/impl/src/main/res/values-zh/translations.xml index 61e7f15f59..02825bca6d 100644 --- a/features/invite/impl/src/main/res/values-zh/translations.xml +++ b/features/invite/impl/src/main/res/values-zh/translations.xml @@ -10,7 +10,7 @@ "你确定要拒绝与 %1$s 私聊?" "拒绝聊天" "没有邀请" - "%1$s (%2$s)邀请了你" + "%1$s(%2$s)邀请了你" "是,拒绝并屏蔽" "你确定要拒绝此房间的加入邀请?这也将阻止 %1$s 与你联系或邀请你加入房间。" "拒绝邀请并屏蔽" diff --git a/features/invitepeople/impl/src/main/res/values-da/translations.xml b/features/invitepeople/impl/src/main/res/values-da/translations.xml index fbb1814e9f..1754ef6e0d 100644 --- a/features/invitepeople/impl/src/main/res/values-da/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-da/translations.xml @@ -2,4 +2,8 @@ "Allerede medlem" "Allerede inviteret" + "Du har i øjeblikket ingen chats med disse kontakter. Bekræft deres invitation til dette rum, før du fortsætter." + "Du har i øjeblikket ingen chats med denne kontakt. Bekræft deres invitation til dette rum, før du fortsætter." + "Inviter nye kontakter til dette rum?" + "Inviter ny kontakt til dette rum?" diff --git a/features/invitepeople/impl/src/main/res/values-hr/translations.xml b/features/invitepeople/impl/src/main/res/values-hr/translations.xml index 66031c5fd7..471b79d709 100644 --- a/features/invitepeople/impl/src/main/res/values-hr/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-hr/translations.xml @@ -2,4 +2,8 @@ "Već je član" "Već je pozvan/a" + "Trenutno nemate razgovora s ovim kontaktima. Potvrdite da ih želite pozvati u ovu sobu prije nego što nastavite." + "Trenutno nemate razgovora s ovim kontaktom. Potvrdite da ste ga pozvali u ovu sobu prije nego što nastavite." + "Pozvati nove kontakte u ovu sobu?" + "Pozvati novi kontakt u ovu sobu?" diff --git a/features/invitepeople/impl/src/main/res/values-hu/translations.xml b/features/invitepeople/impl/src/main/res/values-hu/translations.xml index 16f35b018c..de2cab0d73 100644 --- a/features/invitepeople/impl/src/main/res/values-hu/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-hu/translations.xml @@ -2,4 +2,8 @@ "Már tag" "Már meghívták" + "Jelenleg nincsenek csevegései ezekkel a kapcsolatokkal. Mielőtt továbbmenne, erősítse meg, hogy meghívja őket ebbe a szobába." + "Jelenleg nincsenek beszélgetései ezzel a személlyel. A folytatás előtt erősítse meg, hogy meghívja ebbe a szobába." + "Új személyeket hív meg ebbe a szobába?" + "Új személyt hív meg ebbe a szobába?" diff --git a/features/linknewdevice/impl/src/main/res/values-be/translations.xml b/features/linknewdevice/impl/src/main/res/values-be/translations.xml index 16372fa6e4..378a405c95 100644 --- a/features/linknewdevice/impl/src/main/res/values-be/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-be/translations.xml @@ -17,6 +17,8 @@ "Калі вы сутыкнуліся з той жа праблемай, паспрабуйце іншую сетку Wi-Fi або скарыстайцеся мабільнымі дадзенымі замест Wi-Fi." "Калі гэта не дапамагло, увайдзіце ўручную" "Злучэнне небяспечнае" + "Вам будзе прапанавана ўвесці дзве лічбы, паказаныя на гэтай прыладзе." + "Увядзіце наступны нумар на іншай прыладзе." "Уваход быў адменены на іншай прыладзе." "Запыт на ўваход скасаваны" "Уваход на іншай прыладзе быў адхілены." @@ -35,4 +37,5 @@ "Каб працягнуць, вам неабходна дазволіць %1$s выкарыстоўваць камеру вашай прылады." "Дазвольце доступ да камеры для сканіравання QR-кода" "Адбылася нечаканая памылка. Калі ласка, паспрабуйце яшчэ раз." + "У чаканні іншай прылады" diff --git a/features/linknewdevice/impl/src/main/res/values-cs/translations.xml b/features/linknewdevice/impl/src/main/res/values-cs/translations.xml index 4b8f230d55..e0150668a3 100644 --- a/features/linknewdevice/impl/src/main/res/values-cs/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-cs/translations.xml @@ -34,6 +34,8 @@ "Pokud narazíte na stejný problém, zkuste jinou síť wifi nebo použijte mobilní data místo wifi" "Pokud to nefunguje, přihlaste se ručně" "Připojení není zabezpečené" + "Budete požádáni o zadání dvou níže uvedených číslic." + "Zadejte níže uvedené číslo na svém dalším zařízení" "Přihlášení bylo na druhém zařízení zrušeno." "Žádost o přihlášení zrušena" "Přihlášení bylo na druhém zařízení odmítnuto." @@ -54,4 +56,5 @@ Zkuste se přihlásit ručně nebo naskenujte QR kód pomocí jiného zařízen "Abyste mohli pokračovat, musíte aplikaci %1$s udělit povolení k použití kamery vašeho zařízení." "Povolte přístup k fotoaparátu a naskenujte QR kód" "Vyskytla se neočekávaná chyba. Prosím zkuste to znovu." + "Čekání na vaše další zařízení" diff --git a/features/linknewdevice/impl/src/main/res/values-cy/translations.xml b/features/linknewdevice/impl/src/main/res/values-cy/translations.xml index b26aed52ef..6b1cb7781f 100644 --- a/features/linknewdevice/impl/src/main/res/values-cy/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-cy/translations.xml @@ -17,6 +17,8 @@ "Os ydych chi\'n dod ar draws yr un broblem, rhowch gynnig ar rwydwaith wifi gwahanol neu defnyddiwch eich data symudol yn lle wifi" "Os nad yw hynny\'n gweithio, mewngofnodwch â llaw" "Nid yw\'r cysylltiad yn ddiogel" + "Bydd gofyn i chi nodi\'r ddau ddigid sy\'n cael eu dangos ar y ddyfais hon." + "Rhowch y rhif isod ar eich dyfais arall" "Cafodd y mewngofnodi ei ddiddymu ar y ddyfais arall." "Cais mewngofnodi wedi\'i ddiddymu" "Cafodd y mewngofnodi ar y ddyfais arall ei wrthod." @@ -35,4 +37,5 @@ Ceisiwch fewngofnodi â llaw, neu sganiwch y cod QR gyda dyfais arall." "Mae angen i chi roi caniatâd i %1$s ddefnyddio camera eich dyfais er mwyn parhau." "Caniatáu mynediad camera i sganio\'r cod QR" "Digwyddodd gwall annisgwyl. Ceisiwch eto." + "Yn aros am eich dyfais arall" diff --git a/features/linknewdevice/impl/src/main/res/values-da/translations.xml b/features/linknewdevice/impl/src/main/res/values-da/translations.xml index 5bc9f04fb9..45f510e90b 100644 --- a/features/linknewdevice/impl/src/main/res/values-da/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-da/translations.xml @@ -34,6 +34,8 @@ "Hvis du støder på det samme problem, kan du prøve et andet wifi-netværk eller bruge dine mobildata i stedet for wifi" "Hvis det ikke virker, skal du logge ind manuelt" "Forbindelsen er ikke sikker" + "Du bliver bedt om at indtaste de to cifre, der vises på denne enhed." + "Indtast nummeret herunder på din anden enhed" "Login blev annulleret på den anden enhed." "Anmodning om login annulleret" "Login blev afvist på den anden enhed." @@ -54,4 +56,5 @@ Prøv at logge ind manuelt, eller scan QR-koden med en anden enhed." "Du skal give tilladelse til at %1$s kan benytte enhedens kamera, for at fortsætte." "Tillad kameraadgang for at scanne QR-koden" "Der opstod en uventet fejl. Prøv venligst igen." + "Venter på din anden enhed" diff --git a/features/linknewdevice/impl/src/main/res/values-de/translations.xml b/features/linknewdevice/impl/src/main/res/values-de/translations.xml index b8ad8b80ef..773878c736 100644 --- a/features/linknewdevice/impl/src/main/res/values-de/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-de/translations.xml @@ -34,6 +34,8 @@ "Wenn das Problem bestehen bleibt, versuche es mit einem anderen WLAN-Netzwerk oder verwende deine mobilen Daten statt WLAN." "Wenn das nicht funktioniert, melde dich manuell an" "Die Verbindung ist nicht sicher" + "Du wirst aufgefordert, die beiden unten abgebildeten Ziffern einzugeben." + "Trage die unten angezeigte Zahl auf einem anderen Device ein" "Die Anmeldung wurde auf dem anderen Gerät abgebrochen." "Anmeldeanfrage abgebrochen" "Die Anmeldung auf dem anderen Gerät wurde abgelehnt." @@ -54,4 +56,5 @@ Versuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Ger "Du musst %1$s die Berechtigung erteilen, die Kamera deines Geräts zu verwenden, um fortzufahren." "Erlaube Zugriff auf die Kamera zum Scannen des QR-Codes" "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es erneut." + "Warten auf dein anderes Gerät" diff --git a/features/linknewdevice/impl/src/main/res/values-el/translations.xml b/features/linknewdevice/impl/src/main/res/values-el/translations.xml index 26c917075b..6c0e77da40 100644 --- a/features/linknewdevice/impl/src/main/res/values-el/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-el/translations.xml @@ -34,6 +34,8 @@ "Εάν αντιμετωπίσεις το ίδιο πρόβλημα, δοκίμασε ένα διαφορετικό δίκτυο wifi ή χρησιμοποίησε τα δεδομένα του κινητού σου αντί για wifi" "Εάν δεν λειτουργήσει, συνδέσου χειροκίνητα" "Η σύνδεση δεν είναι ασφαλής" + "Θα σου ζητηθεί να εισάγεις τα δύο ψηφία που εμφανίζονται σε αυτήν τη συσκευή." + "Εισήγαγε τον παρακάτω αριθμό στην άλλη συσκευή σου" "Η σύνδεση ακυρώθηκε στην άλλη συσκευή." "Το αίτημα σύνδεσης ακυρώθηκε" "Η σύνδεση απορρίφθηκε στην άλλη συσκευή." @@ -54,4 +56,5 @@ "Πρέπει να δώσεις άδεια για %1$s για να χρησιμοποιήσεις την κάμερα της συσκευής σου και να συνεχίσεις." "Επέτρεψε την πρόσβαση της κάμερας για σάρωση του κωδικού QR" "Παρουσιάστηκε ένα απροσδόκητο σφάλμα. Παρακαλώ προσπάθησε ξανά." + "Αναμονή για την άλλη σου συσκευή" diff --git a/features/linknewdevice/impl/src/main/res/values-es/translations.xml b/features/linknewdevice/impl/src/main/res/values-es/translations.xml index 032813a2c4..c33dc3ad88 100644 --- a/features/linknewdevice/impl/src/main/res/values-es/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-es/translations.xml @@ -17,6 +17,8 @@ "Si te encuentras con el mismo problema, prueba con una red wifi diferente o usa tus datos móviles en lugar de wifi" "Si eso no funciona, inicia sesión manualmente" "La conexión no es segura" + "Se te pedirá que introduzcas los dos dígitos mostrados en este dispositivo." + "Introduce el número que aparece a continuación en tu otro dispositivo" "El inicio de sesión se canceló en el otro dispositivo." "Solicitud de inicio de sesión cancelada" "El inicio de sesión se rechazó en el otro dispositivo." @@ -35,4 +37,5 @@ Intenta iniciar sesión manualmente o escanea el código QR con otro dispositivo "Tienes que dar permiso a %1$s para que utilice la cámara de tu dispositivo y así poder continuar." "Permite el acceso a la cámara para escanear el código QR" "Se ha producido un error inesperado. Vuelve a intentarlo." + "A la espera de tu otro dispositivo" diff --git a/features/linknewdevice/impl/src/main/res/values-et/translations.xml b/features/linknewdevice/impl/src/main/res/values-et/translations.xml index 6aa1398e0a..10f8af5e11 100644 --- a/features/linknewdevice/impl/src/main/res/values-et/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-et/translations.xml @@ -34,6 +34,8 @@ "Kui sama probleem kordub, siis kasuta mõnda muud WiFi- või mobiilset andmedsideühendust" "Kui see ka ei aita, siis logi sisse käsitsi" "Ühendus pole turvaline" + "Sul palutakse sisestada kaks selles seadmes kuvatud numbrit." + "Sisesta see number oma teises seadmes" "Sisselogimine katkestati teises seadmes." "Sisselogimispäring on tühistatud" "Sisselogimisest on teises seadmes keeldutud." @@ -54,4 +56,5 @@ Proovi käsitsi sisselogimist või skaneeri QR-koodi mõne muu seadmega.""Jätkamiseks pead lubama, et %1$s saab kasutada sinu nutiseadme kaamerat" "QR-koodi lugemiseks luba kaamerat kasutada" "Tekkis ootamatu viga. Palun proovi uuesti." + "Ootame sinu teise seadme järgi" diff --git a/features/linknewdevice/impl/src/main/res/values-eu/translations.xml b/features/linknewdevice/impl/src/main/res/values-eu/translations.xml index 06cc0fd857..8680ad94c7 100644 --- a/features/linknewdevice/impl/src/main/res/values-eu/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-eu/translations.xml @@ -16,6 +16,8 @@ "Saiatu berriro QR kodearekin saioa hasten sare-arazo bat izan bada" "Horrek ez badu funtzionatzen, hasi saioa eskuz" "Konexioa ez da segurua" + "Gailu honetan agertzen diren bi digituak sartzeko eskatuko zaizu." + "Sartu beheko zenbakia beste gailuan" "Saioa hasteko eskaera bertan behera utzi da beste gailuan" "Saioa hasteko eskaera bertan behera utzi da" "Saioa hasteari uko egin zaio beste dispositiboan." @@ -33,4 +35,5 @@ Saiatu saioa eskuz hasten, edo eskaneatu QR kodea beste gailu batean." "QR kode okerra" "Baimendu kameraren sarbidea QR kodea eskaneatzeko" "Ustekabeko errore bat gertatu da. Saiatu berriro." + "Beste gailuaren zain" diff --git a/features/linknewdevice/impl/src/main/res/values-fa/translations.xml b/features/linknewdevice/impl/src/main/res/values-fa/translations.xml index 804fa653ad..07c329ef6a 100644 --- a/features/linknewdevice/impl/src/main/res/values-fa/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-fa/translations.xml @@ -15,6 +15,8 @@ "اکنون چه؟" "ورود دستی در صورت کار نکردنش" "اتّصال ناامن" + "از شما خواسته خواهد شد که دو رقم نشان داده روی این افزاره را وارد کنید." + "شمارهٔ زیر را روی افزارهٔ دیگرتان وارد کنید" "ورود روی افزارهٔ دیگر لغو شد." "درخواست ورد لغو شد" "ورود به دست افزارهٔ دیگر رد شد." @@ -33,4 +35,5 @@ "برای ادامه باید اجازهٔ استفادهٔ %1$s از دوربین افزاره‌تان را بدهید." "اجازهٔ دسترسی دوربین برای پویش کد پاس" "خطایی غیرمنتظره رخ داد. لطفاً دوباره تلاش کنید." + "منتظر افزارهٔ دیگرتان" diff --git a/features/linknewdevice/impl/src/main/res/values-fi/translations.xml b/features/linknewdevice/impl/src/main/res/values-fi/translations.xml index f8e999f886..0ba5a30e58 100644 --- a/features/linknewdevice/impl/src/main/res/values-fi/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-fi/translations.xml @@ -34,6 +34,8 @@ "Jos kohtaat saman ongelman, kokeile toista wifi-verkkoa tai käytä mobiilidataa wifi-yhteyden sijaan" "Jos tämä ei auta, kirjaudu sisään manuaalisesti" "Yhteys ei ole turvallinen" + "Sinua pyydetään antamaan tässä laitteessa näkyvät kaksi numeroa." + "Kirjoita alla oleva numero toisella laitteellasi" "Kirjautuminen peruutettiin toisella laitteella." "Kirjautumispyyntö peruutettu" "Kirjautuminen hylättiin toisella laitteella." @@ -54,4 +56,5 @@ Yritä kirjautua sisään manuaalisesti tai skannaa QR-koodi toisella laitteella "Jatkaaksesi sinun on annettava lupa %1$s -sovellukselle käyttää laitteesi kameraa." "Salli lupa kameraan QR-koodin skannaamiseksi" "Tapahtui odottamaton virhe. Yritä uudelleen." + "Odotetaan toista laitettasi" diff --git a/features/linknewdevice/impl/src/main/res/values-fr/translations.xml b/features/linknewdevice/impl/src/main/res/values-fr/translations.xml index 0c91dca7a1..12a770af17 100644 --- a/features/linknewdevice/impl/src/main/res/values-fr/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-fr/translations.xml @@ -34,6 +34,8 @@ "Si vous rencontrez le même problème, essayez un autre réseau wifi ou utilisez vos données mobiles au lieu du wifi" "Si cela ne fonctionne pas, connectez-vous manuellement" "La connexion n’est pas sécurisée" + "Il vous sera demandé de saisir les deux chiffres affichés sur cet appareil." + "Saisissez le nombre ci-dessous sur votre autre appareil" "La connexion a été annulée sur l’autre appareil." "Demande de connexion annulée" "La connexion a été refusée sur l’autre appareil." @@ -52,4 +54,5 @@ "Vous devez autoriser %1$s à utiliser la camera de votre appareil pour continuer." "Autoriser l’usage de la caméra pour scanner le code QR" "Une erreur inattendue s’est produite. Veuillez réessayer." + "En attente de votre autre session" diff --git a/features/linknewdevice/impl/src/main/res/values-hr/translations.xml b/features/linknewdevice/impl/src/main/res/values-hr/translations.xml index 20c194ef93..8561e63ad3 100644 --- a/features/linknewdevice/impl/src/main/res/values-hr/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-hr/translations.xml @@ -34,6 +34,8 @@ "Ako se problem ponovi, pokušajte s drugom Wi-Fi mrežom ili mobilnim podatcima umjesto Wi-Fi-ja." "Ako to ne uspije, prijavite se ručno" "Veza nije sigurna" + "Od vas će se zatražiti da unesete dvije znamenke prikazane na ovom uređaju." + "Unesite ispod navedeni broj u svoj drugi uređaj" "Prijava je otkazana na drugom uređaju." "Zahtjev za prijavu je otkazan" "Prijava je odbijena na drugom uređaju." @@ -54,4 +56,5 @@ Pokušajte se prijaviti ručno ili skenirajte QR kod drugim uređajem." "Za nastavak morate dati dopuštenje za %1$s da biste se mogli služiti kamerom svog uređaja." "Dopustite pristup kameri kako biste mogli skenirati QR kod" "Došlo je do neočekivane pogreške. Pokušajte ponovno." + "Čekanje na vaš drugi uređaj" diff --git a/features/linknewdevice/impl/src/main/res/values-hu/translations.xml b/features/linknewdevice/impl/src/main/res/values-hu/translations.xml index 51fe30bbd8..8cefed94cc 100644 --- a/features/linknewdevice/impl/src/main/res/values-hu/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-hu/translations.xml @@ -34,6 +34,8 @@ "Ha ugyanezzel a problémával találkozik, próbálkozzon másik Wi-Fi-hálózattal, vagy a Wi-Fi helyett használja a mobil-adatkapcsolatát" "Ha ez nem működik, jelentkezzen be kézileg" "A kapcsolat nem biztonságos" + "A rendszer kérni fogja, hogy adja meg az alábbi két számjegyet az eszközén." + "Adja meg az alábbi számot a másik eszközén" "A bejelentkezést megszakították a másik eszközön." "Bejelentkezési kérés törölve" "A bejelentkezést elutasították a másik eszközön." @@ -54,4 +56,5 @@ Próbáljon meg kézileg bejelentkezni, vagy olvassa be a QR-kódot egy másik e "A folytatáshoz engedélyeznie kell, hogy az %1$s használhassa az eszköz kameráját." "Engedélyezze a kamera elérését a QR-kód beolvasásához" "Váratlan hiba történt. Próbálja meg újra." + "Várakozás a másik eszközre" diff --git a/features/linknewdevice/impl/src/main/res/values-in/translations.xml b/features/linknewdevice/impl/src/main/res/values-in/translations.xml index 20badba9ba..5508993090 100644 --- a/features/linknewdevice/impl/src/main/res/values-in/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-in/translations.xml @@ -17,6 +17,8 @@ "Jika Anda mengalami masalah yang sama, coba jaringan Wi-Fi yang berbeda atau gunakan data seluler Anda daripada Wi-Fi" "Jika tidak berhasil, masuk secara manual" "Koneksi tidak aman" + "Anda akan diminta untuk memasukkan dua digit yang ditunjukkan di perangkat ini." + "Masukkan nomor bawah di perangkat Anda yang lain" "Proses masuk dibatalkan di perangkat lain." "Permintaan masuk dibatalkan" "Proses masuk ditolak di perangkat lain." @@ -35,4 +37,5 @@ Coba masuk secara manual, atau pindai kode QR dengan perangkat lain." "Anda perlu memberikan izin ke %1$s untuk menggunakan kamera perangkat Anda untuk melanjutkan." "Izinkan akses kamera untuk memindai kode QR" "Terjadi kesalahan tak terduga. Silakan coba lagi." + "Menunggu perangkat Anda yang lain" diff --git a/features/linknewdevice/impl/src/main/res/values-it/translations.xml b/features/linknewdevice/impl/src/main/res/values-it/translations.xml index 9a6476823a..6a32c70fe4 100644 --- a/features/linknewdevice/impl/src/main/res/values-it/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-it/translations.xml @@ -34,6 +34,8 @@ "Se riscontri lo stesso problema, prova con un altra rete wifi o usa i dati mobili al posto del wifi." "Se il problema persiste, accedi manualmente" "La connessione non è sicura" + "Ti verrà chiesto di inserire le due cifre mostrate su questo dispositivo." + "Inserisci il numero qui sotto sull\'altro dispositivo" "L\'accesso è stato annullato sull\'altro dispositivo." "Richiesta di accesso annullata" "L\'accesso è stato rifiutato sull\'altro dispositivo." @@ -54,4 +56,5 @@ Prova ad accedere manualmente o scansiona il codice QR con un altro dispositivo. "Per continuare, è necessario fornire l\'autorizzazione a %1$s per utilizzare la fotocamera del dispositivo." "Consenti l\'accesso alla fotocamera per la scansione del codice QR" "Si è verificato un errore inatteso. Riprova." + "In attesa dell\'altro dispositivo" diff --git a/features/linknewdevice/impl/src/main/res/values-ja/translations.xml b/features/linknewdevice/impl/src/main/res/values-ja/translations.xml index 6cfd5baf84..c4f09dcd0e 100644 --- a/features/linknewdevice/impl/src/main/res/values-ja/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-ja/translations.xml @@ -18,7 +18,7 @@ "サインインが無効です。もう一度試してください。" "サインインが時間内に完了しませんでした" "%1$s を他の端末で開いてください" - "%1$s を選択してください" + "%1$s を選択" "\"QRコードでサインイン\"" "表示されているQRコードを一方の端末で読み取ってください" "%1$s を他の端末で開いてください" @@ -34,6 +34,8 @@ "同様の問題が発生する場合は、異なるWi-Fiやモバイルデータ通信を試してください" "問題が解決しない場合は、手動でサインインしてください" "接続が安全ではありません" + "この端末に表示される2つの数字の入力を要求されます" + "もう一方に表示される数字を入力してください" "もう一方の端末がサインインをキャンセルしました" "サインインのリクエストがキャンセルされました" "もう一方の端末でサインインを拒否されました" @@ -54,4 +56,5 @@ "続行するには、%1$s にカメラの使用を許可する必要があります。" "QRコードを読み取るため、カメラへのアクセスを許可" "予期せぬ問題が発生しました。もう一度試してください。" + "一方の端末を待機しています" diff --git a/features/linknewdevice/impl/src/main/res/values-ko/translations.xml b/features/linknewdevice/impl/src/main/res/values-ko/translations.xml index 3b31c8fdc2..1d69f58ca5 100644 --- a/features/linknewdevice/impl/src/main/res/values-ko/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-ko/translations.xml @@ -34,6 +34,8 @@ "동일한 문제를 겪으신 경우 다른 Wi-Fi 네트워크를 사용해 보거나 Wi-Fi 대신 모바일 데이터를 사용해 보세요." "만약 작동하지 않는 경우, 수동으로 로그인하세요." "연결이 안전하지 않습니다" + "이 장치에 표시된 두 자리 숫자를 입력하라는 메시지가 표시됩니다." + "다른 device 에 아래 번호를 입력하세요" "다른 기기에서 로그인이 취소되었습니다." "로그인 요청이 취소되었습니다" "다른 기기에서 로그인이 거부되었습니다." @@ -54,4 +56,5 @@ "계속하려면 %1$s 가 기기의 카메라를 사용할 수 있도록 권한을 부여해야 합니다." "카메라 액세스를 허용하여 QR 코드를 스캔하세요" "예기치 않은 오류가 발생했습니다. 다시 시도해 주세요." + "다른 기기를 기다리고 있습니다" diff --git a/features/linknewdevice/impl/src/main/res/values-nb/translations.xml b/features/linknewdevice/impl/src/main/res/values-nb/translations.xml index 6b8541b25b..4e8844ee2f 100644 --- a/features/linknewdevice/impl/src/main/res/values-nb/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-nb/translations.xml @@ -34,6 +34,8 @@ "Hvis du støter på det samme problemet, kan du prøve et annet wifi-nettverk eller bruke mobildata i stedet for wifi" "Hvis det ikke fungerer, kan du logge på manuelt" "Forbindelsen er ikke sikker" + "Du blir bedt om å skrive inn de to sifrene som vises på denne enheten." + "Skriv inn nummeret nedenfor på den andre enheten" "Påloggingen ble kansellert på den andre enheten." "Påloggingsforespørsel kansellert" "Påloggingen ble avvist på den andre enheten." @@ -54,4 +56,5 @@ Prøv å logge på manuelt, eller skann QR-koden med en annen enhet." "Du må gi tillatelse til at %1$s kan bruke enhetens kamera for å fortsette." "Tillat kameratilgang for å skanne QR-koden" "Det oppstod en uventet feil. Prøv igjen." + "Venter på den andre enheten din" diff --git a/features/linknewdevice/impl/src/main/res/values-nl/translations.xml b/features/linknewdevice/impl/src/main/res/values-nl/translations.xml index 407a470e48..6dbc2c18c2 100644 --- a/features/linknewdevice/impl/src/main/res/values-nl/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-nl/translations.xml @@ -17,6 +17,8 @@ "Als je hetzelfde probleem ondervindt, probeer dan een ander wifi-netwerk of gebruik je mobiele data in plaats van wifi." "Als dat niet werkt, log dan handmatig in" "Verbinding niet veilig" + "Daar word je gevraagd om de twee cijfers in te voeren die op dit apparaat worden weergegeven." + "Voer het onderstaande nummer in op je andere apparaat" "De aanmelding is geannuleerd op het andere apparaat." "Login verzoek geannuleerd" "De aanmelding is geweigerd op het andere apparaat." @@ -35,4 +37,5 @@ Probeer handmatig in te loggen, of scan de QR code met een ander apparaat.""Je moet %1$s toestemming geven om de camera van je apparaat te gebruiken om verder te gaan." "Cameratoegang toestaan om de QR-code te scannen" "Er is een onverwachte fout opgetreden. Probeer het opnieuw." + "Aan het wachten op je andere apparaat" diff --git a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml index 4db42a2a49..18b731a528 100644 --- a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml @@ -17,6 +17,8 @@ "Jeśli napotkasz ten sam problem, użyj innej sieci Wi-FI lub danych mobilnych" "Jeśli to nie zadziała, zaloguj się ręcznie" "Połączenie nie jest bezpieczne" + "Zostaniesz poproszony o wprowadzenie dwóch cyfr widocznych na tym urządzeniu." + "Wprowadź numer poniżej na innym urządzeniu" "Logowanie zostało anulowane na drugim urządzeniu." "Prośba o logowanie została anulowana" "Logowanie zostało odrzucone na drugim urządzeniu." @@ -35,4 +37,5 @@ Spróbuj zalogować się ręcznie lub zeskanuj kod QR na innym urządzeniu.""Musisz przyznać uprawnienia %1$s do korzystania z kamery, aby kontynuować." "Zezwól na dostęp do kamery, aby zeskanować kod QR" "Wystąpił nieoczekiwany błąd. Spróbuj ponownie." + "Oczekiwanie na drugie urządzenie" diff --git a/features/linknewdevice/impl/src/main/res/values-pt-rBR/translations.xml b/features/linknewdevice/impl/src/main/res/values-pt-rBR/translations.xml index f11bdc6e6d..1680e5c0ff 100644 --- a/features/linknewdevice/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-pt-rBR/translations.xml @@ -34,6 +34,8 @@ "Se o problema persistir, tente uma rede Wi-Fi diferente ou use seus dados móveis em vez de Wi-Fi" "Se isso não funcionar, entre manualmente" "Conexão insegura" + "Você será solicitado a inserir os dois dígitos mostrados neste dispositivo." + "Digite o número abaixo no seu outro dispositivo" "A entrada foi cancelada no outro dispositivo." "Solicitação de entrada foi cancelada" "A entrada foi recusada no outro dispositivo." @@ -54,4 +56,5 @@ Tente entrar manualmente ou ler o código QR com outro dispositivo." "Você deve permitir que o %1$s use a câmera do seu dispositivo para continuar." "Permita o acesso à câmera para ler o código QR" "Ocorreu um erro inesperado. Tente novamente." + "Aguardando seu outro dispositivo" diff --git a/features/linknewdevice/impl/src/main/res/values-pt/translations.xml b/features/linknewdevice/impl/src/main/res/values-pt/translations.xml index da6da08f38..eff27b17f0 100644 --- a/features/linknewdevice/impl/src/main/res/values-pt/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-pt/translations.xml @@ -17,6 +17,8 @@ "Se tiveres o mesmo problema, experimenta uma rede Wi-Fi diferente ou utiliza os teus dados móveis." "Se isso não funcionar, inicia sessão manualmente" "Ligação insegura" + "Ser-te-á pedido que insiras os dois dígitos indicados neste dispositivo." + "Insere o número abaixo no teu dispositivo" "O início de sessão foi cancelado no outro dispositivo." "Pedido de início de sessão cancelado" "O início de sessão foi rejeitado no outro dispositivo." @@ -35,4 +37,5 @@ Tenta iniciar a sessão manualmente ou digitaliza o código QR com outro disposi "Para continuar, tens que dar permissão à %1$s para aceder à câmara do teu dispositivo." "Permitir o acesso à câmara para ler o código QR" "Ocorreu um erro inesperado. Tenta novamente." + "À espera do teu outro dispositivo" diff --git a/features/linknewdevice/impl/src/main/res/values-ro/translations.xml b/features/linknewdevice/impl/src/main/res/values-ro/translations.xml index f1a4f3db59..c99b537084 100644 --- a/features/linknewdevice/impl/src/main/res/values-ro/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-ro/translations.xml @@ -33,6 +33,8 @@ "Dacă întâmpinați aceeași problemă, încercați o altă rețea Wi-Fi sau utilizați datele mobile în loc de Wi-Fi." "Dacă nu funcționează, conectați-vă manual" "Conexiunea nu este sigură" + "Vi se va cere să introduceți cele două cifre afișate pe acest dispozitiv." + "Introduceți numărul de mai jos pe celălalt dispozitiv" "Autentificarea a fost anulată de pe celălalt dispozitiv." "Cererea de autentificare a fost anulată" "Autentificarea a fost refuzată pe celălalt dispozitiv." @@ -51,4 +53,5 @@ "Trebuie să acordați permisiunea ca %1$s să folosească camera dispozitivului pentru a continua." "Permiteți accesul la cameră pentru a scana codul QR" "A apărut o eroare neașteptată. Vă rugăm să încercați din nou." + "În așteptarea celuilalt dispozitiv" diff --git a/features/linknewdevice/impl/src/main/res/values-ru/translations.xml b/features/linknewdevice/impl/src/main/res/values-ru/translations.xml index 39506417b6..6a8b645c4f 100644 --- a/features/linknewdevice/impl/src/main/res/values-ru/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-ru/translations.xml @@ -34,6 +34,8 @@ "Если вы столкнулись с той же проблемой, попробуйте сменить точку доступа Wi-Fi или используйте мобильные данные" "Если это не помогло, войдите вручную" "Соединение не защищено" + "Вам нужно будет ввести две цифры, показанные на этом устройстве." + "Введите показанный номер на своем другом устройстве" "Вход на другом устройстве был отменен." "Запрос на вход отменен" "Вход в систему был отклонен на другом устройстве." @@ -54,4 +56,5 @@ "Чтобы продолжить, вам необходимо разрешить %1$s использовать камеру вашего устройства." "Разрешите доступ к камере для сканирования QR-кода" "Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз." + "Ожидание другого устройства" diff --git a/features/linknewdevice/impl/src/main/res/values-sk/translations.xml b/features/linknewdevice/impl/src/main/res/values-sk/translations.xml index cb430671bb..f64c01328b 100644 --- a/features/linknewdevice/impl/src/main/res/values-sk/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-sk/translations.xml @@ -34,6 +34,8 @@ "Ak narazíte na rovnaký problém, vyskúšajte inú sieť Wi-Fi alebo namiesto siete Wi-Fi použite mobilné dáta" "Ak to nefunguje, prihláste sa manuálne" "Pripojenie nie je bezpečené" + "Budete požiadaní o zadanie dvoch číslic zobrazených na tomto zariadení." + "Zadajte nižšie uvedené číslo na vašom druhom zariadení" "Prihlásenie bolo zrušené na druhom zariadení." "Žiadosť o prihlásenie bola zrušená" "Prihlásenie bolo zamietnuté na druhom zariadení." @@ -54,4 +56,5 @@ Skúste sa prihlásiť manuálne alebo naskenujte QR kód pomocou iného zariade "Ak chcete pokračovať, musíte udeliť povolenie aplikácii %1$s používať fotoaparát vášho zariadenia." "Povoľte prístup k fotoaparátu na naskenovanie QR kódu" "Vyskytla sa neočakávaná chyba. Prosím, skúste to znova." + "Čaká sa na vaše druhé zariadenie" diff --git a/features/linknewdevice/impl/src/main/res/values-sv/translations.xml b/features/linknewdevice/impl/src/main/res/values-sv/translations.xml index 8a1bef434a..8800b31bbd 100644 --- a/features/linknewdevice/impl/src/main/res/values-sv/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-sv/translations.xml @@ -17,6 +17,8 @@ "Om du stöter på samma problem, prova ett annat wifi-nätverk eller använd din mobildata istället för wifi" "Om det inte fungerar, logga in manuellt" "Anslutningen är inte säker" + "Du kommer att bli ombedd att ange de två siffrorna som visas på den här enheten." + "Ange numret nedan på din andra enhet" "Inloggningen avbröts på den andra enheten." "Inloggningsförfrågan avbröts" "Inloggningen avvisades på den andra enheten." @@ -35,4 +37,5 @@ Prova att logga in manuellt eller skanna QR-koden med en annan enhet." "Du måste ge tillstånd för %1$s att använda enhetens kamera för att kunna fortsätta." "Tillåt kameraåtkomst för att skanna QR-koden" "Ett oväntat fel inträffade. Vänligen försök igen." + "Väntar på din andra enhet" diff --git a/features/linknewdevice/impl/src/main/res/values-tr/translations.xml b/features/linknewdevice/impl/src/main/res/values-tr/translations.xml index e5fd989c0b..3c8767f64c 100644 --- a/features/linknewdevice/impl/src/main/res/values-tr/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-tr/translations.xml @@ -33,6 +33,8 @@ "Aynı sorunla karşılaşırsanız, farklı bir wifi ağı deneyin veya wifi yerine mobil verinizi kullanın" "Bu işe yaramazsa, manuel olarak oturum açın" "Bağlantı güvenli değil" + "Bu cihazda gösterilen iki haneyi girmeniz istenecektir." + "Aşağıdaki numarayı diğer cihazınıza girin" "Oturum açma işlemi diğer cihazda iptal edildi." "Oturum açma isteği iptal edildi" "Diğer cihazda oturum açma işlemi reddedildi." @@ -51,4 +53,5 @@ Manuel olarak oturum açmayı deneyin veya QR kodunu başka bir cihazla tarayın "Devam etmek için %1$s cihazınızın kamerasını kullanmasına izin vermeniz gerekir." "QR kodunu taramak için kamera erişimine izin verin" "Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin." + "Diğer cihazınız bekleniyor" diff --git a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml index 875b5aed16..fe5b1a7460 100644 --- a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml @@ -33,6 +33,8 @@ "Якщо ви зіткнулися з тією ж проблемою, спробуйте іншу мережу Wi-Fi або використовуйте мобільний інтернет замість Wi-Fi" "Якщо це не спрацює, увійдіть вручну" "З\'єднання не безпечне" + "Вас попросять ввести дві цифри, показані на цьому пристрої." + "Введіть номер нижче на іншому пристрої" "Вхід було скасовано на іншому пристрої." "Запит на вхід скасовано" "Вхід був відхилений на іншому пристрої." @@ -53,4 +55,5 @@ "Вам потрібно дати дозвіл %1$s на використання камери вашого пристрою, щоб продовжити." "Надайте доступ до камери, щоб сканувати QR-код" "Сталася несподівана помилка. Будь ласка, спробуйте ще раз." + "Чекаємо на ваш інший пристрій" diff --git a/features/linknewdevice/impl/src/main/res/values-ur/translations.xml b/features/linknewdevice/impl/src/main/res/values-ur/translations.xml index 54d2c2e401..0b4bb02226 100644 --- a/features/linknewdevice/impl/src/main/res/values-ur/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-ur/translations.xml @@ -17,6 +17,8 @@ "اگر آپ کو بھی یہی مسئلہ درپیش ہو، تو کوئی دوسرا وائی فائی شبکہ آزمائیں یا وائی فائی کے بجائے اپنے محمول بیانات استعمال کریں۔" "اگر یہ کام نہ کرے، تو دستی طور پر داخل ہوں" "اتصال محفوظ نہیں" + "آپ سے اس آلے پر دکھائے گئے دو ہندسوں کو درج کرنے کو کہا جائے گا۔" + "اپنے دوسرے آلے پر درج ذیل نمبر درج کریں" "دوسرے آلے پر دخول منسوخ کر دیا گیا تھا۔" "دخول کی درخواست منسوخ" "دوسرے آلہ پر دخول کو مسترد کر دیا گیا تھا۔" @@ -35,4 +37,5 @@ "جاری رکھنے کے لیے آپ %1$s کو اپنے آلے کا تصویرگر استعمال کرنے کی اجازت دینے کی ضرورت ہے۔" "کیو آر رمز کو مسح ضوئی کرنے کے لئے تصویرگر تک رسائی کی اجازت دیں" "ایک غیر متوقع نقص واقع ہوا۔ برائے مہربانی دوبارہ کوشش کریں۔" + "آپکے دوسرے آلے کا منتظر" 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 ed08ee1a04..1d436b5f4a 100644 --- a/features/linknewdevice/impl/src/main/res/values-uz/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-uz/translations.xml @@ -34,6 +34,8 @@ "Xuddi shu muammoga duch kelsangiz, boshqa wifi tarmogʻini sinang yoki wifi oʻrniga mobil internetdan foydalaning" "Agar bunisi ishlamasa, oddiy usulda kiring" "Ulanish xavfsiz emas" + "Sizdan ushbu qurilmada koʻrsatilgan ikkita raqamni kiritish soʻraladi." + "Narigi qurilmada quyidagi raqamni kiriting" "Boshqa qurilmadan hisobga kirish bekor qilindi." "Tizimga kirish soʻrovi bekor qilindi" "Boshqa qurilmadan hisobga kirish bekor qilindi." @@ -54,4 +56,5 @@ Oddiy usulda kiring yoki boshqa qurilma bilan QR kodni skanerlang." "Davom etish uchun %1$s qurilmangiz kamerasidan foydalanishiga ruxsat berishingiz kerak." "QR kodni skanerlash uchun kameraga ruxsat bering" "Kutilmagan xatolik yuz berdi. Qayta urining." + "Boshqa qurilmangiz kutilmoqda" 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 3aa047125a..e18fbc13b6 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 @@ -34,6 +34,8 @@ "如果遇到相同的問題,請嘗試使用其他 wifi 網路或您的行動數據" "若無法運作,請手動登入" "連線不安全" + "系統會要求您輸入此裝置上顯示的兩位數字。" + "在您的其他裝置上輸入以下數字" "已在其他裝置上取消登入。" "已取消登入請求" "其他裝置拒絕登入。" @@ -54,4 +56,5 @@ "您必須授予 %1$s 權限以使用裝置相機才能繼續。" "允許相機權限以掃描 QR code" "發生意外錯誤。請再試一次。" + "等待您的其他裝置" diff --git a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml index 1bd74d5104..cabcb5ccd0 100644 --- a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml @@ -34,6 +34,8 @@ "如果遇到同样的问题,请尝试使用不同的 WiFi 网络或使用移动数据代替 WiFi" "如果不起作用,请手动登录" "连接不安全" + "你将被要求输入此设备上显示的两位数字。" + "在你的其它设备上输入以下数字" "登录被另一台设备取消" "登录请求已取消" "另一设备上的登录请求已被拒绝。" @@ -54,4 +56,5 @@ "你需要授予 %1$s 使用设备摄像头的权限才能继续。" "允许访问摄像头以扫描二维码" "发生了意外错误。请再试一次。" + "正在等待其它设备" diff --git a/features/location/impl/src/main/res/values-da/translations.xml b/features/location/impl/src/main/res/values-da/translations.xml index f15ab0fb2f..4d4c5d00bc 100644 --- a/features/location/impl/src/main/res/values-da/translations.xml +++ b/features/location/impl/src/main/res/values-da/translations.xml @@ -1,4 +1,5 @@ + "Din live-positionshistorik gemmes i rummet og er synlig for medlemmerne, når sessionen er afsluttet." "Vælg, hvor længe du vil dele din aktuelle position." diff --git a/features/lockscreen/impl/src/main/res/values-fa/translations.xml b/features/lockscreen/impl/src/main/res/values-fa/translations.xml index 56dc91e835..bd2000b94d 100644 --- a/features/lockscreen/impl/src/main/res/values-fa/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-fa/translations.xml @@ -34,5 +34,5 @@ "استفاده از زیست‌سنجی" "استفاده از پین" - "خارج شدن…" + "برداشتن افزاره…" diff --git a/features/lockscreen/impl/src/main/res/values-in/translations.xml b/features/lockscreen/impl/src/main/res/values-in/translations.xml index 0396f56b0c..e0054cda62 100644 --- a/features/lockscreen/impl/src/main/res/values-in/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-in/translations.xml @@ -32,5 +32,5 @@ Pilih sesuatu yang mudah untuk diingat. Jika Anda lupa PIN ini, Anda akan dikelu "Gunakan biometrik" "Gunakan PIN" - "Mengeluarkan dari akun…" + "Mengeluarkan device dari akun…" diff --git a/features/lockscreen/impl/src/main/res/values-pt/translations.xml b/features/lockscreen/impl/src/main/res/values-pt/translations.xml index a6b2516fba..fca6fbcb9e 100644 --- a/features/lockscreen/impl/src/main/res/values-pt/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-pt/translations.xml @@ -23,7 +23,7 @@ Escolhe algo memorável. Se te esqueceres deste PIN, a tua sessão será termina "Insere o mesmo PIN duas vezes" "Os PINs não coincidem" "Terás de voltar a iniciar sessão e criar um novo PIN para continuar" - "Estás a terminar a sessão" + "O teu dispositivo está a ser removido" "Tens %1$d tentativa de desbloqueio" "Tens %1$d tentativas de desbloqueio" @@ -34,5 +34,5 @@ Escolhe algo memorável. Se te esqueceres deste PIN, a tua sessão será termina "Utilizar biometria" "Utilizar PIN" - "A terminar sessão…" + "A remover dispositivo…" 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 62da77cbb5..f3e93668fd 100644 --- a/features/lockscreen/impl/src/main/res/values-zh/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-zh/translations.xml @@ -32,5 +32,5 @@ "使用生物识别" "使用 PIN 码" - "正在删除设备……" + "正在移除设备…" diff --git a/features/login/impl/src/main/res/values-be/translations.xml b/features/login/impl/src/main/res/values-be/translations.xml index 307ccf7263..d9d69503c5 100644 --- a/features/login/impl/src/main/res/values-be/translations.xml +++ b/features/login/impl/src/main/res/values-be/translations.xml @@ -24,7 +24,7 @@ "Няправільнае імя карыстальніка і/або пароль" "Гэта несапраўдны ідэнтыфікатар карыстальніка. Чаканы фармат: ‘@user:homeserver.org’" "Гэты сервер настроены на выкарыстанне маркераў абнаўлення. Яны не падтрымліваюцца пры ўваходзе на аснове пароля." - "Выбраны хатні сервер не падтрымлівае пароль або ўваход у OIDC. Калі ласка, звярніцеся да адміністратара або абярыце іншы хатні сервер." + "Выбраны хатні сервер не падтрымлівае пароль або ўваход у OAuth. Калі ласка, звярніцеся да адміністратара або абярыце іншы хатні сервер." "Увядзіце свае даныя" "Matrix - гэта адкрытая сетка для бяспечнай, дэцэнтралізаванай сувязі." "Сардэчна запрашаем!" diff --git a/features/login/impl/src/main/res/values-bg/translations.xml b/features/login/impl/src/main/res/values-bg/translations.xml index 6ccc7c9129..c6c74ff1a8 100644 --- a/features/login/impl/src/main/res/values-bg/translations.xml +++ b/features/login/impl/src/main/res/values-bg/translations.xml @@ -21,7 +21,7 @@ "Този акаунт бе деактивиран." "Неправилно потребителско име и/или парола" "Това не е валиден потребителски идентификатор. Очакван формат: ‘@user:homeserver.org’" - "Избраният сървър не поддържа влизане с парола или OIDC. Моля, свържете се с вашия администратор или изберете друг сървър." + "Избраният сървър не поддържа влизане с парола или OAuth. Моля, свържете се с вашия администратор или изберете друг сървър." "Въведете своите данни" "Matrix е отворена мрежа за сигурна, децентрализирана комуникация." "Добре дошли отново!" 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 fa31796c3b..c5887de6c6 100644 --- a/features/login/impl/src/main/res/values-cs/translations.xml +++ b/features/login/impl/src/main/res/values-cs/translations.xml @@ -32,7 +32,7 @@ "Nesprávné uživatelské jméno nebo heslo" "Toto není platný identifikátor uživatele. Očekávaný formát: \'@user:homeserver.org\'" "Tento server je nakonfigurován tak, aby používal obnovovací tokeny. Ty nejsou podporovány při použití přihlašovacích údajů založených na hesle." - "Vybraný domovský server nepodporuje přihlášení pomocí hesla nebo OIDC. Kontaktujte prosím svého správce nebo vyberte jiný domovský server." + "Vybraný domovský server nepodporuje přihlášení pomocí hesla nebo OAuth. Kontaktujte prosím svého správce nebo vyberte jiný domovský server." "Zadejte své údaje" "Matrix je otevřená síť pro bezpečnou a decentralizovanou komunikaci." "Vítejte zpět!" diff --git a/features/login/impl/src/main/res/values-cy/translations.xml b/features/login/impl/src/main/res/values-cy/translations.xml index b8988a9889..0f44287ed4 100644 --- a/features/login/impl/src/main/res/values-cy/translations.xml +++ b/features/login/impl/src/main/res/values-cy/translations.xml @@ -32,7 +32,7 @@ "Enw defnyddiwr a/neu gyfrinair anghywir" "Nid yw hwn yn ddynodwr defnyddiwr dilys. Fformat disgwyliedig: ‘@user:homeserver.org’" "Mae\'r gweinydd hwn wedi\'i ffurfweddu i ddefnyddio tocynnau adnewyddu. Nid yw\'r rhain yn cael eu cefnogi wrth ddefnyddio mewngofnodi ar sail cyfrinair." - "Nid yw\'r gweinydd cartref ddewiswyd yn cefnogi cyfrinair na mewngofnodi OIDC. Cysylltwch â\'ch gweinyddwr neu dewis gweinydd cartref arall." + "Nid yw\'r gweinydd cartref ddewiswyd yn cefnogi cyfrinair na mewngofnodi OAuth. Cysylltwch â\'ch gweinyddwr neu dewis gweinydd cartref arall." "Rhowch eich manylion" "Mae Matrix yn rhwydwaith agored ar gyfer cyfathrebu diogel, datganoledig." "Croeso nôl!" 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 284284cc3e..35d66a6e69 100644 --- a/features/login/impl/src/main/res/values-da/translations.xml +++ b/features/login/impl/src/main/res/values-da/translations.xml @@ -28,16 +28,24 @@ "Hvad er adressen på din server?" "Vælg din server" "Opret konto" - "Denne konto er blevet deaktiveret." + "Denne konto er blevet slettet." "Forkert brugernavn og/eller adgangskode" "Dette er ikke en gyldig brugeridentifikation. Forventet format: \'@bruger:hjemmeserver.org\'" "Denne server er konfigureret til at bruge opdateringstokens. Disse understøttes ikke, når du bruger adgangskodebaseret login." - "Den valgte hjemmeserver understøtter ikke adgangskode eller OIDC-login. Kontakt venligst din administrator eller vælg en anden hjemmeserver." + "Den valgte hjemmeserver understøtter ikke adgangskode eller OAuth-login. Kontakt venligst din administrator eller vælg en anden hjemmeserver." "Indtast dine oplysninger" "Matrix er et åbent netværk for sikker, decentraliseret kommunikation." "Velkommen tilbage!" "Log ind på %1$s" + "Åbn Element Classic" + "Åbn Element Classic på din enhed" + "Gå til Indstillinger > Sikkerhed og privatliv" + "I Nøgleadministration skal du, under Kryptografi, vælge Gendannelse af krypterede meddelelser" + "Følg instruktionerne for at aktivere dit nøglelager" + "Gå tilbage til %1$s" + "Aktivér dit nøglelager, før du fortsætter til %1$s" "Version %1$s" + "Kontoen kontrolleres…" "Log ind manuelt" "Log ind på %1$s" "Log ind med QR-kode" 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 dced91a1c9..89e4412d0f 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -28,11 +28,11 @@ "Wie lautet die Adresse deines Servers?" "Wähle deinen Server aus" "Konto erstellen" - "Dieses Konto wurde deaktiviert." + "Dieses Konto wurde gelöscht." "Falscher Nutzername und/oder Passwort" "Dies ist keine gültige Nutzerkennung. Erwartetes Format: \'@nutzer:homeserver.org\'" "Dieser Server ist so konfiguriert, dass er Refresh-Tokens verwendet. Diese werden für die passwortbasierte Anmeldung nicht unterstützt." - "Der ausgewählte Homeserver unterstützt weder den Login per Passwort noch per OIDC. Bitte kontaktiere deinen Administrator oder wähle einen anderen Homeserver." + "Der ausgewählte Homeserver unterstützt weder den Login per Passwort noch per OAuth. Bitte kontaktiere deinen Administrator oder wähle einen anderen Homeserver." "Gib deine Daten ein" "Matrix ist ein offenes Netzwerk für eine sichere, dezentrale Kommunikation." "Willkommen zurück!" 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 c87027477d..85640698f3 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -32,7 +32,7 @@ "Λανθασμένο όνομα χρήστη ή κωδικός πρόσβασης" "Αυτό δεν είναι έγκυρο αναγνωριστικό χρήστη. Αναμενόμενη μορφή: \'@χρήστης:homeserver.org\'" "Αυτός ο διακομιστής έχει ρυθμιστεί ώστε να χρησιμοποιεί διακριτικά ανανέωσης. Αυτά δεν υποστηρίζονται όταν χρησιμοποιείς σύνδεση μέσω κωδικού πρόσβασης." - "Ο επιλεγμένος οικιακός διακομιστής δεν υποστηρίζει κωδικό πρόσβασης ή σύνδεση OIDC. Επικοινωνήστε με τον διαχειριστή σου ή επέλεξε άλλο οικιακό διακομιστή." + "Ο επιλεγμένος οικιακός διακομιστής δεν υποστηρίζει κωδικό πρόσβασης ή σύνδεση OAuth. Επικοινωνήστε με τον διαχειριστή σου ή επέλεξε άλλο οικιακό διακομιστή." "Εισήγαγε τα στοιχεία σου" "Το Matrix είναι ένα ανοιχτό δίκτυο για ασφαλή, αποκεντρωμένη επικοινωνία." "Καλωσόρισες ξανά!" diff --git a/features/login/impl/src/main/res/values-es/translations.xml b/features/login/impl/src/main/res/values-es/translations.xml index df6a06ab29..3b9ffbe2dd 100644 --- a/features/login/impl/src/main/res/values-es/translations.xml +++ b/features/login/impl/src/main/res/values-es/translations.xml @@ -29,7 +29,7 @@ "Usuario y/o contraseña incorrectos" "Este no es un id de usuario válido. Formato esperado: \'@user:homeserver.org\'" "Este servidor está configurado para utilizar tokens de actualización. Estos no son compatibles cuando se utiliza el inicio de sesión basado en contraseña." - "El servidor base seleccionado no admite el inicio de sesión usando contraseña ni OIDC. Ponte en contacto con tu administrador o elige otro servidor base." + "El servidor base seleccionado no admite el inicio de sesión usando contraseña ni OAuth. Ponte en contacto con tu administrador o elige otro servidor base." "Introduce tus datos" "Matrix es una red abierta para una comunicación segura y descentralizada." "¡Hola de nuevo!" 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 7ac4e99694..b0b60009d4 100644 --- a/features/login/impl/src/main/res/values-et/translations.xml +++ b/features/login/impl/src/main/res/values-et/translations.xml @@ -32,7 +32,7 @@ "Vigane kasutajanimi ja/või salasõna" "See ei ole korrektne kasutajanimi. Õige vorming on: „@kasutaja:koduserver.ee“" "See server on seadistatud kasutama tunnusloa põhist sisselogimist. Salasõnaga sisselogimisel see võimalus aga ei ole toetatud." - "Valitud koduserver ei toeta salasõna ega OIDC-põhist sisselogimist. Lisateavet saad koduserveri haldajalt, aga sa võid ka valida mõne teise serveri." + "Valitud koduserver ei toeta salasõna ega OAuth-põhist sisselogimist. Lisateavet saad koduserveri haldajalt, aga sa võid ka valida mõne teise serveri." "Sisesta oma andmed" "Matrix on avatud võrk turvalise ja hajutatud suhtluse jaoks." "Tere tulemast tagasi!" diff --git a/features/login/impl/src/main/res/values-eu/translations.xml b/features/login/impl/src/main/res/values-eu/translations.xml index 355e63546c..78a13e5810 100644 --- a/features/login/impl/src/main/res/values-eu/translations.xml +++ b/features/login/impl/src/main/res/values-eu/translations.xml @@ -21,7 +21,7 @@ "Sortu kontua" "Kontu hau desaktibatuta dago." "Erabiltzaile-izena edo/eta pasahitza okerrak" - "Hautatutako zerbitzaria ez da bateragarria pasahitz edo OIDC saio-hasierarekin. Jarri harremanetan administratzailearekin edo aukeratu beste zerbitzari bat." + "Hautatutako zerbitzaria ez da bateragarria pasahitz edo OAuth saio-hasierarekin. Jarri harremanetan administratzailearekin edo aukeratu beste zerbitzari bat." "Sartu zure datuak" "Matrix komunikazio seguru eta deszentralizaturako sare irekia da." "Ongi etorri!" diff --git a/features/login/impl/src/main/res/values-fa/translations.xml b/features/login/impl/src/main/res/values-fa/translations.xml index ef7062a88a..d903103c1b 100644 --- a/features/login/impl/src/main/res/values-fa/translations.xml +++ b/features/login/impl/src/main/res/values-fa/translations.xml @@ -20,10 +20,10 @@ "نشانی کارسازتان چیست؟" "کارسازتان را برگزینید" "ایجاد حساب" - "این حساب از کار افتاده است." + "این حساب حذف شده است." "نام کاربری یا گذرواژه نامعتبر است" "این یک شناسه کاربری معتبر نیست. قالب صحیح: ‪«@user:homeserver.or" - "کارساز اصلی انتخاب شده از رمز عبور یا ورود OIDC پشتیبانی نمی کند. لطفا با مدیر خود تماس بگیرید یا یک کارساز خانگی دیگر را انتخاب کنید." + "کارساز اصلی انتخاب شده از رمز عبور یا ورود OAuth پشتیبانی نمی کند. لطفا با مدیر خود تماس بگیرید یا یک کارساز خانگی دیگر را انتخاب کنید." "جزییاتتان را وارد کنید" "ماتریکس شبکه‌ای بار برای ارتباطات نامتمرکز و امن است." "خوش برگشتید!" 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 0d795811b1..4f5225be67 100644 --- a/features/login/impl/src/main/res/values-fi/translations.xml +++ b/features/login/impl/src/main/res/values-fi/translations.xml @@ -32,7 +32,7 @@ "Väärä käyttäjänimi ja/tai salasana" "Tämä ei ole kelvollinen käyttäjätunnus. Odotettu muoto: \'@käyttäjä:kotipalvelin.fi\'" "Tämä palvelin on määritetty käyttämään refresh tokeneja. Näitä ei tueta salasanapohjaisen kirjautumisen kanssa." - "Valitsemasi kotipalvelin ei tue salasana- tai OIDC-kirjautumista. Ota yhteyttä palvelimesi ylläpitäjään tai valitse toinen kotipalvelin." + "Valitsemasi kotipalvelin ei tue salasana- tai OAuth-kirjautumista. Ota yhteyttä palvelimesi ylläpitäjään tai valitse toinen kotipalvelin." "Anna tietosi" "Matrix on avoin verkko turvallista, hajautettua viestintää varten." "Tervetuloa takaisin!" 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 3435eb7d40..504517aad7 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -28,11 +28,11 @@ "Quelle est l’adresse de votre serveur ?" "Choisissez votre serveur" "Créer un compte" - "Ce compte a été désactivé." + "Ce compte a été supprimé." "Nom d’utilisateur et/ou mot de passe incorrects" "Il ne s’agit pas d’un identifiant utilisateur valide. Format attendu : « @user:homeserver.org »" "Ce serveur est configuré pour utiliser des tokens d’actualisation. Ils ne sont pas pris en charge lors de l’utilisation d’une connexion basée sur un mot de passe." - "Le serveur d’accueil sélectionné ne prend pas en charge le mot de passe ou la connexion OIDC. Contactez votre administrateur ou choisissez un autre serveur d’accueil." + "Le serveur d’accueil sélectionné ne prend pas en charge le mot de passe ou la connexion OAuth. Contactez votre administrateur ou choisissez un autre serveur d’accueil." "Saisissez vos identifiants" "Matrix est un réseau ouvert pour une communication sécurisée et décentralisée." "Content de vous revoir !" 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 b52dd77d7f..f578790380 100644 --- a/features/login/impl/src/main/res/values-hr/translations.xml +++ b/features/login/impl/src/main/res/values-hr/translations.xml @@ -32,7 +32,7 @@ "Netočno korisničko ime i/ili zaporka" "To nije valjani identifikator korisnika. Očekivani oblik: ‘@korisnik:matičniposlužitelj.org’" "Ovaj je poslužitelj konfiguriran za korištenje tokena za osvježavanje. Oni nisu podržani kada se upotrebljava prijava temeljena na zaporki." - "Odabrani matični poslužitelj ne podržava zaporku ili OIDC prijavu. Obratite se administratoru ili odaberite drugi matični poslužitelj." + "Odabrani matični poslužitelj ne podržava zaporku ili OAuth prijavu. Obratite se administratoru ili odaberite drugi matični poslužitelj." "Unesite svoje podatke" "Matrix je otvorena mreža za sigurnu, decentraliziranu komunikaciju." "Dobro došli natrag!" 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 c2b2fefddb..26534cc523 100644 --- a/features/login/impl/src/main/res/values-hu/translations.xml +++ b/features/login/impl/src/main/res/values-hu/translations.xml @@ -28,11 +28,11 @@ "Mi a kiszolgálója címe?" "Válassza ki a kiszolgálóját" "Fiók létrehozása" - "Ez a fiók deaktiválva lett." + "Ez a fiók törölve lett." "Helytelen felhasználónév vagy jelszó" "Ez nem érvényes felhasználóazonosító. A várt formátum: „@user:homeserver.org”" "Ez a kiszolgáló frissítési tokenek használatára van beállítva. Ezek jelszó alapú bejelentkezés esetén nem támogatottak." - "A kiválasztott Matrix-kiszolgáló nem támogatja a jelszavas vagy OIDC-alapú bejelentkezést. Lépjen kapcsolatba a kiszolgáló adminisztrátorával, vagy válasszon másik Matrix-kiszolgálót." + "A kiválasztott Matrix-kiszolgáló nem támogatja a jelszavas vagy OAuth-alapú bejelentkezést. Lépjen kapcsolatba a kiszolgáló adminisztrátorával, vagy válasszon másik Matrix-kiszolgálót." "Adja meg adatait" "A Matrix egy nyitott hálózat a biztonságos, decentralizált kommunikációhoz." "Örülünk, hogy visszatért!" diff --git a/features/login/impl/src/main/res/values-in/translations.xml b/features/login/impl/src/main/res/values-in/translations.xml index e05fd8746d..4b9f3ffdef 100644 --- a/features/login/impl/src/main/res/values-in/translations.xml +++ b/features/login/impl/src/main/res/values-in/translations.xml @@ -32,7 +32,7 @@ "Nama pengguna dan/atau kata sandi salah" "Ini bukan pengenal pengguna yang valid. Format yang diharapkan: \'@pengguna:homeserver.org\'" "Server ini diatur untuk menggunakan token penyegaran. Ini tidak didukung ketika menggunakan log masuk berbasis kata sandi." - "Homeserver yang dipilih tidak mendukung log masuk kata sandi atau OIDC. Silakan hubungi admin Anda atau pilih homeserver yang lain." + "Homeserver yang dipilih tidak mendukung log masuk kata sandi atau OAuth. Silakan hubungi admin Anda atau pilih homeserver yang lain." "Masukkan detail Anda" "Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi." "Selamat datang kembali!" 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 e882654e4b..3753d58390 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -32,7 +32,7 @@ "Nome utente e/o password errati" "Questo non è un identità utente valida. il formato atteso é: \'@user:homeserver.org\'" "Questo server è configurato per usare i token di aggiornamento. Non sono supportati quando si usa l\'accesso basato su password." - "L\'homeserver selezionato non supporta la password o l\'accesso OIDC. Contatta il tuo amministratore o scegli un altro homeserver." + "L\'homeserver selezionato non supporta la password o l\'accesso OAuth. Contatta il tuo amministratore o scegli un altro homeserver." "Inserisci i tuoi dati" "Matrix è una rete aperta per comunicazioni sicure e decentralizzate." "Bentornato!" 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 219605ab22..42698e27dc 100644 --- a/features/login/impl/src/main/res/values-ja/translations.xml +++ b/features/login/impl/src/main/res/values-ja/translations.xml @@ -1,18 +1,18 @@ - "アカウントの提供元を変更" + "アカウント提供元を変更" "ホームサーバーのアドレス" - "検索用のキーワードまたはドメインのアドレスを入力してください。" + "検索のキーワードまたはドメインのアドレスを入力してください。" "会社やコミュニティ, 個人のサーバーなどを検索します。" - "アカウントの提供元を検索" - "メールアプリのように、あなたの会話はここに保管されています。" + "アカウント提供元を検索" + "メールアプリのように、あなたの会話はこのサーバー上に保管されます。" "%s にサインインを試みています" - "メールアプリのように、あなたの会話はここに保管されています。" - "%s にアカウントの作成を試みています" + "メールアプリのように、あなたの会話はこのサーバー上に保管されます。" + "%s 上にアカウントを作成しようとしています" "Matrix.org は Matrix.org Foundation が運営する、大規模で安全な分散型コミュニケーションを実現する無償のサーバーです。" "その他" - "自身のサーバーや仕事用のアカウントにサインインするには、アカウント提供元のサーバーを指定してください。" - "アカウントの提供元を変更" + "自身のサーバーや仕事用のアカウントにサインインするには、アカウント提供元を変更してください。" + "アカウント提供元を変更" "Google Play" "%1$s では Element Pro を使用する必要があります。アプリストアよりダウンロードしてください。" "Element Pro が必要です" @@ -27,11 +27,11 @@ "サーバーのアドレスは何ですか?" "サーバーを選択" "アカウントを作成" - "このアカウントは無効化されています。" + "アカウントは削除されました。" "ユーザー名またはパスワードが違います" "無効なユーザーIDです。正しい形式は \"@ユーザー:ホームサーバー\" です。" "このサーバーはリフレッシュトークンを使用します。パスワードを使用したログインとは併用できません。" - "指定したホームサーバはパスワードまたはOIDCによるログインに対応していません。管理者に問い合わせるか、異なるホームサーバーを使用してください。" + "指定したホームサーバはパスワードまたはOAuthによるログインに対応していません。管理者に問い合わせるか、異なるホームサーバーを使用してください。" "詳細を入力" "Matrix は安全で分散型のオープンなネットワークです。" "お待ちしておりました。" @@ -80,8 +80,8 @@ "%1$s に非対応" "読み取る" "コンピュータで %1$s を開く" - "アバターをタップしてください" - "%1$s を選択してください" + "アバターをタップ" + "%1$s を選択" "\"新しい端末を追加\"" "この端末でQRコードを読み取る" "アカウント提供元が対応する場合にのみ使用できます。" @@ -98,11 +98,11 @@ "一方の端末を待機しています" "アカウント提供元が、サインインを検証するために以下の文字列を要求することがあります。" "検証コード" - "アカウントの提供元を変更" + "アカウント提供元を変更" "Element 開発者用の非公開のサーバーです。" "Matrix は安全で分散型のオープンなネットワークです。" - "メールアプリのように、あなたの会話はここに保管されています。" + "メールアプリのように、あなたの会話はこのサーバー上に保管されます。" "%1$s にサインインを試みています" "アカウント提供元を選択" - "%1$s 上にアカウントの作成を試みています" + "%1$s 上にアカウントを作成しようとしています" diff --git a/features/login/impl/src/main/res/values-ka/translations.xml b/features/login/impl/src/main/res/values-ka/translations.xml index 54e277ec12..04db3fda13 100644 --- a/features/login/impl/src/main/res/values-ka/translations.xml +++ b/features/login/impl/src/main/res/values-ka/translations.xml @@ -23,7 +23,7 @@ "არასწორი მომხმარებლის სახელი და/ან პაროლი" "მოცემული მომხმარებლის იდენტიფიკატორი არასწორია. დასაშვები ფორმატი: ‘@user:homeserver.org’" "ეს სერვერი კონფიგურირებულია განახლების გასაღებების გამოსაყენებლად. პაროლზე დაფუძნებული შეცვლისას ისინი მხარდაჭერილი არაა." - "მოცემული სახლის სერვერი მხარს არ უჭერს პაროლით ან OIDC-ით შესვლას. გთხოვთ, დაუკავშირდეთ თქვენს ადმინისტრატორს ან აარჩიეთ სხვა სახლის სერვერი." + "მოცემული სახლის სერვერი მხარს არ უჭერს პაროლით ან OAuth-ით შესვლას. გთხოვთ, დაუკავშირდეთ თქვენს ადმინისტრატორს ან აარჩიეთ სხვა სახლის სერვერი." "შეიყვანეთ თქვენი დეტალები" "Matrix არის ღია ქსელი უსაფრთხო, დეცენტრალიზებული კომუნიკაციისთვის." "კეთილი იყოს თქვენი მობრძანება!" 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 c870377fc4..338ba628c9 100644 --- a/features/login/impl/src/main/res/values-ko/translations.xml +++ b/features/login/impl/src/main/res/values-ko/translations.xml @@ -32,7 +32,7 @@ "잘못된 아이디/비밀번호" "이 사용자 ID는 유효하지 않습니다. 예상 형식: ‘@user:homeserver.org’" "이 서버는 새로 고침 토큰을 사용하도록 구성되어 있습니다. 비밀번호 기반 로그인을 사용하는 경우 이 기능은 지원되지 않습니다." - "선택한 홈 서버는 password 또는 OIDC 로그인을 지원하지 않습니다. 관리자에게 문의하거나 다른 홈 서버를 선택하세요." + "선택한 홈 서버는 password 또는 OAuth 로그인을 지원하지 않습니다. 관리자에게 문의하거나 다른 홈 서버를 선택하세요." "귀하의 세부 정보를 입력하십시오" "Matrix 는 안전하고 분산된 커뮤니케이션을 위한 개방형 네트워크입니다." "다시 돌아온 걸 환영합니다!" 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 870e2c4d31..dc1a2b7ba6 100644 --- a/features/login/impl/src/main/res/values-lt/translations.xml +++ b/features/login/impl/src/main/res/values-lt/translations.xml @@ -31,7 +31,7 @@ "Ši paskyra buvo išjungta." "Neteisingas vartotojo vardas ir (arba) slaptažodis" "Tai nėra tinkamas vartotojo vardas. Reikalingas formatas: \'@vartotojas:serveris.org\'" - "Pasirinktas serveris nepalaiko slaptažodžio ar OIDC prisijungimo. Susisiekite su serverio administracija arba pasirinkite kitą serverį." + "Pasirinktas serveris nepalaiko slaptažodžio ar OAuth prisijungimo. Susisiekite su serverio administracija arba pasirinkite kitą serverį." "Įveskite savo duomenis" "Matrix yra atviras tinklas, skirtas saugiam, decentralizuotam bendravimui." "Sveiki sugrįžę!" 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 5957b902ce..6645691b84 100644 --- a/features/login/impl/src/main/res/values-nb/translations.xml +++ b/features/login/impl/src/main/res/values-nb/translations.xml @@ -32,7 +32,7 @@ "Feil brukernavn og/eller passord" "Dette er ikke en gyldig brukeridentifikator. Forventet format: \'@bruker:homeserver.org\'" "Denne serveren er konfigurert til å bruke oppdateringstokener. Disse støttes ikke når du bruker passordbasert pålogging." - "Den valgte hjemmeserveren støtter ikke passord eller OIDC-pålogging. Ta kontakt med administratoren din eller velg en annen hjemmeserver." + "Den valgte hjemmeserveren støtter ikke passord eller OAuth-pålogging. Ta kontakt med administratoren din eller velg en annen hjemmeserver." "Skriv inn opplysningene dine" "Matrix er et åpent nettverk for sikker, desentralisert kommunikasjon." "Velkommen tilbake!" diff --git a/features/login/impl/src/main/res/values-nl/translations.xml b/features/login/impl/src/main/res/values-nl/translations.xml index 8a7f695156..e5d90e2234 100644 --- a/features/login/impl/src/main/res/values-nl/translations.xml +++ b/features/login/impl/src/main/res/values-nl/translations.xml @@ -24,7 +24,7 @@ "Onjuiste gebruikersnaam en/of wachtwoord" "Dit is geen geldige gebruikers-ID. Verwacht formaat: \'@user:homeserver.org\'" "Deze server is geconfigureerd om verversingstokens te gebruiken. Deze worden niet ondersteund bij inloggen met een wachtwoord." - "De geselecteerde homeserver ondersteunt geen wachtwoord of OIDC aanmelding. Neem contact op met je beheerder of kies een andere homeserver." + "De geselecteerde homeserver ondersteunt geen wachtwoord of OAuth aanmelding. Neem contact op met je beheerder of kies een andere homeserver." "Vul je gegevens in" "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." "Welkom terug!" diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index 0c7810abe7..b134395adf 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -32,7 +32,7 @@ "Nieprawidłowa nazwa użytkownika i/lub hasło" "To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \'@user:homeserver.org\'" "Ten serwer został skonfigurowany do korzystania z tokenów odświeżania. Nie są one obsługiwane, gdy korzystasz z hasła." - "Wybrany serwer domowy nie obsługuje uwierzytelniania hasłem, ani OIDC. Skontaktuj się z jego administratorem lub wybierz inny serwer domowy." + "Wybrany serwer domowy nie obsługuje uwierzytelniania hasłem, ani OAuth. Skontaktuj się z jego administratorem lub wybierz inny serwer domowy." "Wprowadź swoje dane" "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." "Witaj ponownie!" diff --git a/features/login/impl/src/main/res/values-pt-rBR/translations.xml b/features/login/impl/src/main/res/values-pt-rBR/translations.xml index afca14d201..ad2ad2b5fb 100644 --- a/features/login/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/login/impl/src/main/res/values-pt-rBR/translations.xml @@ -32,7 +32,7 @@ "Nome de usuário e/ou senha incorretos" "Esse não é um identificador de usuário válido. Formato esperado: \'@usuário:servidor.org\'" "Este servidor está configurado para usar tokens recarregados. Não há suporte a eles ao entrar por uma senha." - "O servidor selecionado não suporta a entrada por senha ou OIDC. Entre em contato com o administrador ou escolha outro servidor." + "O servidor selecionado não suporta a entrada por senha ou OAuth. Entre em contato com o administrador ou escolha outro servidor." "Digite seus dados" "A Matrix é uma rede aberta para comunicação segura e descentralizada." "Boas-vindas novamente!" diff --git a/features/login/impl/src/main/res/values-pt/translations.xml b/features/login/impl/src/main/res/values-pt/translations.xml index c2aa0d5ed6..ff3cae843d 100644 --- a/features/login/impl/src/main/res/values-pt/translations.xml +++ b/features/login/impl/src/main/res/values-pt/translations.xml @@ -28,11 +28,11 @@ "Qual é o endereço do teu servidor?" "Seleciona o teu servidor" "Criar conta" - "Esta conta foi desativada." + "Esta conta foi eliminada." "Nome de utilizador ou senha incorretos" "Identificador de utilizador inválido. Formato esperado: ‘@utilizador:servidor.org’" "Este servidor está configurado para utilizar \"tokens\" de atualização. Estes não são suportados quando utilizas o início de sessão por senha." - "O servidor selecionado não suporta início de sessão por senha nem por OIDC. Por favor, contacta o teu administrador ou escolhe outro servidor." + "O servidor selecionado não suporta início de sessão por senha nem por OAuth. Por favor, contacta o teu administrador ou escolhe outro servidor." "Insere o teus detalhes" "A Matrix é uma rede aberta de comunicação descentralizada e segura." "Bem-vindo(a) de volta!" diff --git a/features/login/impl/src/main/res/values-ro/translations.xml b/features/login/impl/src/main/res/values-ro/translations.xml index 6dddc4d0bf..ec9b260208 100644 --- a/features/login/impl/src/main/res/values-ro/translations.xml +++ b/features/login/impl/src/main/res/values-ro/translations.xml @@ -32,7 +32,7 @@ "Utilizator și/sau parolă incorecte" "Acesta nu este un identificator de utilizator valid. Format așteptat: „@user:homeserver.org”" "Acest server este configurat pentru a utiliza token-uri de reîmprospătare. Acestea nu sunt acceptate atunci când utilizați autentificare bazată pe parolă." - "Homeserver-ul selectat nu acceptă autentificarea prin parola sau OIDC. Te rugăm să contactezi administratorul sau să alegi un alt homeserver." + "Homeserver-ul selectat nu acceptă autentificarea prin parola sau OAuth. Te rugăm să contactezi administratorul sau să alegi un alt homeserver." "Introduceți detaliile" "Matrix este o rețea deschisă pentru o comunicare sigură și descentralizată." "Bine ați revenit!" 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 4437c19056..329bad30af 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -32,7 +32,7 @@ "Неверное имя пользователя и/или пароль" "Это некорректный идентификатор пользователя. Правильный формат: @user:homeserver.org" "Этот сервер настроен на использование токенов обновления. Они не поддерживаются при использовании входа на основе пароля." - "Выбранный сервер не поддерживает вход по паролю и OIDC. Пожалуйста, свяжитесь с администратором или выберите другой сервер." + "Выбранный сервер не поддерживает вход по паролю и OAuth. Пожалуйста, свяжитесь с администратором или выберите другой сервер." "Введите свои данные" "Matrix — это открытая сеть для безопасной децентрализованной связи." "Рады видеть вас снова!" diff --git a/features/login/impl/src/main/res/values-sk/translations.xml b/features/login/impl/src/main/res/values-sk/translations.xml index 9bd494dd56..b2c3077de2 100644 --- a/features/login/impl/src/main/res/values-sk/translations.xml +++ b/features/login/impl/src/main/res/values-sk/translations.xml @@ -32,7 +32,7 @@ "Nesprávne používateľské meno a/alebo heslo" "Toto nie je platný identifikátor používateľa. Očakávaný formát: \'@pouzivatel:homeserver.sk\'" "Tento server je nakonfigurovaný tak, aby používal obnovovacie tokeny. Pri prihlasovaní na základe hesla nie sú podporované." - "Vybraný domovský server nepodporuje prihlásenie pomocou hesla alebo OIDC. Obráťte sa na správcu alebo vyberte iný domovský server." + "Vybraný domovský server nepodporuje prihlásenie pomocou hesla alebo OAuth. Obráťte sa na správcu alebo vyberte iný domovský server." "Zadajte svoje údaje" "Matrix je otvorená sieť pre bezpečnú a decentralizovanú komunikáciu." "Vitajte späť!" diff --git a/features/login/impl/src/main/res/values-sv/translations.xml b/features/login/impl/src/main/res/values-sv/translations.xml index 33fb76b5bd..396f2025b7 100644 --- a/features/login/impl/src/main/res/values-sv/translations.xml +++ b/features/login/impl/src/main/res/values-sv/translations.xml @@ -32,7 +32,7 @@ "Felaktigt användarnamn och/eller lösenord" "Detta är inte en giltig användaridentifierare. Förväntat format: \'@användare:hemserver.org\'" "Den här servern är konfigurerad för att använda uppdateringstokens. Dessa stöds inte när du använder lösenordsbaserad inloggning." - "Den valda hemservern stöder inte lösenord eller OIDC-inloggning. Kontakta administratören eller välj en annan hemserver." + "Den valda hemservern stöder inte lösenord eller OAuth-inloggning. Kontakta administratören eller välj en annan hemserver." "Ange dina uppgifter" "Matrix är ett öppet nätverk för säker, decentraliserad kommunikation." "Välkommen tillbaka!" diff --git a/features/login/impl/src/main/res/values-tr/translations.xml b/features/login/impl/src/main/res/values-tr/translations.xml index 1574fca3a8..05bb9bab15 100644 --- a/features/login/impl/src/main/res/values-tr/translations.xml +++ b/features/login/impl/src/main/res/values-tr/translations.xml @@ -28,7 +28,7 @@ "Yanlış kullanıcı adı ve/veya şifre" "Bu geçerli bir kullanıcı tanımlayıcısı değil. Kullanılması gereken biçim: \'@user:homeserver.org\'" "Bu sunucu, yenileme belirteçlerini kullanacak şekilde yapılandırılmıştır. Parola tabanlı oturum açma kullanılırken bunlar desteklenmez." - "Seçilen ana sunucu parola veya OIDC oturum açmayı desteklemiyor. Lütfen yöneticinizle iletişime geçin veya başka bir ana sunucu seçin." + "Seçilen ana sunucu parola veya OAuth oturum açmayı desteklemiyor. Lütfen yöneticinizle iletişime geçin veya başka bir ana sunucu seçin." "Bilgilerinizi girin" "Matrix, güvenli, merkezi olmayan iletişim için açık bir ağdır." "Tekrar hoş geldiniz!" diff --git a/features/login/impl/src/main/res/values-uk/translations.xml b/features/login/impl/src/main/res/values-uk/translations.xml index b93a66fed2..0d8eca42cf 100644 --- a/features/login/impl/src/main/res/values-uk/translations.xml +++ b/features/login/impl/src/main/res/values-uk/translations.xml @@ -32,7 +32,7 @@ "Неправильне ім\'я користувача та/або пароль" "Це недійсний ідентифікатор користувача. Очікуваний формат: \'@user:homeserver.org\'" "Цей сервер налаштований на використання оновлюваних токенів. Вони не підтримуються, якщо використовується вхід за допомогою основі пароля." - "Обраний домашній сервер не підтримує вхід за допомогою пароля або OIDC. Зверніться до адміністратора або виберіть інший домашній сервер." + "Обраний домашній сервер не підтримує вхід за допомогою пароля або OAuth. Зверніться до адміністратора або виберіть інший домашній сервер." "Введіть свої дані" "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації." "З поверненням!" diff --git a/features/login/impl/src/main/res/values-ur/translations.xml b/features/login/impl/src/main/res/values-ur/translations.xml index 334d5b6ea6..6762ab16af 100644 --- a/features/login/impl/src/main/res/values-ur/translations.xml +++ b/features/login/impl/src/main/res/values-ur/translations.xml @@ -24,7 +24,7 @@ "غلط صارف نام اور/یا لفظ عبور" "یہ صالح صارف شناسه نہیں ہے۔ متوقع شکل: @صارف:منزلی خادم" "یہ خادم تازگی کی رموزِ ممیز استعمال کرنے کے لئے تشکیل دیا گیا ہے۔ لفظ عبور پر مبنی دخول استعمال کرتے ہوئے ان کی حمایت نہیں کی جاتی۔" - "منتخب منزلی خادم کلمۂ عبوری یا OIDC دخول کا تعاون نہیں کرتا۔ برائے مہربانی اپنے منتظم سے رابطہ کریں یا کوئی اور منزلی خادم چنیں۔" + "منتخب منزلی خادم کلمۂ عبوری یا OAuth دخول کا تعاون نہیں کرتا۔ برائے مہربانی اپنے منتظم سے رابطہ کریں یا کوئی اور منزلی خادم چنیں۔" "اپنی تفصیلات درج کریں" "میٹرکس محفوظ، غیر مرکزی مواصلت کے لئے ایک کھلا شبکہ ہے۔" "واپس خوش آمدید!" 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 07b3d8835b..546397935b 100644 --- a/features/login/impl/src/main/res/values-uz/translations.xml +++ b/features/login/impl/src/main/res/values-uz/translations.xml @@ -31,7 +31,7 @@ "Notog\'ri foydalanuvchi nomi va/yoki parol" "Bu haqiqiy foydalanuvchi identifikatori emas. Kutilayotgan format: \'@user:homeserver.org\'" "Ushbu server yangilash tokenlaridan foydalanishga moslashtirilgan. Parolga asoslangan tizimga kirishda bunday tokenlar qoʻllab-quvvatlanmaydi." - "Tanlangan uy serveri parol yoki OIDC loginni qo\'lab-quvvatlamaydi. Iltimos, administratoringizga murojaat qiling yoki boshqa uy serverini tanlang." + "Tanlangan uy serveri parol yoki OAuth loginni qo\'lab-quvvatlamaydi. Iltimos, administratoringizga murojaat qiling yoki boshqa uy serverini tanlang." "Tafsilotlaringizni kiriting" "Matrix xavfsiz, markazlashmagan aloqa uchun ochiq tarmoqdir." "Qaytib kelganingizdan xursandmiz!" 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 4d9b921ea5..66089a4708 100644 --- a/features/login/impl/src/main/res/values-vi/translations.xml +++ b/features/login/impl/src/main/res/values-vi/translations.xml @@ -31,7 +31,7 @@ "Tên người dùng và/hoặc mật khẩu không chính xác" "Đây không phải là mã nhận dạng người dùng hợp lệ. Định dạng mong đợi: ‘@user:homeserver.org’" "Máy chủ này được cấu hình sử dụng refresh token. Điều này không được hỗ trợ khi đăng nhập bằng mật khẩu." - "Homeserver đã chọn không hỗ trợ đăng nhập bằng mật khẩu hoặc OIDC. Vui lòng liên hệ với quản trị viên của cậu hoặc chọn một homeserver khác." + "Homeserver đã chọn không hỗ trợ đăng nhập bằng mật khẩu hoặc OAuth. Vui lòng liên hệ với quản trị viên của cậu hoặc chọn một homeserver khác." "Nhập thông tin chi tiết của bạn." "Matrix là một mạng mở cho việc liên lạc an toàn và phi tập trung." "Chào mừng bạn quay trở lại!" 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 7170288c5d..c4d16f5928 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 @@ -32,7 +32,7 @@ "不正確的使用者名稱或密碼" "此非有效的使用者識別字串。預期的格式:‘@user:homeserver.org’" "此伺服器已設定為使用重新整理權杖。使用以密碼為基礎的登入方式時,不支援這些功能。" - "選定的家伺服器不支援密碼或 OIDC 登入。請聯絡您的管理員或選擇其他家伺服器。" + "選定的家伺服器不支援密碼或 OAuth 登入。請聯絡您的管理員或選擇其他家伺服器。" "輸入您的詳細資料" "Matrix 是一個開放網路,為了安全且去中心化的通訊而生。" "歡迎回來!" 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 ac125ba945..8e86b51d7b 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -21,18 +21,18 @@ %1$s" "所选账户提供者不支持滑动同步。需要升级服务器才能使用 %1$s。" "%1$s 不允许连接到 %2$s。" - "本应用已配置为允许访问:%1$s 。" + "此 app 已配置为允许访问:%1$s。" "账户提供者 %1$s 不被允许。" "主服务器 URL" "输入域名地址。" "你的服务器地址是什么?" "选择服务器" "创建账户" - "该账户已被停用。" + "此账户已被删除。" "用户名与(或)密码不正确" "这不是合法的用户 ID。预期格式:“@user:homeserver.org”。" "此服务器使用刷新令牌。使用密码登录时不支持这些功能。" - "该服务器不支持密码登录与 OIDC 登录。请联系服务器管理员或选择另一服务器。" + "该服务器不支持密码登录与 OAuth 登录。请联系服务器管理员或选择另一服务器。" "输入详细信息" "Matrix 是一个用于安全、去中心化通信的开放网络。" "欢迎回来!" @@ -51,7 +51,7 @@ "使用二维码登录" "创建账户" "欢迎回来" - "欢迎使用 %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 f8d5ffa651..10fb6ef04a 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -32,7 +32,7 @@ "Incorrect username and/or password" "This is not a valid user identifier. Expected format: ‘@user:homeserver.org’" "This server is configured to use refresh tokens. These aren\'t supported when using password based login." - "The selected homeserver doesn\'t support password or OIDC login. Please contact your admin or choose another homeserver." + "The selected homeserver doesn\'t support password or OAuth login. Please contact your admin or choose another homeserver." "Enter your details" "Matrix is an open network for secure, decentralised communication." "Welcome back!" 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 9021aee4da..0218642abc 100644 --- a/features/logout/impl/src/main/res/values-de/translations.xml +++ b/features/logout/impl/src/main/res/values-de/translations.xml @@ -4,15 +4,15 @@ "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." + "Dies ist dein einziges Gerät. Wenn du es entfernst, benötigst du einen Wiederherstellungsschlüssel, um deine digitale Identität zu bestätigen und deine verschlüsselten Chats bei deiner nächsten Anmeldung wiederherzustellen." + "Du bist dabei, den Zugriff auf deine verschlüsselten Chats zu verlieren" + "Deine Schlüssel wurden noch gesichert, während du offline gegangen bist. Stelle die Verbindung wieder her, damit deine Schlüssel gesichert werden können, bevor du dieses Gerät entfernst." "Deine Schlüssel werden noch gesichert" "Bitte warte, bis der Vorgang abgeschlossen ist, bevor du dieses Gerät entfernst." "Deine Schlüssel werden noch gesichert" "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." + "Dies ist dein einziges Gerät. Wenn du es entfernst, benötigst du einen Wiederherstellungsschlüssel, um deine digitale Identität zu bestätigen und deine verschlüsselten Chats bei deiner nächsten Anmeldung wiederherzustellen." "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." + "Dies ist dein einziges Gerät. Wenn du es entfernst, benötigst du einen Wiederherstellungsschlüssel, um deine digitale Identität zu bestätigen und deine verschlüsselten Chats bei deiner nächsten Anmeldung wiederherzustellen." "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-fa/translations.xml b/features/logout/impl/src/main/res/values-fa/translations.xml index 8dfaad8580..d286ded539 100644 --- a/features/logout/impl/src/main/res/values-fa/translations.xml +++ b/features/logout/impl/src/main/res/values-fa/translations.xml @@ -1,16 +1,16 @@ - "مطمئنید که می‌خواهید از حسابتان خارج شوید؟" - "خروج" - "خروج" - "خارج شدن…" + "مطمئنید که می‌خواهید این افزاره را بردارید؟" + "برداشتن این افزاره" + "برداشتن این افزاره" + "برداشتن افزاره…" "دارید از واپسین نشستتان خارج می‌شوید. اگر اکنون خارج شوید پیام‌های رمزنگاشته‌تان را از دست خواهید داد." "پشتیبان را خاموش کرده‌اید" "در هنگامی که آفلاین شدید، کلیدهای شما هنوز در حال پشتیبان‌گیری بودند. دوباره متصل شوید ، تا قبل از خروج از کلیدهایتان نسخه پشتیبان‌ گرفته شود." "کلیدهایتان هنوز در حال پشتیبان گیریند" "لطفاً پیش از خروج منتظر پایانش شوید." "کلیدهایتان هنوز در حال پشتیبان گیریند" - "خروج" + "برداشتن این افزاره" "شما در آستانه خروج از آخرین جلسه خود هستید. اگر اکنون از سیستم خارج شوید، دسترسی به پیام های رمزگذاری شده تان را از دست خواهید داد." "بازگردانی برپا نشده" "دارید از واپسین نشستتان خارج می‌شوید. اگر اکنون خارج شوید ممکن است پیام‌های رمزنگاشته‌تان را از دست بدهید." diff --git a/features/logout/impl/src/main/res/values-in/translations.xml b/features/logout/impl/src/main/res/values-in/translations.xml index dabf83545e..9d63573973 100644 --- a/features/logout/impl/src/main/res/values-in/translations.xml +++ b/features/logout/impl/src/main/res/values-in/translations.xml @@ -1,16 +1,16 @@ - "Apakah Anda yakin ingin keluar dari akun?" - "Keluar dari akun" - "Keluar dari akun" - "Mengeluarkan dari akun…" + "Apakah Anda yakin ingin non aktifkan device dari akun?" + "Hapus device dari akun" + "Hapus device dari akun" + "Mengeluarkan device dari akun…" "Anda akan keluar dari sesi terakhir Anda. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda." "Anda telah menonaktifkan pencadangan" "Kunci Anda masih dicadangkan saat Anda luring. Sambungkan kembali sehingga kunci Anda dapat dicadangkan sebelum keluar." "Kunci Anda masih dicadangkan" "Mohon tunggu hingga proses ini selesai sebelum keluar." "Kunci Anda masih dicadangkan" - "Keluar dari akun" + "Hapus device dari akun" "Anda akan keluar dari sesi Anda yang terakhir. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda." "Pemulihan belum disiapkan" "Anda akan keluar dari sesi terakhir Anda. Jika Anda keluar sekarang, Anda mungkin kehilangan akses ke pesan terenkripsi Anda." diff --git a/features/logout/impl/src/main/res/values-pt/translations.xml b/features/logout/impl/src/main/res/values-pt/translations.xml index b8a7161c21..76e4f09d42 100644 --- a/features/logout/impl/src/main/res/values-pt/translations.xml +++ b/features/logout/impl/src/main/res/values-pt/translations.xml @@ -1,18 +1,18 @@ - "Tens a certeza que queres terminar a sessão?" - "Terminar sessão" - "Terminar sessão" - "A terminar sessão…" - "Estás prestes a terminar a tua última sessão. Se continuares, perderás o acesso às tuas mensagens cifradas." - "Desativaste a cópia de segurança" - "As tuas chaves ainda estavam a ser guardadas quando ficaste desligado. Volta a ligar-te para que as tuas chaves possam ser guardadas antes de encerrares a sessão." + "Tens a certeza que queres remover este dispositivo?" + "Remover este dispositivo" + "Remover este dispositivo" + "A remover dispositivo…" + "Este é o teu único dispositivo. Se o removeres, da próxima vez que iniciares sessão, precisarás da chave de recuperação para confirmares a tua identidade digital e recuperares as tuas conversas cifradas." + "Estás prestes a perder o acesso às tuas conversas privadas" + "As tuas chaves ainda estavam a ser guardadas quando ficaste desligado. Volta a ligar-te para que as tuas chaves possam ser guardadas antes de removeres o dispositivo." "As tuas chaves ainda estão a ser guardadas" - "Por favor, aguarda a conclusão desta operação antes de terminares a sessão." + "Por favor, aguarda a conclusão desta operação antes de removeres o dispositivo." "As tuas chaves ainda estão a ser guardadas" - "Terminar sessão" - "Estás prestes a terminar a tua última sessão. Se continuares, perderás o acesso às tuas mensagens cifradas." - "Recuperação não configurada" - "Estás prestes a terminar a tua última sessão. Se continuares, poderás perder o acesso às tuas mensagens cifradas." - "Guardaste a tua chave de recuperação?" + "Remover este dispositivo" + "Este é o teu único dispositivo. Se o removeres, da próxima vez que iniciares sessão, precisarás da chave de recuperação para confirmares a tua identidade digital e recuperares as tuas conversas cifradas." + "Estás prestes a perder o acesso às tuas conversas cifradas" + "Este é o teu único dispositivo. Se o removeres, da próxima vez que iniciares sessão, precisarás da chave de recuperação para confirmares a tua identidade digital e recuperares as tuas conversas cifradas." + "Certifica-te de que tens acesso à tua chave de recuperação antes de removeres este dispositivo" diff --git a/features/logout/impl/src/main/res/values-zh/translations.xml b/features/logout/impl/src/main/res/values-zh/translations.xml index 3370b40f3c..f18904d03b 100644 --- a/features/logout/impl/src/main/res/values-zh/translations.xml +++ b/features/logout/impl/src/main/res/values-zh/translations.xml @@ -1,16 +1,16 @@ "你确定要移除此设备?" - "删除此设备" - "删除此设备" - "正在删除设备……" + "移除此设备" + "移除此设备" + "正在移除设备…" "这是你的唯一设备。一旦移除,下次登录时你需要使用恢复密钥验证数字身份并恢复加密聊天。" "你即将失去加密聊天的访问权" "当你离线时,密钥仍在备份。重新连接以便在移除设备之前备份密钥。" "你的密钥仍在备份中" "请等待此操作完成再移除此设备。" "你的密钥仍在备份中" - "删除此设备" + "移除此设备" "这是你的唯一设备。一旦移除,下次登录时你需要使用恢复密钥验证数字身份并恢复加密聊天。" "你即将失去加密聊天的访问权" "这是你的唯一设备。一旦移除,下次登录时你需要使用恢复密钥验证数字身份并恢复加密聊天。" diff --git a/features/messages/impl/src/main/res/values-da/translations.xml b/features/messages/impl/src/main/res/values-da/translations.xml index 390d03f451..e068df293a 100644 --- a/features/messages/impl/src/main/res/values-da/translations.xml +++ b/features/messages/impl/src/main/res/values-da/translations.xml @@ -35,7 +35,7 @@ "Optag video" "Vedhæftning" "Foto- og videobibliotek" - "Del lokation" + "Del placering" "Afstemning" "Tekstformatering" "Beskedhistorikken er i øjeblikket ikke tilgængelig." diff --git a/features/messages/impl/src/main/res/values-fa/translations.xml b/features/messages/impl/src/main/res/values-fa/translations.xml index 446239c095..dcac058d2f 100644 --- a/features/messages/impl/src/main/res/values-fa/translations.xml +++ b/features/messages/impl/src/main/res/values-fa/translations.xml @@ -27,7 +27,7 @@ "ضبط ویدیو" "پیوست" "کتابخانهٔ عکس و ویدیو" - "مکان" + "هم‌رسانی مکان" "نظرسنجی" "قالب‌بندی متن" "تاریخچه پیام درحال حاضر دردسترس نیست." diff --git a/features/messages/impl/src/main/res/values-in/translations.xml b/features/messages/impl/src/main/res/values-in/translations.xml index 508f4d5476..7a0994f65e 100644 --- a/features/messages/impl/src/main/res/values-in/translations.xml +++ b/features/messages/impl/src/main/res/values-in/translations.xml @@ -34,7 +34,7 @@ "Rekam video" "Lampiran" "Pustaka Foto & Video" - "Lokasi" + "Membagi Lokasi" "Jajak pendapat" "Pemformatan Teks" "Riwayat pesan saat ini tidak tersedia di ruangan ini" diff --git a/features/messages/impl/src/main/res/values-ja/translations.xml b/features/messages/impl/src/main/res/values-ja/translations.xml index 4fd18e8db5..037c0f7d67 100644 --- a/features/messages/impl/src/main/res/values-ja/translations.xml +++ b/features/messages/impl/src/main/res/values-ja/translations.xml @@ -34,7 +34,7 @@ "写真を撮影" "動画を撮影" "添付ファイル" - "アルバムの写真・動画" + "アルバムの写真と動画" "場所を共有" "投票" "書式設定" diff --git a/features/messages/impl/src/main/res/values-pt/translations.xml b/features/messages/impl/src/main/res/values-pt/translations.xml index 054d2a1759..2fb5173169 100644 --- a/features/messages/impl/src/main/res/values-pt/translations.xml +++ b/features/messages/impl/src/main/res/values-pt/translations.xml @@ -35,7 +35,7 @@ "Gravar vídeo" "Anexo" "Biblioteca de fotos e vídeos" - "Localização" + "Partilhar localização" "Sondagem" "Formatação de texto" "De momento, o histórico de mensagens está indisponível." diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index 26518d656c..fc576aaf11 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -21,13 +21,13 @@ "无法上传该文件。" "处理要上传的媒体失败,请重试。" "上传媒体失败,请重试。" - "允许的最大文件大小为%1$s 。" + "允许的最大文件大小为 %1$s。" "文件太大,无法上传" "第 %1$d 个项目,共 %2$d 个" "优化图像质量" "处理中…" "屏蔽用户" - "请确认是否要隐藏该用户当前和未来的所有信息" + "请确认是否要隐藏该用户当前和未来的所有消息" "此消息将举报给服务器管理员。他们无法读取任何加密消息。" "举报此内容的理由" "相机" diff --git a/features/preferences/impl/src/main/res/values-da/translations.xml b/features/preferences/impl/src/main/res/values-da/translations.xml index f258fb0952..2f828a4063 100644 --- a/features/preferences/impl/src/main/res/values-da/translations.xml +++ b/features/preferences/impl/src/main/res/values-da/translations.xml @@ -11,6 +11,14 @@ "Skjul avatarer i anmodninger om invitation til rum" "Skjul forhåndsvisning af medier i tidslinjen" "Laboratorier" + "Den afstand, du skal tilbagelægge for at udløse en opdatering." + "Sørg for, at \"nøjagtig placering\" er aktiveret for denne app. For at ændre på tilladelsen skal du gå til %1$s." + "App-indstillinger" + "Live placeringsopdateringer" + + "Hver %1$d meter" + "Hver %1$d meter" + "Upload fotos og videoer hurtigere, og reducér dataforbrug" "Optimér mediekvaliteten" "Moderation og sikkerhed" diff --git a/features/preferences/impl/src/main/res/values-hr/translations.xml b/features/preferences/impl/src/main/res/values-hr/translations.xml index 250af33d49..a40a6feccd 100644 --- a/features/preferences/impl/src/main/res/values-hr/translations.xml +++ b/features/preferences/impl/src/main/res/values-hr/translations.xml @@ -11,6 +11,15 @@ "Sakrij avatare u zahtjevima za poziv u sobu" "Sakrij preglede medija na vremenskoj traci" "Laboratoriji" + "Udaljenost koju morate prijeći da biste pokrenuli ažuriranje." + "Provjerite je li \"Precizna lokacija\" omogućena za ovu aplikaciju. Za promjenu dopuštenja idite na %1$s ." + "Postavke aplikacije" + "Ažuriranja lokacije uživo" + + "Svaki %1$d metar" + "Svaki %1$d metar" + "Svaki %1$d metara" + "Brže prenesite fotografije i videozapise te smanjite potrošnju podataka" "Optimiziraj kvalitetu medija" "Moderiranje i sigurnost" diff --git a/features/preferences/impl/src/main/res/values-hu/translations.xml b/features/preferences/impl/src/main/res/values-hu/translations.xml index c588e60eaf..d75166df5e 100644 --- a/features/preferences/impl/src/main/res/values-hu/translations.xml +++ b/features/preferences/impl/src/main/res/values-hu/translations.xml @@ -11,6 +11,14 @@ "Profilképek elrejtése a szobameghívókban" "Médiaelőnézetek elrejtése az idővonalon" "Kísérletek" + "A megtett távolság miután a helyadat frissül." + "Győződjön meg arról, hogy a „Pontos helymeghatározás” engedélyezve van ehhez az alkalmazáshoz. Az engedély módosításához menjen ide:%1$s ." + "Alkalmazásbeállítások" + "Élő helymeghatározás" + + "Minden %1$d méter" + "Minden %1$d méter" + "Töltse fel gyorsabban a fényképeket és videókat, valamint csökkentse az adatforgalmat" "Média minőségének optimalizálása" "Moderálás és biztonság" diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml index 10cbca0ada..22334c4120 100644 --- a/features/preferences/impl/src/main/res/values-ja/translations.xml +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -18,9 +18,9 @@ "%1$dm ごと" - "写真や動画を高速で送信してデータ使用量を減らす" + "写真や動画を高速で送信してデータ使用量を減らします。" "メディアの品質を最適化" - "制限と安全" + "セキュリティと制限" "自動的に画像を最適化してアップロード時間とファイルサイズを削減します。" "画像のアップロード画質を最適化" "%1$s 変更するにはタップしてください。" @@ -53,7 +53,7 @@ "プロフィールを更新中…" "スレッドへの返信を有効化" "変更を適用するためにアプリケーションは再起動します。" - "開発段階の最新機能を試します。未完成のため変更や不安定な挙動を生じる可能性があります。" + "開発段階の最新機能を試すことができます。未完成のため、変更や不安定な挙動が生じる可能性があります。" "探究したいですか?" "ラボ" "追加設定" @@ -68,7 +68,7 @@ "すべてのメッセージ" "メンションとキーワードのみ" "ダイレクトチャットで以下の通知を受け取る" - "グループチャットでは以下の通知を受け取る" + "グループチャットで以下の通知を受け取る" "この端末で通知を受け取る" "設定が修正されていません。再試行してください。" "グループチャット" @@ -77,7 +77,7 @@ "メンション" "すべて" "メンション" - "以下を通知する" + "以下を通知" @ルームで通知を受け取る "通知を受け取るには、%1$s を変更してください。" "システム設定" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index d57fb3b740..41eb147141 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -12,7 +12,7 @@ "在时间线上隐藏媒体预览" "实验室" "触发一次更新所需的移动距离。" - "确保已为 app 启用“精确位置”。如需更改该权限请转到 %1$s 。" + "确保已为 app 启用“精确位置”。如需更改该权限请转到 %1$s。" "App 设置" "实时位置更新" @@ -44,13 +44,13 @@ "解除屏蔽" "可以重新接收他们的消息。" "解除屏蔽用户" - "正在解除屏蔽……" + "正在解除屏蔽…" "显示名称" "你的显示名称" "遇到未知错误,无法更改信息。" "无法更新个人资料" "编辑个人资料" - "更新个人资料……" + "正在更新个人资料…" "启用消息列中的回复" "App 将重启以应用此更改。" "尝试我们最新的开发理念。这些功能尚未最终确定,可能不稳定,也可能会发生变化。" diff --git a/features/rageshake/api/src/main/res/values-zh/translations.xml b/features/rageshake/api/src/main/res/values-zh/translations.xml index ca81dd2d2c..8c78bbbc9c 100644 --- a/features/rageshake/api/src/main/res/values-zh/translations.xml +++ b/features/rageshake/api/src/main/res/values-zh/translations.xml @@ -1,6 +1,6 @@ - "%1$s 上次使用时崩溃了。想和我们分享崩溃报告吗?" + "%1$s 上次使用时曾崩溃过。是否与我们分享崩溃报告?" "你似乎愤怒地摇晃了手机。是否打开 Bug 报告页面?" "摇一摇" "检测阈值" diff --git a/features/rageshake/impl/src/main/res/values-zh/translations.xml b/features/rageshake/impl/src/main/res/values-zh/translations.xml index b34badea08..c42141d291 100644 --- a/features/rageshake/impl/src/main/res/values-zh/translations.xml +++ b/features/rageshake/impl/src/main/res/values-zh/translations.xml @@ -13,7 +13,7 @@ "日志文件过大,无法包含在本次报告中,请通过其它方式发送给我们。" "发送屏幕截图" "为确认一切正常运行,日志中将包含你的消息。如要发送不含消息的日志,请关闭此设置。" - "%1$s 上次使用时崩溃了。想和我们分享崩溃报告吗?" + "%1$s 上次使用时曾崩溃过。是否与我们分享崩溃报告?" "如果你遭遇通知相关问题,上传通知设置可以帮助我们调查根本原因。请注意:这些规则可能包含私人信息,例如你的显示名称或用于接收通知的关键词。" "发送通知设置" "查看日志" diff --git a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml index c526d059bc..2bd79bddd2 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml @@ -10,7 +10,7 @@ "مدیرن و ناظران" "برداشتن افراد و رد درخواست‌های پیوستن" "تغییر چهرک اتاق" - "ویرایش اتاق" + "ویرایش جزییات" "تغییر نام اتاق" "دگرگونی موضوع اتاق" "فرستادن پیام‌ها" diff --git a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml index 9d792fcc74..b28cf8e524 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ "管理员" - "封禁成员" + "封禁人员" "更改设置" "移除消息" "成员" @@ -39,7 +39,7 @@ "保存更改?" "暂无被封禁的用户。" - "%1$d 被禁用" + "%1$d 人被封禁" "检查拼写或尝试新搜索" "未找到 “%1$s” 相关结果" diff --git a/features/roomdetails/impl/src/main/res/values-da/translations.xml b/features/roomdetails/impl/src/main/res/values-da/translations.xml index e381a30957..2217e0b9c6 100644 --- a/features/roomdetails/impl/src/main/res/values-da/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-da/translations.xml @@ -153,7 +153,7 @@ Vi anbefaler ikke at aktivere kryptering for rum, som alle kan finde og deltage "Adgang" "Alle i autoriserede klynger kan deltage." "Alle i %1$s kan deltage." - "Medlemmer af rummet" + "Medlemmer af klyngen" "Klynger understøttes ikke i øjeblikket" "Du skal bruge en adresse for at gøre det synligt i det offentlige register." "Adresse" diff --git a/features/roomdetails/impl/src/main/res/values-fa/translations.xml b/features/roomdetails/impl/src/main/res/values-fa/translations.xml index bfe743fd1b..364c94c6f2 100644 --- a/features/roomdetails/impl/src/main/res/values-fa/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fa/translations.xml @@ -14,7 +14,7 @@ "مدیرن و ناظران" "برداشتن افراد و رد درخواست‌های پیوستن" "تغییر چهرک اتاق" - "ویرایش اتاق" + "ویرایش جزییات" "تغییر نام اتاق" "دگرگونی موضوع اتاق" "فرستادن پیام‌ها" @@ -40,7 +40,7 @@ "رمز شده" "رمزنگاری نشده" "اتاق عمومی" - "ویرایش اتاق" + "ویرایش جزییات" "خطایی ناشناخته رخ داد و اطّلاعات قابل تغییر نبودند." "ناتوان در به‌روز رسانی اتاق" "پیام‌ها با قفل محافظت می‌شوند. فقط شما و گیرندگان، کلیدهای منحصر به فرد برای باز کردن قفل آنها را دارید." diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index d2cc6773fb..267cdf5c04 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -9,7 +9,7 @@ "主服务器不支持在加密房间中的此选项,因此在某些房间你可能无法收到通知。" "投票" "管理员" - "封禁成员" + "封禁人员" "移除消息" "成员" "邀请人员" @@ -55,7 +55,7 @@ "无法取消静音此房间,请重试。" "完成之前请勿关闭 app。" "正在准备邀请…" - "邀请朋友" + "邀请人员" "离开聊天" "离开房间" "媒体与文件" @@ -75,7 +75,7 @@ "正在更新房间…" "暂无被封禁的用户。" - "%1$d 被禁用" + "%1$d 人被封禁" "检查拼写或尝试新搜索" "未找到 “%1$s” 相关结果" @@ -145,7 +145,7 @@ "任何人" "选择哪些无需邀请即可加入此房间的空间成员。%1$s" "管理空间" - "仅限受邀者加入。" + "仅限受邀人员加入。" "仅限受邀者" "访问权限" "任何位于已授权空间的成员均可加入。" diff --git a/features/roomdetailsedit/impl/src/main/res/values-fa/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-fa/translations.xml index bbbd63d171..a339ecd57f 100644 --- a/features/roomdetailsedit/impl/src/main/res/values-fa/translations.xml +++ b/features/roomdetailsedit/impl/src/main/res/values-fa/translations.xml @@ -1,6 +1,6 @@ - "ویرایش اتاق" + "ویرایش جزییات" "خطایی ناشناخته رخ داد و اطّلاعات قابل تغییر نبودند." "ناتوان در به‌روز رسانی اتاق" "به‌روز کردن اتاق…" diff --git a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml index 2c7e6584b8..bfd456f130 100644 --- a/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-zh/translations.xml @@ -13,7 +13,7 @@ "查看个人资料" "移除用户" "删除成员并禁止重新加入?" - "正在移除 %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 8363cb9754..d53086a6d1 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -2,9 +2,9 @@ "Backup deaktivieren" "Backup aktivieren" - "Speichere deine kryptographische Identität und die Nachrichtenschlüssel auf dem Server. Auf diese Weise kannst du deinen Nachrichtenverlauf auf neuen Geräten einsehen. %1$s." + "Dadurch kannst du deinen Chatverlauf auf allen neuen Geräten einsehen. Er ist außerdem für die Sicherung von Chats und deiner digitalen Identität erforderlich. %1$s." "Schlüsselspeicher" - "Der Schlüsselspeicher muss aktiviert sein, um Datenwiederherstellung zu ermöglichen." + "Die Schlüsselspeicherung muss aktiviert sein, damit deine Chats gesichert werden können." "Schlüssel von diesem Gerät hochladen" "Schlüsselspeicherung zulassen" "Wiederherstellungsschlüssel ändern" @@ -34,10 +34,10 @@ "Du musst alle deine bestehenden Geräte und Kontakte erneut verifizieren." "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?" - "Das Löschen des Schlüsselspeichers entfernt deine kryptografische Identität und deine Nachrichtenschlüssel vom Server. Die folgenden Sicherheitsfunktionen werden deaktiviert:" + "Löschen" + "Wenn du alle deine Geräte entfernst, gehen deine verschlüsselten Chatverläufe verloren und du musst deine digitale Identität zurücksetzen." + "Bist du sicher, dass du den Schlüsselspeicher löschen möchtest?" + "Durch das Löschen des Schlüsselspeichers werden deine digitale Identität und deine Nachrichtenschlüssel vom Server entfernt und die folgenden Sicherheitsfunktionen deaktiviert:" "Kein Nachrichtenverlauf für verschlüsselte Nachrichten auf neuen Geräten" "Kein Zugriff auf verschlüsselten Nachrichten, wenn du überall von %1$s abgemeldet bist" "Möchtest du die Speicherung der Schlüssel wirklich deaktivieren und entfernen?" diff --git a/features/securebackup/impl/src/main/res/values-ja/translations.xml b/features/securebackup/impl/src/main/res/values-ja/translations.xml index 7a7dd041fe..72c8c90809 100644 --- a/features/securebackup/impl/src/main/res/values-ja/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ja/translations.xml @@ -21,7 +21,7 @@ "生成された回復鍵をパスワードマネージャや暗号化に対応するメモアプリに保存してください。" "他の端末を使用して暗号化をリセット" "リセットを続行" - "アカウントの情報と連絡先や設定などは残ります" + "アカウントの情報や連絡先, 設定などは残ります" "サーバー上にのみ存在する過去のメッセージは確認できなくなります" "すべての端末と連絡先を再度検証する必要があります" "デジタルIDのリセットは、他のサインイン済みの端末と、回復鍵の両方へのアクセスを失った場合にのみ行ってください。" diff --git a/features/securebackup/impl/src/main/res/values-pt/translations.xml b/features/securebackup/impl/src/main/res/values-pt/translations.xml index 1e5d8b03ab..66051ca04b 100644 --- a/features/securebackup/impl/src/main/res/values-pt/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pt/translations.xml @@ -2,7 +2,7 @@ "Desativar a cópia de segurança" "Ativar a cópia de segurança" - "Guarda a tua identidade criptográfica e as chaves de mensagens de forma segura no servidor. Isto permitir-te-á ver o teu histórico de mensagens em qualquer dispositivo novo. %1$s." + "Permite-te ver o teu histórico de mensagens em qualquer dispositivo novo. É necessário para teres cópias de segurança das tuas conversas e da tua identidade digital. %1$s." "Armazenamento de chaves" "O armazenamento de chaves deve ser ativado para configurar a recuperação." "Carrega chaves a partir deste dispositivo" @@ -11,7 +11,7 @@ "Recupera a tua identidade criptográfica e o histórico de mensagens com uma chave de recuperação, caso tenhas perdido todos os teus dispositivos existentes." "Insere a chave de recuperação" "O teu armazenamento de chaves está atualmente dessincronizado." - "Configurar recuperação" + "Chave de recuperação" "Abre a %1$s num computador" "Iniciar sessão novamente" "Quando te for pedido para verificares o teu dispositivo, seleciona %1$s" @@ -25,10 +25,10 @@ "Necessitarás de verificar todos os teus dispositivos e contactos novamente." "Repõe a tua identidade apenas se não tiveres acesso a mais nenhum dispositivo com sessão iniciada e se tiveres perdido a tua chave de recuperação." "Repõe a tua identidade caso não consigas confirmar de outra forma" - "Desligar" - "Perderás as tuas mensagens cifradas se tiveres terminado a sessão em todos os teus dispositivos." - "Tens a certeza que queres desativar a cópia de segurança?" - "Desativar a cópia de segurança irá remover a atual cópia da chave de cifragem e desativar outras funcionalidades de segurança. Neste caso, irás:" + "Eliminar" + "Perderás os históricos de conversas cifradas e terás que repor a tua identidade digital caso removas todos os teus dispositivos." + "Tens a certeza que queres eliminar o armazenamento de chaves?" + "Eliminar o armazenamento de chaves irá remover a tua identidade digital e chaves de mensagem do servidor. Irá também desativar as seguintes funcionalidades de segurança:" "Não ter o histórico de mensagens cifradas em novos dispositivos" "Perder o acesso às tuas mensagens cifradas se terminares todas as sessões %1$s" "Tens a certeza que queres desativar a cópia de segurança?" @@ -58,7 +58,7 @@ "Gerar a tua chave de recuperação" "Não partilhes isto com ninguém!" "Recuperação configurada com sucesso" - "Configurar recuperação" + "Chave de recuperação" "Sim, repor agora" "Este processo é irreversível." "Tens a certeza que pretendes repor a tua cifra?" diff --git a/features/securebackup/impl/src/main/res/values-zh/translations.xml b/features/securebackup/impl/src/main/res/values-zh/translations.xml index c2e7d5c2cb..459291614e 100644 --- a/features/securebackup/impl/src/main/res/values-zh/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh/translations.xml @@ -48,7 +48,7 @@ "恢复密钥已确认" "输入恢复密钥" "恢复密钥已复制" - "正在生成……" + "正在生成…" "保存恢复密钥" "将此恢复密钥保存在安全的地方,例如密码管理器、加密笔记或物理保险箱。" "点击复制恢复密钥" diff --git a/features/securityandprivacy/impl/src/main/res/values-da/translations.xml b/features/securityandprivacy/impl/src/main/res/values-da/translations.xml index 659799693b..566c26b4af 100644 --- a/features/securityandprivacy/impl/src/main/res/values-da/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-da/translations.xml @@ -29,7 +29,7 @@ Vi anbefaler ikke at aktivere kryptering for rum, som alle kan finde og deltage "Adgang" "Alle i autoriserede klynger kan deltage." "Alle i %1$s kan deltage." - "Medlemmer af rummet" + "Medlemmer af klyngen" "Klynger understøttes ikke i øjeblikket" "Du skal bruge en adresse for at gøre det synligt i det offentlige register." "Adresse" diff --git a/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml b/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml index dda5834ba7..09a22f06b3 100644 --- a/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-zh/translations.xml @@ -24,7 +24,7 @@ "任何人" "选择哪些无需邀请即可加入此房间的空间成员。%1$s" "管理空间" - "仅限受邀者加入。" + "仅限受邀人员加入。" "仅限受邀者" "访问权限" "任何位于已授权空间的成员均可加入。" 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 f50879c573..2e46202dd4 100644 --- a/features/verifysession/impl/src/main/res/values-de/translations.xml +++ b/features/verifysession/impl/src/main/res/values-de/translations.xml @@ -3,7 +3,7 @@ "Bestätigung unmöglich?" "Erstelle einen neuen Wiederherstellungsschlüssel" "Wähle eine Verifizierungsmethode, um den sicheren Nachrichtenversand einzurichten." - "Bestätige deine Identität" + "Bestätige deine digitale Identität" "Ein anderes Gerät verwenden" "Wiederherstellungsschlüssel verwenden" "Du kannst jetzt verschlüsselte Nachrichten lesen und versenden. Dein Chatpartner vertraut nun diesem Gerät." @@ -17,7 +17,7 @@ "Bestätige, dass die folgenden Zahlen mit denen in deiner anderen Sitzung übereinstimmen." "Vergleiche die Zahlen" "Jetzt kannst du verschlüsselte Nachrichten sicher auf deinem anderen Gerät schreiben und lesen." - "Jetzt kannst du der Identität dieses Nutzers vertrauen, wenn du Nachrichten sendest oder empfängst." + "Jetzt kannst du beim Senden oder Empfangen von Nachrichten der digitalen Identität dieses Nutzers vertrauen." "Gerät verifiziert" "Wiederherstellungsschlüssel eingeben" "Entweder ist die Anfrage abgelaufen, oder die Anfrage wurde abgelehnt, oder es gab eine Unstimmigkeit bei der Überprüfung." @@ -42,7 +42,7 @@ "Öffne die App auf einem anderen verifizierten Gerät" "Verifiziere diesen Nutzer für zusätzliche Sicherheit durch den Vergleich einer Reihe von Emojis auf den Geräten. Verwende dazu einen vertraulichen Kommunikationskanal." "Diesen Nutzer verifizieren?" - "Für zusätzliche Sicherheit möchte ein anderer Nutzer deine Identität verifizieren. Es werden dir einige Emojis zum Vergleich angezeigt." + "Zur zusätzlichen Sicherheit möchte ein anderer Nutzer deine digitale Identität verifizieren. Dir werden einige Emojis zum Abgleich angezeigt." "Du solltest ein Popup-Fenster auf dem anderen Gerät sehen. Starte die Verifizierung von dort aus." "Starte die Verifizierung auf dem anderen Gerät" "Starte die Verifizierung auf dem anderen Gerät" diff --git a/features/verifysession/impl/src/main/res/values-fa/translations.xml b/features/verifysession/impl/src/main/res/values-fa/translations.xml index ffc03e1f19..aa902a94e1 100644 --- a/features/verifysession/impl/src/main/res/values-fa/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fa/translations.xml @@ -32,5 +32,5 @@ "مطابقند" "برای ادامه، درخواست شروع فرآیند تأیید را در جلسه دیگر خود بپذیرید." "منظر پذیرش درخواست" - "خارج شدن…" + "برداشتن افزاره…" diff --git a/features/verifysession/impl/src/main/res/values-in/translations.xml b/features/verifysession/impl/src/main/res/values-in/translations.xml index 021a528646..05a5bae0ab 100644 --- a/features/verifysession/impl/src/main/res/values-in/translations.xml +++ b/features/verifysession/impl/src/main/res/values-in/translations.xml @@ -50,5 +50,5 @@ "Setelah diterima, Anda akan dapat melanjutkan verifikasi." "Terima permintaan untuk memulai proses verifikasi di sesi Anda yang lain untuk melanjutkan." "Menunggu untuk menerima permintaan" - "Mengeluarkan dari akun…" + "Mengeluarkan device dari akun…" diff --git a/features/verifysession/impl/src/main/res/values-pt/translations.xml b/features/verifysession/impl/src/main/res/values-pt/translations.xml index bf32d3c7b9..2bbda1497a 100644 --- a/features/verifysession/impl/src/main/res/values-pt/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pt/translations.xml @@ -3,7 +3,7 @@ "Não é possível confirmar?" "Criar uma nova chave de recuperação" "Verifica este dispositivo para configurar o envio seguro de mensagens." - "Confirma que és tu" + "Confirma a tua identidade digital" "Utilizar outro dispositivo" "Utilizar chave de recuperação" "Agora podes ler ou enviar mensagens de forma segura, e qualquer pessoa com quem converses também pode confiar neste dispositivo." @@ -50,5 +50,5 @@ "Uma vez aceite, poderás continuar com a verificação." "Para continuar, aceita o pedido de verificação na tua outra sessão." "À aguardar a aceitação do pedido" - "A terminar sessão…" + "A remover dispositivo…" diff --git a/features/verifysession/impl/src/main/res/values-zh/translations.xml b/features/verifysession/impl/src/main/res/values-zh/translations.xml index 63cb67330b..61b7b078dd 100644 --- a/features/verifysession/impl/src/main/res/values-zh/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh/translations.xml @@ -9,7 +9,7 @@ "现在你可以安全地读取或发送消息,并且与你聊天的任何人也可以信任此设备。" "设备已验证" "使用其它设备" - "正在等待其它设备……" + "正在等待其它设备…" "发生了一些错误。网络请求超时,或者被服务器拒绝。" "确认以下 Emoji 与你的其它设备上显示的相匹配。" "比较 Emoji" @@ -25,7 +25,7 @@ "打开已有会话" "重试验证" "准备就绪" - "等待比对……" + "正在等待对比…" "比较一组唯一的 Emoji。" "比较唯一的 Emoji,确保它们以相同顺序排列。" "已登录" @@ -50,5 +50,5 @@ "一旦被接受,你将能够继续进行验证。" "接受此请求以在另一会话中开始验证流程以继续操作。" "等待接受请求" - "正在删除设备……" + "正在移除设备…" diff --git a/libraries/dateformatter/impl/src/main/res/values-zh/translations.xml b/libraries/dateformatter/impl/src/main/res/values-zh/translations.xml index 9fab311a1d..d1ee550b73 100644 --- a/libraries/dateformatter/impl/src/main/res/values-zh/translations.xml +++ b/libraries/dateformatter/impl/src/main/res/values-zh/translations.xml @@ -1,5 +1,5 @@ - "%1$s在 %2$s" + "于 %1$s %2$s" "本月" diff --git a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml index 35a501c7a2..f7e5d7d7f2 100644 --- a/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-zh/translations.xml @@ -45,8 +45,8 @@ "你将房间名称更改为 %1$s" "%1$s 移除了房间名称" "你移除了房间名称" - "%1$s 没有任何更改" - "你未做任何更改" + "%1$s 未产生任何更改" + "你未产生任何更改" "%1$s 更改了已置顶的消息" "你更改了已置顶的消息" "%1$s 置顶了 1 个消息" diff --git a/libraries/matrixui/src/main/res/values-da/translations.xml b/libraries/matrixui/src/main/res/values-da/translations.xml index 5b4970f003..f2dfa27073 100644 --- a/libraries/matrixui/src/main/res/values-da/translations.xml +++ b/libraries/matrixui/src/main/res/values-da/translations.xml @@ -3,5 +3,7 @@ "Send invitation" "Kunne du tænke dig at starte en samtale med %1$s?" "Send invitation?" + "Du har i øjeblikket ingen samtaler med denne person. Bekræft invitationen, før du fortsætter." + "Vil du starte en chat med denne nye kontakt?" "%1$s(%2$s ) inviterede dig" diff --git a/libraries/matrixui/src/main/res/values-zh/translations.xml b/libraries/matrixui/src/main/res/values-zh/translations.xml index b466f13226..e05e21095d 100644 --- a/libraries/matrixui/src/main/res/values-zh/translations.xml +++ b/libraries/matrixui/src/main/res/values-zh/translations.xml @@ -5,5 +5,5 @@ "发送邀请?" "你与此人暂无任何聊天。请确认对方被邀请后再继续。" "是否与新联系人开始聊天?" - "%1$s (%2$s)邀请了你" + "%1$s(%2$s)邀请了你" diff --git a/libraries/mediaviewer/impl/src/main/res/values-da/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-da/translations.xml index 5d88458495..6108eab22d 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-da/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-da/translations.xml @@ -16,6 +16,7 @@ "Filnavn" "Ikke flere filer at vise" "Ikke flere medier at vise" + "Filoplysninger" "Uploadet af" "Uploadet på" diff --git a/libraries/mediaviewer/impl/src/main/res/values-fr/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-fr/translations.xml index b6334095ab..77372c1374 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-fr/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-fr/translations.xml @@ -16,6 +16,7 @@ "Nom du fichier" "Il n’y a plus de fichiers à montrer" "Il n’y a plus de médias à montrer" + "Informations sur le fichier" "Envoyé par" "Envoyé le" diff --git a/libraries/mediaviewer/impl/src/main/res/values-hr/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-hr/translations.xml index 7637fbf350..2a417cc070 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-hr/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-hr/translations.xml @@ -16,6 +16,7 @@ "Naziv datoteke" "Nema više datoteka za prikaz" "Nema više medijskih sadržaja za prikaz" + "Informacije o datoteci" "Prenio/la" "Preneseno na" diff --git a/libraries/mediaviewer/impl/src/main/res/values-hu/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-hu/translations.xml index 14cc11fb96..4f4d244d44 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-hu/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-hu/translations.xml @@ -16,6 +16,7 @@ "Fájlnév" "Nincs több megjeleníthető fájl" "Nincs több megjeleníthető média" + "Fájlinformáció" "Feltöltötte:" "Feltöltve:" diff --git a/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml index cb4da33df8..9e136b0884 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-ja/translations.xml @@ -16,6 +16,7 @@ "ファイル名" "これ以上ファイルはありません" "これ以上メディアはありません" + "ファイル情報" "アップロード元" "アップロード先" diff --git a/libraries/push/impl/src/main/res/values-zh/translations.xml b/libraries/push/impl/src/main/res/values-zh/translations.xml index 21988770c0..881dbcdc54 100644 --- a/libraries/push/impl/src/main/res/values-zh/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh/translations.xml @@ -14,7 +14,7 @@ "UnifiedPush 分发器注册失败,你将无法再接收通知。请检查 app 的通知设置及推送分发器的状态。" "你有新消息。" - "你有 %d 条新消息。" + "你有 %d 个新消息。" "📞 来电" "📹 来电" diff --git a/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml b/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml index fdde227bef..f79cb2f30c 100644 --- a/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml +++ b/libraries/textcomposer/impl/src/main/res/values-zh/translations.xml @@ -4,8 +4,8 @@ "切换符号列表" "取消并关闭文本格式" "切换代码块" - "可选的标题……" - "加密信息…" + "添加标题…" + "已加密的消息…" "消息…" "未加密的消息…" "创建链接" 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 e9ed8edaa4..f1ff7ec747 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -14,9 +14,10 @@ "Krypteringsoplysninger" "Udvid tekstfeltet for beskeder" "Skjul adgangskode" + "Info" "Deltag i opkald" "Hop til bunden" - "Flyt kortet til min lokation" + "Flyt kortet til min placering" "Kun omtaler" "Lyd slået fra" "Nye omtaler" @@ -48,8 +49,10 @@ "Send filer" "Afsenderens placering" "Tidsbegrænset handling påkrævet, du har et minut til at bekræfte" + "Indstillinger, handling påkrævet" "Vis adgangskode" "Start et opkald" + "Start et videoopkald" "Start et taleopkald" "Deaktiveret rum" "Avatar for bruger" @@ -87,12 +90,15 @@ "Deaktiver konto" "Afvis" "Afvis og blokér" + "Slet" + "Slet konto" "Slet afstemning" "Fravælg alle" "Deaktiver" "Kassér" "Afvis" "Færdig" + "Hent" "Redigér" "Rediger billedtekst" "Redigér afstemning" @@ -160,7 +166,7 @@ "Send talebesked" "Del" "Del link" - "Del liveplacering" + "Del placering live" "Vis" "Log ind igen" "Fjern denne enhed" @@ -200,7 +206,9 @@ "Beta" "Blokerede brugere" "Bobler" + "Opkald afvist" "Opkald startet" + "Du afviste et opkald" "Backup af samtale" "Kopieret til udklipsholder" "Ophavsret" @@ -357,7 +365,7 @@ "Noget gik galt" "Vi stødte på et problem. Prøv venligst igen." "Klynge" - "Medlemmer af rummet" + "Medlemmer af klyngen" "Hvad handler denne klynge om?" "%1$d Klynge" @@ -465,6 +473,13 @@ Er du sikker på, at du vil fortsætte?" "Valgmuligheder" "Fjern %1$s" "Indstillinger" + "Ingen deler deres placering" + "Deler placering live" + + "%1$d person" + "%1$d personer" + + "På kortet" "Det lykkedes ikke at vælge medie. Prøv igen." "Tryk på en besked og vælg \"%1$s\" for at inkludere den her." "Fastgør vigtige beskeder, så de let kan opdages" @@ -489,14 +504,15 @@ Er du sikker på, at du vil fortsætte?" "Besked i %1$s" "Udvid" "Reducér" + "Deler placering live" "Du ser allerede dette rum!" "%1$s af %2$s" "%1$s Fastgjorte beskeder" "Indlæser besked…" "Se alle" "Samtale" - "Del lokation" - "Del min lokation" + "Del placering" + "Del min placering" "Åbn i Apple Maps" "Åbn i Google Maps" "Åbn i OpenStreetMap" @@ -512,7 +528,7 @@ Er du sikker på, at du vil fortsætte?" "Beskeden blev ikke sendt fordi %1$s s bekræftede digitale identitet blev nulstillet." "Meddelelsen er ikke sendt, fordi %1$s ikke har bekræftet alle enheder." "Beskeden er ikke sendt, fordi du ikke har verificeret en eller flere af dine enheder." - "Lokation" + "Placering" "Version: %1$s (%2$s)" "da" "Historiske beskeder er ikke tilgængelige på denne enhed" 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 81cb12eb78..739d003f88 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -447,6 +447,7 @@ Möchtest du wirklich fortfahren?" "%1$s konnte nicht auf deinen Standort zugreifen. Bitte versuche es später erneut." "Fehler beim Hochladen der Sprachnachricht." "Der Chat existiert nicht mehr oder die Einladung ist nicht mehr gültig." + "Bitte aktiviere dein GPS, um auf standortbezogene Funktionen zugreifen zu können." "Nachricht nicht gefunden" "%1$s hat keine Berechtigung, auf deinen Standort zuzugreifen. Du kannst den Zugriff in den Einstellungen aktivieren." "%1$s hat keine Berechtigung, auf deinen Standort zuzugreifen. Erlaube unten den Zugriff." @@ -473,7 +474,7 @@ Möchtest du wirklich fortfahren?" "%1$d fixierte Nachrichten" "Fixierte Nachrichten" - "Du wirst jetzt zu deinem %1$s Konto geleitet, um deine Identität zurückzusetzen. Danach wirst du zur App zurückgebracht." + "Du wirst gleich zu deinem %1$s Konto weitergeleitet, um deine digitale Identität zurückzusetzen. Danach kehrst du zur App zurück." "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." @@ -509,7 +510,7 @@ Möchtest du wirklich fortfahren?" "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, da die verifizierte digitale Identität von %1$s zurückgesetzt wurde." "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." "Standort" @@ -519,5 +520,5 @@ Möchtest du wirklich fortfahren?" "Für den Zugriff auf den Nachrichtenverlauf musst du dieses Gerät verifizieren" "Du hast keinen Zugriff auf diese Nachricht." "Nachricht kann nicht entschlüsselt werden" - "Diese Nachricht wurde entweder blockiert, weil du dein Gerät nicht verifiziert hast oder weil der Absender deine Identität verifizieren muss." + "Diese Nachricht wurde entweder blockiert, weil du dein Gerät nicht verifiziert hast, oder weil der Absender deine digitale Identität verifizieren muss." diff --git a/libraries/ui-strings/src/main/res/values-fa/translations.xml b/libraries/ui-strings/src/main/res/values-fa/translations.xml index fbe716bc49..872493f7de 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -145,7 +145,7 @@ "هم‌رسانی پیوند" "نمایش" "ورود دوباره" - "خروج" + "برداشتن این افزاره" "خروج به هر صورت" "پرش" "آغاز" @@ -389,7 +389,7 @@ "گشودن در نقشه‌های اپل" "گشودن در نقشه‌های گوگل" "گشودن در اوپن‌استریت‌مپ" - "هم‌رسانی این مکان" + "هم‌رسانی مکان گزیده" "فضاهایی که ساخته یا پیوسته‌اید." "%1$s • %2$s" "‏%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 08791b1b38..7e0c4e9481 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -14,6 +14,7 @@ "Détails du chiffrement" "Augmenter la taille du composeur" "Masquer le mot de passe" + "Info" "Rejoindre l’appel" "Retourner à la fin de la conversation" "Déplacer la carte vers ma position" @@ -48,6 +49,7 @@ "Envoyer des fichiers" "Position de l’expéditeur" "Action limitée dans le temps requise, vous avez une minute pour effectuer la vérification" + "Paramètres, action requise" "Afficher le mot de passe" "Démarrer un appel" "Passer un appel vidéo" @@ -96,6 +98,7 @@ "Annuler" "Ignorer" "Terminé" + "Télécharger" "Modifier" "Modifier la légende" "Modifier le sondage" @@ -203,7 +206,9 @@ "Bêta" "Utilisateurs bloqués" "Bulles" + "Appel rejeté" "Appel démarré" + "Vous avez rejeté un appel" "Sauvegarde des discussions" "Copié dans le presse-papiers" "Droits d’auteur" 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 61c9ea54e2..2382eafc1a 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -15,6 +15,7 @@ "Pojedinosti o šifriranju" "Proširi tekstno polje poruke" "Sakrij zaporku" + "Informacije" "Pridruži se pozivu" "Idi na dno" "Pomakni kartu na moju lokaciju" @@ -50,6 +51,7 @@ "Pošalji datoteke" "Lokacija pošiljatelja" "Potrebna je vremenski ograničena radnja, imate jednu minutu za potvrdu" + "Postavke, potrebna je radnja" "Prikaži zaporku" "Započni poziv" "Započni videopoziv" @@ -90,12 +92,15 @@ "Deaktiviraj račun" "Odbij" "Odbij i blokiraj" + "Izbriši" + "Izbriši račun" "Izbriši anketu" "Poništi sve odabire" "Onemogući" "Odbaci" "Odbaci" "Gotovo" + "Preuzmi" "Uredi" "Uredi opis" "Uredi anketu" @@ -203,7 +208,9 @@ "Beta" "Blokirani korisnici" "Mjehurići" + "Poziv je odbijen" "Poziv je započeo" + "Odbili ste poziv" "Sigurnosna kopija razgovora" "Kopirano u međuspremnik" "Autorsko pravo" @@ -475,6 +482,14 @@ Jeste li sigurni da želite nastaviti?" "Mogućnosti" "Ukloni %1$s" "Postavke" + "Nitko ne dijeli svoju lokaciju" + "Dijeljenje lokacije uživo" + + "%1$d osoba" + "%1$d osoba" + "%1$d ljudi" + + "Na karti" "Odabir medija nije uspio, pokušajte ponovno." "Pritisnite poruku i odaberite “%1$s” kako biste uključili ovdje." "Prikvačite važne poruke kako bi ih se lakše moglo pronaći" 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 06f49eba93..f6498f228f 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -14,6 +14,7 @@ "Titkosítás részletei" "Üzenet szövegmezőjének kibontása" "Jelszó elrejtése" + "Információ" "Csatlakozás a híváshoz" "Ugrás az aljára" "Térkép áthelyezése a jelenlegi helyre" @@ -48,6 +49,7 @@ "Fájlküldés" "Felhasználó tartózkodási helye" "Időkorlátos művelet szükséges, egy perce van az ellenőrzésre" + "Beállítások, beavatkozás szükséges" "Jelszó megjelenítése" "Hanghívás indítása" "Videohívás indítása" @@ -88,12 +90,15 @@ "Fiók deaktiválása" "Elutasítás" "Elutasítás és letiltás" + "Törlés" + "Fiók törlése" "Szavazás törlése" "Kijelölés megszüntetése" "Letiltás" "Elvetés" "Eltüntetés" "Kész" + "Letöltés" "Szerkesztés" "Felirat szerkesztése" "Szavazás szerkesztése" @@ -201,7 +206,9 @@ "Béta" "Letiltott felhasználók" "Buborékok" + "Hívás elutasítva" "A hívás elindult" + "Elutasított egy hívást" "Csevegés biztonsági mentése" "A vágólapra másolva" "Szerzői jogok" diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index 5a095a074f..77e405e1c8 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -144,7 +144,7 @@ "Bagikan tautan" "Tampilkan" "Masuk lagi" - "Keluar dari akun" + "Hapus device dari akun" "Keluar saja" "Lewati" "Mulai" 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 ae5592d3f6..1c022f850f 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -13,6 +13,7 @@ "暗号化の詳細" "入力欄を拡大" "パスワードを非表示" + "情報" "通話に参加" "一番下へ" "現在地に移動" @@ -46,6 +47,7 @@ "ファイルを送信" "送信者の位置情報" "1分以内に検証を完了してください" + "処置が必要な設定" "パスワードを表示" "通話を開始" "ビデオ通話を開始" @@ -67,6 +69,7 @@ "通話" "キャンセル" "今回のみキャンセル" + "ファイルを選択" "写真を選択" "クリア" "閉じる" @@ -94,6 +97,7 @@ "破棄" "無視" "完了" + "ダウンロード" "編集" "キャプションを編集" "投票を編集" @@ -196,12 +200,14 @@ "通知を同期中…" "あなたがルームを退出" "セッションからログアウトされました" - "外観" + "テーマ" "音声" "ベータ版" "ブロックしたユーザー" "ふきだし" + "通話を拒否しました" "通話を開始しました" + "通話を拒否しました" "チャットをバックアップ" "クリップボードにコピーしました" "著作権" diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index 56346fe1ac..dd15875590 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -152,8 +152,8 @@ "Partilhar ligação" "Mostrar" "Iniciar sessão novamente" - "Terminar sessão" - "Terminar mesmo assim" + "Remover este dispositivo" + "Remover mesmo assim" "Saltar" "Iniciar" "Iniciar conversa" @@ -322,7 +322,7 @@ Razão: %1$s." "Partilhar espaço" "Localização partilhada" "Espaço partilhado" - "A terminar sessão" + "A remover dispositivo" "Algo correu mal" "Encontramos um erro. Por favor, tenta novamente." "Espaço" @@ -458,7 +458,7 @@ Tens a certeza de que queres continuar?" "Abrir no Apple Maps" "Abrir no Google Maps" "Abrir no OpenStreetMap" - "Partilhar este local" + "Partilhar local selecionado" "Espaços que criaste ou nos quais entraste." "%1$s • %2$s" "Espaço %1$s" 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 7bd218ca54..974e91b530 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -40,7 +40,7 @@ "%1$s 已读" "点击以显示全部" - "撤回反应 %1$s" + "移除反应:%1$s" "移除反应:%1$s" "房间头像" "发送文件" @@ -110,9 +110,9 @@ "前往设置" "忽略" "邀请" - "邀请朋友" - "邀请别人加入 %1$s" - "邀请别人加入 %1$s" + "邀请人员" + "邀请人员加入 %1$s" + "邀请人员加入 %1$s" "邀请" "加入" "了解更多" @@ -145,7 +145,7 @@ "回复" "在消息列中回复" "举报" - "报告错误" + "报告 bug" "举报内容" "举报对话" "举报房间" @@ -165,8 +165,8 @@ "共享实时位置" "显示" "再次登录" - "删除此设备" - "仍要删除此设备" + "移除此设备" + "仍要移除此设备" "跳过" "开始" "开始聊天" @@ -238,7 +238,7 @@ 原因:%1$s。" "所有人" "失败" - "收藏夹" + "收藏" "已收藏" "文件" "文件已删除" @@ -285,7 +285,7 @@ "或" "其它选项" "密码" - "用户" + "人员" "永久链接" "权限" "已置顶" @@ -408,7 +408,7 @@ "由于你当时不在房间内,%1$s(%2$s)已将消息向你共享。" "由于你当时不在房间内,%1$s 已将消息向你共享。" "此房间已配置为允许新成员阅读历史。%1$s" - "%1$s的数字身份已重置。%2$s" + "%1$s 的数字身份已重置。%2$s" "%1$s %2$s 的数字身份已重置。%3$s" "(%1$s)" "%1$s 的数字身份已重置。" @@ -440,7 +440,7 @@ "你的主服务器需要升级,以支持 Matrix 认证服务和账户创建。" "永久链接创建失败" "%1$s 无法加载地图,请稍后再试。" - "加载消息失败" + "消息加载失败" "%1$s 无法访问你的位置,请稍后再试。" "无法上传语音消息。" "该房间已不存在或邀请已失效。" @@ -495,7 +495,7 @@ "共享实时位置" "已经位于此房间!" "%1$s / %2$s" - "置顶消息 %1$s" + "%1$s 个已置顶的消息" "正在加载消息…" "查看全部" "聊天" @@ -511,9 +511,9 @@ "创建空间以组织房间" "空间 %1$s" "空间" - "共享于%1$s" + "已共享 %1$s" "在地图上" - "消息未发送,因为%1$s的已验证数字身份已被重置。" + "消息未能发送,因为 %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 9db9bb4751..cdb3c52e6a 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -71,6 +71,7 @@ "Call" "Cancel" "Cancel for now" + "Choose file" "Choose photo" "Clear" "Close" diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png index 8843434a9f..08a4e04bba 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e31bebf55244a497eaf3442701b0db8b5ee6c061944c1b4e72da487660104643 -size 40044 +oid sha256:9b6138083429a82d1de576009df367a52361b39e5ac094d0c4abc0bb47e89550 +size 41888 diff --git a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png index 4e4cdee57b..5771464dd2 100644 --- a/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ce67e2cd809b3ba7f32c57cf87208e71a92df71b545bea2554ed7f6d28e78e7 -size 41381 +oid sha256:981e3075d5285a630932c02427cca3d46efad74a640f12d35da8e0f29fb4b779 +size 43474 diff --git a/screenshots/de/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_de.png b/screenshots/de/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_de.png index 21c6405a77..1cc92bddf4 100644 --- a/screenshots/de/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_de.png +++ b/screenshots/de/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22e0fb8867a616d7d575f9262996f66730cb61f8b0e9c2c74fffbb92b3a1fd06 -size 25852 +oid sha256:ac79f05488afb65d5675a8068ac1c70c7cddc81b1db5445f1314ce53a1da8ba1 +size 27143 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png index fdbc13a1ee..5edce6541b 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b62cf320453eb36be6e486e3100c3be1420fcdfd068f2276d27a824fb84e3f05 -size 42064 +oid sha256:9c1602858c58d4f05c5c3d816cde905af8cd888ae9337215119902b0dbdf1cbc +size 43609 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png index ddbdfb051f..641671bf3f 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88633b6deed6e44e354cf3c8ac9e8553f0dd41743198cf5d8ff57de51ecd45e4 -size 35217 +oid sha256:1acc89193300b0ea268c127c98c7d46b8e23841933750d99d597a8713e1698ed +size 36762 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png index 0dafa02950..b9ce42a450 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0887222f914448055346fd314b3a8bfdaeda5262b76f509749ec01877728a821 -size 48344 +oid sha256:0f5bddbb812e5fd0863a8c1308349f627f0e8fd865ee36f995a29666e0816b0d +size 49843 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png index 8051720f82..f8be736047 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c355fb7f9e899e9cc7fe9a4a0aefacb7f57e669b60927b9c77f29630a6168b0 -size 41774 +oid sha256:5e141bd8ca4767ded168a1e7cb574df8d33797e05ced6615287469b282d985b1 +size 43319 diff --git a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png index 40197c311f..5697209279 100644 --- a/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png +++ b/screenshots/de/features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6085e75ee0b5669b078b7ff40c6f9e91f04263967a46076dda95802992224318 -size 31603 +oid sha256:15bba5407bbda9070cf2109165e4fb9455450c8d6dd504dea7b521640fcfa48d +size 33229 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png new file mode 100644 index 0000000000..efd83f7af8 --- /dev/null +++ b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2e4ee3ec519388e7acdedac96636aa3f0e0d9dc4f4a061a0b3e4c345b824a3d +size 24961 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png new file mode 100644 index 0000000000..b7a581021f --- /dev/null +++ b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d367fc2d1c620eb370e28db890e4f01acd85b0273b241d0b0b701f23939fabc8 +size 25377 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png new file mode 100644 index 0000000000..0c1e7996ff --- /dev/null +++ b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6175b377fcdb3f70739c36ceb1d59a7e108d8f1d08b4c10ec6d28744ff0f0545 +size 27442 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_de.png b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_de.png deleted file mode 100644 index b51bbdbfc7..0000000000 --- a/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cf13adc113fe7b1127eedde7ed659ac11afb25b25be22f757dfd22c363e011f5 -size 29190 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_de.png b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_de.png new file mode 100644 index 0000000000..67b0361c5c --- /dev/null +++ b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26a5736c3ce48028bde69a7f029ffaed5d18e490b32fbb455d35d89f90f7e169 +size 30385 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_de.png b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_de.png new file mode 100644 index 0000000000..c39d87d73c --- /dev/null +++ b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9caedf891866305599b0cc1887f46fc2ae7e0c6ca903860df247eb48eadf3708 +size 45796 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_de.png b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_de.png new file mode 100644 index 0000000000..950a33e731 --- /dev/null +++ b/screenshots/de/features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:469c3186032dae6ed8d4203277b9a45d5c5f648e7688a5a6804231ac648daef4 +size 30940 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_de.png b/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_de.png deleted file mode 100644 index 097191f4f2..0000000000 --- a/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ba628bba3efe736cbfd164d8c5a403ef042cefd29fef6307fc2c2694798b0e18 -size 23407 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_de.png b/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_de.png deleted file mode 100644 index d9912fb3e0..0000000000 --- a/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:811bc09258019248f5cd94ee8cfeb070b1471f510ba4ad16b427e4c574db46a9 -size 23660 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_de.png b/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_de.png deleted file mode 100644 index cc6b3c7a57..0000000000 --- a/screenshots/de/features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7dada5eb605d5558baea8b01101bfbb8cc31338b2ce76035a8fcb449cdd8e77b -size 25776 diff --git a/screenshots/de/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_de.png b/screenshots/de/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_de.png new file mode 100644 index 0000000000..630aee04c5 --- /dev/null +++ b/screenshots/de/features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:495afd76bb17398747975e89e5dadb28e7b8c20309725264be293420b8518ec8 +size 38456 diff --git a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_2_de.png b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_2_de.png index 92ffd71139..308abe5a72 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_2_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf9aea8bd7c9f6d7eb7f31a71ec412ae0f143c60bc6834a1f2ad99e538d87875 -size 33758 +oid sha256:a1e6cd137958c6f3cd9ddad7cdf9dcd35c9b9963cdab164c232ebefa50b7a81b +size 33815 diff --git a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png index 0f07d0568c..7ea7736a31 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:968c091419c902a4c135a4498ebe2422566d0f2dac72882e81ac5dc6572a9e77 -size 42859 +oid sha256:06fa1d9cfcdd7e81dd5d08f584651d982136e7491041b4db6c0feb9875c2db49 +size 43509 diff --git a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_4_de.png b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_4_de.png index feacf82d89..0b411260ec 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_4_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e71f2781efd689a0c57613cf03fec734474128ae444b8079d6124f8b9aa19fb -size 45605 +oid sha256:0b41b171588b46f2b17fe366d311da43653c43dc1eccf539c7f02c12d1c7a21f +size 45688 diff --git a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_8_de.png b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_8_de.png new file mode 100644 index 0000000000..cba542a991 --- /dev/null +++ b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e77e5930c00c3389179fc5a60a6a2d173223adaf742a53b6900ab96ab0af88a +size 22202 diff --git a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_de.png b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_de.png index 1ea459175f..0e9606c453 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91215fa6820bbe0d6da772de2720cde77bc731f28954d067c6a6a0d95709f624 -size 19238 +oid sha256:748da581859b8b1a05a2b5703c17b31f6725d26713053063dc825b425b4d4131 +size 19317 diff --git a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_de.png b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_de.png index 45ed4366dc..7127f05f27 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:419f4edd8b097ca40f68d5012c5b0c0e6c1301b6efcd01b13ce0c8e7a13996c6 -size 25430 +oid sha256:446b2dbace2a10eb7332886ce7fa83f992c5314f3a66fd402a13200e9f0f06b2 +size 25489 diff --git a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_de.png b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_de.png index a9af23935f..c5645b1b44 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e40215a3f06166fa78319875ca074876e41e19a9155794f4d0b68a132045a276 -size 27975 +oid sha256:84da7365709446471e67dedd9f733786989f56fa1d3fe83ea5ec02344076983f +size 28966 diff --git a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_de.png b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_de.png index e172ea6f3d..f466ac0135 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1684330a9b215bb22fbefe2e59d456c9cbc31e75e01828c67a256b0a02b667f -size 25956 +oid sha256:a7b92adb8584cf31853a01bda52aacab97df832360399adbf63980ebb612ce76 +size 26029 diff --git a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_de.png b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_de.png index 4b15ed217c..2fdab6284a 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e96f99f81040aa3214a1acd937d25299d080ca0191258562cb08f78fbdeff7e -size 26188 +oid sha256:cde54cd972be78cb89278b4382d7b71297bdeddb0a16503211ed0342ad059a2b +size 26237 diff --git a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_de.png b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_de.png index 75f85cba2e..fbda7d633d 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:759da98dca2f26b5a7e87954fceba866e7fb526dc36587b62cb3d01f3ba29b53 -size 34992 +oid sha256:76c3bacabeab51017a076a58ff61176ec45fff9711b86471cf1e6752692a201a +size 35056 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png index f4290dda6e..8381a894f4 100644 --- a/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2eb237f3bea51645310fe28e66a374ee7eea722d262261faf7a2d4ad7bfc9515 -size 30400 +oid sha256:6ad541415245d6e6ca95514db2aa053691d8d2c8193cf0268be67cc74b1af4ea +size 32928 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png index 8cf129ffae..6a87af5d60 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ad009477e6df04362db43d17c2a43599ae19812ef4244b0ffdd436e18662969 -size 32383 +oid sha256:da8a5e9159c4817b5c500d721e378e51d1f3ed6bea5468b54e4e66db1969c292 +size 34873 diff --git a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_5_de.png b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_5_de.png index c6a8d72619..ec9de6ee4e 100644 --- a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_5_de.png +++ b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c3b505df79be2829a102e9a0249fc23c5f5de1e7fa19570a1fd1e5ab7f9aaee -size 30819 +oid sha256:228c78854193cffdf1a0a22a80eb742b01dcef195192196f7b63c32f3d0666e8 +size 30823 diff --git a/screenshots/de/features.login.impl.login_LoginModeView_Day_5_de.png b/screenshots/de/features.login.impl.login_LoginModeView_Day_5_de.png index c6a8d72619..ec9de6ee4e 100644 --- a/screenshots/de/features.login.impl.login_LoginModeView_Day_5_de.png +++ b/screenshots/de/features.login.impl.login_LoginModeView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c3b505df79be2829a102e9a0249fc23c5f5de1e7fa19570a1fd1e5ab7f9aaee -size 30819 +oid sha256:228c78854193cffdf1a0a22a80eb742b01dcef195192196f7b63c32f3d0666e8 +size 30823 diff --git a/screenshots/de/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_de.png b/screenshots/de/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_de.png index 50663c9d70..7848b3de7f 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8153b9a20bb2cda60b59abb617f527b165f54fee15235384b580de74b2ae31aa -size 37912 +oid sha256:7ead8637651c4d0e3c0f6e78c596c4781d00ecb493bdf54ac96670b55ff541c2 +size 38217 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png index 92ffd71139..308abe5a72 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf9aea8bd7c9f6d7eb7f31a71ec412ae0f143c60bc6834a1f2ad99e538d87875 -size 33758 +oid sha256:a1e6cd137958c6f3cd9ddad7cdf9dcd35c9b9963cdab164c232ebefa50b7a81b +size 33815 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png index 3e1a99aec0..da94eb9d22 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de35cb70fa0076e5c1d0ab35cdae0b48cac90aa0c0223538276054e69768fd2a -size 42776 +oid sha256:3eeb6eb4ff66c0558d2abc960a8bffc757d6a8fd043f9c4eee4667176de38617 +size 43485 diff --git a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png index 11011887f3..49aa77efd2 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a4508363f01ad58b30503ff92236349b619feaa5716524438a2f52f033d71e6 -size 26225 +oid sha256:e1c0c74a437c19c02f04c6de9898fc8fcce98ebdd0161f97d9973d6bf091db58 +size 27056 diff --git a/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png b/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png index e55f0530fd..4119ae071b 100644 --- a/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png +++ b/screenshots/de/features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f27bdc5b6fc21700a4f8512230084f1131d9804eb7cd4366d61f90deaf55bb60 -size 56835 +oid sha256:b742d5311fc1961bc9a5a61658e77fdf1ab3f83b5fb93e0a4fedd7f50a3faacb +size 56999 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png index 38bcc092a9..c19097e89a 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21e1cce3efb6c835a83b1a0c29dc1aadbcf6d5a4c2e839343f71fa30ea6dd0c4 -size 91151 +oid sha256:392e090f14a98249b1cf3cf4acf180a817c41dbc8b4320ad5b8a2b4636ba0f14 +size 86883 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png index 4fe8b578bd..c84f36df47 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be7af996c56f6c75636688d88c70814dd7c93e3963255d6dc2e89fc8032a51c5 -size 90886 +oid sha256:2488a2d453b8a8cd086e531e1c49ac2d41186713b85c1aba3df73cf6c7a5f1e8 +size 86605 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png index e22e792f54..8dd9a8233d 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7901b1eb373bfac3fa7a9549c66c157b0d70cd885364646fa37e014056d0bcd8 -size 78805 +oid sha256:f0870cc34ef448fc914f7f4a688781bacaca59edad593509ee5cb333fdcf4acd +size 73713 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png index c872795d91..50752acb56 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40745997037a4b3856628bc8d485c8131f4586e0f855513fdfe97b2470507bc4 -size 70087 +oid sha256:844f24409611ccc30b514427c72cd057ed838a1b4ba058a4c6dd941858908e65 +size 66529 diff --git a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png index 198287f424..e20e0c63c8 100644 --- a/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png +++ b/screenshots/de/features.logout.impl_AccountDeactivationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3471dcaa2c715b6c3fb8c6b5223f1cb398af8d9b7ff013af11f4c6feef7d4615 -size 61333 +oid sha256:cf40d60799deb62643ca650deb1a5b5e18f5d26ebca7927064c51a0f3a8b771a +size 57890 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png index ba6edcd46e..7354b5bf41 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f86f77e8055c5d568e4f1e3bf1757a140fef5839eadd8f17731fc079a0c08bbf -size 58945 +oid sha256:08fa6f2925434cc451adb7296041af54941b7b9e126887bd529692fa208060ae +size 69544 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png index ba6edcd46e..7354b5bf41 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f86f77e8055c5d568e4f1e3bf1757a140fef5839eadd8f17731fc079a0c08bbf -size 58945 +oid sha256:08fa6f2925434cc451adb7296041af54941b7b9e126887bd529692fa208060ae +size 69544 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png index 7704df7d91..ed1172e6ae 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a56b1ee1bde9ad25090371050081ce13c900d6d085c21b63abd858229fe482d -size 42706 +oid sha256:fadcc1a9018cca35bd08be7f7f4d670e55ec362c15c0ef89625988da6be95ca9 +size 47451 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png index 71073f21cd..dd9ecc5fed 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed9b2497d9c154f8bad06b5f0405d193f21549d9a0b4a661becce745d7203002 -size 50459 +oid sha256:652613c8509079b395d964c0290272a09b6a9bf4ca02c18d6edcae0b43e06d16 +size 61053 diff --git a/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png b/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png index dccb62e40c..dd9ecc5fed 100644 --- a/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png +++ b/screenshots/de/features.logout.impl_LogoutView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50089edf349ad41016816bf861fb35237c2e4e4ba588846607ecdb100fa624dd -size 41703 +oid sha256:652613c8509079b395d964c0290272a09b6a9bf4ca02c18d6edcae0b43e06d16 +size 61053 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_de.png index af84cc0319..1c168e3cfe 100644 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:579709deae308329674cf4d47805485699f42c67e6b6779b78e95f45437aab4d -size 26045 +oid sha256:e78774044b40b63565ef540b6c1fae9fd97c105ffcc049e524e8a80d88435b50 +size 27225 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png index 6224a55c6d..8478c19fda 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71815785672b31d061a25b3980ecb368c54d1e7259533fd1989819ae3c922e2a -size 74688 +oid sha256:e697b923e1e387be4bd8d3a8de0482c9be4a670192f29bb3c5529ff211e9e442 +size 71612 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png index 6224a55c6d..8478c19fda 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71815785672b31d061a25b3980ecb368c54d1e7259533fd1989819ae3c922e2a -size 74688 +oid sha256:e697b923e1e387be4bd8d3a8de0482c9be4a670192f29bb3c5529ff211e9e442 +size 71612 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png index 4147e93eef..9462258aaf 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a47734fb0be5195c915373f922ed2fb87f3d89c5c517fefd0fea00cad76bbca4 -size 75418 +oid sha256:4fb4462ae1261dc77869d984152bac7bd810c92a82782c36e2bcc448d3aa6459 +size 72336 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png index f8fa0ef3e5..73080a8c95 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4c12cdd10cc2fb443c4dc248ab03740fd68cb8a2f8021225bee5010dd5e8438 -size 45465 +oid sha256:eb86dfe02f725547da2b90a4f9390db134f1f27e8c0253a33ae47ed9feb36cee +size 45289 diff --git a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png index 44eb24b2f7..186d5c4500 100644 --- a/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3aa8259805201e40926ad24b4ac815c38ad03c06df4a931342d954704899366e -size 43769 +oid sha256:85c622ee5e7cc5377b07b9df0d6ed856551200af720101f084c56260d5024516 +size 43767 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png index 69691a898d..5db03f0da8 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ba5eceb0adc4b9feb3834f967dac81f1e2b6766934f6aadd54f3be011a98f6b -size 43156 +oid sha256:3644179c35846aec7a93ee45a6e0ee14ec1ca7795ca270a26cddc7c9813cedd3 +size 40448 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png index 69691a898d..5db03f0da8 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ba5eceb0adc4b9feb3834f967dac81f1e2b6766934f6aadd54f3be011a98f6b -size 43156 +oid sha256:3644179c35846aec7a93ee45a6e0ee14ec1ca7795ca270a26cddc7c9813cedd3 +size 40448 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png index 2add9f0e02..122e462156 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb7e2b92bd620115488d20e501f4040a042907dcf93d24fc77ce5a9fc178b83d -size 70404 +oid sha256:4978ac3b31f5f03fc81846e64c183a857d1f468bc1dc2816b123b92e5b2a1824 +size 67792 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png index 53994b7029..6d0b15b0f1 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1293917283d4db5644f4cdbb00a76b0071dbbde7574b8ec3376f19a0fcf6dbb9 -size 75856 +oid sha256:552461f34b6873315ec01cc013fbc3ef4a0796c9bfa0bfd445ef94e7db2d3317 +size 73308 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png index 7a1dbd9583..6e24f8a5ad 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:587ae11b72d16310df68b70367a7c1dba8611dd252be29c9e403d7dfb216f43b -size 56498 +oid sha256:e2f75acc56ee1d7e6d0381db66cc8771f787e37c51171d1d0e478045759a8997 +size 54450 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png index 2f90072e8c..822271d7a7 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54130f6586c04b3eca992f3b3ab08772c3a8dc838800dc0847aaa30fad664021 -size 68285 +oid sha256:f1c9d7db00eb7b3eb03328c7e885e8ed608e8747851e3beab4c9f2d9613fb1b3 +size 65694 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png index 81fccd7025..f0e0b4d14e 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be67cbcb3279bb0d0849ee037d4f5310d7c8e56e87906838c0c0588da19ff6ce -size 52661 +oid sha256:23ded671d28f0bf1f6f857575603e4f4a63e666ce184aa1cb24d09e868f98bef +size 51149 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png index cdc5c1bd63..75a0e8a25a 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e065760677d14694ab6444762666f2d3af5fe8069cdbb08fdd9ddd3b5d53207 -size 44405 +oid sha256:9acf83c1389f316025d5aa95fe3ba43dc871df0cf01cdf364a228090c2873ff0 +size 41709 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png index 0c892f4de1..08ee8d01ed 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7e3df55da07e3d081934df198f12cefed4599acc8eb8b3db25907cc5062e430 -size 45029 +oid sha256:17cc8bd2c275abd9f02a6ec753c05e8af0426c3831ed51d1caa3e3b034ec48eb +size 42318 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png index 69691a898d..5db03f0da8 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ba5eceb0adc4b9feb3834f967dac81f1e2b6766934f6aadd54f3be011a98f6b -size 43156 +oid sha256:3644179c35846aec7a93ee45a6e0ee14ec1ca7795ca270a26cddc7c9813cedd3 +size 40448 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png index 079249afcb..efef76cdd6 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba49338dbd77ebbfc82d555433e03c9ed222355ac8d716dac5b1677811e55e6a -size 41844 +oid sha256:5e39e5084b58380e734fa88b624e4715489bf01411997a35f4eebcfffa11edb1 +size 39552 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png index e20d4f0a54..391331f263 100644 --- a/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png +++ b/screenshots/de/features.securebackup.impl.root_SecureBackupRootView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b39a9cbacf1e86133a1031a105dec92a910a364f4758de3d48a8c63db232430 -size 44028 +oid sha256:a4b9d3c8cdbd10537eba77829cd3c91f18e6637ae1d02fcbc242cc26e860e226 +size 41319 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png index fd27a4660d..700a209aba 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0ff3fab68e7412f4007b2fbed67268f114064097e3256d051b235cee3350296 -size 50172 +oid sha256:4c89bb4bfe847f0a71ec7b74627b21f9e20245472d16ba413416eb3705d5859d +size 50721 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png index 13bedfc6b3..742c8b1be9 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:deaffb7054cdb7dff2437f94f19bbb7a135e468d205fd87df9fd24a863483008 -size 46802 +oid sha256:785114ab0576fe9a69fcffa7dff1252ea660345a5706949e461878859dde0c33 +size 47362 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_de.png index 1292c01a4f..894b66623c 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90ec71c1f37b2cadc100c3ad14fc03aa1abb76881834a97c9d7db9deef49456f -size 40043 +oid sha256:ada44308165eefb690684726100507bc2c20e1d363a3555f7d8975c6645e0536 +size 40144 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png index d6f33a24d0..62f0a77598 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9212912117ff8653d8cc2c15eb360e2da0ef68e5ef79846f3e2f00f1fab9c8a -size 62526 +oid sha256:1ae69f5a8fc884a2ca02d8c84e9342b9633512de78348a0bb2d661d5735e708a +size 63185 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png index 4e2a7b2671..3fc33a270d 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d61ffb76ac311f35f3b3b5e83810e62524efbca9721f35812d1ae2386482b1ee -size 59008 +oid sha256:6930558f6c4cda30d6a83fa320a7a17d4c45db0bfb2e9bf21b13701d047e76a2 +size 59611 diff --git a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png index b723e43390..388cb2f945 100644 --- a/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png +++ b/screenshots/de/features.securebackup.impl.setup_SecureBackupSetupView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa77b425148e59b5d230f835baacc1ca3ac184a09e538057bf5d6438f20f83a4 -size 41503 +oid sha256:57dc90ddefeb2743ef616ddd11e5a9cb3847d714e2f452e2e58f7d7cc02c3422 +size 41780 diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_11_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_11_de.png index fc2d5b8229..4cfccb8015 100644 --- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_11_de.png +++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6d6cb69eb5d310ca7dae9127015fb3443325b16322c94958c4bf947fcc70514 -size 29438 +oid sha256:00d1fe85f79d7d25867287c50e50f2d0b37b52fe93c4cee70b17da485c912639 +size 30380 diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_2_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_2_de.png index ce7583ad06..ce9e73fd68 100644 --- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_2_de.png +++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84fb184c49d26ad7636588885daf3c9169209975a5b0e2f1c9ffcea6a3875683 -size 43302 +oid sha256:70c06787bdb7614fb66fb9c16a9703fc572500cbd4b7ba48d806b6c6bb68b649 +size 44169 diff --git a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_4_de.png b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_4_de.png index 95995db201..5c5957c19b 100644 --- a/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_4_de.png +++ b/screenshots/de/features.verifysession.impl.incoming_IncomingVerificationView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2087ce92d6d532a71a1dcc3f0824a34107316030e25ce58d46696675ddd6f264 -size 42907 +oid sha256:9bcad1fdaeb5596e17cddad4498d58208eccb7dcf38efdc7434bf82badffb5ea +size 43767 diff --git a/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_de.png b/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_de.png index 275f38c3f5..5673458928 100644 --- a/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_de.png +++ b/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2e955575444e16c332ab1e22cc121566a4f8744b8e0a01c69c5f3a9ce8ba033 -size 29507 +oid sha256:3ffba2cf2bdbed63ffd3f378a9e5b2a8c08bc316c500d7c782dbca8152c07224 +size 30449 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 0bf3fbcf3b..2cd7772aff 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,99 +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",20567,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20573,], ["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",20567,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20567,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20567,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20567,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20567,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20567,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20567,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20567,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20567,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20567,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20567,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20573,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20573,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20573,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20573,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20573,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20573,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20573,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20573,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20573,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20573,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20573,], ["features.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",20567,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20567,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20573,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20573,], ["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",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20573,], ["features.messages.impl.actionlist_ActionListViewContent_Day_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",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20567,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20567,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20567,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20567,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20567,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20567,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20570,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20567,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20567,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20567,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20567,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20573,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20573,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20573,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20573,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20573,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20573,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20573,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20573,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20573,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20567,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20567,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20567,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20567,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20567,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20573,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20573,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20573,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20573,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20573,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20570,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20570,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20570,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20567,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20573,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20573,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20573,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20573,], ["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",20567,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20573,], ["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",20567,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20573,], ["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",20567,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20573,], ["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",20567,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20573,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_0_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_0_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_1_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_1_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_2_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_2_en",0,], @@ -103,19 +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","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20567,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20567,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20573,], ["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",20567,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20573,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.matrix.ui.components_AvatarPickerSizes_Day_0_en","libraries.matrix.ui.components_AvatarPickerSizes_Night_0_en",0,], ["libraries.matrix.ui.components_AvatarPickerViewRtl_Day_0_en","libraries.matrix.ui.components_AvatarPickerViewRtl_Night_0_en",0,], @@ -145,22 +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",20567,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20573,], ["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",20567,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20567,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20567,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20567,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20567,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20567,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20567,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20573,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20567,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20567,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20567,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20567,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20567,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20573,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20573,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20573,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20573,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20573,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -171,140 +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",20567,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20567,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20573,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20573,], ["features.messages.impl.timeline.components_CallMenuItem_Day_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",20567,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20573,], ["features.messages.impl.timeline.components_CallMenuItem_Day_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",20567,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20567,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20567,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20567,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20567,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20567,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20573,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20573,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20573,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20573,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20573,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20573,], ["features.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",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20567,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20567,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20567,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20573,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20573,], ["features.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",20567,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20567,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20567,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20567,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20567,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20573,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20573,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20573,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20573,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20573,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20567,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20573,], ["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",20567,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20567,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20567,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20567,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20567,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20567,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20567,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20567,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20573,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20573,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20573,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20573,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20573,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20573,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20573,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20573,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20577,], ["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",20567,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20567,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20567,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20567,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20567,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20567,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20567,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20573,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20573,], ["libraries.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","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20567,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20567,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20567,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20567,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20567,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20567,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20573,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20573,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20573,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20573,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20573,], ["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",20567,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20567,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20567,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20567,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20567,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20567,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20567,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20567,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20567,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20567,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20567,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20567,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20567,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20567,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20567,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20567,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20567,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20567,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20567,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20567,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20573,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20573,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20573,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20573,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20573,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20573,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20573,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20573,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20573,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20573,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20573,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20573,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20573,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20573,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20573,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20573,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20573,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20573,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20573,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20573,], ["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","",20567,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20567,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20567,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20567,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20567,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20567,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20567,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20573,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20573,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20573,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20573,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20573,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20573,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20573,], ["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",20567,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20567,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20567,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20573,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20573,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20573,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_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",20567,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20573,], ["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",20567,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20567,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20567,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20567,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20567,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20567,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20567,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20567,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20567,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20573,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20573,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20573,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20573,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20573,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20573,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20573,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20573,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20573,], ["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,], @@ -319,20 +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",20567,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20567,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20567,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20567,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20567,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20567,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20567,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20567,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20567,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20567,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20567,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20567,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20567,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20570,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20573,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20573,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20573,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20573,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20573,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20573,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20573,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20573,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20573,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20573,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20573,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20573,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20573,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20573,], ["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,], @@ -340,28 +341,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20567,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20567,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20573,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20573,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_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",20567,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20567,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20567,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20567,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20567,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20567,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20567,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20567,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20567,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20567,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20573,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20573,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20573,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20573,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20573,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20573,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20573,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20573,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20573,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20577,], ["features.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,], @@ -381,49 +383,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",20567,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20567,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20567,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20573,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20573,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20573,], ["features.messages.impl.timeline.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",20567,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20567,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20573,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20573,], ["features.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",20570,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20573,], ["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",20567,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20567,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20567,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20567,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20567,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20573,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20573,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20573,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20573,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20573,], ["features.home.impl.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",20567,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20567,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20573,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20573,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20567,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20567,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20573,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20573,], ["features.home.impl_HomeView_Day_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",20567,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20567,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20567,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20567,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20567,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20567,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20567,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20567,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20567,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20567,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20567,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20567,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20567,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20573,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20573,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20573,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20573,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20573,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20573,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20573,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20573,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20573,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20573,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20573,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20573,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20573,], ["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,], @@ -438,8 +440,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",20567,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20567,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20573,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20573,], ["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,], @@ -447,119 +449,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",20567,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20573,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_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",20567,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20573,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_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",20567,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20567,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20573,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20573,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20567,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20567,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20573,], ["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",20567,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20567,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20570,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20573,], ["features.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",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20573,], ["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",20567,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20567,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20567,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20573,], ["features.invitepeople.impl_InvitePeopleView_Day_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20567,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20567,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20567,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20567,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20567,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20567,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20567,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20567,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20573,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20573,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20573,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20573,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20573,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20573,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20573,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20573,], ["features.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",20567,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20567,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20567,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20567,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20567,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20573,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20573,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20573,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20567,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20567,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20573,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20573,], ["features.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",20567,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20567,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20567,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20567,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20567,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20567,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20567,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20567,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20573,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20573,], ["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",20567,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20567,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20567,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20567,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20567,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20567,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20573,], ["features.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",20567,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20573,], ["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,], @@ -614,45 +616,45 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20567,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20573,], ["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",20567,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20567,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20567,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20573,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20573,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20573,], ["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",20567,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20567,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20567,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20567,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20567,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20567,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20567,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20567,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20567,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20567,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20567,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20567,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20567,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20570,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20570,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20567,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20567,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20567,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20567,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20567,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20567,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20567,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20567,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20567,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20567,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20567,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20567,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20573,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20573,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20573,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20573,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20573,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20573,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20573,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20573,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20573,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20573,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20573,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20573,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20573,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20573,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20573,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20573,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20573,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20573,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20573,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20573,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20573,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20573,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20573,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20573,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20573,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20573,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20573,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20567,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20567,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20567,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20567,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20573,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20573,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20573,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20573,], ["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,], @@ -665,26 +667,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20567,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20570,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20567,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20570,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20570,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20570,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20573,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20573,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20573,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20573,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20573,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20573,], ["libraries.mediaviewer.impl.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",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20567,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20567,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20573,], ["libraries.mediaviewer.impl.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,], @@ -692,15 +694,15 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20570,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20570,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20573,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20570,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20573,], ["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","",20570,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20573,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -710,15 +712,15 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20567,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20567,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20573,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20567,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20573,], ["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","",20567,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20573,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -732,7 +734,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",20567,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20573,], ["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,], @@ -741,7 +743,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",20567,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20573,], ["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,], @@ -750,23 +752,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20567,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20567,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20567,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20567,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20567,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20567,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20567,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20567,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20567,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20567,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20567,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20567,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20567,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20567,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20567,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20573,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20573,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20573,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20573,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20573,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20573,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20573,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20573,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20573,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20573,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20573,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20573,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20573,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20573,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20573,], ["features.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",20567,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20573,], ["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,], @@ -777,113 +779,113 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20567,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20567,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20567,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20573,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20573,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20573,], ["features.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",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20567,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20570,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20573,], ["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",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20567,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20573,], ["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",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20567,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20567,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20573,], ["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",20567,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20567,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20567,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20567,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20567,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20567,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20573,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20573,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20573,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20573,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20573,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20573,], ["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",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20567,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20567,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20573,], ["features.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",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20567,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20567,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20567,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20567,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20567,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20567,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20573,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20573,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20573,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20573,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20573,], ["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",20567,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20567,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20567,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20567,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20567,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20573,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20573,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20573,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20573,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20573,], ["features.poll.api.pollcontent_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",20567,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20567,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20567,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20567,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20567,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20567,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20567,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20567,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20567,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20567,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20567,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20573,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20573,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20573,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20573,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20573,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20573,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20573,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20573,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20573,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20573,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20573,], ["features.poll.api.pollcontent_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,], @@ -897,223 +899,225 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20567,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20567,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20567,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20567,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20570,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20570,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20573,], ["features.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","",20567,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20567,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20573,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20573,], ["libraries.designsystem.components_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",20567,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20567,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20567,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20567,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20567,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20567,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20567,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20567,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20567,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20567,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20567,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20567,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20567,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20567,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20567,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20567,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20567,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20567,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20567,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20567,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20567,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20573,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20573,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20573,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20573,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20573,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20573,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20573,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20573,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20573,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20573,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20573,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20573,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20573,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20573,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20573,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20573,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20573,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20573,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20573,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20573,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20573,], ["libraries.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",20567,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20567,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20573,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20573,], ["features.rageshake.api.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",20567,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20567,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20567,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20567,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20567,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20567,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20567,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20573,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20573,], ["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",20567,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20567,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20567,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20567,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20567,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20567,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20567,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20567,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20567,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20567,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20567,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20567,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20567,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20567,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20567,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20567,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20567,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20573,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20573,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20573,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20573,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20573,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20573,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20573,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20573,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20573,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20573,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20573,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20573,], ["features.messages.impl.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",20567,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20567,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20567,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20567,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20567,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20573,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20573,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20573,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20573,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20573,], ["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",20567,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20567,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20573,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20573,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20567,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20567,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20567,], -["features.roomdetails.impl_RoomDetails_0_en","",20567,], -["features.roomdetails.impl_RoomDetails_10_en","",20567,], -["features.roomdetails.impl_RoomDetails_11_en","",20567,], -["features.roomdetails.impl_RoomDetails_12_en","",20567,], -["features.roomdetails.impl_RoomDetails_13_en","",20567,], -["features.roomdetails.impl_RoomDetails_14_en","",20567,], -["features.roomdetails.impl_RoomDetails_15_en","",20567,], -["features.roomdetails.impl_RoomDetails_16_en","",20567,], -["features.roomdetails.impl_RoomDetails_17_en","",20567,], -["features.roomdetails.impl_RoomDetails_18_en","",20567,], -["features.roomdetails.impl_RoomDetails_19_en","",20567,], -["features.roomdetails.impl_RoomDetails_1_en","",20567,], -["features.roomdetails.impl_RoomDetails_20_en","",20567,], -["features.roomdetails.impl_RoomDetails_21_en","",20567,], -["features.roomdetails.impl_RoomDetails_22_en","",20567,], -["features.roomdetails.impl_RoomDetails_2_en","",20567,], -["features.roomdetails.impl_RoomDetails_3_en","",20567,], -["features.roomdetails.impl_RoomDetails_4_en","",20567,], -["features.roomdetails.impl_RoomDetails_5_en","",20567,], -["features.roomdetails.impl_RoomDetails_6_en","",20567,], -["features.roomdetails.impl_RoomDetails_7_en","",20567,], -["features.roomdetails.impl_RoomDetails_8_en","",20567,], -["features.roomdetails.impl_RoomDetails_9_en","",20567,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20567,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20567,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20567,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20567,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20567,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20567,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20567,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20567,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20567,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20573,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20573,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20573,], +["features.roomdetails.impl_RoomDetails_0_en","",20573,], +["features.roomdetails.impl_RoomDetails_10_en","",20573,], +["features.roomdetails.impl_RoomDetails_11_en","",20573,], +["features.roomdetails.impl_RoomDetails_12_en","",20573,], +["features.roomdetails.impl_RoomDetails_13_en","",20573,], +["features.roomdetails.impl_RoomDetails_14_en","",20573,], +["features.roomdetails.impl_RoomDetails_15_en","",20573,], +["features.roomdetails.impl_RoomDetails_16_en","",20573,], +["features.roomdetails.impl_RoomDetails_17_en","",20573,], +["features.roomdetails.impl_RoomDetails_18_en","",20573,], +["features.roomdetails.impl_RoomDetails_19_en","",20573,], +["features.roomdetails.impl_RoomDetails_1_en","",20573,], +["features.roomdetails.impl_RoomDetails_20_en","",20573,], +["features.roomdetails.impl_RoomDetails_21_en","",20573,], +["features.roomdetails.impl_RoomDetails_22_en","",20573,], +["features.roomdetails.impl_RoomDetails_2_en","",20573,], +["features.roomdetails.impl_RoomDetails_3_en","",20573,], +["features.roomdetails.impl_RoomDetails_4_en","",20573,], +["features.roomdetails.impl_RoomDetails_5_en","",20573,], +["features.roomdetails.impl_RoomDetails_6_en","",20573,], +["features.roomdetails.impl_RoomDetails_7_en","",20573,], +["features.roomdetails.impl_RoomDetails_8_en","",20573,], +["features.roomdetails.impl_RoomDetails_9_en","",20573,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20573,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20573,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20573,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20573,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20573,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20573,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20573,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20573,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20573,], ["features.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",20567,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20567,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20567,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20567,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20567,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20567,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20567,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20567,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20567,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20573,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20573,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20573,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20577,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20577,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20577,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20577,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20577,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20577,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20573,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20573,], ["features.home.impl.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",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20567,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20567,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20567,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20573,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20573,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20573,], ["features.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",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20567,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20567,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20573,], ["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",20567,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20567,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20567,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20567,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20567,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20567,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20573,], ["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,], @@ -1136,16 +1140,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20567,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20567,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20573,], ["features.home.impl.components_RoomSummaryRow_Day_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",20567,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20573,], ["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,], @@ -1154,119 +1158,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",20567,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20573,], ["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",20567,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20567,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20573,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20573,], ["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",20567,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20567,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20567,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20567,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20567,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20567,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20567,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20567,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20573,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20573,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20573,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20573,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20573,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20573,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20573,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20573,], ["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","",20567,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20573,], ["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","",20567,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20567,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20567,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20567,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20567,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20567,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20567,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20567,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20567,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20567,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20567,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20567,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20567,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20567,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20567,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20573,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20573,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20573,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20573,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20573,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20573,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20573,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20573,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20573,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20573,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20573,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20573,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20573,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20573,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20573,], ["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,], @@ -1289,35 +1293,35 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20567,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20567,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20567,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20567,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20567,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20567,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20567,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20567,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20567,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20567,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20567,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20567,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20567,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20567,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20567,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20573,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20573,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20573,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20573,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20573,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20573,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20573,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20573,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20573,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20573,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20573,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20573,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20573,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20573,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20573,], ["features.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",20567,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20567,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20567,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20567,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20567,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20567,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20567,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20570,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20570,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20567,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20567,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20573,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20573,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20573,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20573,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20573,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20573,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20573,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20573,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20573,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20573,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20573,], ["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,], @@ -1327,107 +1331,107 @@ 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",20567,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20573,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20567,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20567,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20567,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20570,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20567,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20573,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20573,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20573,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20573,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20573,], ["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",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20567,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20567,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20567,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20567,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20567,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20567,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20567,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20567,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20567,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20567,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20567,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20567,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20567,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20567,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20567,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20573,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20573,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20573,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20573,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20573,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20573,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20573,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20573,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20573,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20573,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20573,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20573,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20573,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20573,], ["libraries.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",20567,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20567,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20567,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20567,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20567,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20567,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20567,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20573,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20573,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20573,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20573,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20573,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20573,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20573,], ["features.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",20567,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20573,], ["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",20567,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20573,], ["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",20567,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20567,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20567,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20567,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20567,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20567,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20567,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20567,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20567,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20567,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20567,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20567,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20570,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20567,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20567,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20567,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20573,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20573,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20573,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20573,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20573,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20573,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20573,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20573,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20573,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20573,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20573,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20573,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20573,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20573,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20573,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20573,], ["libraries.textcomposer_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",20567,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20567,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20573,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20573,], ["libraries.designsystem.components.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,], @@ -1440,17 +1444,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20567,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20567,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20573,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20573,], ["features.messages.impl.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","",20567,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20567,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20567,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20573,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20573,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20573,], ["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",20567,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20567,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20573,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20573,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_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,], @@ -1460,18 +1464,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",20567,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20573,], ["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",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20573,], ["features.messages.impl.timeline.components_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,], @@ -1479,18 +1483,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",20567,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20573,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_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",20567,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20567,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20573,], ["features.messages.impl.timeline.components_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",20567,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20573,], ["features.messages.impl.timeline.components_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,], @@ -1499,44 +1503,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20573,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_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",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20573,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_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",20567,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20573,], ["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","",20567,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20573,], ["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",20567,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20573,], ["features.messages.impl.timeline.components.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",20567,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20573,], ["features.messages.impl.timeline.components.event_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",20570,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20570,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20570,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20570,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20567,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20567,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20573,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20573,], ["features.messages.impl.timeline.components_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",20567,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20567,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20573,], ["features.messages.impl.timeline.components_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",20567,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20573,], ["features.messages.impl.timeline.components.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,], @@ -1545,8 +1549,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",20567,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20573,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20573,], ["features.messages.impl.timeline.components_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,], @@ -1561,8 +1565,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",20567,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20567,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20573,], ["features.messages.impl.timeline.components.event_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,], @@ -1585,84 +1589,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",20567,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20567,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20570,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20567,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20573,], ["features.messages.impl.timeline_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",20567,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20573,], ["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",20567,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20573,], ["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",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20567,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20567,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20573,], ["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",20567,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20567,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20567,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20567,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20567,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20567,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20573,], ["features.messages.impl.typing_TypingNotificationView_Day_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","",20567,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20573,], ["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",20567,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20567,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20567,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20567,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20573,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20573,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20573,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20573,], ["features.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",20567,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20573,], ["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",20567,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20573,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20567,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20567,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20567,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20567,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20567,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20567,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20567,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20567,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20567,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20567,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20567,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20567,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20567,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20573,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20573,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20573,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20573,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20573,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20573,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20573,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20573,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20573,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20573,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20573,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20573,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20573,], ["features.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",20567,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20567,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20573,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20573,], ["features.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",20567,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20573,], ["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.login.impl.changeserver_ChangeServerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_5_en.png index 16668cae13..c4a683e701 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d62d11d8d8ccbbbbe811f157ecc20f31096a017f4acb36061a29e2aaefbd3e8 -size 25132 +oid sha256:44e078c64ab932a6e9ce2d429efb5f44556d4a923f4949e75dd2bd99591c4533 +size 25242 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_5_en.png index 20a22487c4..2a6cbdf049 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6d0f6746f6ccea9db09a6d351e5aae7d10d4d623edf00059bfece647731c2e5 -size 23959 +oid sha256:a2d413d264af067d4e03743cd50be879c91796a3f0907f40cefcdc6b0e466897 +size 24020 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_5_en.png index 16668cae13..c4a683e701 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d62d11d8d8ccbbbbe811f157ecc20f31096a017f4acb36061a29e2aaefbd3e8 -size 25132 +oid sha256:44e078c64ab932a6e9ce2d429efb5f44556d4a923f4949e75dd2bd99591c4533 +size 25242 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_5_en.png index 20a22487c4..2a6cbdf049 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.login_LoginModeView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6d0f6746f6ccea9db09a6d351e5aae7d10d4d623edf00059bfece647731c2e5 -size 23959 +oid sha256:a2d413d264af067d4e03743cd50be879c91796a3f0907f40cefcdc6b0e466897 +size 24020 From e81ab35f5b9f483cf412d50dfe545923292579c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 08:06:30 +0200 Subject: [PATCH 0323/1083] Update dependency io.nlopez.compose.rules:detekt to v0.5.8 (#6711) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index dfd32f0872..474b868eda 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,7 +46,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.5.7") + detektPlugins("io.nlopez.compose.rules:detekt:0.5.8") detektPlugins(project(":tests:detekt-rules")) } From 5733c3149a7d7cfa319a7ca8e8b9cac7657a7a7e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 08:07:11 +0200 Subject: [PATCH 0324/1083] Update dependency com.posthog:posthog-android to v3.43.0 (#6704) 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 3a06ccd49c..3c73a55a15 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -221,7 +221,7 @@ haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics -posthog = "com.posthog:posthog-android:3.39.0" +posthog = "com.posthog:posthog-android:3.43.0" sentry = "io.sentry:sentry-android:8.40.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 27869c0e0427b8a9c289399930cfac0743efcfcf Mon Sep 17 00:00:00 2001 From: Hi Dude! Date: Mon, 4 May 2026 09:30:05 +0300 Subject: [PATCH 0325/1083] Fix calls on Huawei devices: skip addWebMessageListener on Chromium < 119 (#6640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix calls on Huawei: skip addWebMessageListener on Chromium < 119 * Fix lint issues, log webview version --------- Co-authored-by: manfrommedan Co-authored-by: Jorge Martín --- .../utils/WebViewWidgetMessageInterceptor.kt | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt index f7ab2c57af..c74ae90abd 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewWidgetMessageInterceptor.kt @@ -140,26 +140,33 @@ class WebViewWidgetMessageInterceptor( } } - // Create a WebMessageListener, which will receive messages from the WebView and reply to them - val webMessageListener = WebViewCompat.WebMessageListener { _, message, _, _, _ -> - onMessageReceived(message.data) - } + // Always register JavascriptInterface as the baseline message channel. + // This works on all WebView implementations including Huawei. + webView.addJavascriptInterface(object { + @JavascriptInterface + fun postMessage(json: String?) { + onMessageReceived(json) + } + }, LISTENER_NAME) - // Use WebMessageListener if supported, otherwise use JavascriptInterface - if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { + // Additionally register WebMessageListener on WebViews that reliably support it. + // Huawei WebView (Chromium < 119) reports WEB_MESSAGE_LISTENER as supported + // but silently drops messages, so we only trust it on Chromium 119+. + // See: https://github.com/element-hq/element-x-android/issues/6632 + val webViewVersionName = WebViewCompat.getCurrentWebViewPackage(webView.context)?.versionName.orEmpty() + Timber.d("Using WebView version: $webViewVersionName") + val webViewVersionCode = webViewVersionName.split(".").firstOrNull()?.toIntOrNull() ?: 0 + + if (webViewVersionCode >= 119 && + WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { WebViewCompat.addWebMessageListener( webView, LISTENER_NAME, setOf("*"), - webMessageListener - ) - } else { - webView.addJavascriptInterface(object { - @JavascriptInterface - fun postMessage(json: String?) { - onMessageReceived(json) + WebViewCompat.WebMessageListener { _, message, _, _, _ -> + onMessageReceived(message.data) } - }, LISTENER_NAME) + ) } } From a0646717a313072ba287c70a158e84f99eaaf832 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 4 May 2026 08:59:46 +0200 Subject: [PATCH 0326/1083] fix test compilation --- .../eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt index e1e8717c4c..177cc27df2 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt @@ -75,6 +75,7 @@ class DefaultRoomLatestEventFormatterTest { profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider), stateContentFormatter = StateContentFormatter(stringProvider), permalinkParser = FakePermalinkParser(), + rtcNotificationContentFormatter = RtcNotificationContentFormatter(fakeMatrixClient, stringProvider) ) } From 61f074ddc1764aaf782842d16f55ecf9e96b9377 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 14:18:15 +0200 Subject: [PATCH 0327/1083] Let our Json parser accept comments and trailing comma. --- .../android/libraries/androidutils/json/JsonProvider.kt | 9 ++++++++- .../impl/DefaultSessionWellknownRetrieverTest.kt | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/json/JsonProvider.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/json/JsonProvider.kt index 1e25599962..12f2957678 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/json/JsonProvider.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/json/JsonProvider.kt @@ -23,6 +23,13 @@ fun interface JsonProvider { @ContributesBinding(AppScope::class) @SingleIn(AppScope::class) class DefaultJsonProvider : JsonProvider { - private val json: Json by lazy { Json { ignoreUnknownKeys = true } } + private val json: Json by lazy { + Json { + ignoreUnknownKeys = true + allowComments = true + allowTrailingComma = true + } + } + override fun invoke() = json } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index faad139a36..e8c97c0220 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -80,7 +80,8 @@ class DefaultSessionWellknownRetrieverTest { "registration_helper_url": "a_registration_url", "enforce_element_pro": true, "rageshake_url": "a_rageshake_url", - "other": true + // Note the trailing comma, and the comment! + "other": true, }""".trimIndent().toByteArray() ) }, From 54525d855e7fdb7104f28f6fa5016312d5a2e160 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 10:04:20 +0000 Subject: [PATCH 0328/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.4 (#6718) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency org.matrix.rustcomponents:sdk-android to v26.05.4 * Fix `RoomInfo` fixture --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- gradle/libs.versions.toml | 2 +- .../libraries/matrix/impl/fixtures/factories/RoomInfo.kt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3c73a55a15..8d91c8a7be 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.04.27" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.4" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt index 491614a7fc..2ce64154f7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt @@ -63,6 +63,7 @@ internal fun aRustRoomInfo( isLowPriority: Boolean = false, activeRoomCallConsensusIntent: RtcCallIntentConsensus = RtcCallIntentConsensus.None, activeServiceMembersCount: Int = 0, + isDm: Boolean = false, ) = RoomInfo( id = id, displayName = displayName, @@ -103,4 +104,5 @@ internal fun aRustRoomInfo( isLowPriority = isLowPriority, activeRoomCallConsensusIntent = activeRoomCallConsensusIntent, activeServiceMembersCount = activeServiceMembersCount.toULong(), + isDm = isDm, ) From 6897cc57212a1746c3efa334380cacfbdd013a82 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Sat, 25 Apr 2026 07:07:15 +0000 Subject: [PATCH 0329/1083] Add clipping to RoomSummaryRow --- .../home/impl/components/RoomSummaryRow.kt | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index f541417104..72ecb5046d 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -29,6 +29,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString @@ -222,20 +223,17 @@ private fun NameAndTimestampRow( modifier = modifier.fillMaxWidth(), horizontalArrangement = spacedBy(16.dp) ) { - Row( - modifier = Modifier.weight(1f), - verticalAlignment = Alignment.CenterVertically, - ) { - // Name - Text( - style = ElementTheme.typography.fontBodyLgMedium, - text = name?.toSafeLength(ellipsize = true) ?: stringResource(id = CommonStrings.common_no_room_name), - fontStyle = FontStyle.Italic.takeIf { name == null }, - color = ElementTheme.colors.roomListRoomName, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } + Text( + modifier = Modifier + .weight(1f) + .clipToBounds(), + style = ElementTheme.typography.fontBodyLgMedium, + text = name?.toSafeLength(ellipsize = true) ?: stringResource(id = CommonStrings.common_no_room_name), + fontStyle = FontStyle.Italic.takeIf { name == null }, + color = ElementTheme.colors.roomListRoomName, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) // Timestamp Text( text = timestamp ?: "", @@ -262,12 +260,12 @@ private fun InviteSubtitle( } if (subtitle != null) { Text( + modifier = modifier.clipToBounds(), text = subtitle, maxLines = 1, overflow = TextOverflow.Ellipsis, style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.roomListRoomMessage, - modifier = modifier, ) } } @@ -326,7 +324,9 @@ private fun MessagePreviewAndIndicatorRow( val messagePreview = room.latestEvent.content() val annotatedMessagePreview = messagePreview as? AnnotatedString ?: AnnotatedString(text = messagePreview.orEmpty().toString()) Text( - modifier = Modifier.weight(1f), + modifier = Modifier + .weight(1f) + .clipToBounds(), text = annotatedMessagePreview, color = ElementTheme.colors.roomListRoomMessage, style = ElementTheme.typography.fontBodyMdRegular, @@ -381,7 +381,9 @@ private fun InviteNameAndIndicatorRow( verticalAlignment = Alignment.CenterVertically, ) { Text( - modifier = Modifier.weight(1f), + modifier = Modifier + .weight(1f) + .clipToBounds(), style = ElementTheme.typography.fontBodyLgMedium, text = name?.toSafeLength(ellipsize = true) ?: stringResource(id = CommonStrings.common_no_room_name), fontStyle = FontStyle.Italic.takeIf { name == null }, From ab85c554ff47707d0e864fafd00d92db6254d5fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 00:49:45 +0000 Subject: [PATCH 0330/1083] Update metro to v1 --- 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 8d91c8a7be..ad7592f0a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.9.0" # DI -metro = "0.13.2" +metro = "1.0.0" # Auto service autoservice = "1.1.1" From c40f916b4fa3d8ea9fc61c1be998a57635ea40fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 10:55:16 +0200 Subject: [PATCH 0331/1083] Merge pull request #6722 from element-hq/renovate/roborazzi Update roborazzi to v1.60.0 --- 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 8d91c8a7be..d17ddc99d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ accompanist = "0.37.3" # Test test_core = "1.7.0" -roborazzi = "1.59.0" +roborazzi = "1.60.0" # Jetbrain datetime = "0.7.1" From 51bcaca9db698ee007efe42cfba61ee39fa4cad3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 May 2026 12:17:51 +0200 Subject: [PATCH 0332/1083] Rename methods around verification, to match SDK naming. --- .../OutgoingVerificationStateMachine.kt | 4 +- .../OutgoingVerificationPresenterTest.kt | 52 +++++++++---------- .../SessionVerificationService.kt | 6 +-- .../RustSessionVerificationService.kt | 4 +- .../FakeSessionVerificationService.kt | 12 ++--- 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationStateMachine.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationStateMachine.kt index 7932ccc484..465fc20066 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationStateMachine.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationStateMachine.kt @@ -46,7 +46,7 @@ class OutgoingVerificationStateMachine( inState { onEnterEffect { event -> when (event.verificationRequest) { - is VerificationRequest.Outgoing.CurrentSession -> sessionVerificationService.requestCurrentSessionVerification() + is VerificationRequest.Outgoing.CurrentSession -> sessionVerificationService.requestDeviceVerification() is VerificationRequest.Outgoing.User -> sessionVerificationService.requestUserVerification(event.verificationRequest.userId) } } @@ -56,7 +56,7 @@ class OutgoingVerificationStateMachine( } inState { onEnterEffect { - sessionVerificationService.startVerification() + sessionVerificationService.startSasVerification() } } inState { diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt index f02f24c9ef..da31b633b1 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt @@ -50,11 +50,11 @@ class OutgoingVerificationPresenterTest { @Test fun `present - Handles requestVerification for session verification`() = runTest { - val requestSessionVerificationRecorder = lambdaRecorder {} - val startVerificationRecorder = lambdaRecorder {} + val requestDeviceVerificationRecorder = lambdaRecorder {} + val startSasVerificationRecorder = lambdaRecorder {} val service = unverifiedSessionService( - requestSessionVerificationLambda = requestSessionVerificationRecorder, - startVerificationLambda = startVerificationRecorder, + requestDeviceVerificationLambda = requestDeviceVerificationRecorder, + startSasVerificationLambda = startSasVerificationRecorder, ) val presenter = createOutgoingVerificationPresenter( service = service, @@ -63,18 +63,18 @@ class OutgoingVerificationPresenterTest { presenter.test { requestVerificationAndAwaitVerifyingState(service) - requestSessionVerificationRecorder.assertions().isCalledOnce() - startVerificationRecorder.assertions().isCalledOnce() + requestDeviceVerificationRecorder.assertions().isCalledOnce() + startSasVerificationRecorder.assertions().isCalledOnce() } } @Test fun `present - Handles requestVerification for user verification`() = runTest { val requestUserVerificationRecorder = lambdaRecorder {} - val startVerificationRecorder = lambdaRecorder {} + val startSasVerificationRecorder = lambdaRecorder {} val service = unverifiedSessionService( requestUserVerificationLambda = requestUserVerificationRecorder, - startVerificationLambda = startVerificationRecorder, + startSasVerificationLambda = startSasVerificationRecorder, ) val presenter = createOutgoingVerificationPresenter( service = service, @@ -84,7 +84,7 @@ class OutgoingVerificationPresenterTest { requestVerificationAndAwaitVerifyingState(service) requestUserVerificationRecorder.assertions().isCalledOnce() - startVerificationRecorder.assertions().isCalledOnce() + startSasVerificationRecorder.assertions().isCalledOnce() } } @@ -106,8 +106,8 @@ class OutgoingVerificationPresenterTest { @Test fun `present - A failure when verifying cancels it`() = runTest { val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, - startVerificationLambda = { }, + requestDeviceVerificationLambda = { }, + startSasVerificationLambda = { }, approveVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) @@ -125,7 +125,7 @@ class OutgoingVerificationPresenterTest { @Test fun `present - A fail when requesting verification resets the state to the canceled one`() = runTest { val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, + requestDeviceVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) presenter.test { @@ -139,8 +139,8 @@ class OutgoingVerificationPresenterTest { @Test fun `present - Canceling the flow once it's verifying cancels it`() = runTest { val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, - startVerificationLambda = { }, + requestDeviceVerificationLambda = { }, + startSasVerificationLambda = { }, cancelVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) @@ -154,8 +154,8 @@ class OutgoingVerificationPresenterTest { @Test fun `present - When verifying, if we receive another challenge we ignore it`() = runTest { val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, - startVerificationLambda = { }, + requestDeviceVerificationLambda = { }, + startSasVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) presenter.test { @@ -168,8 +168,8 @@ class OutgoingVerificationPresenterTest { @Test fun `present - Go back after cancellation returns to initial state`() = runTest { val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, - startVerificationLambda = { }, + requestDeviceVerificationLambda = { }, + startSasVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) presenter.test { @@ -189,8 +189,8 @@ class OutgoingVerificationPresenterTest { VerificationEmoji(number = 30) ) val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, - startVerificationLambda = { }, + requestDeviceVerificationLambda = { }, + startSasVerificationLambda = { }, approveVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) @@ -215,8 +215,8 @@ class OutgoingVerificationPresenterTest { @Test fun `present - When verification is declined, the flow is canceled`() = runTest { val service = unverifiedSessionService( - requestSessionVerificationLambda = { }, - startVerificationLambda = { }, + requestDeviceVerificationLambda = { }, + startSasVerificationLambda = { }, declineVerificationLambda = { }, ) val presenter = createOutgoingVerificationPresenter(service) @@ -298,23 +298,23 @@ class OutgoingVerificationPresenterTest { } private suspend fun unverifiedSessionService( - requestSessionVerificationLambda: () -> Unit = { lambdaError() }, + requestDeviceVerificationLambda: () -> Unit = { lambdaError() }, requestUserVerificationLambda: (UserId) -> Unit = { lambdaError() }, cancelVerificationLambda: () -> Unit = { lambdaError() }, approveVerificationLambda: () -> Unit = { lambdaError() }, declineVerificationLambda: () -> Unit = { lambdaError() }, - startVerificationLambda: () -> Unit = { lambdaError() }, + startSasVerificationLambda: () -> Unit = { lambdaError() }, resetLambda: (Boolean) -> Unit = { }, acknowledgeVerificationRequestLambda: (VerificationRequest.Incoming) -> Unit = { lambdaError() }, acceptVerificationRequestLambda: () -> Unit = { lambdaError() }, ): FakeSessionVerificationService { return FakeSessionVerificationService( - requestCurrentSessionVerificationLambda = requestSessionVerificationLambda, + requestDeviceVerificationLambda = requestDeviceVerificationLambda, requestUserVerificationLambda = requestUserVerificationLambda, cancelVerificationLambda = cancelVerificationLambda, approveVerificationLambda = approveVerificationLambda, declineVerificationLambda = declineVerificationLambda, - startVerificationLambda = startVerificationLambda, + startSasVerificationLambda = startSasVerificationLambda, resetLambda = resetLambda, acknowledgeVerificationRequestLambda = acknowledgeVerificationRequestLambda, acceptVerificationRequestLambda = acceptVerificationRequestLambda, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt index 4d2e786038..38a00d833d 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt @@ -33,7 +33,7 @@ interface SessionVerificationService { /** * Request verification of the current session. */ - suspend fun requestCurrentSessionVerification() + suspend fun requestDeviceVerification() /** * Request verification of the user with the given [userId]. @@ -56,9 +56,9 @@ interface SessionVerificationService { suspend fun declineVerification() /** - * Starts the verification of the unverified session from another device. + * Transition the current verification request into a SAS verification flow. */ - suspend fun startVerification() + suspend fun startSasVerification() /** * Returns the verification service state to the initial step. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt index 7fb2935897..b2a13f5f1a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt @@ -124,7 +124,7 @@ class RustSessionVerificationService( this.listener = listener } - override suspend fun requestCurrentSessionVerification() = tryOrFail { + override suspend fun requestDeviceVerification() = tryOrFail { ensureEncryptionIsInitialized() verificationController.requestDeviceVerification() currentVerificationRequest = VerificationRequest.Outgoing.CurrentSession @@ -146,7 +146,7 @@ class RustSessionVerificationService( override suspend fun declineVerification() = tryOrFail { verificationController.declineVerification() } - override suspend fun startVerification() = tryOrFail { + override suspend fun startSasVerification() = tryOrFail { verificationController.startSasVerification() } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt index f4f12a435e..dab4d48952 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt @@ -22,12 +22,12 @@ import kotlinx.coroutines.flow.StateFlow class FakeSessionVerificationService( initialSessionVerifiedStatus: SessionVerifiedStatus = SessionVerifiedStatus.Unknown, - private val requestCurrentSessionVerificationLambda: () -> Unit = { lambdaError() }, + private val requestDeviceVerificationLambda: () -> Unit = { lambdaError() }, private val requestUserVerificationLambda: (UserId) -> Unit = { lambdaError() }, private val cancelVerificationLambda: () -> Unit = { lambdaError() }, private val approveVerificationLambda: () -> Unit = { lambdaError() }, private val declineVerificationLambda: () -> Unit = { lambdaError() }, - private val startVerificationLambda: () -> Unit = { lambdaError() }, + private val startSasVerificationLambda: () -> Unit = { lambdaError() }, private val resetLambda: (Boolean) -> Unit = { lambdaError() }, private val acknowledgeVerificationRequestLambda: (VerificationRequest.Incoming) -> Unit = { lambdaError() }, private val acceptVerificationRequestLambda: () -> Unit = { lambdaError() }, @@ -40,8 +40,8 @@ class FakeSessionVerificationService( override val sessionVerifiedStatus: StateFlow = _sessionVerifiedStatus override val needsSessionVerification: Flow = _needsSessionVerification - override suspend fun requestCurrentSessionVerification() { - requestCurrentSessionVerificationLambda() + override suspend fun requestDeviceVerification() { + requestDeviceVerificationLambda() } override suspend fun requestUserVerification(userId: UserId) { @@ -60,8 +60,8 @@ class FakeSessionVerificationService( declineVerificationLambda() } - override suspend fun startVerification() { - startVerificationLambda() + override suspend fun startSasVerification() { + startSasVerificationLambda() } override suspend fun reset(cancelAnyPendingVerificationAttempt: Boolean) { From a12b5191558ec080f18fb6e95c35e1204ac4a207 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 5 May 2026 13:14:30 +0200 Subject: [PATCH 0333/1083] Allow cancelling room loading in Home screen (#6723) Previously, this was disabled by mistake, since it's the default behavior. --- .../io/element/android/features/home/impl/HomeFlowNode.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt index 81e7969080..00f285e3f4 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope import com.bumble.appyx.core.lifecycle.subscribe @@ -171,6 +172,7 @@ class HomeFlowNode( if (loadingJoinedRoomJob.value.isLoading()) { DelayedVisibility(duration = 400.milliseconds) { ProgressDialog( + properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true), onDismissRequest = { loadingJoinedRoomJob.value.dataOrNull()?.cancel() loadingJoinedRoomJob.value = AsyncData.Uninitialized From 2d203e83b9dcbab198e43b62d5f1c8000d64c1aa Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 5 May 2026 15:24:27 +0200 Subject: [PATCH 0334/1083] Revert PR #6642 (#6724) * Revert "Change native back button behavior in EC view (close settings in EC with os native back) (#6642)" This reverts commit 6ba4679908ae1a3c7b0f698c10fda649aff9f8a5. * Fix API breaks from revert --- .../call/impl/ui/CallScreenBackPressPolicy.kt | 26 --- .../features/call/impl/ui/CallScreenView.kt | 36 ++--- .../call/ui/CallScreenBackPressPolicyTest.kt | 96 ------------ .../features/call/ui/CallScreenViewTest.kt | 148 ------------------ 4 files changed, 10 insertions(+), 296 deletions(-) delete mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt delete mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt delete mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt deleted file mode 100644 index cd47cd8bb1..0000000000 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.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.features.call.impl.ui -internal sealed interface CallScreenBackPressAction { - data object DispatchEscapeToWebView : CallScreenBackPressAction - data object EnterPictureInPicture : CallScreenBackPressAction -} - -internal object CallScreenBackPressPolicy { - fun resolve( - supportPip: Boolean, - hasWebView: Boolean, - fromNative: Boolean, - ): CallScreenBackPressAction? { - return when { - hasWebView && fromNative -> CallScreenBackPressAction.DispatchEscapeToWebView - hasWebView && supportPip -> CallScreenBackPressAction.EnterPictureInPicture - else -> null - } - } -} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index ea3668316b..1c68a62f55 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -64,15 +64,11 @@ internal fun CallScreenView( requestPermissions: (Array, RequestPermissionCallback) -> Unit, modifier: Modifier = Modifier, ) { - var callWebView by remember { mutableStateOf(null) } - - fun handleBack(fromNative: Boolean = false) { - when (CallScreenBackPressPolicy.resolve(supportPip = pipState.supportPip, hasWebView = callWebView != null, fromNative)) { - CallScreenBackPressAction.EnterPictureInPicture -> - pipState.eventSink(PictureInPictureEvent.EnterPictureInPicture) - CallScreenBackPressAction.DispatchEscapeToWebView -> - callWebView?.dispatchEscKeyEvent() - null -> Timber.d("Back press with unsupported pip is a no-op") + fun handleBack() { + if (pipState.supportPip) { + pipState.eventSink.invoke(PictureInPictureEvent.EnterPictureInPicture) + } else { + state.eventSink(CallScreenEvent.Hangup) } } @@ -80,7 +76,7 @@ internal fun CallScreenView( modifier = modifier, ) { padding -> BackHandler { - handleBack(fromNative = true) + handleBack() } if (state.webViewError != null) { ErrorDialog( @@ -115,7 +111,6 @@ internal fun CallScreenView( }, onConsoleMessage = onConsoleMessage, onCreateWebView = { webView -> - callWebView = webView webView.addBackHandler(onBackPressed = ::handleBack) val interceptor = WebViewWidgetMessageInterceptor( webView = webView, @@ -140,7 +135,6 @@ internal fun CallScreenView( pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) }, onDestroyWebView = { - callWebView = null // Reset audio mode webViewAudioManager?.onCallStopped() } @@ -149,7 +143,6 @@ internal fun CallScreenView( AsyncData.Uninitialized, is AsyncData.Loading -> ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait)) - is AsyncData.Failure -> { Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") ErrorDialog( @@ -157,7 +150,6 @@ internal fun CallScreenView( onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, ) } - is AsyncData.Success -> Unit } } @@ -256,18 +248,15 @@ private fun WebView.setup( private fun WebView.addBackHandler(onBackPressed: () -> Unit) { addJavascriptInterface( - JavascriptBackHandler { - onBackPressed() + object { + @Suppress("unused") + @JavascriptInterface + fun onBackPressed() = onBackPressed() }, "backHandler" ) } -private fun WebView.dispatchEscKeyEvent() { - dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_ESCAPE)) - dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_ESCAPE)) -} - @PreviewsDayNight @Composable internal fun CallScreenViewPreview( @@ -286,8 +275,3 @@ internal fun CallScreenViewPreview( internal fun InvalidAudioDeviceDialogPreview() = ElementPreview { InvalidAudioDeviceDialog(invalidAudioDeviceReason = InvalidAudioDeviceReason.BT_AUDIO_DEVICE_DISABLED) {} } - -internal fun interface JavascriptBackHandler { - @JavascriptInterface - fun onBackPressed() -} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt deleted file mode 100644 index f07f7039d3..0000000000 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt +++ /dev/null @@ -1,96 +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.features.call.ui - -import com.google.common.truth.Truth.assertThat -import io.element.android.features.call.impl.ui.CallScreenBackPressAction -import io.element.android.features.call.impl.ui.CallScreenBackPressPolicy -import org.junit.Test - -class CallScreenBackPressPolicyTest { - @Test - fun `resolve returns dispatch escape when a web view is available and native button is pressed`() { - val result = CallScreenBackPressPolicy.resolve( - supportPip = false, - hasWebView = true, - fromNative = true, - ) - - assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) - } - - @Test - fun `resolve dispatch escape when there is a web view and pip is supported on native button press`() { - val result = CallScreenBackPressPolicy.resolve( - supportPip = true, - hasWebView = true, - fromNative = true, - ) - - assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) - } - - @Test - fun `resolve returns hangup when there is no web view and pip is not supported from native button`() { - val result = CallScreenBackPressPolicy.resolve( - supportPip = false, - hasWebView = false, - fromNative = true, - ) - - assertThat(result).isNull() - } - - @Test - fun `resolve returns hangup when there is no web view even though pip is supported from native button`() { - val result = CallScreenBackPressPolicy.resolve( - supportPip = true, - hasWebView = false, - fromNative = true, - ) - - assertThat(result).isNull() - } - - @Test - fun `resolve goes to pip if its not from native but from the webview`() { - val result = CallScreenBackPressPolicy.resolve( - supportPip = true, - hasWebView = true, - fromNative = false, - ) - - assertThat(result).isEqualTo(CallScreenBackPressAction.EnterPictureInPicture) - } - @Test - fun `resolve hangs up if its not from native but from the webview and pip is not supported`() { - val result = CallScreenBackPressPolicy.resolve( - supportPip = false, - hasWebView = true, - fromNative = false, - ) - - assertThat(result).isNull() - } - - @Test - fun `invalid cases (event comes from webview but there is now webview) all result in hangup`() { - val withPipSupport = CallScreenBackPressPolicy.resolve( - supportPip = true, - hasWebView = false, - fromNative = false, - ) - assertThat(withPipSupport).isNull() - val withOutPipSupport = CallScreenBackPressPolicy.resolve( - supportPip = false, - hasWebView = false, - fromNative = false, - ) - assertThat(withOutPipSupport).isNull() - } -} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt deleted file mode 100644 index e4f9c10a3c..0000000000 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt +++ /dev/null @@ -1,148 +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. - */ - -@file:OptIn(ExperimentalTestApi::class) - -package io.element.android.features.call.ui - -import android.view.KeyEvent -import android.webkit.WebView -import androidx.activity.ComponentActivity -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.test.AndroidComposeUiTest -import androidx.compose.ui.test.ExperimentalTestApi -import androidx.compose.ui.test.v2.runAndroidComposeUiTest -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.call.impl.pip.PictureInPictureEvent -import io.element.android.features.call.impl.pip.aPictureInPictureState -import io.element.android.features.call.impl.ui.CallScreenEvent -import io.element.android.features.call.impl.ui.CallScreenView -import io.element.android.features.call.impl.ui.JavascriptBackHandler -import io.element.android.features.call.impl.ui.aCallScreenState -import io.element.android.tests.testutils.EventsRecorder -import io.element.android.tests.testutils.pressBackKey -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.annotation.Config -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements -import org.robolectric.annotation.Resetter -import org.robolectric.shadows.ShadowWebView - -@RunWith(AndroidJUnit4::class) -class CallScreenViewTest { - @Test - fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() = runAndroidComposeUiTest { - val callEvents = EventsRecorder() - - setCallScreenView( - state = aCallScreenState(eventSink = callEvents), - useInspectionMode = true, - ) - - pressBackKey() - - callEvents.assertEmpty() - } - - @Config(shadows = [RecordingShadowWebView::class]) - @Test - fun `pressing back key dispatches escape key events to web view when pip is unsupported`() = runAndroidComposeUiTest { - setCallScreenView( - state = aCallScreenState(), - useInspectionMode = false, - ) - - pressBackKey() - - val dispatchedEvents = RecordingShadowWebView.dispatchedEvents - assertEquals(2, dispatchedEvents.size) - assertEquals(KeyEvent.ACTION_DOWN, dispatchedEvents[0].action) - assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[0].keyCode) - assertEquals(KeyEvent.ACTION_UP, dispatchedEvents[1].action) - assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[1].keyCode) - } - - @Config(shadows = [RecordingShadowWebView::class]) - @Test - fun `web view javascript back handler emits pip event when pip is supported`() = runAndroidComposeUiTest { - val pipEvents = EventsRecorder() - - setCallScreenView( - state = aCallScreenState(), - useInspectionMode = false, - pipState = aPictureInPictureState( - supportPip = true, - eventSink = pipEvents, - ), - ) - - runOnIdle { - RecordingShadowWebView.invokeJavascriptBackHandler() - } - - pipEvents.assertSize(2) - pipEvents.assertTrue(0) { it is PictureInPictureEvent.SetPipController } - pipEvents.assertTrue(1) { it is PictureInPictureEvent.EnterPictureInPicture } - } -} - -private fun AndroidComposeUiTest.setCallScreenView( - state: io.element.android.features.call.impl.ui.CallScreenState, - useInspectionMode: Boolean, - pipState: io.element.android.features.call.impl.pip.PictureInPictureState = aPictureInPictureState(supportPip = false), -) { - setContent { - // Inspection mode disables AndroidView creation; keep it configurable per test. - CompositionLocalProvider(LocalInspectionMode provides useInspectionMode) { - CallScreenView( - state = state, - pipState = pipState, - onConsoleMessage = {}, - requestPermissions = { _, _ -> }, - ) - } - } -} - -@Implements(WebView::class) -internal class RecordingShadowWebView : ShadowWebView() { - companion object { - val dispatchedEvents = mutableListOf() - private var backHandlerJavascriptInterface: JavascriptBackHandler? = null - - @Resetter - @JvmStatic - @Suppress("unused") - fun resetRecordedEvents() { - dispatchedEvents.clear() - backHandlerJavascriptInterface = null - } - - fun invokeJavascriptBackHandler() { - val backHandler = checkNotNull(backHandlerJavascriptInterface) { "Expected backHandler JavaScript interface to be registered" } - backHandler.onBackPressed() - } - } - - @Implementation - protected override fun addJavascriptInterface(`object`: Any, name: String) { - super.addJavascriptInterface(`object`, name) - if (name == "backHandler") { - backHandlerJavascriptInterface = `object` as? JavascriptBackHandler - } - } - - @Implementation - @Suppress("unused") - fun dispatchKeyEvent(event: KeyEvent): Boolean { - dispatchedEvents += KeyEvent(event) - return false - } -} From 0a9259604bdeecfd1b943b9c867ce9bb1d5ea098 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 May 2026 15:29:32 +0200 Subject: [PATCH 0335/1083] Improve FakeSessionVerificationService --- .../IncomingVerificationPresenterTest.kt | 3 +++ .../OutgoingVerificationPresenterTest.kt | 12 ++++++++---- .../FakeSessionVerificationService.kt | 16 ++++++++-------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt index c9b9e25b74..a8d3802268 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt @@ -99,6 +99,7 @@ class IncomingVerificationPresenterTest { emojiState.eventSink(IncomingVerificationViewEvents.ConfirmVerification) val emojiWaitingItem = awaitItem() assertThat((emojiWaitingItem.step as IncomingVerificationState.Step.Verifying).isWaiting).isTrue() + advanceUntilIdle() approveVerificationLambda.assertions().isCalledOnce() // Remote confirm that the emojis match fakeSessionVerificationService.emitVerificationFlowState( @@ -161,6 +162,7 @@ class IncomingVerificationPresenterTest { emojiState.eventSink(IncomingVerificationViewEvents.DeclineVerification) val emojiWaitingItem = awaitItem() assertThat((emojiWaitingItem.step as IncomingVerificationState.Step.Verifying).isWaiting).isTrue() + advanceUntilIdle() declineVerificationLambda.assertions().isCalledOnce() // Remote confirm that there is a failure fakeSessionVerificationService.emitVerificationFlowState( @@ -260,6 +262,7 @@ class IncomingVerificationPresenterTest { emojiState.eventSink(IncomingVerificationViewEvents.GoBack) val emojiWaitingItem = awaitItem() assertThat((emojiWaitingItem.step as IncomingVerificationState.Step.Verifying).isWaiting).isTrue() + advanceUntilIdle() declineVerificationLambda.assertions().isCalledOnce() // Remote confirm that there is a failure fakeSessionVerificationService.emitVerificationFlowState( diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt index da31b633b1..947d75dd39 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt @@ -27,6 +27,8 @@ import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.test import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -271,6 +273,7 @@ class OutgoingVerificationPresenterTest { } } + context(testScope: TestScope) private suspend fun ReceiveTurbine.requestVerificationAndAwaitVerifyingState( fakeService: FakeSessionVerificationService, sessionVerificationData: SessionVerificationData = SessionVerificationData.Emojis(emptyList()), @@ -278,6 +281,7 @@ class OutgoingVerificationPresenterTest { var state = awaitItem() assertThat(state.step).isEqualTo(Step.Initial) state.eventSink(OutgoingVerificationViewEvents.RequestVerification) + testScope.advanceUntilIdle() // Await for other device response: fakeService.emitVerificationFlowState(VerificationFlowState.DidAcceptVerificationRequest) state = awaitItem() @@ -286,6 +290,7 @@ class OutgoingVerificationPresenterTest { state = awaitItem() assertThat(state.step).isEqualTo(Step.Ready) state.eventSink(OutgoingVerificationViewEvents.StartSasVerification) + testScope.advanceUntilIdle() // Await for other device response (again): fakeService.emitVerificationFlowState(VerificationFlowState.DidStartSasVerification) state = awaitItem() @@ -297,7 +302,7 @@ class OutgoingVerificationPresenterTest { return state } - private suspend fun unverifiedSessionService( + private fun unverifiedSessionService( requestDeviceVerificationLambda: () -> Unit = { lambdaError() }, requestUserVerificationLambda: (UserId) -> Unit = { lambdaError() }, cancelVerificationLambda: () -> Unit = { lambdaError() }, @@ -309,6 +314,7 @@ class OutgoingVerificationPresenterTest { acceptVerificationRequestLambda: () -> Unit = { lambdaError() }, ): FakeSessionVerificationService { return FakeSessionVerificationService( + initialSessionVerifiedStatus = SessionVerifiedStatus.NotVerified, requestDeviceVerificationLambda = requestDeviceVerificationLambda, requestUserVerificationLambda = requestUserVerificationLambda, cancelVerificationLambda = cancelVerificationLambda, @@ -318,9 +324,7 @@ class OutgoingVerificationPresenterTest { resetLambda = resetLambda, acknowledgeVerificationRequestLambda = acknowledgeVerificationRequestLambda, acceptVerificationRequestLambda = acceptVerificationRequestLambda, - ).apply { - emitVerifiedStatus(SessionVerifiedStatus.NotVerified) - } + ) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt index dab4d48952..0aeeebf86d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt @@ -40,31 +40,31 @@ class FakeSessionVerificationService( override val sessionVerifiedStatus: StateFlow = _sessionVerifiedStatus override val needsSessionVerification: Flow = _needsSessionVerification - override suspend fun requestDeviceVerification() { + override suspend fun requestDeviceVerification() = simulateLongTask { requestDeviceVerificationLambda() } - override suspend fun requestUserVerification(userId: UserId) { + override suspend fun requestUserVerification(userId: UserId) = simulateLongTask { requestUserVerificationLambda(userId) } - override suspend fun cancelVerification() { + override suspend fun cancelVerification() = simulateLongTask { cancelVerificationLambda() } - override suspend fun approveVerification() { + override suspend fun approveVerification() = simulateLongTask { approveVerificationLambda() } - override suspend fun declineVerification() { + override suspend fun declineVerification() = simulateLongTask { declineVerificationLambda() } - override suspend fun startSasVerification() { + override suspend fun startSasVerification() = simulateLongTask { startSasVerificationLambda() } - override suspend fun reset(cancelAnyPendingVerificationAttempt: Boolean) { + override suspend fun reset(cancelAnyPendingVerificationAttempt: Boolean) = simulateLongTask { resetLambda(cancelAnyPendingVerificationAttempt) } @@ -75,7 +75,7 @@ class FakeSessionVerificationService( this.listener = listener } - override suspend fun acknowledgeVerificationRequest(verificationRequest: VerificationRequest.Incoming) { + override suspend fun acknowledgeVerificationRequest(verificationRequest: VerificationRequest.Incoming) = simulateLongTask { acknowledgeVerificationRequestLambda(verificationRequest) } From 28e1062eed4939ca8de4a9ba9dd4370b589cff51 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Tue, 5 May 2026 17:02:52 +0300 Subject: [PATCH 0336/1083] Reimplement "Natural media viewer swiping order" (#6715) --- .../impl/viewer/MediaViewerDataSource.kt | 23 ++-------- .../impl/viewer/MediaViewerPresenter.kt | 22 ++++------ .../impl/viewer/MediaViewerView.kt | 1 + .../impl/viewer/MediaViewerPresenterTest.kt | 43 +++++++++---------- 4 files changed, 33 insertions(+), 56 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 24e48531f0..eadbd544fc 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 @@ -122,25 +122,11 @@ class MediaViewerDataSource( */ private fun buildMediaViewerPageList(groupedItems: List) = buildList { // Filter out DateSeparator items, we do not need them for the media viewer - 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 -> + val groupedItemsNoDateSeparator = groupedItems.filterNot { it is MediaItem.DateSeparator } + pagerKeysHandler.accept(groupedItemsNoDateSeparator) + groupedItemsNoDateSeparator.forEach { mediaItem -> when (mediaItem) { + is MediaItem.DateSeparator -> Unit is MediaItem.Event -> { val sourceUrl = mediaItem.mediaSource().safeUrl val localMedia = localMediaStates.getOrPut(sourceUrl) { @@ -164,7 +150,6 @@ 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 60f03bb1e0..138c73c383 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 @@ -177,21 +177,18 @@ class MediaViewerPresenter( currentIndex: IntState, data: State>, ) { + // With newest-first ordering, backward loading indicator is at the last index val isRenderingLoadingBackward by remember { derivedStateOf { - currentIndex.intValue == 0 && + currentIndex.intValue == data.value.lastIndex && data.value.size > 1 && - data.value.firstOrNull() is MediaViewerPageData.Loading && - (data.value.firstOrNull() as? MediaViewerPageData.Loading)?.direction == Timeline.PaginationDirection.BACKWARDS + data.value.lastOrNull() is MediaViewerPageData.Loading } } if (isRenderingLoadingBackward) { LaunchedEffect(Unit) { // Observe the loading data vanishing - snapshotFlow { - val first = data.value.firstOrNull() - first is MediaViewerPageData.Loading && first.direction == Timeline.PaginationDirection.BACKWARDS - } + snapshotFlow { data.value.lastOrNull() is MediaViewerPageData.Loading } .distinctUntilChanged() .filter { !it } .onEach { showNoMoreItemsSnackbar() } @@ -205,21 +202,18 @@ class MediaViewerPresenter( currentIndex: IntState, data: State>, ) { + // With newest-first ordering, forward loading indicator is at the first index val isRenderingLoadingForward by remember { derivedStateOf { - currentIndex.intValue == data.value.lastIndex && + currentIndex.intValue == 0 && data.value.size > 1 && - data.value.lastOrNull() is MediaViewerPageData.Loading && - (data.value.lastOrNull() as? MediaViewerPageData.Loading)?.direction == Timeline.PaginationDirection.FORWARDS + data.value.firstOrNull() is MediaViewerPageData.Loading } } if (isRenderingLoadingForward) { LaunchedEffect(Unit) { // Observe the loading data vanishing - snapshotFlow { - val last = data.value.lastOrNull() - last is MediaViewerPageData.Loading && last.direction == Timeline.PaginationDirection.FORWARDS - } + snapshotFlow { data.value.firstOrNull() is MediaViewerPageData.Loading } .distinctUntilChanged() .filter { !it } .onEach { showNoMoreItemsSnackbar() } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 738d940453..3738f6643b 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -182,6 +182,7 @@ fun MediaViewerView( // Pre-load previous and next pages beyondViewportPageCount = 1, key = { index -> state.listData[index].pagerKey }, + reverseLayout = true, ) { page -> when (val dataForPage = state.listData[page]) { is MediaViewerPageData.Failure -> { 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 caacb03804..86689859ad 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(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), + fileItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) val updatedState = awaitItem() - // User navigate to the last item (forward loading indicator) + // User navigate to the first item (forward loading indicator) updatedState.eventSink( - MediaViewerEvent.OnNavigateTo(2) + MediaViewerEvent.OnNavigateTo(0) ) // data source claims that there is no more items to load forward mediaGalleryDataSource.emitGroupedMediaItems( @@ -614,21 +614,19 @@ class MediaViewerPresenterTest { if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(aBackwardLoadingIndicator, anImage), + fileItems = persistentListOf(anImage, aBackwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage), + imageAndVideoItems = persistentListOf(anImage, aBackwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) - var stateWithSnackbar = awaitItem() - while (stateWithSnackbar.snackbarMessage == null) { - stateWithSnackbar = awaitItem() - } - assertThat(stateWithSnackbar.snackbarMessage.messageResId).isEqualTo(expectedSnackbarResId) + skipItems(1) + val stateWithSnackbar = awaitItem() + assertThat(stateWithSnackbar.snackbarMessage!!.messageResId).isEqualTo(expectedSnackbarResId) } } @@ -667,42 +665,41 @@ class MediaViewerPresenterTest { if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), + fileItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) val updatedState = awaitItem() - // User navigate to the first item (backward loading indicator) + // User navigate to the last item (backward loading indicator) updatedState.eventSink( - MediaViewerEvent.OnNavigateTo(0) + MediaViewerEvent.OnNavigateTo(2) ) + 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(anImage, aForwardLoadingIndicator), + fileItems = persistentListOf(aForwardLoadingIndicator, anImage), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(anImage, aForwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage), fileItems = persistentListOf(), ) } ) ) - var stateWithSnackbar = awaitItem() - while (stateWithSnackbar.snackbarMessage == null) { - stateWithSnackbar = awaitItem() - } - assertThat(stateWithSnackbar.snackbarMessage.messageResId).isEqualTo(expectedSnackbarResId) + skipItems(1) + val stateWithSnackbar = awaitItem() + assertThat(stateWithSnackbar.snackbarMessage!!.messageResId).isEqualTo(expectedSnackbarResId) } } @@ -720,7 +717,7 @@ class MediaViewerPresenterTest { mediaGalleryDataSource.emitGroupedMediaItems( AsyncData.Success( GroupedMediaItems( - imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), fileItems = persistentListOf(), ) ) From 54a66669887ffdb10511d6b2c6d57e10dea583d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 14:05:26 +0000 Subject: [PATCH 0337/1083] Update dependency net.zetetic:sqlcipher-android to v4.15.0 --- 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 d17ddc99d7..8fe2bde9e5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -200,7 +200,7 @@ matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } -sqlcipher = "net.zetetic:sqlcipher-android:4.14.1" +sqlcipher = "net.zetetic:sqlcipher-android:4.15.0" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" unifiedpush = "org.unifiedpush.android:connector:3.3.2" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" From 384c806131b4f679a0741c9ebd59213a30df3413 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 May 2026 16:22:32 +0200 Subject: [PATCH 0338/1083] Fix compilation warnings --- .../features/preferences/impl/tasks/ClearCacheUseCase.kt | 3 +-- .../features/rageshake/impl/reporter/DefaultBugReporter.kt | 3 +-- .../libraries/matrix/ui/media/ImageLoaderFactories.kt | 3 +-- .../io/element/android/libraries/network/RetrofitFactory.kt | 5 ++--- .../libraries/voicerecorder/impl/audio/DefaultEncoder.kt | 3 +-- 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt index 6c26866e93..6977525548 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt @@ -11,7 +11,6 @@ package io.element.android.features.preferences.impl.tasks import android.content.Context import coil3.SingletonImageLoader import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.preferences.impl.DefaultCacheService import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -33,7 +32,7 @@ class DefaultClearCacheUseCase( private val matrixClient: MatrixClient, private val coroutineDispatchers: CoroutineDispatchers, private val defaultCacheService: DefaultCacheService, - private val okHttpClient: Provider, + private val okHttpClient: () -> OkHttpClient, private val pushService: PushService, private val seenInvitesStore: SeenInvitesStore, private val activeRoomsHolder: ActiveRoomsHolder, diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt index b4e7faa01e..2568a6fba9 100755 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt @@ -14,7 +14,6 @@ import androidx.core.net.toFile import androidx.core.net.toUri import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import dev.zacsweers.metro.SingleIn import io.element.android.appconfig.RageshakeConfig import io.element.android.features.rageshake.api.logs.createWriteToFilesConfiguration @@ -77,7 +76,7 @@ class DefaultBugReporter( private val screenshotHolder: ScreenshotHolder, private val crashDataStore: CrashDataStore, private val coroutineDispatchers: CoroutineDispatchers, - private val okHttpClient: Provider, + private val okHttpClient: () -> OkHttpClient, private val userAgentProvider: UserAgentProvider, private val sessionStore: SessionStore, private val buildMeta: BuildMeta, diff --git a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt index e67e630e97..ef654a4cf7 100644 --- a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt +++ b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt @@ -16,7 +16,6 @@ import coil3.gif.GifDecoder import coil3.network.okhttp.OkHttpNetworkFetcherFactory import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import okhttp3.OkHttpClient @@ -29,7 +28,7 @@ interface ImageLoaderFactory { @ContributesBinding(AppScope::class) class DefaultImageLoaderFactory( @ApplicationContext private val context: Context, - private val okHttpClient: Provider, + private val okHttpClient: () -> OkHttpClient, ) : ImageLoaderFactory { private val okHttpNetworkFetcherFactory = OkHttpNetworkFetcherFactory( callFactory = { diff --git a/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt b/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt index 88240c3d65..39a54dca61 100644 --- a/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt +++ b/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.network import dev.zacsweers.metro.Inject -import dev.zacsweers.metro.Provider import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.core.uri.ensureTrailingSlash import okhttp3.MediaType.Companion.toMediaType @@ -19,8 +18,8 @@ import retrofit2.converter.kotlinx.serialization.asConverterFactory @Inject class RetrofitFactory( - private val okHttpClient: Provider, - private val json: Provider, + private val okHttpClient: () -> OkHttpClient, + private val json: () -> JsonProvider, ) { fun create(baseUrl: String): Retrofit = Retrofit.Builder() .baseUrl(baseUrl.ensureTrailingSlash()) diff --git a/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt b/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt index 9d471f7a6d..9d41b0da92 100644 --- a/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt +++ b/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.voicerecorder.impl.audio import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import io.element.android.libraries.di.RoomScope import io.element.android.opusencoder.OggOpusEncoder import timber.log.Timber @@ -20,7 +19,7 @@ import java.io.File */ @ContributesBinding(RoomScope::class) class DefaultEncoder( - private val encoderProvider: Provider, + private val encoderProvider: () -> OggOpusEncoder, config: AudioConfig, ) : Encoder { private val bitRate = config.bitRate From 3b3b4813b685a3fa94126fbe8b6429d8c334467c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 May 2026 16:50:22 +0200 Subject: [PATCH 0339/1083] Detekt and ktlint are confused with Kotlin context... --- .../impl/outgoing/OutgoingVerificationPresenterTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt index 947d75dd39..c6cbfca281 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt @@ -6,6 +6,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:Suppress("UnusedImports") + package io.element.android.features.verifysession.impl.outgoing import app.cash.turbine.ReceiveTurbine From a7711b7d524c4c8b1592aac5c4c3cbaeba24fa06 Mon Sep 17 00:00:00 2001 From: Kurban Sagitov <58472509+krbns@users.noreply.github.com> Date: Tue, 5 May 2026 18:10:24 +0300 Subject: [PATCH 0340/1083] Fix low width image message (#6692) * fix low width image message * added previews for narrow images * Update screenshots --------- Co-authored-by: ElementBot --- .../components/event/TimelineItemImageView.kt | 47 ++++++++++++++++++- .../event/TimelineItemImageContentProvider.kt | 6 ++- ...s.event_ATimelineItemEventRow_Day_0_en.png | 3 ++ ...event_ATimelineItemEventRow_Night_0_en.png | 3 ++ 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en.png diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt index bef06bcd73..0e0a98a96c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemImageView.kt @@ -58,6 +58,7 @@ import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.wysiwyg.compose.EditorStyledText import io.element.android.wysiwyg.link.Link +private const val TALL_IMAGE_RATIO_DIVISOR = 3 @Composable fun TimelineItemImageView( content: TimelineItemImageContent, @@ -79,7 +80,7 @@ fun TimelineItemImageView( Modifier } TimelineItemAspectRatioBox( - modifier = containerModifier.blurHashBackground(content.blurhash, alpha = 0.9f), + modifier = containerModifier.blurHashBackground(content.blurhash, alpha = 0.9f).align(Alignment.CenterHorizontally), aspectRatio = coerceRatioWhenHidingContent(content.aspectRatio, hideMediaContent), ) { ProtectedView( @@ -123,7 +124,14 @@ fun TimelineItemImageView( LocalContentColor provides ElementTheme.colors.textPrimary, LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular ) { - val aspectRatio = content.aspectRatio ?: DEFAULT_ASPECT_RATIO + val width = content.width ?: 0 + val height = content.height ?: 0 + // if image is narrow and tall use DEFAULT_ASPECT_RATIO + val aspectRatio = if (width < height / TALL_IMAGE_RATIO_DIVISOR) { + DEFAULT_ASPECT_RATIO + } else { + content.aspectRatio ?: DEFAULT_ASPECT_RATIO + } EditorStyledText( modifier = Modifier .padding(horizontal = 4.dp) // This is (12.dp - 8.dp) contentPadding from CommonLayout @@ -200,3 +208,38 @@ internal fun TimelineImageWithCaptionRowPreview() = ElementPreview { ) } } + +@PreviewsDayNight +@Composable +internal fun ATimelineItemEventRowPreview() = ElementPreview { + Column { + sequenceOf(false, true).forEach { isMine -> + ATimelineItemEventRow( + event = aTimelineItemEvent( + isMine = isMine, + content = aTimelineItemImageContent( + filename = "image.jpg", + caption = "A long caption that may wrap into several lines", + width = 80, + height = 300, + aspectRatio = 80f / 300f, + ), + groupPosition = TimelineItemGroupPosition.Last, + ), + ) + } + ATimelineItemEventRow( + event = aTimelineItemEvent( + isMine = false, + content = aTimelineItemImageContent( + filename = "image.jpg", + caption = "Narrow image with null aspectRatio", + width = 80, + height = 300, + aspectRatio = null, + ), + groupPosition = TimelineItemGroupPosition.Last, + ), + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContentProvider.kt index d07d5db6a4..6d3b114428 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContentProvider.kt @@ -28,6 +28,8 @@ fun aTimelineItemImageContent( blurhash: String? = A_BLUR_HASH, filename: String = "A picture.jpg", caption: String? = null, + width: Int? = null, + height: Int? = 300, ) = TimelineItemImageContent( filename = filename, fileSize = 4 * 1024 * 1024L, @@ -38,8 +40,8 @@ fun aTimelineItemImageContent( thumbnailSource = null, mimeType = MimeTypes.IMAGE_JPEG, blurhash = blurhash, - width = null, - height = 300, + width = width, + height = height, thumbnailWidth = null, thumbnailHeight = 150, aspectRatio = aspectRatio, diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png new file mode 100644 index 0000000000..08169845d5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86eac241e9084cc830ff13d231908da2eb0dff246aa5cac64dddaac68a5d5f13 +size 295298 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en.png new file mode 100644 index 0000000000..06dd93b269 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:578a3707102c7754f607c3a14f94f32cafa30ee570db174386533c484cb4773c +size 295031 From 51816e0281e8a45aa40a65a2ade47a421e6fcc80 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Tue, 5 May 2026 13:04:37 -0700 Subject: [PATCH 0341/1083] Move jumpToUnreadButton to bottom, remove badge count --- .../impl/timeline/TimelinePresenter.kt | 53 +---- .../messages/impl/timeline/TimelineState.kt | 4 +- .../impl/timeline/TimelineStateProvider.kt | 7 +- .../messages/impl/timeline/TimelineView.kt | 123 ++++-------- .../impl/timeline/model/JumpToUnreadState.kt | 32 --- .../impl/timeline/model/NewEventState.kt | 7 +- .../model/event/TimelineItemEventContent.kt | 22 --- .../impl/timeline/TimelinePresenterTest.kt | 182 +++++------------- 8 files changed, 104 insertions(+), 326 deletions(-) delete mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt 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 6e0145f742..8dbb53d7cd 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 @@ -30,10 +30,8 @@ import io.element.android.features.messages.impl.crypto.sendfailure.resolve.Reso import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactoryConfig -import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.features.messages.impl.timeline.model.event.isMessageContent import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemTypingNotificationModel import io.element.android.features.messages.impl.typing.TypingNotificationState @@ -281,26 +279,16 @@ class TimelinePresenter( // read marker advances in place — the SDK swaps the marker virtual item to a new position // without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the // bottom of the room. - val jumpToUnreadState = remember { mutableStateOf(JumpToUnreadState.Disabled) } + val readMarkerIndex = remember { mutableStateOf(null) } LaunchedEffect(timelineItems, displayJumpToUnread) { if (!displayJumpToUnread) { - jumpToUnreadState.value = JumpToUnreadState.Disabled + readMarkerIndex.value = null return@LaunchedEffect } val items = timelineItems - jumpToUnreadState.value = withContext(dispatchers.computation) { - var markerIdx = -1 - var unread = 0 - for ((i, item) in items.withIndex()) { - if ((item as? TimelineItem.Virtual)?.model is TimelineItemReadMarkerModel) { - markerIdx = i - break - } - if (item is TimelineItem.Event && item.isCountableNewMessage()) { - unread++ - } - } - if (markerIdx < 0) JumpToUnreadState.NoMarker else JumpToUnreadState.Loaded(markerIdx, unread) + readMarkerIndex.value = withContext(dispatchers.computation) { + items.indexOfFirst { (it as? TimelineItem.Virtual)?.model is TimelineItemReadMarkerModel } + .takeIf { it >= 0 } } } @@ -353,7 +341,8 @@ class TimelinePresenter( resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, - jumpToUnreadState = jumpToUnreadState.value, + displayJumpToUnread = displayJumpToUnread, + readMarkerIndex = readMarkerIndex.value, eventSink = ::handleEvent, ) } @@ -411,10 +400,6 @@ class TimelinePresenter( * This method compute the hasNewItem state passed as a [MutableState] each time the timeline items size changes. * Basically, if we got new timeline event from sync or local, either from us or another user, we update the state so we tell we have new items. * The state never goes back to None from this method, but need to be reset from somewhere else. - * - * The [NewEventState.FromOther] variant carries the running count of incoming messages from other users - * since [prevMostRecentItemId] last advanced to a local-user event or the timeline returned to the bottom - * — this drives the badge on the scroll-to-bottom button. */ private suspend fun computeNewItemState( timelineItems: ImmutableList, @@ -438,19 +423,7 @@ class TimelinePresenter( if (hasNewEvent) { // Scroll to bottom if the new event is from me, even if sent from another device - if (newMostRecentItem.isMine) { - newEventState.value = NewEventState.FromMe - } else { - var delta = 0 - for (item in timelineItems) { - if (item.identifier() == prevMostRecentItemIdValue) break - if (item is TimelineItem.Event && item.isCountableNewMessage()) { - delta++ - } - } - val previousCount = (newEventState.value as? NewEventState.FromOther)?.messageCount ?: 0 - newEventState.value = NewEventState.FromOther(previousCount + delta) - } + newEventState.value = if (newMostRecentItem.isMine) NewEventState.FromMe else NewEventState.FromOther } prevMostRecentItemId.value = newMostRecentItemId } @@ -496,16 +469,6 @@ private fun FocusRequestState.onFocusEventRender(): FocusRequestState { } } -/** - * Whether this event should be counted toward the unread / new-message badges: a user-facing - * message from someone other than the local user, that wasn't pulled in via back-pagination. - */ -private fun TimelineItem.Event.isCountableNewMessage(): Boolean { - return !isMine && - origin != TimelineItemEventOrigin.PAGINATION && - content.isMessageContent() -} - // Workaround for not having the server names available, get possible server names from the user ids of the room members private fun calculateServerNamesForRoom(room: JoinedRoom): List { // If we have no room members, return right ahead diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 6f48a8d9fc..d66dfe3031 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -11,7 +11,6 @@ package io.element.android.features.messages.impl.timeline import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.components.MessageShieldData -import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.typing.TypingNotificationState @@ -36,7 +35,8 @@ data class TimelineState( val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val displayThreadSummaries: Boolean, val displayFloatingDateBadge: Boolean, - val jumpToUnreadState: JumpToUnreadState, + val displayJumpToUnread: Boolean, + val readMarkerIndex: Int?, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 0ea48c3c35..5ba3a41618 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -12,7 +12,6 @@ import io.element.android.features.messages.impl.crypto.sendfailure.resolve.Reso import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData -import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.ReadReceiptData import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -58,7 +57,8 @@ fun aTimelineState( resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), displayThreadSummaries: Boolean = false, displayFloatingDateBadge: Boolean = false, - jumpToUnreadState: JumpToUnreadState = JumpToUnreadState.NoMarker, + displayJumpToUnread: Boolean = false, + readMarkerIndex: Int? = null, newEventState: NewEventState = NewEventState.None, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { @@ -80,7 +80,8 @@ fun aTimelineState( resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, - jumpToUnreadState = jumpToUnreadState, + displayJumpToUnread = displayJumpToUnread, + readMarkerIndex = readMarkerIndex, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index b93f9e950d..d04f55bb2c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -19,7 +19,6 @@ import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding @@ -49,9 +48,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.rememberNestedScrollInteropConnection -import androidx.compose.ui.res.pluralStringResource 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 androidx.compose.ui.unit.IntOffset @@ -65,7 +62,6 @@ import io.element.android.features.messages.impl.timeline.components.toText import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.aFakeTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.focus.FocusRequestStateView -import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent @@ -78,14 +74,12 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.FloatingActionButton import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag -import io.element.android.libraries.ui.strings.CommonPlurals import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.time.isTalkbackActive import io.element.android.wysiwyg.link.Link @@ -221,8 +215,8 @@ fun TimelineView( newEventState = state.newEventState, isLive = state.isLive, focusRequestState = state.focusRequestState, - jumpToUnreadState = state.jumpToUnreadState, - topInset = floatingDateTopOffset, + displayJumpToUnread = state.displayJumpToUnread, + readMarkerIndex = state.readMarkerIndex, onScrollFinishAt = ::onScrollFinishAt, onJumpToLive = ::onJumpToLive, onFocusEventRender = ::onFocusEventRender, @@ -306,8 +300,8 @@ private fun BoxScope.TimelineScrollHelper( forceJumpToBottomVisibility: Boolean, forceJumpToReadMarkerVisibility: Boolean, focusRequestState: FocusRequestState, - jumpToUnreadState: JumpToUnreadState, - topInset: Dp, + displayJumpToUnread: Boolean, + readMarkerIndex: Int?, onScrollFinishAt: (Int) -> Unit, onJumpToLive: () -> Unit, onFocusEventRender: () -> Unit, @@ -321,14 +315,10 @@ private fun BoxScope.TimelineScrollHelper( } val isJumpToUnreadVisible by remember { derivedStateOf { - when { - forceJumpToReadMarkerVisibility -> true - jumpToUnreadState !is JumpToUnreadState.Loaded -> false - else -> { - val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false - jumpToUnreadState.markerIndex > lastVisibleIndex - } - } + if (forceJumpToReadMarkerVisibility) return@derivedStateOf true + val markerIndex = readMarkerIndex ?: return@derivedStateOf false + val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false + markerIndex > lastVisibleIndex } } val isJumpToBottomVisible = !canAutoScroll || forceJumpToBottomVisibility || !isLive @@ -359,9 +349,9 @@ private fun BoxScope.TimelineScrollHelper( } fun jumpToReadMarker() { - val loaded = jumpToUnreadState as? JumpToUnreadState.Loaded ?: return + val markerIndex = readMarkerIndex ?: return coroutineScope.launch { - lazyListState.animateScrollToItemCenter(loaded.markerIndex) + lazyListState.animateScrollToItemCenter(markerIndex) } } @@ -403,28 +393,21 @@ private fun BoxScope.TimelineScrollHelper( icon = CompoundIcons.ChevronDown(), contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), isVisible = isJumpToBottomVisible, - // Hide the badge entirely when the feature is off, regardless of the count value. - count = if (jumpToUnreadState is JumpToUnreadState.Disabled) 0 else newEventState.messageCount, + hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther, modifier = Modifier .align(Alignment.BottomEnd) .padding(end = 24.dp, bottom = 12.dp), onClick = ::jumpToBottom, ) - val unreadCount = (jumpToUnreadState as? JumpToUnreadState.Loaded)?.unreadCount ?: 0 - val jumpToUnreadDescription = if (unreadCount > 0) { - pluralStringResource(CommonPlurals.a11y_jump_to_unread_messages_count, unreadCount, unreadCount) - } else { - stringResource(id = CommonStrings.a11y_jump_to_unread_messages) - } JumpToPositionButton( icon = CompoundIcons.ChevronUp(), - contentDescription = jumpToUnreadDescription, + contentDescription = stringResource(id = CommonStrings.a11y_jump_to_unread_messages), isVisible = isJumpToUnreadVisible, - count = unreadCount, - // Top padding includes [topInset] so the FAB sits below any pinned-events banner. + hasUnread = true, + // Stacked directly above the scroll-to-bottom FAB: 12dp base + 36dp FAB + 8dp gap. modifier = Modifier - .align(Alignment.TopEnd) - .padding(end = 24.dp, top = topInset + 12.dp), + .align(Alignment.BottomEnd) + .padding(end = 24.dp, bottom = 56.dp), onClick = ::jumpToReadMarker, ) } @@ -434,7 +417,7 @@ private fun JumpToPositionButton( icon: ImageVector, contentDescription: String, isVisible: Boolean, - count: Int, + hasUnread: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -459,8 +442,8 @@ private fun JumpToPositionButton( contentDescription = contentDescription, ) } - TimelineCountBadge( - count = count, + TimelineUnreadIndicator( + isVisible = hasUnread, modifier = Modifier .align(Alignment.TopEnd) .offset { IntOffset(x = 4.dp.roundToPx(), y = -4.dp.roundToPx()) }, @@ -469,39 +452,18 @@ private fun JumpToPositionButton( } } -/** - * Small accent badge overlaid on a timeline FAB. Shows the count when it's between 1 and 9, otherwise a dot. - * Renders nothing when [count] is zero or negative. - */ @Composable -private fun TimelineCountBadge( - count: Int, +private fun TimelineUnreadIndicator( + isVisible: Boolean, modifier: Modifier = Modifier, ) { - when { - count <= 0 -> return - count <= 9 -> Box( - modifier = modifier - .defaultMinSize(minWidth = 16.dp, minHeight = 16.dp) - .background(color = ElementTheme.colors.bgActionPrimaryRest, shape = CircleShape) - .border(width = 2.dp, color = ElementTheme.colors.iconOnSolidPrimary, shape = CircleShape) - .padding(horizontal = 4.dp), - contentAlignment = Alignment.Center, - ) { - Text( - text = count.toString(), - color = ElementTheme.colors.textOnSolidPrimary, - style = ElementTheme.typography.fontBodyXsMedium, - textAlign = TextAlign.Center, - ) - } - else -> Box( - modifier = modifier - .size(12.dp) - .background(color = ElementTheme.colors.bgActionPrimaryRest, shape = CircleShape) - .border(width = 2.dp, color = ElementTheme.colors.iconOnSolidPrimary, shape = CircleShape), - ) - } + if (!isVisible) return + Box( + modifier = modifier + .size(12.dp) + .background(color = ElementTheme.colors.iconSuccessPrimary, shape = CircleShape) + .border(width = 2.dp, color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape), + ) } @PreviewsDayNight @@ -541,8 +503,8 @@ internal fun TimelineViewPreview( @Composable private fun TimelineViewWithReadMarker( - unreadMessagesCount: Int, - newMessagesCount: Int, + hasUnreadAbove: Boolean, + hasUnreadBelow: Boolean, ) { val timelineItems = persistentListOf( aTimelineItemEvent(isMine = false), @@ -558,11 +520,12 @@ private fun TimelineViewWithReadMarker( TimelineView( state = aTimelineState( timelineItems = timelineItems, + displayJumpToUnread = true, // Index points past the loaded items, mirroring the real-world state the FAB // represents: the user has scrolled past the read marker, so it's no longer in // view. The actual scroll target doesn't matter for a static preview. - jumpToUnreadState = JumpToUnreadState.Loaded(markerIndex = timelineItems.size, unreadCount = unreadMessagesCount), - newEventState = if (newMessagesCount > 0) NewEventState.FromOther(newMessagesCount) else NewEventState.None, + readMarkerIndex = if (hasUnreadAbove) timelineItems.size else null, + newEventState = if (hasUnreadBelow) NewEventState.FromOther else NewEventState.None, ), timelineProtectionState = aTimelineProtectionState(), onUserDataClick = {}, @@ -582,24 +545,12 @@ private fun TimelineViewWithReadMarker( @PreviewsDayNight @Composable -internal fun TimelineViewWithReadMarkerNoBadgesPreview() = ElementPreview { - TimelineViewWithReadMarker(unreadMessagesCount = 0, newMessagesCount = 0) +internal fun TimelineViewWithReadMarkerNoIndicatorsPreview() = ElementPreview { + TimelineViewWithReadMarker(hasUnreadAbove = false, hasUnreadBelow = false) } @PreviewsDayNight @Composable -internal fun TimelineViewWithReadMarkerNumericBadgePreview() = ElementPreview { - TimelineViewWithReadMarker(unreadMessagesCount = 3, newMessagesCount = 0) -} - -@PreviewsDayNight -@Composable -internal fun TimelineViewWithReadMarkerDotBadgesPreview() = ElementPreview { - TimelineViewWithReadMarker(unreadMessagesCount = 47, newMessagesCount = 0) -} - -@PreviewsDayNight -@Composable -internal fun TimelineViewWithReadMarkerBothCountsPreview() = ElementPreview { - TimelineViewWithReadMarker(unreadMessagesCount = 5, newMessagesCount = 3) +internal fun TimelineViewWithReadMarkerBothIndicatorsPreview() = ElementPreview { + TimelineViewWithReadMarker(hasUnreadAbove = true, hasUnreadBelow = true) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt deleted file mode 100644 index 8154445015..0000000000 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/JumpToUnreadState.kt +++ /dev/null @@ -1,32 +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.features.messages.impl.timeline.model - -import androidx.compose.runtime.Immutable - -/** - * Drives the jump-to-unread FAB and the count badge on the scroll-to-bottom FAB. - * - * The two affordances share state because they're both gated on the same feature flag and both - * use counts derived from the same timeline scan. - */ -@Immutable -sealed interface JumpToUnreadState { - /** Feature flag is off — neither the FAB nor the new-message badge is shown. */ - data object Disabled : JumpToUnreadState - - /** Feature flag is on, but no read marker is present in the current timeline window. */ - data object NoMarker : JumpToUnreadState - - /** - * Feature flag is on and the read marker is loaded at [markerIndex]. The FAB shows when the - * marker is above the viewport; the badge displays [unreadCount] when greater than zero. - */ - data class Loaded(val markerIndex: Int, val unreadCount: Int) : JumpToUnreadState -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt index eb60d6780f..f80640dd0f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/NewEventState.kt @@ -13,15 +13,10 @@ import androidx.compose.runtime.Immutable /** * Model if there is a new event in the timeline and if it is from me or from other. * This can be used to scroll to the bottom of the list when a new event is added. - * - * [FromOther] also carries the running count of incoming messages from other users since the - * timeline was last at the bottom — used to drive the badge on the scroll-to-bottom button. */ @Immutable sealed interface NewEventState { - val messageCount: Int get() = 0 - data object None : NewEventState data object FromMe : NewEventState - data class FromOther(override val messageCount: Int) : NewEventState + data object FromOther : NewEventState } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt index fe2c264932..9c4c48d11e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt @@ -99,28 +99,6 @@ fun TimelineItemEventContent.isEdited(): Boolean = when (this) { */ fun TimelineItemEventContent.isRedacted(): Boolean = this is TimelineItemRedactedContent -/** - * Whether the event content is a user-facing message that should be counted toward unread totals. - * Excludes state events, profile changes, membership changes, redactions, and unknown content. - */ -fun TimelineItemEventContent.isMessageContent(): Boolean = when (this) { - is TimelineItemTextBasedContent, - is TimelineItemAudioContent, - is TimelineItemEncryptedContent, - is TimelineItemFileContent, - is TimelineItemImageContent, - is TimelineItemStickerContent, - is TimelineItemLocationContent, - is TimelineItemPollContent, - is TimelineItemVoiceContent, - is TimelineItemVideoContent, - is TimelineItemLegacyCallInviteContent, - is TimelineItemRtcNotificationContent -> true - is TimelineItemStateContent, - is TimelineItemRedactedContent, - TimelineItemUnknownContent -> false -} - fun TimelineItemEventContentWithAttachment.duration(): Duration? { return when (this) { is TimelineItemAudioContent -> duration diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index bec7895c63..860d73a835 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -16,7 +16,6 @@ import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactoryCreator import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.components.aCriticalShield -import io.element.android.features.messages.impl.timeline.model.JumpToUnreadState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.typing.aTypingNotificationState @@ -364,17 +363,14 @@ class TimelinePresenterTest { } consumeItemsUntilPredicate { it.timelineItems.size == 4 } awaitLastSequentialItem().also { state -> - // Both events received during the FromMe window are counted now that the timeline - // has progressed past it: prevMostRecentItemId points at the local user's "1", - // so "2" and "3" are both new countable messages. - assertThat(state.newEventState).isEqualTo(NewEventState.FromOther(2)) + assertThat(state.newEventState).isEqualTo(NewEventState.FromOther) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - jumpToUnreadState reports loaded marker and unread count, excluding state events`() = runTest { + fun `present - readMarkerIndex points at the read marker virtual item`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -394,47 +390,16 @@ class TimelinePresenterTest { MatrixTimelineItem.Event(UniqueId("msg-newest"), anEventTimelineItem(content = aMessageContent())), ) ) - consumeItemsUntilPredicate { it.jumpToUnreadState is JumpToUnreadState.Loaded }.last().also { state -> - // 2 message items above the marker; the membership state event is skipped. - assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.Loaded(markerIndex = 3, unreadCount = 2)) + consumeItemsUntilPredicate { it.readMarkerIndex != null }.last().also { state -> + assertThat(state.readMarkerIndex).isEqualTo(3) + assertThat(state.displayJumpToUnread).isTrue() } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - jumpToUnreadState count excludes own messages and PAGINATION-origin events`() = runTest { - val timelineItems = MutableStateFlow(emptyList()) - val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter( - timeline = timeline, - featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), - ) - presenter.test { - awaitFirstItem() - // After processing (factory reverses): [other-newest, own-msg, paginated, read-marker, msg-old] - timelineItems.emit( - listOf( - MatrixTimelineItem.Event(UniqueId("msg-old"), anEventTimelineItem(content = aMessageContent())), - MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker), - MatrixTimelineItem.Event( - UniqueId("paginated"), - anEventTimelineItem(content = aMessageContent()).copy(origin = TimelineItemEventOrigin.PAGINATION), - ), - MatrixTimelineItem.Event(UniqueId("own-msg"), anEventTimelineItem(content = aMessageContent(), isOwn = true)), - MatrixTimelineItem.Event(UniqueId("other-newest"), anEventTimelineItem(content = aMessageContent())), - ) - ) - consumeItemsUntilPredicate { it.jumpToUnreadState is JumpToUnreadState.Loaded }.last().also { state -> - // Only `other-newest` counts: own-msg and paginated are filtered out. - assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.Loaded(markerIndex = 3, unreadCount = 1)) - } - cancelAndIgnoreRemainingEvents() - } - } - - @Test - fun `present - jumpToUnreadState is NoMarker when no read marker present`() = runTest { + fun `present - readMarkerIndex is null when no read marker present`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -450,16 +415,41 @@ class TimelinePresenterTest { ) ) consumeItemsUntilPredicate { - it.timelineItems.size == 2 && it.jumpToUnreadState == JumpToUnreadState.NoMarker + it.timelineItems.size == 2 && it.readMarkerIndex == null }.last().also { state -> - assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.NoMarker) + assertThat(state.readMarkerIndex).isNull() } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - FromOther count increments by N when N events from others arrive in one batch`() = runTest { + fun `present - readMarkerIndex stays null when JumpToUnread feature flag is disabled`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val presenter = createTimelinePresenter( + timeline = timeline, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to false)), + ) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("msg-old"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker), + MatrixTimelineItem.Event(UniqueId("msg-newest"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 3 }.last().also { state -> + assertThat(state.displayJumpToUnread).isFalse() + assertThat(state.readMarkerIndex).isNull() + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - newEventState becomes FromOther when an event from another user arrives`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -471,16 +461,11 @@ class TimelinePresenterTest { listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) ) consumeItemsUntilPredicate { it.timelineItems.size == 1 } - // Three new events from another user arrive in a single batch. timelineItems.getAndUpdate { items -> - items + listOf( - MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent())), - MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent())), - MatrixTimelineItem.Event(UniqueId("3"), anEventTimelineItem(content = aMessageContent())), - ) + items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(3) }.last().also { state -> - assertThat(state.newEventState).isEqualTo(NewEventState.FromOther(3)) + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther }.last().also { state -> + assertThat(state.newEventState).isEqualTo(NewEventState.FromOther) } cancelAndIgnoreRemainingEvents() } @@ -503,8 +488,7 @@ class TimelinePresenterTest { timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - val countedState = consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) }.last() - assertThat(countedState.newEventState).isEqualTo(NewEventState.FromOther(1)) + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther } initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(0)) consumeItemsUntilPredicate { it.newEventState == NewEventState.None }.last().also { state -> assertThat(state.newEventState).isEqualTo(NewEventState.None) @@ -514,7 +498,7 @@ class TimelinePresenterTest { } @Test - fun `present - newEventState transitions to FromMe when latest event is from me, dropping the count`() = runTest { + fun `present - newEventState transitions to FromMe when latest event is from me`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -524,12 +508,12 @@ class TimelinePresenterTest { listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) ) consumeItemsUntilPredicate { it.timelineItems.size == 1 } - // First, an event from another user increments the count. + // First, an event from another user moves us to FromOther. timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) } - // Then the local user sends a message: state moves to FromMe (which carries no count). + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther } + // Then the local user sends a message: state moves to FromMe. timelineItems.getAndUpdate { items -> items + listOf( MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(content = aMessageContent(), isOwn = true)), @@ -537,14 +521,13 @@ class TimelinePresenterTest { } consumeItemsUntilPredicate { it.newEventState == NewEventState.FromMe }.last().also { state -> assertThat(state.newEventState).isEqualTo(NewEventState.FromMe) - assertThat(state.newEventState.messageCount).isEqualTo(0) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - FromOther count does not reset on OnScrollFinished firstIndex other than 0`() = runTest { + fun `present - newEventState does not reset on OnScrollFinished firstIndex other than 0`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -557,19 +540,18 @@ class TimelinePresenterTest { timelineItems.getAndUpdate { items -> items + listOf(MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent()))) } - consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) } - // Scrolling stops above the bottom: the count must NOT reset. + consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther } + // Scrolling stops above the bottom: state must NOT reset. initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(5)) advanceUntilIdle() - // No state should emit with the count back at 0. val drained = consumeItemsUntilTimeout() - assertThat(drained.any { it.newEventState.messageCount == 0 }).isFalse() + assertThat(drained.any { it.newEventState == NewEventState.None }).isFalse() cancelAndIgnoreRemainingEvents() } } @Test - fun `present - FromOther count does not increment for events with PAGINATION origin`() = runTest { + fun `present - newEventState stays None for events with PAGINATION origin`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter(timeline) @@ -579,7 +561,7 @@ class TimelinePresenterTest { listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) ) consumeItemsUntilPredicate { it.timelineItems.size == 1 } - // A back-paginated event arrives. It should not bump the badge. + // A back-paginated event arrives. It should not flip newEventState. timelineItems.getAndUpdate { items -> items + listOf( MatrixTimelineItem.Event( @@ -589,38 +571,14 @@ class TimelinePresenterTest { ) } consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> - assertThat(state.newEventState.messageCount).isEqualTo(0) + assertThat(state.newEventState).isEqualTo(NewEventState.None) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - FromOther count does not increment for state events`() = runTest { - val timelineItems = MutableStateFlow(emptyList()) - val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter(timeline) - presenter.test { - awaitFirstItem() - timelineItems.emit( - listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) - ) - consumeItemsUntilPredicate { it.timelineItems.size == 1 } - // A membership change arrives. It should not bump the badge. - timelineItems.getAndUpdate { items -> - items + listOf( - MatrixTimelineItem.Event(UniqueId("membership"), anEventTimelineItem(content = aRoomMembershipContent())), - ) - } - consumeItemsUntilPredicate { it.timelineItems.size == 2 }.last().also { state -> - assertThat(state.newEventState.messageCount).isEqualTo(0) - } - cancelAndIgnoreRemainingEvents() - } - } - - @Test - fun `present - jumpToUnreadState markerIndex is 0 when the read marker is the only item`() = runTest { + fun `present - readMarkerIndex is 0 when the read marker is the only item`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -632,44 +590,8 @@ class TimelinePresenterTest { timelineItems.emit( listOf(MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker)) ) - consumeItemsUntilPredicate { it.jumpToUnreadState is JumpToUnreadState.Loaded }.last().also { state -> - assertThat(state.jumpToUnreadState).isEqualTo(JumpToUnreadState.Loaded(markerIndex = 0, unreadCount = 0)) - } - cancelAndIgnoreRemainingEvents() - } - } - - @Test - fun `present - FromOther count accumulates across multiple batches as prevMostRecentItemId advances`() = runTest { - val timelineItems = MutableStateFlow(emptyList()) - val timeline = FakeTimeline(timelineItems = timelineItems) - val presenter = createTimelinePresenter(timeline) - presenter.test { - awaitFirstItem() - // Seed prevMostRecentItemId so subsequent emissions count as new events. - timelineItems.emit( - listOf(MatrixTimelineItem.Event(UniqueId("seed"), anEventTimelineItem(content = aMessageContent()))) - ) - consumeItemsUntilPredicate { it.timelineItems.size == 1 } - // Batch 1: 1 new event → count = 1. - timelineItems.getAndUpdate { items -> - items + listOf(MatrixTimelineItem.Event(UniqueId("b1-1"), anEventTimelineItem(content = aMessageContent()))) - } - consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(1) } - // Batch 2: 2 more new events → count = 3. - timelineItems.getAndUpdate { items -> - items + listOf( - MatrixTimelineItem.Event(UniqueId("b2-1"), anEventTimelineItem(content = aMessageContent())), - MatrixTimelineItem.Event(UniqueId("b2-2"), anEventTimelineItem(content = aMessageContent())), - ) - } - consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(3) } - // Batch 3: 1 more new event → count = 4. - timelineItems.getAndUpdate { items -> - items + listOf(MatrixTimelineItem.Event(UniqueId("b3-1"), anEventTimelineItem(content = aMessageContent()))) - } - consumeItemsUntilPredicate { it.newEventState == NewEventState.FromOther(4) }.last().also { state -> - assertThat(state.newEventState).isEqualTo(NewEventState.FromOther(4)) + consumeItemsUntilPredicate { it.readMarkerIndex != null }.last().also { state -> + assertThat(state.readMarkerIndex).isEqualTo(0) } cancelAndIgnoreRemainingEvents() } From aed149731bcd4d68e49ca7fb0d87aab61591717d Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Tue, 5 May 2026 17:26:57 -0700 Subject: [PATCH 0342/1083] Add mark as read buttons --- .../messages/impl/timeline/TimelineEvent.kt | 2 + .../impl/timeline/TimelinePresenter.kt | 8 ++ .../messages/impl/timeline/TimelineView.kt | 118 +++++++++++++----- .../impl/timeline/TimelinePresenterTest.kt | 34 +++++ .../theme/components/DropdownMenuItem.kt | 3 +- .../src/main/res/values/temporary.xml | 1 + 6 files changed, 135 insertions(+), 31 deletions(-) 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 e9a6ce5549..5330fc00d3 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 @@ -25,6 +25,8 @@ sealed interface TimelineEvent { data object HideShieldDialog : TimelineEvent + data object MarkAllAsRead : TimelineEvent + /** * Events coming from a timeline item. */ 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 8dbb53d7cd..6f5be45163 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 @@ -95,6 +95,7 @@ class TimelinePresenter( private val roomCallStatePresenter: Presenter, private val featureFlagService: FeatureFlagService, private val analyticsService: AnalyticsService, + private val markAsFullyRead: MarkAsFullyRead, ) : Presenter { private val tag = "TimelinePresenter" @@ -224,6 +225,13 @@ class TimelinePresenter( timelineController.focusOnLive() } TimelineEvent.HideShieldDialog -> messageShieldDialogData.value = null + TimelineEvent.MarkAllAsRead -> sessionCoroutineScope.launch { + val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { + Timber.tag(tag).w(it, "Failed to get latest event id to mark as fully read") + return@launch + } ?: return@launch + markAsFullyRead(room.roomId, latestEventId) + } is TimelineEvent.ShowShieldDialog -> messageShieldDialogData.value = event.messageShieldData is TimelineEvent.ComputeVerifiedUserSendFailure -> { resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(event.event)) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index d04f55bb2c..7bc84ed718 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -16,19 +16,24 @@ import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.FloatingActionButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -42,6 +47,8 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -51,6 +58,7 @@ import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -72,8 +80,10 @@ import io.element.android.libraries.androidutils.system.copyToClipboard import io.element.android.libraries.designsystem.components.dialogs.AlertDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.FloatingActionButton +import io.element.android.libraries.designsystem.text.roundToPx +import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline @@ -131,6 +141,10 @@ fun TimelineView( state.eventSink(TimelineEvent.JumpToLive) } + fun onMarkAllAsRead() { + state.eventSink(TimelineEvent.MarkAllAsRead) + } + val context = LocalContext.current val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) val view = LocalView.current @@ -220,6 +234,7 @@ fun TimelineView( onScrollFinishAt = ::onScrollFinishAt, onJumpToLive = ::onJumpToLive, onFocusEventRender = ::onFocusEventRender, + onMarkAllAsRead = ::onMarkAllAsRead, ) if (state.displayFloatingDateBadge && useReverseLayout) { @@ -305,6 +320,7 @@ private fun BoxScope.TimelineScrollHelper( onScrollFinishAt: (Int) -> Unit, onJumpToLive: () -> Unit, onFocusEventRender: () -> Unit, + onMarkAllAsRead: () -> Unit, ) { val coroutineScope = rememberCoroutineScope() val isScrollFinished by remember { derivedStateOf { !lazyListState.isScrollInProgress } } @@ -389,27 +405,30 @@ private fun BoxScope.TimelineScrollHelper( } } - JumpToPositionButton( - icon = CompoundIcons.ChevronDown(), - contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), - isVisible = isJumpToBottomVisible, - hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther, + Column( modifier = Modifier .align(Alignment.BottomEnd) - .padding(end = 24.dp, bottom = 12.dp), - onClick = ::jumpToBottom, - ) - JumpToPositionButton( - icon = CompoundIcons.ChevronUp(), - contentDescription = stringResource(id = CommonStrings.a11y_jump_to_unread_messages), - isVisible = isJumpToUnreadVisible, - hasUnread = true, - // Stacked directly above the scroll-to-bottom FAB: 12dp base + 36dp FAB + 8dp gap. - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(end = 24.dp, bottom = 56.dp), - onClick = ::jumpToReadMarker, - ) + .padding(end = 24.dp, bottom = 24.dp) + ) { + JumpToPositionButton( + icon = CompoundIcons.ChevronUp(), + contentDescription = stringResource(id = CommonStrings.a11y_jump_to_unread_messages), + modifier = Modifier.padding(bottom = if (isJumpToBottomVisible) 12.dp else 0.dp), + isVisible = isJumpToUnreadVisible, + hasUnread = true, + onClick = ::jumpToReadMarker, + onMarkAsRead = onMarkAllAsRead, + ) + JumpToPositionButton( + icon = CompoundIcons.ChevronDown(), + contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), + isVisible = isJumpToBottomVisible, + hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther, + onClick = ::jumpToBottom, + onMarkAsRead = onMarkAllAsRead, + dotAlignment = Alignment.BottomCenter, + ) + } } @Composable @@ -419,7 +438,9 @@ private fun JumpToPositionButton( isVisible: Boolean, hasUnread: Boolean, onClick: () -> Unit, + onMarkAsRead: () -> Unit, modifier: Modifier = Modifier, + dotAlignment: Alignment = Alignment.TopCenter, ) { AnimatedVisibility( modifier = modifier, @@ -427,26 +448,63 @@ private fun JumpToPositionButton( enter = scaleIn(animationSpec = tween(100)), exit = scaleOut(animationSpec = tween(100)), ) { + var menuExpanded by remember { mutableStateOf(false) } Box { - FloatingActionButton( - onClick = onClick, - elevation = FloatingActionButtonDefaults.elevation(4.dp, 4.dp, 4.dp, 4.dp), - shape = CircleShape, - modifier = Modifier.size(36.dp), - containerColor = ElementTheme.colors.bgSubtleSecondary, - contentColor = ElementTheme.colors.iconSecondary, + Box( + modifier = Modifier + .size(36.dp) + .shadow(elevation = 0.dp, shape = CircleShape) + .background(color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape) + .clip(CircleShape) + .border(1.dp, ElementTheme.colors.borderDisabled, CircleShape) + .combinedClickable( + onClick = onClick, + onLongClick = { menuExpanded = true }, + ) + .testTag(TestTags.floatingActionButton), + contentAlignment = Alignment.Center, ) { Icon( modifier = Modifier.size(24.dp), imageVector = icon, contentDescription = contentDescription, + tint = ElementTheme.colors.iconSecondary, ) + DropdownMenu( + expanded = menuExpanded, + onDismissRequest = { menuExpanded = false }, + minWidth = 0.dp, + offset = DpOffset(x = -44.dp, y = 40.dp) + ) { + Row( + modifier = Modifier + .clickable { + menuExpanded = false + onMarkAsRead() + } + .padding(horizontal = 12.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = CompoundIcons.MarkAsRead(), + contentDescription = null, + tint = ElementTheme.colors.iconPrimary, + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(id = CommonStrings.action_mark_as_read), + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontBodyLgRegular, + ) + } + } } + val dotYOffset = if (dotAlignment == Alignment.BottomCenter) 4.dp else (-4).dp TimelineUnreadIndicator( isVisible = hasUnread, modifier = Modifier - .align(Alignment.TopEnd) - .offset { IntOffset(x = 4.dp.roundToPx(), y = -4.dp.roundToPx()) }, + .align(dotAlignment) + .offset { IntOffset(x = 0, y = dotYOffset.roundToPx()) }, ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 860d73a835..b5f0e93847 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -1206,6 +1206,38 @@ class TimelinePresenterTest { } } + @Test + fun `present - MarkAllAsRead invokes markAsFullyRead with latest event id`() = runTest { + val markAsFullyReadRecorder = lambdaRecorder { _, _ -> } + val presenter = createTimelinePresenter( + timeline = FakeTimeline(getLatestEventIdResult = { Result.success(AN_EVENT_ID) }), + markAsFullyRead = FakeMarkAsFullyRead(markAsFullyReadRecorder), + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(TimelineEvent.MarkAllAsRead) + advanceUntilIdle() + markAsFullyReadRecorder.assertions().isCalledOnce().with(value(A_ROOM_ID), value(AN_EVENT_ID)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - MarkAllAsRead does not invoke markAsFullyRead when latest event id lookup fails`() = runTest { + val markAsFullyReadRecorder = lambdaRecorder { _, _ -> } + val presenter = createTimelinePresenter( + timeline = FakeTimeline(getLatestEventIdResult = { Result.failure(RuntimeException("boom")) }), + markAsFullyRead = FakeMarkAsFullyRead(markAsFullyReadRecorder), + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(TimelineEvent.MarkAllAsRead) + advanceUntilIdle() + markAsFullyReadRecorder.assertions().isNeverCalled() + cancelAndIgnoreRemainingEvents() + } + } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { return awaitItem() } @@ -1244,6 +1276,7 @@ class TimelinePresenterTest { sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(), featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), + markAsFullyRead: MarkAsFullyRead = FakeMarkAsFullyRead { _, _ -> }, ): TimelinePresenter { return TimelinePresenter( timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(), @@ -1262,6 +1295,7 @@ class TimelinePresenterTest { roomCallStatePresenter = { aStandByCallState() }, featureFlagService = featureFlagService, analyticsService = FakeAnalyticsService(), + markAsFullyRead = markAsFullyRead, ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt index 31c3f3c49b..5c0e0f914b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt @@ -35,6 +35,7 @@ fun DropdownMenuItem( leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, enabled: Boolean = true, + contentPadding: PaddingValues = DropDownMenuItemDefaults.contentPadding, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) { androidx.compose.material3.DropdownMenuItem( @@ -49,7 +50,7 @@ fun DropdownMenuItem( trailingIcon = trailingIcon, enabled = enabled, colors = DropDownMenuItemDefaults.colors(), - contentPadding = DropDownMenuItemDefaults.contentPadding, + contentPadding = contentPadding, interactionSource = interactionSource ) } diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index 26c83aaa53..e930968f8f 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -7,6 +7,7 @@ "Black" + "Mark as read" "Jump to unread messages" "Jump to %1$d unread message" From 880a1896172b4e6424bf3fad8a6e669eaa4f935f Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Tue, 5 May 2026 17:27:36 -0700 Subject: [PATCH 0343/1083] Code cleanup, accessibility checks --- .../home/impl/roomlist/RoomListContextMenu.kt | 2 +- .../impl/roomlist/RoomListContextMenuTest.kt | 2 +- .../messages/impl/timeline/TimelinePresenter.kt | 5 +++++ .../messages/impl/timeline/TimelineView.kt | 11 ++++++++--- .../impl/timeline/TimelinePresenterTest.kt | 16 ++++++++++++++++ .../theme/components/DropdownMenuItem.kt | 3 +-- .../android/libraries/testtags/TestTags.kt | 6 ++++++ 7 files changed, 38 insertions(+), 7 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt index 66982961fd..b3da4f89c7 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt @@ -111,7 +111,7 @@ private fun RoomListModalBottomSheetContent( ListItem( headlineContent = { Text( - text = stringResource(id = R.string.screen_roomlist_mark_as_read), + text = stringResource(id = CommonStrings.action_mark_as_read), style = MaterialTheme.typography.bodyLarge, ) }, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt index 5fa2adf9d6..c66cb03fad 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenuTest.kt @@ -36,7 +36,7 @@ class RoomListContextMenuTest { contextMenu = contextMenu, eventSink = eventsRecorder, ) - clickOn(R.string.screen_roomlist_mark_as_read) + clickOn(CommonStrings.action_mark_as_read) eventsRecorder.assertList( listOf( RoomListEvent.HideContextMenu, 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 6f5be45163..5fb63a4f4b 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 @@ -287,6 +287,11 @@ class TimelinePresenter( // read marker advances in place — the SDK swaps the marker virtual item to a new position // without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the // bottom of the room. + // + // Limitation: when the read marker is outside the loaded window (gaps, pagination), this + // returns null and the jump-to-unread button stays hidden. Proper fix needs an SDK + // accessor for the m.fully_read marker plus FocusedOnEvent navigation on click; gated + // behind FeatureFlags.JumpToUnread until that lands. val readMarkerIndex = remember { mutableStateOf(null) } LaunchedEffect(timelineItems, displayJumpToUnread) { if (!displayJumpToUnread) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 7bc84ed718..d67323abd9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -48,7 +48,6 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -88,6 +87,7 @@ import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.testtags.TestTag import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -418,6 +418,7 @@ private fun BoxScope.TimelineScrollHelper( hasUnread = true, onClick = ::jumpToReadMarker, onMarkAsRead = onMarkAllAsRead, + testTag = TestTags.jumpToUnreadButton, ) JumpToPositionButton( icon = CompoundIcons.ChevronDown(), @@ -426,6 +427,7 @@ private fun BoxScope.TimelineScrollHelper( hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther, onClick = ::jumpToBottom, onMarkAsRead = onMarkAllAsRead, + testTag = TestTags.jumpToBottomButton, dotAlignment = Alignment.BottomCenter, ) } @@ -439,6 +441,7 @@ private fun JumpToPositionButton( hasUnread: Boolean, onClick: () -> Unit, onMarkAsRead: () -> Unit, + testTag: TestTag, modifier: Modifier = Modifier, dotAlignment: Alignment = Alignment.TopCenter, ) { @@ -453,15 +456,15 @@ private fun JumpToPositionButton( Box( modifier = Modifier .size(36.dp) - .shadow(elevation = 0.dp, shape = CircleShape) .background(color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape) .clip(CircleShape) .border(1.dp, ElementTheme.colors.borderDisabled, CircleShape) .combinedClickable( onClick = onClick, onLongClick = { menuExpanded = true }, + onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), ) - .testTag(TestTags.floatingActionButton), + .testTag(testTag), contentAlignment = Alignment.Center, ) { Icon( @@ -476,6 +479,8 @@ private fun JumpToPositionButton( minWidth = 0.dp, offset = DpOffset(x = -44.dp, y = 40.dp) ) { + // Hand-rolled instead of DropdownMenuItem: padding here is tighter + // than DropdownMenuItem's 12.dp default to match the Figma spec. Row( modifier = Modifier .clickable { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index b5f0e93847..7f083af3b0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -1238,6 +1238,22 @@ class TimelinePresenterTest { } } + @Test + fun `present - MarkAllAsRead does not invoke markAsFullyRead when there is no latest event`() = runTest { + val markAsFullyReadRecorder = lambdaRecorder { _, _ -> } + val presenter = createTimelinePresenter( + timeline = FakeTimeline(getLatestEventIdResult = { Result.success(null) }), + markAsFullyRead = FakeMarkAsFullyRead(markAsFullyReadRecorder), + ) + presenter.test { + val initialState = awaitFirstItem() + initialState.eventSink(TimelineEvent.MarkAllAsRead) + advanceUntilIdle() + markAsFullyReadRecorder.assertions().isNeverCalled() + cancelAndIgnoreRemainingEvents() + } + } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { return awaitItem() } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt index 5c0e0f914b..31c3f3c49b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt @@ -35,7 +35,6 @@ fun DropdownMenuItem( leadingIcon: @Composable (() -> Unit)? = null, trailingIcon: @Composable (() -> Unit)? = null, enabled: Boolean = true, - contentPadding: PaddingValues = DropDownMenuItemDefaults.contentPadding, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) { androidx.compose.material3.DropdownMenuItem( @@ -50,7 +49,7 @@ fun DropdownMenuItem( trailingIcon = trailingIcon, enabled = enabled, colors = DropDownMenuItemDefaults.colors(), - contentPadding = contentPadding, + contentPadding = DropDownMenuItemDefaults.contentPadding, interactionSource = interactionSource ) } diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index e564ddac41..87ca215099 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -98,6 +98,12 @@ object TestTags { */ val floatingActionButton = TestTag("floating-action-button") + /** + * Timeline jump-to-position buttons (long-press exposes "Mark as read"). + */ + val jumpToUnreadButton = TestTag("jump-to-unread-button") + val jumpToBottomButton = TestTag("jump-to-bottom-button") + /** * Timeline. */ From 47ca5a5f2fed5510e198085e10529785c19afae1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 01:36:24 +0000 Subject: [PATCH 0344/1083] Update dependency org.maplibre.gl:android-sdk to v13.1.0 --- 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 d17ddc99d7..5b99d65539 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -207,7 +207,7 @@ vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil3", version.ref = "telephoto" } telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" } statemachine = "com.freeletics.flowredux:compose:1.2.2" -maplibre = "org.maplibre.gl:android-sdk:13.0.2" +maplibre = "org.maplibre.gl:android-sdk:13.1.0" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_compose = "org.maplibre.compose:maplibre-compose:0.12.1" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" From 784f5df426008bffa72e6660d837158ef6d1f349 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Tue, 5 May 2026 18:44:11 -0700 Subject: [PATCH 0345/1083] Mark as read menu ui tweaks --- .../messages/impl/timeline/TimelineView.kt | 121 +++++++++++++----- 1 file changed, 90 insertions(+), 31 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index d67323abd9..81f40b7a61 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -10,8 +10,10 @@ package io.element.android.features.messages.impl.timeline import android.view.HapticFeedbackConstants import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut import androidx.compose.foundation.background @@ -34,6 +36,7 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -48,18 +51,26 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupPositionProvider +import androidx.compose.ui.window.PopupProperties import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureView @@ -80,7 +91,6 @@ import io.element.android.libraries.designsystem.components.dialogs.AlertDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.roundToPx -import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter @@ -448,8 +458,8 @@ private fun JumpToPositionButton( AnimatedVisibility( modifier = modifier, visible = isVisible, - enter = scaleIn(animationSpec = tween(100)), - exit = scaleOut(animationSpec = tween(100)), + enter = scaleIn(animationSpec = tween(220), initialScale = 0.8f) + fadeIn(animationSpec = tween(220)), + exit = scaleOut(animationSpec = tween(180), targetScale = 0.8f) + fadeOut(animationSpec = tween(180)), ) { var menuExpanded by remember { mutableStateOf(false) } Box { @@ -473,34 +483,60 @@ private fun JumpToPositionButton( contentDescription = contentDescription, tint = ElementTheme.colors.iconSecondary, ) - DropdownMenu( - expanded = menuExpanded, - onDismissRequest = { menuExpanded = false }, - minWidth = 0.dp, - offset = DpOffset(x = -44.dp, y = 40.dp) - ) { - // Hand-rolled instead of DropdownMenuItem: padding here is tighter - // than DropdownMenuItem's 12.dp default to match the Figma spec. - Row( - modifier = Modifier - .clickable { - menuExpanded = false - onMarkAsRead() - } - .padding(horizontal = 12.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, + val menuTransitionState = remember { MutableTransitionState(false) } + .apply { targetState = menuExpanded } + if (menuTransitionState.currentState || menuTransitionState.targetState) { + val gapPx = with(LocalDensity.current) { 8.dp.roundToPx() } + val positionProvider = remember(gapPx) { CenterStartOfAnchorPositionProvider(gapPx) } + Popup( + popupPositionProvider = positionProvider, + onDismissRequest = { menuExpanded = false }, + properties = PopupProperties(focusable = true), ) { - Icon( - imageVector = CompoundIcons.MarkAsRead(), - contentDescription = null, - tint = ElementTheme.colors.iconPrimary, - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = stringResource(id = CommonStrings.action_mark_as_read), - color = ElementTheme.colors.textPrimary, - style = ElementTheme.typography.fontBodyLgRegular, - ) + // Anchor the scale to the right-center edge so the menu visually grows + // outward from the FAB it's attached to. + val transformOrigin = TransformOrigin(pivotFractionX = 1f, pivotFractionY = 0.5f) + AnimatedVisibility( + visibleState = menuTransitionState, + enter = scaleIn( + animationSpec = tween(180), + initialScale = 0.9f, + transformOrigin = transformOrigin, + ) + fadeIn(animationSpec = tween(180)), + exit = scaleOut( + animationSpec = tween(140), + targetScale = 0.9f, + transformOrigin = transformOrigin, + ) + fadeOut(animationSpec = tween(140)), + ) { + // Hand-rolled instead of DropdownMenuItem: padding here is tighter + // than DropdownMenuItem's 12.dp default to match the Figma spec. + Row( + modifier = Modifier + .shadow(elevation = 1.dp, shape = RoundedCornerShape(8.dp)) + .clip(RoundedCornerShape(8.dp)) + .background(ElementTheme.colors.bgCanvasDefaultLevel1) + .border(1.dp, ElementTheme.colors.borderDisabled, RoundedCornerShape(8.dp)) + .clickable { + menuExpanded = false + onMarkAsRead() + } + .padding(horizontal = 12.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = CompoundIcons.MarkAsRead(), + contentDescription = null, + tint = ElementTheme.colors.iconTertiary, + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(id = CommonStrings.action_mark_as_read), + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontBodyLgRegular, + ) + } + } } } } @@ -617,3 +653,26 @@ internal fun TimelineViewWithReadMarkerNoIndicatorsPreview() = ElementPreview { internal fun TimelineViewWithReadMarkerBothIndicatorsPreview() = ElementPreview { TimelineViewWithReadMarker(hasUnreadAbove = true, hasUnreadBelow = true) } + +/** + * Anchors the popup so its right edge sits [gapPx] to the left of the anchor and its vertical + * center matches the anchor's. Adapts to localized menu widths and FAB size; coerced to stay + * on-screen. + */ +private class CenterStartOfAnchorPositionProvider( + private val gapPx: Int, +) : PopupPositionProvider { + override fun calculatePosition( + anchorBounds: IntRect, + windowSize: IntSize, + layoutDirection: LayoutDirection, + popupContentSize: IntSize, + ): IntOffset { + val x = anchorBounds.left - popupContentSize.width - gapPx + val y = anchorBounds.top + (anchorBounds.height - popupContentSize.height) / 2 + return IntOffset( + x = x.coerceIn(0, (windowSize.width - popupContentSize.width).coerceAtLeast(0)), + y = y.coerceIn(0, (windowSize.height - popupContentSize.height).coerceAtLeast(0)), + ) + } +} From 70452842d31e6e037ae32ed4a29c583f0d8bf6c1 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 6 May 2026 11:16:13 +0200 Subject: [PATCH 0346/1083] Make icons in the Chat screen top bar 16dp (#6733) * Make icons in the Chat screen top bar 16dp. This matches the designs in Figma. * Fix the padding between the title and the icons * Update screenshots --------- Co-authored-by: ElementBot --- .../features/messages/impl/topbars/MessagesViewTopBar.kt | 9 ++++++++- ...messages.impl.topbars_MessagesViewTopBar_Day_0_en.png | 4 ++-- ...ssages.impl.topbars_MessagesViewTopBar_Night_0_en.png | 4 ++-- .../features.messages.impl_MessagesViewA11y_en.png | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index 4d7242ebf5..b1a31da443 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable @@ -91,9 +92,12 @@ internal fun MessagesViewTopBar( modifier = titleModifier ) + val iconModifier = Modifier.size(16.dp) + when (dmUserIdentityState) { IdentityState.Verified -> { Icon( + modifier = iconModifier, imageVector = CompoundIcons.Verified(), tint = ElementTheme.colors.iconSuccessPrimary, contentDescription = null, @@ -101,6 +105,7 @@ internal fun MessagesViewTopBar( } IdentityState.VerificationViolation -> { Icon( + modifier = iconModifier, imageVector = CompoundIcons.ErrorSolid(), tint = ElementTheme.colors.iconCriticalPrimary, contentDescription = null, @@ -112,11 +117,13 @@ internal fun MessagesViewTopBar( when (sharedHistoryIcon) { SharedHistoryIcon.NONE -> Unit SharedHistoryIcon.SHARED -> Icon( + modifier = iconModifier, imageVector = CompoundIcons.History(), tint = ElementTheme.colors.iconInfoPrimary, contentDescription = stringResource(CommonStrings.common_shared_history), ) SharedHistoryIcon.WORLD_READABLE -> Icon( + modifier = iconModifier, imageVector = CompoundIcons.UserProfileSolid(), tint = ElementTheme.colors.iconInfoPrimary, contentDescription = stringResource(CommonStrings.common_world_readable_history), @@ -150,7 +157,7 @@ private fun RoomAvatarAndNameRow( ) Text( modifier = Modifier - .padding(horizontal = 8.dp) + .padding(start = 8.dp) .semantics { heading() }, diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png index b2c131b124..68e8a2127e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e26887bd81e10726414e1833029b4b51e22e534684a230777ca50f86024af994 -size 56430 +oid sha256:dc098d35a0af82ec65dee8ccadf6df83246fbbc7933239fd940de938a4dd4476 +size 55995 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png index 41b8b16bcc..13207941ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce44cf850169736008a3f3fc21a2be4fb044badfae631b0284ce379b325879df -size 55533 +oid sha256:fb5305c7ccf69c49fde95cd3601bf2ee103988775b366cb2ee3fcd04e8673729 +size 55131 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png index 59b336cb1a..c214011ea7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c64b270815016ecd157fe430538090afc8f94c4ec2402a6c6de01ff1d762db94 -size 131744 +oid sha256:23aabf96e5dc84257968a77ad406a8f3952b24fa8d8c03612bddfc08b6c990c6 +size 131751 From 34f001d22ce2c09f8c983bc7795d866067aacac8 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 6 May 2026 14:35:08 +0200 Subject: [PATCH 0347/1083] Fix back button sometimes not working after exiting a thread (#6732) When I reproduced the issue, it looked like the coroutine used to mark as read and then exit the room was canceled, leaving the `markingAsReadAndExiting` variable with `true` value and preventing the exit block from running again. --- .../element/android/features/messages/impl/MessagesPresenter.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index b98bd764de..5271906fff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -272,6 +272,8 @@ class MessagesPresenter( } } navigator.close() + }.invokeOnCompletion { + markingAsReadAndExiting.set(false) } } } From f4cf704335c3a1abbcada78c0d84bc236ba13599 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 15:31:52 +0200 Subject: [PATCH 0348/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.6 (#6734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency org.matrix.rustcomponents:sdk-android to v26.05.6 * Fix API breaks: - Add `RoomMember.isServiceMember`. - Add `beacon` and `beaconInfo` power levels. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- .../features/createroom/impl/ConfigureRoomPresenterTest.kt | 4 +++- .../impl/permissions/ChangeRoomPermissionsStateProvider.kt | 3 +++ .../impl/permissions/ChangeRoomPermissionsPresenterTest.kt | 4 +++- gradle/libs.versions.toml | 2 +- .../matrix/api/room/powerlevels/RoomPowerLevelsValues.kt | 2 ++ .../impl/room/powerlevels/RoomPowerLevelsValuesMapper.kt | 2 ++ .../libraries/matrix/impl/fixtures/factories/RoomMember.kt | 2 ++ .../matrix/impl/fixtures/factories/RoomPowerLevelsValues.kt | 6 +++++- .../matrix/impl/fixtures/fakes/FakeFfiRoomPowerLevels.kt | 2 ++ .../room/powerlevels/RoomPowerLevelsValuesMapperTest.kt | 4 ++++ .../android/libraries/matrix/test/room/FakeBaseRoom.kt | 2 ++ 11 files changed, 29 insertions(+), 4 deletions(-) diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt index fcedcb2367..b9d7eb6e7d 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt @@ -301,7 +301,9 @@ class ConfigureRoomPresenterTest { roomName = 0, roomAvatar = 0, roomTopic = 0, - spaceChild = 0 + spaceChild = 0, + beacon = 0, + beaconInfo = 0, ), users = persistentMapOf(), ) diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsStateProvider.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsStateProvider.kt index 2760272d8a..700a82795e 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsStateProvider.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsStateProvider.kt @@ -63,5 +63,8 @@ private fun previewPermissions(): RoomPowerLevelsValues { // SpaceManagement section spaceChild = RoomMember.Role.Moderator.powerLevel, stateDefault = RoomMember.Role.Moderator.powerLevel, + // Live location beacon section + beacon = RoomMember.Role.Admin.powerLevel, + beaconInfo = RoomMember.Role.Moderator.powerLevel, ) } diff --git a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt index ba7d47adb2..72b2b8b5e7 100644 --- a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt +++ b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt @@ -148,7 +148,9 @@ class ChangeRoomPermissionsPresenterTest { roomName = Moderator.powerLevel, roomAvatar = Moderator.powerLevel, roomTopic = Moderator.powerLevel, - spaceChild = initialPermissions.spaceChild + spaceChild = initialPermissions.spaceChild, + beacon = initialPermissions.beacon, + beaconInfo = initialPermissions.beaconInfo, ) ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6d4fbe6827..c03d164728 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.4" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.6" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt index e8f88ed86d..6606465389 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/RoomPowerLevelsValues.kt @@ -19,4 +19,6 @@ data class RoomPowerLevelsValues( val roomAvatar: Long, val roomTopic: Long, val spaceChild: Long, + val beacon: Long, + val beaconInfo: Long, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapper.kt index 5e2a1c82da..499868795a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapper.kt @@ -26,6 +26,8 @@ object RoomPowerLevelsValuesMapper { roomAvatar = values.roomAvatar, roomTopic = values.roomTopic, spaceChild = values.spaceChild, + beacon = values.beacon, + beaconInfo = values.beaconInfo, ) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt index 77fa814cca..6b4f958d84 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt @@ -24,6 +24,7 @@ internal fun aRustRoomMember( isIgnored: Boolean = false, role: RoomMemberRole = RoomMemberRole.USER, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId.value, displayName = displayName, @@ -34,4 +35,5 @@ internal fun aRustRoomMember( isIgnored = isIgnored, suggestedRoleForPowerLevel = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevelsValues.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevelsValues.kt index 1c1bbb42e3..28af0093f6 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevelsValues.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevelsValues.kt @@ -22,6 +22,8 @@ internal fun aRustRoomPowerLevelsValues( roomAvatar: Long, roomTopic: Long, spaceChild: Long, + beacon: Long, + beaconInfo: Long, ) = RoomPowerLevelsValues( ban = ban, invite = invite, @@ -33,5 +35,7 @@ internal fun aRustRoomPowerLevelsValues( roomName = roomName, roomAvatar = roomAvatar, roomTopic = roomTopic, - spaceChild = spaceChild + spaceChild = spaceChild, + beacon = beacon, + beaconInfo = beaconInfo, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoomPowerLevels.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoomPowerLevels.kt index c47c4406b6..985dc935ff 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoomPowerLevels.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiRoomPowerLevels.kt @@ -32,4 +32,6 @@ fun defaultFfiRoomPowerLevelValues() = RoomPowerLevelsValues( roomTopic = 50, spaceChild = 50, usersDefault = 0, + beacon = 0, + beaconInfo = 0, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapperTest.kt index f298da8b42..65f2d1e2d5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsValuesMapperTest.kt @@ -30,6 +30,8 @@ class RoomPowerLevelsValuesMapperTest { roomAvatar = 9, roomTopic = 10, spaceChild = 11, + beacon = 12, + beaconInfo = 13, ) ) ).isEqualTo( @@ -44,6 +46,8 @@ class RoomPowerLevelsValuesMapperTest { roomAvatar = 9, roomTopic = 10, spaceChild = 11, + beacon = 12, + beaconInfo = 13, ) ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt index 4ceddc414c..5ea2de888b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeBaseRoom.kt @@ -223,4 +223,6 @@ fun defaultRoomPowerLevelValues() = RoomPowerLevelsValues( roomAvatar = 50, roomTopic = 50, spaceChild = 50, + beacon = 0, + beaconInfo = 0, ) From 9b91fabbd699d69107d1378c6b7f34f17f462d87 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 6 May 2026 15:33:17 +0200 Subject: [PATCH 0349/1083] Use 'Report a problem' string instead of 'Report bug' (#6735) * Use 'Report a problem' instead of 'Report bug'. This old string will be deleted soon. * Update screenshots --------- Co-authored-by: ElementBot --- .../features/rageshake/api/crash/CrashDetectionView.kt | 2 +- .../rageshake/api/detection/RageshakeDetectionView.kt | 2 +- .../test/snapshots/images/appnav.root_RootView_Day_0_en.png | 4 ++-- .../test/snapshots/images/appnav.root_RootView_Day_1_en.png | 4 ++-- .../test/snapshots/images/appnav.root_RootView_Night_0_en.png | 4 ++-- .../test/snapshots/images/appnav.root_RootView_Night_1_en.png | 4 ++-- ...atures.rageshake.api.crash_CrashDetectionView_Day_0_en.png | 4 ++-- ...ures.rageshake.api.crash_CrashDetectionView_Night_0_en.png | 4 ++-- ...ageshake.api.detection_RageshakeDialogContent_Day_0_en.png | 4 ++-- ...eshake.api.detection_RageshakeDialogContent_Night_0_en.png | 4 ++-- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt index 5db1d4f076..ea78ed5a2c 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt @@ -43,7 +43,7 @@ private fun CrashDetectionContent( onDismiss: () -> Unit = { }, ) { ConfirmationDialog( - title = stringResource(id = CommonStrings.action_report_bug), + title = stringResource(id = CommonStrings.common_report_a_problem), content = stringResource(id = R.string.crash_detection_dialog_content, appName), submitText = stringResource(id = CommonStrings.action_yes), cancelText = stringResource(id = CommonStrings.action_no), diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt index 745a362637..c60bd4e1bf 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt @@ -77,7 +77,7 @@ private fun RageshakeDialogContent( onYesClick: () -> Unit = { }, ) { ConfirmationDialog( - title = stringResource(id = CommonStrings.action_report_bug), + title = stringResource(id = CommonStrings.common_report_a_problem), content = stringResource(id = R.string.rageshake_detection_dialog_content), thirdButtonText = stringResource(id = CommonStrings.action_disable), submitText = stringResource(id = CommonStrings.action_yes), diff --git a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_0_en.png index 8ab5f8a44a..559c023aa7 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d225730fee6fae0d93396a6c47dcd7abd86ba8902ac521c96e05fa36f619bbd -size 25840 +oid sha256:ba67fa9a541371f84cdc16dcc0c069e0cfda486c2b21dbb885cee7e0d9b6b005 +size 26924 diff --git a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_1_en.png index e2037ca626..788daaf8df 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f27f94a461f5b4bc5289ac41691e3736a73ddcbb9e1f2a1d0c9390a0ce5cb44b -size 27919 +oid sha256:00f8ec369fa64c6bbd97b37a5b53481438e74abdb5d366d32e3acae29460659c +size 29075 diff --git a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_0_en.png index 9df8fe1585..6ac6642b35 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:708a157d8a7cb5da2b2ea52c12f9b10c172ec380dfcec09583adfe2ea4af3d74 -size 24610 +oid sha256:0a38ade8b9a5e3ce85fbe63ae76d2e856ac46c6cdc012a4952cb191fcbe8979f +size 25577 diff --git a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_1_en.png index 00e1659da8..5451e763d5 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.root_RootView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:260ea7d9f891afdea78a6d546138cbad7586fe2210058d3774d549c9918c2ccd -size 26529 +oid sha256:1ae9d78458ea0b9d4b258be0620698abb699bcbc70275d98adfd992d8d50ec59 +size 27541 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Day_0_en.png index 1dcb5f4f8f..3c898e8ab5 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc7a2e36694227df123681799f09bb2ee3dae24258679557193ae69ecf4c2871 -size 24012 +oid sha256:17a23d0c9d2993b81edb72f19ba6ec03f24b79a2f732e7af6d3594c96503723c +size 24978 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Night_0_en.png index 65a0322a88..b3f17cafcb 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.api.crash_CrashDetectionView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18bbb07caa3cae740bb80297ced37fc3e8c92b48cd0935f716a86e0664737a75 -size 22815 +oid sha256:e2d914dbf6a309cffcba36f0affecf19287ad06c751f50b23a51e9df23bfd12e +size 23859 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Day_0_en.png index 77b4b1e222..b8fb7eb092 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31a1989c17263d25d5bde65a7b0399b58c9e77d320654ac9f0e65f0fe2410b15 -size 25882 +oid sha256:eea615f75cb1c3db04cffba9798f6662376f1c1db6825aa73c2db6f10192d23d +size 26959 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Night_0_en.png index d8fdf936f2..5bc6eeb700 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.api.detection_RageshakeDialogContent_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28f410c8068e0d7586af4c727ce5ba131e56387472f661b34841139e1e43cd3d -size 24788 +oid sha256:56c84d3a772d03eb016807b886df9728a5fbaf07e3fc6dc2ce4353007aec405a +size 25726 From 0daf7ecc7dbfcf0048901b38da30299c1d7a0a3f Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Wed, 6 May 2026 06:49:42 -0700 Subject: [PATCH 0350/1083] Konsist fixes Co-Authored-By: Claude Opus 4.7 (1M context) --- .../io/element/android/tests/konsist/KonsistPreviewTest.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 23a91fda00..6dc0e7fc56 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 @@ -160,10 +160,8 @@ class KonsistPreviewTest { "TimelineItemVoiceViewUnifiedPreview", "TimelineVideoWithCaptionRowPreview", "TimelineViewMessageShieldPreview", - "TimelineViewWithReadMarkerBothCountsPreview", - "TimelineViewWithReadMarkerDotBadgesPreview", - "TimelineViewWithReadMarkerNoBadgesPreview", - "TimelineViewWithReadMarkerNumericBadgePreview", + "TimelineViewWithReadMarkerBothIndicatorsPreview", + "TimelineViewWithReadMarkerNoIndicatorsPreview", "UserAvatarColorsPreview", "UserProfileHeaderSectionWithVerificationViolationPreview", "VoiceItemViewPlayPreview", From 6ef9315468e38445f6b6a5a8d13a5e66ba0cfb6f Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 6 May 2026 16:05:19 +0200 Subject: [PATCH 0351/1083] =?UTF-8?q?Remove=20RoomDirectorySearch=20featur?= =?UTF-8?q?e=20flag=20=E2=80=94=20always=20enable=20the=20feature=20(#6736?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove RoomDirectorySearch feature flag, always enable the feature Co-authored-by: stefanceriu <637564+stefanceriu@users.noreply.github.com> * Apply ktlint formatting Co-authored-by: jmartinesp <480955+jmartinesp@users.noreply.github.com> * Update screenshots --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stefanceriu <637564+stefanceriu@users.noreply.github.com> Co-authored-by: jmartinesp <480955+jmartinesp@users.noreply.github.com> Co-authored-by: ElementBot --- .../AppDeveloperSettingsPresenter.kt | 12 ----------- .../AppDeveloperSettingsPresenterTest.kt | 18 ----------------- .../startchat/impl/root/StartChatPresenter.kt | 10 ---------- .../startchat/impl/root/StartChatState.kt | 1 - .../impl/root/StartChatStateProvider.kt | 5 ----- .../startchat/impl/root/StartChatView.kt | 14 ++++++------- .../impl/root/StartChatPresenterTest.kt | 20 ------------------- .../startchat/impl/root/StartChatViewTest.kt | 1 - .../libraries/featureflag/api/FeatureFlags.kt | 7 ------- ...tchat.impl.root_StartChatView_Day_0_en.png | 4 ++-- ...tchat.impl.root_StartChatView_Day_3_en.png | 4 ++-- ...tchat.impl.root_StartChatView_Day_4_en.png | 4 ++-- ...tchat.impl.root_StartChatView_Day_5_en.png | 3 --- ...hat.impl.root_StartChatView_Night_0_en.png | 4 ++-- ...hat.impl.root_StartChatView_Night_3_en.png | 4 ++-- ...hat.impl.root_StartChatView_Night_4_en.png | 4 ++-- ...hat.impl.root_StartChatView_Night_5_en.png | 3 --- 17 files changed, 18 insertions(+), 100 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_5_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_5_en.png diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt index 4c76c6ec7e..e7ad6e2284 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenter.kt @@ -25,10 +25,7 @@ import io.element.android.features.rageshake.api.preferences.RageshakePreference import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.extensions.runCatchingExceptions -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.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.preferences.api.store.AppPreferencesStore import kotlinx.collections.immutable.ImmutableList @@ -45,7 +42,6 @@ class AppDeveloperSettingsPresenter( private val featureFlagService: FeatureFlagService, private val rageshakePresenter: Presenter, private val appPreferencesStore: AppPreferencesStore, - private val buildMeta: BuildMeta, ) : Presenter { @Composable override fun present(): AppDeveloperSettingsState { @@ -71,14 +67,6 @@ class AppDeveloperSettingsPresenter( LaunchedEffect(Unit) { featureFlagService.getAvailableFeatures() - .run { - // Never display room directory search in release builds for Play Store - if (buildMeta.flavorDescription == "GooglePlay" && buildMeta.buildType == BuildType.RELEASE) { - filterNot { it.key == FeatureFlags.RoomDirectorySearch.key } - } else { - this - } - } .forEach { feature -> enabledFeatures.add(EnabledFeature(feature, featureFlagService.isFeatureEnabled(feature))) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt index 0e9d774e84..3d2cc85e54 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPresenterTest.kt @@ -13,13 +13,9 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.preferences.impl.developer.tracing.LogLevelItem import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.featureflag.api.Feature -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeature import io.element.android.libraries.featureflag.test.FakeFeatureFlagService -import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -68,18 +64,6 @@ class AppDeveloperSettingsPresenterTest { } } - @Test - fun `present - ensures Room directory search is not present on release Google Play builds`() = runTest { - val buildMeta = aBuildMeta(buildType = BuildType.RELEASE, flavorDescription = "GooglePlay") - val presenter = createAppDeveloperSettingsPresenter(buildMeta = buildMeta) - presenter.test { - skipItems(1) - awaitItem().also { state -> - assertThat(state.features).doesNotContain(FeatureFlags.RoomDirectorySearch) - } - } - } - @Test fun `present - ensures state is updated when enabled feature event is triggered`() = runTest { val presenter = createAppDeveloperSettingsPresenter() @@ -156,13 +140,11 @@ class AppDeveloperSettingsPresenterTest { } ), preferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), - buildMeta: BuildMeta = aBuildMeta(), ): AppDeveloperSettingsPresenter { return AppDeveloperSettingsPresenter( featureFlagService = featureFlagService, rageshakePresenter = { aRageshakePreferencesState() }, appPreferencesStore = preferencesStore, - buildMeta = buildMeta, ) } } diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt index e176f202ad..079ece4180 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt @@ -10,8 +10,6 @@ package io.element.android.features.startchat.impl.root import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -24,8 +22,6 @@ import io.element.android.features.startchat.impl.userlist.UserListPresenterArgs import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.usersearch.api.UserRepository import kotlinx.coroutines.launch @@ -37,7 +33,6 @@ class StartChatPresenter( userListDataStore: UserListDataStore, private val startDMAction: StartDMAction, private val buildMeta: BuildMeta, - private val featureFlagService: FeatureFlagService, ) : Presenter { private val presenter = presenterFactory.create( UserListPresenterArgs( @@ -54,10 +49,6 @@ class StartChatPresenter( val localCoroutineScope = rememberCoroutineScope() val startDmActionState: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } - val isRoomDirectorySearchEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch) - }.collectAsState(initial = false) - fun handleEvent(event: StartChatEvents) { when (event) { is StartChatEvents.StartDM -> localCoroutineScope.launch { @@ -75,7 +66,6 @@ class StartChatPresenter( applicationName = buildMeta.applicationName, userListState = userListState, startDmAction = startDmActionState.value, - isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled, eventSink = ::handleEvent, ) } diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt index 65f977d3e3..e6746e1302 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt @@ -16,6 +16,5 @@ data class StartChatState( val applicationName: String, val userListState: UserListState, val startDmAction: AsyncAction, - val isRoomDirectorySearchEnabled: Boolean, val eventSink: (StartChatEvents) -> Unit, ) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt index a1e8f9d4f0..41a3551d1d 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt @@ -55,9 +55,6 @@ open class StartChatStateProvider : PreviewParameterProvider { aCreateRoomRootState( startDmAction = aConfirmingStartDmWithMatrixUser() ), - aCreateRoomRootState( - isRoomDirectorySearchEnabled = true, - ), ) } @@ -75,12 +72,10 @@ fun aCreateRoomRootState( applicationName: String = "Element X Preview", userListState: UserListState = aUserListState(), startDmAction: AsyncAction = AsyncAction.Uninitialized, - isRoomDirectorySearchEnabled: Boolean = false, eventSink: (StartChatEvents) -> Unit = {}, ) = StartChatState( applicationName = applicationName, userListState = userListState, startDmAction = startDmAction, - isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled, eventSink = eventSink, ) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt index e077cbe82e..7537fee524 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt @@ -176,14 +176,12 @@ private fun CreateRoomActionButtonsList( onClick = onNewRoomClick, ) } - if (state.isRoomDirectorySearchEnabled) { - item { - CreateRoomActionButton( - iconRes = CompoundDrawables.ic_compound_list_bulleted, - text = stringResource(id = R.string.screen_room_directory_search_title), - onClick = onRoomDirectorySearchClick, - ) - } + item { + CreateRoomActionButton( + iconRes = CompoundDrawables.ic_compound_list_bulleted, + text = stringResource(id = R.string.screen_room_directory_search_title), + onClick = onRoomDirectorySearchClick, + ) } item { CreateRoomActionButton( diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt index 2bc15e989d..57f6cd2333 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt @@ -17,8 +17,6 @@ import io.element.android.features.startchat.impl.userlist.FakeUserListPresenter import io.element.android.features.startchat.impl.userlist.FakeUserListPresenterFactory import io.element.android.features.startchat.impl.userlist.UserListDataStore import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser @@ -155,34 +153,16 @@ class StartChatPresenterTest { ) } } - - @Test - fun `present - room directory search`() = runTest { - val presenter = createStartChatPresenter(isRoomDirectorySearchEnabled = true) - presenter.test { - skipItems(1) - awaitItem().let { state -> - assertThat(state.isRoomDirectorySearchEnabled).isTrue() - } - } - } } internal fun createStartChatPresenter( startDMAction: StartDMAction = FakeStartDMAction(), - isRoomDirectorySearchEnabled: Boolean = false, ): StartChatPresenter { - val featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.RoomDirectorySearch.key to isRoomDirectorySearchEnabled, - ), - ) return StartChatPresenter( presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()), userRepository = FakeUserRepository(), userListDataStore = UserListDataStore(), startDMAction = startDMAction, - featureFlagService = featureFlagService, buildMeta = aBuildMeta(), ) } diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt index abcb70113b..916611bf20 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatViewTest.kt @@ -123,7 +123,6 @@ class StartChatViewTest { setStartChatView( aCreateRoomRootState( eventSink = eventsRecorder, - isRoomDirectorySearchEnabled = true ), onRoomDirectorySearchClick = it ) 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 15e61f4260..cdda66579b 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 @@ -22,13 +22,6 @@ enum class FeatureFlags( override val isFinished: Boolean, override val isInLabs: Boolean = false, ) : Feature { - RoomDirectorySearch( - key = "feature.roomdirectorysearch", - title = "Room directory search", - description = "Allow user to search for public rooms in their homeserver", - defaultValue = { false }, - isFinished = false, - ), ShowBlockedUsersDetails( key = "feature.showBlockedUsersDetails", title = "Show blocked users details", diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_0_en.png index ad21975ebd..a95c48fec0 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2c745de02098d9e38f75fa7c34f436ad4f7770f4d0cbab03949e0f3c6bfc958 -size 25557 +oid sha256:1d22817145519d17475a09dbe9f5e3a71ec6b5ff9e917d7a92b06feb3ba865c9 +size 29049 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png index 815a4f9ed5..d0d1748a80 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76947cf0ea5358646af7726987bd3cd3c49694aceba9850bb0e60a63f3fe669d -size 49542 +oid sha256:2f2bf708bff2bf2a2581c0eb0adfa63b38f0fd5f5fda214594049c2b40a98e09 +size 48731 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png index 920ac350fe..c2b61f4018 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf3add28f315b5f7de06dbdf5b6d5fb96552f648a95a620e50b65fa970de32dd -size 41513 +oid sha256:657e469b19b815ad54ef7ccd6a140d33031301de504690cb520c482f469fa8c4 +size 38559 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_5_en.png deleted file mode 100644 index a95c48fec0..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_5_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d22817145519d17475a09dbe9f5e3a71ec6b5ff9e917d7a92b06feb3ba865c9 -size 29049 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_0_en.png index 8071ebd4ea..8e03ad6ce9 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4c1e564d2cdb6f6a61a02274d63e2610c9b75f7f53c36b473716bba2400798e -size 24752 +oid sha256:bb277b825fefc001450c45a0786afce546f2e0cf7be878ed7bcf401c501c2431 +size 27988 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png index ef1431db80..7aea3012b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:884e301844c610497bf5b5d52445e8124e9eaafd591853a55ab72175096942ab -size 49336 +oid sha256:de50204e7681fead39e7a8f298149b2657a3663197ddc1cfacce4389641f74f5 +size 48222 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png index 6b225ffae0..cc73f71d0c 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81be06688e135d746d30140e61aa168f0d7bfecad1a12e54d9d26e3eb55be0be -size 39897 +oid sha256:02a03b83eaf866a7a65ec26f57fa810a08ad7128d11d2db6ad203bf405a1bb05 +size 37097 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_5_en.png deleted file mode 100644 index 8e03ad6ce9..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_5_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bb277b825fefc001450c45a0786afce546f2e0cf7be878ed7bcf401c501c2431 -size 27988 From 2a694f6dfdc8b4ce5af3410fc637eed674b6ddf2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 17:44:37 +0200 Subject: [PATCH 0352/1083] Create PreviewData with sample of UGC used for preview. Fix preview issue where username was used for room/avatar name. --- .../impl/ui/CallNotificationDataProvider.kt | 6 ++- .../impl/model/RoomListRoomSummaryProvider.kt | 20 +++++---- .../AcceptDeclineInviteStateProvider.kt | 5 ++- .../impl/DefaultInvitePeopleStateProvider.kt | 33 +++++++++------ .../joinroom/impl/JoinRoomStateProvider.kt | 11 +++-- .../KnockRequestsBannerStateProvider.kt | 11 +++-- .../impl/show/ShowLocationStateProvider.kt | 3 +- .../LoginWithClassicStateProvider.kt | 3 +- .../messages/impl/MessagesStateProvider.kt | 5 ++- .../identity/IdentityChangeStateProvider.kt | 3 +- ...lveVerifiedUserSendFailureStateProvider.kt | 5 ++- .../impl/timeline/TimelineStateProvider.kt | 6 ++- .../typing/TypingNotificationStateProvider.kt | 27 +++++++----- .../impl/roles/ChangeRolesStateProvider.kt | 18 ++++---- .../members/RoomMemberListStateProvider.kt | 27 ++++++++---- ...ternalRoomMemberModerationStateProvider.kt | 5 ++- .../impl/leave/LeaveSpaceStateProvider.kt | 3 +- .../settings/SpaceSettingsStateProvider.kt | 3 +- .../IncomingVerificationStateProvider.kt | 5 ++- .../components/avatar/AvatarDataProvider.kt | 6 ++- .../designsystem/preview/PreviewData.kt | 26 ++++++++++++ .../ui/components/MatrixUserProvider.kt | 41 ++++++++++++------- .../matrix/ui/components/SelectedUser.kt | 3 +- .../matrix/ui/components/SpaceHeaderView.kt | 12 ++++-- .../matrix/ui/components/SpaceMembersView.kt | 12 ++++-- .../matrix/ui/components/SpaceRoomProvider.kt | 10 +++-- .../reply/InReplyToDetailsProvider.kt | 3 +- ...tomSheetStateDeleteConfirmationProvider.kt | 3 +- .../MediaBottomSheetStateDetailsProvider.kt | 3 +- .../impl/gallery/MediaGalleryStateProvider.kt | 3 +- .../impl/viewer/MediaViewerStateProvider.kt | 3 +- 31 files changed, 214 insertions(+), 110 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewData.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallNotificationDataProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallNotificationDataProvider.kt index 3a51a014df..9e551b3e1b 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallNotificationDataProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallNotificationDataProvider.kt @@ -9,6 +9,8 @@ package io.element.android.features.call.impl.ui import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.call.impl.notifications.CallNotificationData +import io.element.android.libraries.designsystem.preview.ROOM_NAME +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB 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,8 +36,8 @@ internal fun aCallNotificationData( roomId = RoomId("!1234:matrix.org"), eventId = EventId("\$asdadadsad:matrix.org"), senderId = UserId("@bob:matrix.org"), - roomName = "A room", - senderName = "Bob", + roomName = ROOM_NAME, + senderName = USER_NAME_BOB, avatarUrl = null, notificationChannelId = "incoming_call", timestamp = 0L, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt index eefb2d6484..09e6c2e6c9 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt @@ -11,6 +11,10 @@ package io.element.android.features.home.impl.model import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.LAST_MESSAGE +import io.element.android.libraries.designsystem.preview.ROOM_NAME +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId @@ -85,16 +89,16 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider { @@ -26,7 +27,7 @@ open class AcceptDeclineInviteStateProvider : PreviewParameterProvider { joinAuthorisationStatus = JoinAuthorisationStatus.IsBanned( banSender = InviteSender( userId = UserId("@alice:domain"), - displayName = "Alice", - avatarData = AvatarData("alice", "Alice", size = AvatarSize.InviteSender), + displayName = USER_NAME_ALICE, + avatarData = AvatarData("alice", USER_NAME_ALICE, size = AvatarSize.InviteSender), membershipChangeReason = "spamming" ), reason = "spamming", @@ -222,7 +225,7 @@ fun aJoinRoomState( internal fun anInviteSender( userId: UserId = UserId("@bob:domain"), - displayName: String = "Bob", + displayName: String = USER_NAME_BOB, avatarData: AvatarData = AvatarData(userId.value, displayName, size = AvatarSize.InviteSender), membershipChangeReason: String? = null, ) = InviteSender( @@ -234,7 +237,7 @@ internal fun anInviteSender( internal fun anInviteData( roomId: RoomId = A_ROOM_ID, - roomName: String = "Room name", + roomName: String = ROOM_NAME, isDm: Boolean = false, ) = InviteData( roomId = roomId, diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerStateProvider.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerStateProvider.kt index 67f1aaae8f..7210e783fe 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerStateProvider.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerStateProvider.kt @@ -11,6 +11,9 @@ package io.element.android.features.knockrequests.impl.banner import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.knockrequests.impl.data.KnockRequestPresentable import io.element.android.features.knockrequests.impl.data.aKnockRequestPresentable +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB +import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE import kotlinx.collections.immutable.toImmutableList class KnockRequestsBannerStateProvider : PreviewParameterProvider { @@ -29,15 +32,15 @@ class KnockRequestsBannerStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aLoginWithClassicState(), - aLoginWithClassicState(isElementPro = true, displayName = "Alice"), + aLoginWithClassicState(isElementPro = true, displayName = USER_NAME_ALICE), ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 16021df3e9..14c83db833 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -44,6 +44,7 @@ import io.element.android.features.roommembermoderation.api.RoomMemberModeration import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.ROOM_NAME import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.encryption.identity.IdentityState @@ -94,8 +95,8 @@ open class MessagesStateProvider : PreviewParameterProvider { } fun aMessagesState( - roomName: String? = "Room name", - roomAvatar: AvatarData = AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom), + roomName: String? = ROOM_NAME, + roomAvatar: AvatarData = AvatarData("!id:domain", ROOM_NAME, size = AvatarSize.TimelineRoom), userEventPermissions: UserEventPermissions = aUserEventPermissions(), composerState: MessageComposerState = aMessageComposerState( textEditorState = aTextEditorStateRich(initialText = "Hello", initialFocus = true), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateProvider.kt index 47d1947766..be53de5f66 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateProvider.kt @@ -11,6 +11,7 @@ package io.element.android.features.messages.impl.crypto.identity import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.ui.room.IdentityRoomMember @@ -32,7 +33,7 @@ class IdentityChangeStateProvider : PreviewParameterProvider { override val values: Sequence @@ -37,10 +38,10 @@ fun aResolveVerifiedUserSendFailureState( eventSink = eventSink ) -fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice.FromOther( +fun anUnsignedDeviceSendFailure(userDisplayName: String = USER_NAME_ALICE) = VerifiedUserSendFailure.UnsignedDevice.FromOther( userDisplayName = userDisplayName, ) -fun aChangedIdentitySendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.ChangedIdentity( +fun aChangedIdentitySendFailure(userDisplayName: String = USER_NAME_ALICE) = VerifiedUserSendFailure.ChangedIdentity( userDisplayName = userDisplayName, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 9840ac5107..e77fcdb08e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -29,6 +29,8 @@ import io.element.android.features.messages.impl.typing.aTypingNotificationState import io.element.android.features.roomcall.api.aStandByCallState import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.ROOM_NAME +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UniqueId @@ -143,7 +145,7 @@ internal fun aTimelineItemEvent( isMine: Boolean = false, isEditable: Boolean = false, canBeRepliedTo: Boolean = false, - senderDisplayName: String = "Sender", + senderDisplayName: String = USER_NAME_ALICE, displayNameAmbiguous: Boolean = false, content: TimelineItemEventContent = aTimelineItemTextContent(), groupPosition: TimelineItemGroupPosition = TimelineItemGroupPosition.None, @@ -253,7 +255,7 @@ internal fun aGroupedEvents( } internal fun aTimelineRoomInfo( - name: String = "Room name", + name: String = ROOM_NAME, isDm: Boolean = false, userHasPermissionToSendMessage: Boolean = true, pinnedEventIds: List = emptyList(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationStateProvider.kt index 0506026b86..e298b3af26 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationStateProvider.kt @@ -9,6 +9,11 @@ package io.element.android.features.messages.impl.typing import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB +import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE +import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID +import io.element.android.libraries.designsystem.preview.USER_NAME_EVE import kotlinx.collections.immutable.toImmutableList class TypingNotificationStateProvider : PreviewParameterProvider { @@ -22,7 +27,7 @@ class TypingNotificationStateProvider : PreviewParameterProvider = listOf( - aMatrixUser(id = "@alice:server.org", displayName = "Alice"), - aMatrixUser(id = "@bob:server.org", displayName = "Bob"), - aMatrixUser(id = "@carol:server.org", displayName = "Carol"), + aMatrixUser(displayName = USER_NAME_ALICE), + aMatrixUser(displayName = USER_NAME_BOB), + aMatrixUser(displayName = USER_NAME_CAROL), ), ) = aChangeRolesState( role = role, @@ -114,22 +118,22 @@ internal fun aChangeRolesStateWithOwners( members = persistentListOf( aRoomMember( userId = UserId("@alice:server.org"), - displayName = "Alice", + displayName = USER_NAME_ALICE, role = RoomMember.Role.Owner(isCreator = true), ), aRoomMember( userId = UserId("@bob:server.org"), - displayName = "Bob", + displayName = USER_NAME_BOB, role = RoomMember.Role.Owner(isCreator = false), ), aRoomMember( userId = UserId("@carol:server.org"), - displayName = "Carol", + displayName = USER_NAME_CAROL, role = RoomMember.Role.Admin, ), aRoomMember( userId = UserId("@david:server.org"), - displayName = "David", + displayName = USER_NAME_DAVID, role = RoomMember.Role.User, ), ), diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt index bc077feb6a..fb213ef0cc 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt @@ -15,6 +15,15 @@ import io.element.android.features.roommembermoderation.api.RoomMemberModeration import io.element.android.features.roommembermoderation.api.RoomMemberModerationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.map +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB +import io.element.android.libraries.designsystem.preview.USER_NAME_CAROL +import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID +import io.element.android.libraries.designsystem.preview.USER_NAME_EVE +import io.element.android.libraries.designsystem.preview.USER_NAME_MALLORY +import io.element.android.libraries.designsystem.preview.USER_NAME_SUSIE +import io.element.android.libraries.designsystem.preview.USER_NAME_VICTOR +import io.element.android.libraries.designsystem.preview.USER_NAME_WALTER import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.RoomMember @@ -143,21 +152,21 @@ fun aRoomMemberList() = persistentListOf( aBannedMallory(), ) -fun anEve(): RoomMember = aRoomMember(UserId("@eve:server.org"), "Eve") +fun anEve(): RoomMember = aRoomMember(UserId("@eve:server.org"), USER_NAME_EVE) -fun aDavid(): RoomMember = aRoomMember(UserId("@david:server.org"), "David") +fun aDavid(): RoomMember = aRoomMember(UserId("@david:server.org"), USER_NAME_DAVID) -fun aCarol(): RoomMember = aRoomMember(UserId("@carol:server.org"), "Carol") +fun aCarol(): RoomMember = aRoomMember(UserId("@carol:server.org"), USER_NAME_CAROL) -fun anAlice() = aRoomMember(UserId("@alice:server.org"), "Alice", role = RoomMember.Role.Admin) -fun aBob() = aRoomMember(UserId("@bob:server.org"), "Bob", role = RoomMember.Role.Moderator) +fun anAlice() = aRoomMember(UserId("@alice:server.org"), USER_NAME_ALICE, role = RoomMember.Role.Admin) +fun aBob() = aRoomMember(UserId("@bob:server.org"), USER_NAME_BOB, role = RoomMember.Role.Moderator) -fun anInvitedVictor() = aRoomMember(UserId("@victor:server.org"), "Victor", membership = RoomMembershipState.INVITE) +fun anInvitedVictor() = aRoomMember(UserId("@victor:server.org"), USER_NAME_VICTOR, membership = RoomMembershipState.INVITE) -fun anInvitedWalter() = aRoomMember(UserId("@walter:server.org"), "Walter", membership = RoomMembershipState.INVITE) +fun anInvitedWalter() = aRoomMember(UserId("@walter:server.org"), USER_NAME_WALTER, membership = RoomMembershipState.INVITE) -fun aBannedSusie(): RoomMember = aRoomMember(UserId("@susie:server.org"), "Susie", membership = RoomMembershipState.BAN) +fun aBannedSusie(): RoomMember = aRoomMember(UserId("@susie:server.org"), USER_NAME_SUSIE, membership = RoomMembershipState.BAN) -fun aBannedMallory(): RoomMember = aRoomMember(UserId("@mallory:server.org"), "Mallory", membership = RoomMembershipState.BAN) +fun aBannedMallory(): RoomMember = aRoomMember(UserId("@mallory:server.org"), USER_NAME_MALLORY, membership = RoomMembershipState.BAN) private fun RoomMember.withIdentity(identityState: IdentityState? = null) = RoomMemberWithIdentityState(this, identityState) diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt index 120a299a7d..2bb4db0c69 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/InternalRoomMemberModerationStateProvider.kt @@ -14,6 +14,7 @@ import io.element.android.features.roommembermoderation.api.ModerationActionStat import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents import io.element.android.features.roommembermoderation.api.RoomMemberModerationPermissions import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.toImmutableList @@ -78,8 +79,8 @@ class InternalRoomMemberModerationStateProvider : PreviewParameterProvider { } fun aLeaveSpaceState( - spaceName: String? = "Space name", + spaceName: String? = SPACE_NAME, isLastOwner: Boolean = false, areCreatorsPrivileged: Boolean = false, selectableSpaceRooms: AsyncData> = AsyncData.Uninitialized, diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsStateProvider.kt index 2030b6885a..36f6a2a1d0 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsStateProvider.kt @@ -9,6 +9,7 @@ package io.element.android.features.space.impl.settings import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.preview.SPACE_NAME import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId @@ -24,7 +25,7 @@ open class SpaceSettingsStateProvider : PreviewParameterProvider { open class MatrixUserWithAvatarProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aMatrixUser(displayName = "John Doe"), - aMatrixUser(displayName = "John Doe", avatarUrl = "anUrl"), + aMatrixUser(displayName = USER_NAME_JOHN_DOE), + aMatrixUser(displayName = USER_NAME_JOHN_DOE, avatarUrl = "anUrl"), ) } fun aMatrixUser( - id: String = "@id_of_alice:server.org", - displayName: String? = "Alice", + id: String? = null, + displayName: String? = USER_NAME_ALICE, avatarUrl: String? = null, ) = MatrixUser( - userId = UserId(id), + userId = UserId(id ?: "@${displayName?.lowercase() ?: "id_of_alice"}:server.org"), displayName = displayName, avatarUrl = avatarUrl, ) fun aMatrixUserList() = listOf( - aMatrixUser("@alice:server.org", "Alice"), - aMatrixUser("@bob:server.org", "Bob"), - aMatrixUser("@carol:server.org", "Carol"), - aMatrixUser("@david:server.org", "David"), - aMatrixUser("@eve:server.org", "Eve"), - aMatrixUser("@justin:server.org", "Justin"), - aMatrixUser("@mallory:server.org", "Mallory"), - aMatrixUser("@susie:server.org", "Susie"), - aMatrixUser("@victor:server.org", "Victor"), - aMatrixUser("@walter:server.org", "Walter"), + aMatrixUser(displayName = USER_NAME_ALICE), + aMatrixUser(displayName = USER_NAME_BOB), + aMatrixUser(displayName = USER_NAME_CAROL), + aMatrixUser(displayName = USER_NAME_DAVID), + aMatrixUser(displayName = USER_NAME_EVE), + aMatrixUser(displayName = USER_NAME_JUSTIN), + aMatrixUser(displayName = USER_NAME_MALLORY), + aMatrixUser(displayName = USER_NAME_SUSIE), + aMatrixUser(displayName = USER_NAME_VICTOR), + aMatrixUser(displayName = USER_NAME_WALTER), ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt index b118dbcbe3..17ec7c6ec7 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_JOHN_DOE import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getBestName @@ -58,7 +59,7 @@ internal fun SelectedUserRtlPreview() = CompositionLocalProvider( ) { ElementPreview { SelectedUser( - matrixUser = aMatrixUser(displayName = "John Doe"), + matrixUser = aMatrixUser(displayName = USER_NAME_JOHN_DOE), canRemove = true, onUserRemove = {}, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt index c3e8292147..97aa6ea613 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt @@ -30,6 +30,10 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB +import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE +import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.spaces.SpaceRoomVisibility import io.element.android.libraries.matrix.api.user.MatrixUser @@ -120,10 +124,10 @@ internal fun SpaceHeaderViewPreview() = ElementPreview { topicMaxLines = 2, visibility = SpaceRoomVisibility.Public, heroes = persistentListOf( - aMatrixUser(id = "@1:d", displayName = "Alice", avatarUrl = "aUrl"), - aMatrixUser(id = "@2:d", displayName = "Bob"), - aMatrixUser(id = "@3:d", displayName = "Charlie", avatarUrl = "aUrl"), - aMatrixUser(id = "@4:d", displayName = "Dave"), + aMatrixUser(id = "@1:d", displayName = USER_NAME_ALICE, avatarUrl = "aUrl"), + aMatrixUser(id = "@2:d", displayName = USER_NAME_BOB), + aMatrixUser(id = "@3:d", displayName = USER_NAME_CHARLIE, avatarUrl = "aUrl"), + aMatrixUser(id = "@4:d", displayName = USER_NAME_DAVID), ), numberOfMembers = 999, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceMembersView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceMembersView.kt index 202ea79d87..6d927989d5 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceMembersView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceMembersView.kt @@ -22,6 +22,10 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB +import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE +import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.matrix.api.user.MatrixUser @@ -98,10 +102,10 @@ internal fun SpaceMembersViewPreview() = ElementPreview( ) { SpaceMembersView( heroes = persistentListOf( - aMatrixUser(id = "@1:d", displayName = "Alice", avatarUrl = "aUrl"), - aMatrixUser(id = "@2:d", displayName = "Bob"), - aMatrixUser(id = "@3:d", displayName = "Charlie", avatarUrl = "aUrl"), - aMatrixUser(id = "@4:d", displayName = "Dave"), + aMatrixUser(id = "@1:d", displayName = USER_NAME_ALICE, avatarUrl = "aUrl"), + aMatrixUser(id = "@2:d", displayName = USER_NAME_BOB), + aMatrixUser(id = "@3:d", displayName = USER_NAME_CHARLIE, avatarUrl = "aUrl"), + aMatrixUser(id = "@4:d", displayName = USER_NAME_DAVID), ), numberOfMembers = 123, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt index db63bba779..d6a582d83c 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceRoomProvider.kt @@ -9,6 +9,8 @@ package io.element.android.libraries.matrix.ui.components import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.preview.SPACE_NAME +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomType @@ -28,10 +30,10 @@ class SpaceRoomProvider : PreviewParameterProvider { state = CurrentUserMembership.LEFT, ), aSpaceRoom( - displayName = "Alice", + displayName = SPACE_NAME, roomType = RoomType.Room, isDirect = true, - heroes = listOf(aMatrixUser(displayName = "Alice")), + heroes = listOf(aMatrixUser(displayName = USER_NAME_ALICE)), state = CurrentUserMembership.JOINED, numJoinedMembers = 2, ), @@ -69,9 +71,9 @@ class SpaceRoomProvider : PreviewParameterProvider { state = CurrentUserMembership.INVITED, ), aSpaceRoom( - displayName = "Alice", + displayName = SPACE_NAME, roomType = RoomType.Space, - heroes = listOf(aMatrixUser(displayName = "Alice")), + heroes = listOf(aMatrixUser(displayName = USER_NAME_ALICE)), state = CurrentUserMembership.JOINED, numJoinedMembers = 2, ), diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt index 5ddf57b723..b66beb009c 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.ui.messages.reply import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.MediaSource @@ -159,7 +160,7 @@ private fun aInReplyToDetails( ) fun aProfileDetailsReady( - displayName: String? = "Sender", + displayName: String? = USER_NAME_ALICE, displayNameAmbiguous: Boolean = false, avatarUrl: String? = null, ) = ProfileDetails.Ready( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt index d5fd46d507..72b16c4e1d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDeleteConfirmationProvider.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.mediaviewer.impl.details import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.mediaviewer.api.MediaInfo @@ -26,7 +27,7 @@ open class MediaBottomSheetStateDeleteConfirmationProvider : PreviewParameterPro fun aMediaBottomSheetStateDeleteConfirmation( mediaInfo: MediaInfo = anImageMediaInfo( - senderName = "Alice", + senderName = USER_NAME_ALICE, ), thumbnailSource: MediaSource? = null, ) = MediaBottomSheetState.DeleteConfirmation( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt index e79bfa5e77..99a6925b9d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.mediaviewer.impl.details import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.anApkMediaInfo @@ -35,7 +36,7 @@ fun aMediaBottomSheetStateDetails( eventId: EventId? = EventId($$"$eventId"), canDelete: Boolean = true, mediaInfo: MediaInfo = anImageMediaInfo( - senderName = "Alice", + senderName = USER_NAME_ALICE, dateSentFull = "December 6, 2024 at 12:59", ), ) = MediaBottomSheetState.Details( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt index 7b5edf594a..75b849cd0c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.mediaviewer.impl.gallery import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.media.WaveFormSamples +import io.element.android.libraries.designsystem.preview.ROOM_NAME import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails @@ -112,7 +113,7 @@ open class MediaGalleryStateProvider : PreviewParameterProvider = AsyncData.Uninitialized, mediaBottomSheetState: MediaBottomSheetState = MediaBottomSheetState.Hidden, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index ef9b533586..cb1da7b9b2 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.media.WaveFormSamples +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.timeline.Timeline @@ -179,7 +180,7 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) ), anImageMediaInfo( - senderName = "Alice", + senderName = USER_NAME_ALICE, dateSent = "21 NOV, 2024", caption = LONG_CAPTION, ).let { From a77c2c0c7e49203c22a6045361d65b46a1965982 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 17:54:22 +0200 Subject: [PATCH 0353/1083] Update ref to submodule. --- enterprise | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise b/enterprise index 1ed9a7e8b4..fb7e9287d9 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 1ed9a7e8b4406a5e6d12f603cfc2083e84f8576f +Subproject commit fb7e9287d9d446012925139842d9aaa8e99a74dc From 4b479638a4e54d104d8ecd76636671144b951d49 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Wed, 6 May 2026 11:55:52 -0700 Subject: [PATCH 0354/1083] Keep jump to unread button position stationary --- .../messages/impl/timeline/TimelineView.kt | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 81f40b7a61..a2a40071c3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -339,7 +339,7 @@ private fun BoxScope.TimelineScrollHelper( lazyListState.firstVisibleItemIndex < 3 && isLive } } - val isJumpToUnreadVisible by remember { + val isJumpToUnreadVisible by remember(readMarkerIndex, forceJumpToReadMarkerVisibility) { derivedStateOf { if (forceJumpToReadMarkerVisibility) return@derivedStateOf true val markerIndex = readMarkerIndex ?: return@derivedStateOf false @@ -418,28 +418,30 @@ private fun BoxScope.TimelineScrollHelper( Column( modifier = Modifier .align(Alignment.BottomEnd) - .padding(end = 24.dp, bottom = 24.dp) + .padding(end = 24.dp, bottom = 16.dp) ) { JumpToPositionButton( icon = CompoundIcons.ChevronUp(), contentDescription = stringResource(id = CommonStrings.a11y_jump_to_unread_messages), - modifier = Modifier.padding(bottom = if (isJumpToBottomVisible) 12.dp else 0.dp), + modifier = Modifier.padding(bottom = 12.dp), isVisible = isJumpToUnreadVisible, hasUnread = true, onClick = ::jumpToReadMarker, onMarkAsRead = onMarkAllAsRead, testTag = TestTags.jumpToUnreadButton, ) - JumpToPositionButton( - icon = CompoundIcons.ChevronDown(), - contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), - isVisible = isJumpToBottomVisible, - hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther, - onClick = ::jumpToBottom, - onMarkAsRead = onMarkAllAsRead, - testTag = TestTags.jumpToBottomButton, - dotAlignment = Alignment.BottomCenter, - ) + Box(modifier = Modifier.size(36.dp)) { + JumpToPositionButton( + icon = CompoundIcons.ChevronDown(), + contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom), + isVisible = isJumpToBottomVisible, + hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther, + onClick = ::jumpToBottom, + onMarkAsRead = onMarkAllAsRead, + testTag = TestTags.jumpToBottomButton, + dotAlignment = Alignment.BottomCenter, + ) + } } } From 223dd1f6b0523173e0ba7003a91bee8e4d8b6991 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 18:27:49 +0200 Subject: [PATCH 0355/1083] Fix invalid userId. --- .../messages/impl/timeline/TimelineStateProvider.kt | 6 +++--- .../android/libraries/designsystem/preview/PreviewData.kt | 1 + .../libraries/matrix/ui/components/MatrixUserProvider.kt | 2 +- .../matrix/ui/messages/reply/InReplyToDetailsProvider.kt | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index e77fcdb08e..0bf293eca4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -30,7 +30,7 @@ import io.element.android.features.roomcall.api.aStandByCallState import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ROOM_NAME -import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_SENDER import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UniqueId @@ -145,7 +145,7 @@ internal fun aTimelineItemEvent( isMine: Boolean = false, isEditable: Boolean = false, canBeRepliedTo: Boolean = false, - senderDisplayName: String = USER_NAME_ALICE, + senderDisplayName: String = USER_NAME_SENDER, displayNameAmbiguous: Boolean = false, content: TimelineItemEventContent = aTimelineItemTextContent(), groupPosition: TimelineItemGroupPosition = TimelineItemGroupPosition.None, @@ -162,7 +162,7 @@ internal fun aTimelineItemEvent( eventId = eventId, transactionId = transactionId, senderId = UserId("@senderId:domain"), - senderAvatar = AvatarData("@senderId:domain", "sender", size = AvatarSize.TimelineSender), + senderAvatar = AvatarData("@senderId:domain", USER_NAME_SENDER, size = AvatarSize.TimelineSender), content = content, reactionsState = timelineItemReactions, readReceiptState = readReceiptState, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewData.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewData.kt index f728cce302..66a6043634 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewData.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewData.kt @@ -16,6 +16,7 @@ const val USER_NAME_EVE = "Eve" const val USER_NAME_JOHN_DOE = "John Doe" const val USER_NAME_JUSTIN = "Justin" const val USER_NAME_MALLORY = "Mallory" +const val USER_NAME_SENDER = "Sender" const val USER_NAME_SUSIE = "Susie" const val USER_NAME_VICTOR = "Victor" const val USER_NAME_WALTER = "Walter" 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 84a226edc7..1b662ad7c1 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 @@ -44,7 +44,7 @@ fun aMatrixUser( displayName: String? = USER_NAME_ALICE, avatarUrl: String? = null, ) = MatrixUser( - userId = UserId(id ?: "@${displayName?.lowercase() ?: "id_of_alice"}:server.org"), + userId = UserId(id ?: "@${displayName?.lowercase()?.replace(" ", "_") ?: "id_of_alice"}:server.org"), displayName = displayName, avatarUrl = avatarUrl, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt index b66beb009c..ca118349e9 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt @@ -9,7 +9,7 @@ package io.element.android.libraries.matrix.ui.messages.reply import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_SENDER import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.MediaSource @@ -160,7 +160,7 @@ private fun aInReplyToDetails( ) fun aProfileDetailsReady( - displayName: String? = USER_NAME_ALICE, + displayName: String? = USER_NAME_SENDER, displayNameAmbiguous: Boolean = false, avatarUrl: String? = null, ) = ProfileDetails.Ready( From a7c4a2b4044a73d86989ff8c484e9fed5f0fef32 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 6 May 2026 20:17:22 +0000 Subject: [PATCH 0356/1083] Update screenshots --- ...te.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en.png | 4 ++-- ...te.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en.png | 4 ++-- ....impl.acceptdecline_AcceptDeclineInviteView_Night_1_en.png | 4 ++-- ....impl.acceptdecline_AcceptDeclineInviteView_Night_2_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_0_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_2_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_3_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_4_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_5_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_0_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_2_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_3_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_4_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_5_en.png | 4 ++-- ...eatures.preferences.impl.user_UserPreferences_Day_0_en.png | 4 ++-- ...tures.preferences.impl.user_UserPreferences_Night_0_en.png | 4 ++-- ...tchat.impl.components_SearchMultipleUsersResultItem_en.png | 4 ++-- ...tartchat.impl.components_SearchSingleUserResultItem_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Day_1_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Day_2_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Day_4_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Night_1_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Night_2_en.png | 4 ++-- .../features.startchat.impl.root_StartChatView_Night_4_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_8_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_8_en.png | 4 ++-- ...aries.matrix.ui.components_CheckableResolvedUserRow_en.png | 4 ++-- ...ies.matrix.ui.components_CheckableUnresolvedUserRow_en.png | 4 ++-- ...ui.components_CreateDmConfirmationBottomSheet_Day_0_en.png | 4 ++-- ...ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png | 4 ++-- ....components_CreateDmConfirmationBottomSheet_Night_0_en.png | 4 ++-- ....components_CreateDmConfirmationBottomSheet_Night_1_en.png | 4 ++-- ...braries.matrix.ui.components_MatrixUserHeader_Day_0_en.png | 4 ++-- ...aries.matrix.ui.components_MatrixUserHeader_Night_0_en.png | 4 ++-- .../libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png | 4 ++-- ...ibraries.matrix.ui.components_MatrixUserRow_Night_0_en.png | 4 ++-- ...matrix.ui.components_SelectedUserCannotRemove_Day_0_en.png | 4 ++-- ...trix.ui.components_SelectedUserCannotRemove_Night_0_en.png | 4 ++-- ...ibraries.matrix.ui.components_SelectedUserRtl_Day_0_en.png | 4 ++-- ...raries.matrix.ui.components_SelectedUserRtl_Night_0_en.png | 4 ++-- .../libraries.matrix.ui.components_SelectedUser_Day_0_en.png | 4 ++-- ...libraries.matrix.ui.components_SelectedUser_Night_0_en.png | 4 ++-- ...raries.matrix.ui.components_SpaceRoomItemView_Day_2_en.png | 4 ++-- ...raries.matrix.ui.components_SpaceRoomItemView_Day_8_en.png | 4 ++-- ...ries.matrix.ui.components_SpaceRoomItemView_Night_2_en.png | 4 ++-- ...ries.matrix.ui.components_SpaceRoomItemView_Night_8_en.png | 4 ++-- .../libraries.matrix.ui.components_UnresolvedUserRow_en.png | 4 ++-- 47 files changed, 94 insertions(+), 94 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en.png index bc93c4c316..a0ab0a2192 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:95096ef9f55d57ea4774f8eaa91d92a01fd44eafd4670442d3db132ff843ede0 -size 21476 +oid sha256:62fee8e8966ff4df0d951aff1d13e8578c9c5a55e89c4407dcc8077c9b1b72af +size 22249 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en.png index d1c7598599..cce585fe3f 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b53f36378be4b4da2608210cb3134923c6f4bf565652c80a1b45cad8216d67da -size 25485 +oid sha256:d3226560d55a9fde8175206c0ce21cb4cd90d900d357003496bf74b719281166 +size 26191 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en.png index 54a3c425c1..6a278db2b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d549ca3000080a6d0c416d7a45d530da96c73184309048126be6304393bc74f9 -size 20082 +oid sha256:643f712799406118deb87af3fab34e8838878dc04e0935b4e54dafaaebd03479 +size 20895 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en.png index 341bcca1a6..2b09d75bc9 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a61181eab30d30f56c5407bb42395a268ff80f7dd455ea04a468f92739e0a87f -size 24194 +oid sha256:c2638b57f0f4ab1876429f096065d121122eaca0b9b06600281526dbf51d7791 +size 24843 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 c98615fb74..9d8eec80cb 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:1da26fc2ffe2216cda7aa1b6b92ba587c9d0bb56aa54586b3073befee96d29b6 -size 40956 +oid sha256:e83c8d052ce340010f97c4ef2750e4b921a129639a0004bd951f71c7348622bf +size 40597 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 9f15832109..18869e3590 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:1a4be2c70eb477dbd58e4e6924d0141f1c8d7205807d968b3a34221c12a301c6 -size 36176 +oid sha256:95e30b24d5a6571cf42a707a01f0458cf509428c9ab8333924e1679f6d4d4f31 +size 35778 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 index f1b39a0d35..2786b0cb8d 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9176ee2b5b78032639d9f51f7680d82f7d3ca916fb587d914f12d075382d65f0 -size 27077 +oid sha256:8e54c2c665235d6b4c45161b4fcc0b8f0a96ce7620bbed9f56e04ecb71916f3e +size 26640 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 index e9cb1772f7..ff630d5aab 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76caf93913c979f3327dec4331d3a5bea5027df45c5cacf55a786b8f677e3162 -size 27340 +oid sha256:c2fd721612e0620c3a4eac0f0835ac1d03ffb36ec45477340bb732ff1c63cc30 +size 26921 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 index 31a44423ce..cb6c51d959 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e457b722fe403205f1394e7347dedb3aba308e48c979ea002399425c9a130fd2 -size 20667 +oid sha256:7c7fc020ec4bcb2f67a3a534a621e71233488b469b24e6bd6d3efa42f9f944a1 +size 20263 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 ebe4511bdf..5fe3875d72 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:6a0202d081e5aed85ca093239fae1c8f46d42fd6e859c818f5c0301597e5b473 -size 41957 +oid sha256:a07bd9ac57c1fb6074b81134edcd169c2c7edc3dd19039766dabbfe8ccd5d8fb +size 41621 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 155302aafc..c188be2848 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:2ae20b874dba38a89a59e418bce33e748449446e0fc913b7f3ff2e87b8200c40 -size 36568 +oid sha256:67bc6eac2128230323aa7dabb6896b98c4249e6fba9edb4d1769f36dbe031135 +size 36346 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 index 15c12f4836..f2ca7b4a6c 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74a4913734d0648115d5056052fa2de8a839bb5a4d2dfdaa3d8ed5f0eef2793d -size 27728 +oid sha256:a40fe5dc4a671ec2384265da36f3d42a3cadb2792823308a62dbd82423110652 +size 27552 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 index 7e4a6475b1..8ce81e889d 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4f8571893bf9292a7d298c7419ea2e3f0363e1c2eca8c5f6aaea7d39143039c -size 27855 +oid sha256:007aeb20270db25edcd3cf2e1ac8e4e0d714e08a043af0473c2263c1e79af452 +size 27634 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 index c325a4e7b5..c402bf81c9 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d5b500d6275bc6ead5e8644b1afb1a0a829e91d4912444e5e0d431322343855 -size 20700 +oid sha256:d644bc2a62596b923d782150334f60b1940730824af0b7a304d2fdfce85cd0e6 +size 20493 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 c6e079dee2..03d5ad5880 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:0805bac4bf9e1c5bb16b4f81b004bcc952563eef98101d8c9c6e856a414977d0 -size 11219 +oid sha256:0dfea70e781debf7a293aee2967c3da314101020698fee97d3551e25f5f378d0 +size 10655 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 f21d99fffc..27f51b2778 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:070163694fe10b465f2903ce2cc88f9ffc67d9489aa5a4e204cd087fd02b8642 -size 11281 +oid sha256:62e127900d00756ecc806eb9d8efb6a11cd9cdcecae6b4bab643b7306a06be2b +size 10435 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png index cad7e55b37..de213ca597 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchMultipleUsersResultItem_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8af941ad8e5b553b82aad8b39abd8b4876d67b6906acf0ee8e4715673d8b35a -size 81462 +oid sha256:80e8c8bf0bf9b34d3de0b0db7f67b84a667a9f510d6e9eefc708de25dd1ca5f8 +size 76725 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png index b5e9457b1a..a980e0c914 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.components_SearchSingleUserResultItem_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f776cecd5278761fe7904b63dd980804a6dc2d3e7acc37fb7ea71d6a1c1e63df -size 42505 +oid sha256:d7e8bc45d019ed73b4795f29b36c28411e8e20cd4bd231e76e8619e011b64b31 +size 40203 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png index a2f44ea5a0..33fa7369ed 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b094f8d20b4b946abcd95bbb0c1d64a0190a5c651b6f434dbd9aef2857a315a7 -size 19991 +oid sha256:27249bb1a928cb325557c8aebf6de344b7cd7a16d3420e8711591f20a3eb36b1 +size 18947 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png index 5e3737d938..ac26997f26 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3fde1e89269c46ac8a6b4f0a05aad45bcc806f2a1b6108c09f7078209f7799c -size 26574 +oid sha256:a5f0abeb2bfbae8fc6b864ea2e6a90b4ab3bcfd3b9f5fa4a06c6a314bd194a5f +size 25660 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png index c2b61f4018..51f05258df 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:657e469b19b815ad54ef7ccd6a140d33031301de504690cb520c482f469fa8c4 -size 38559 +oid sha256:4b372f9fd8570c977cd882f396004fe8fd0794ca3070a11394e0d6af6354987a +size 38154 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png index 5e457ea444..b37d6fa5d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f37ae64424323d6772fca7b43f175e8c02356833bed02bb9661acbfb102c194 -size 19358 +oid sha256:c5e6a562525d8ded0fddb365beaef933d2701bcd4548e589bffd54e1bd0a3b11 +size 18087 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png index 6fe0a0be87..4592dbb299 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d42e8795792b250696206f5f9fabcac3b7249b3709cf90d8f2503091769e5343 -size 25324 +oid sha256:e22f1f07193011c1db785e3827e73d05d8bf96fd12559e3d7a744b2b978b7bf4 +size 24196 diff --git a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png index cc73f71d0c..76810b5897 100644 --- a/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.startchat.impl.root_StartChatView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02a03b83eaf866a7a65ec26f57fa810a08ad7128d11d2db6ad203bf405a1bb05 -size 37097 +oid sha256:a8a1a8fe51f741748817a0a1c497fc164d0e1e711ce458182a654b1fee8e5741 +size 36417 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_8_en.png index d0d02d6321..aef669fae0 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65446447e07a1a6cc08ed566e1aaea7a1209f1e1f5f752dec5e598819333761d -size 34595 +oid sha256:781bf8c86e88c9ee564f45de7446ee2eb554efe68ae9e708aa1b5bde7fce6d6b +size 34137 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_8_en.png index 844a7c3c54..3c90a4f7ef 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e467732ff44f080bb1a698d4f6f2427480c5456980066ffd9ab6970b093c3d64 -size 33206 +oid sha256:45c706bb63ab7df8e66898ec67fabbf8c227cac421b8c5eda84a2f6532c8f199 +size 32504 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png index 3aa2f3157d..28e63caa03 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableResolvedUserRow_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a986526c80130e11a0ec9c6450e4cd77dc40ef4a09082a1c526eebabebf4c03 -size 49746 +oid sha256:d372726c65f1887a8eba63f04301212780ef04410fd0758d314562f6899859ea +size 46072 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png index 1ef0d7dd02..1cd0c138e2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CheckableUnresolvedUserRow_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2ca690a89bebaa351990cab34155afcfa7a0b9f02312757fcb933ba97ab9310 -size 101952 +oid sha256:ea6ea46123a211b87daadf29aa87588f4e0fa5e5c25ddc0307db490c72f865d5 +size 96925 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en.png index c7e3599c58..1c57c30014 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb4d6bfb9c412de00a2b4956032dd42906b5451eb99e6ebb1880dc01f6b55af5 -size 26077 +oid sha256:fbbe069eaeff3c1bfb39e4b3e3356e92864f10a57ca4ccb2029e38b5977b6f45 +size 25648 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png index d7ff4a1d2f..e8d101b4b7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26bf76ccdb56d042422553f557d91d0f26d874a710f696ac106c5c2b5590d332 -size 38833 +oid sha256:97e6bbc6cc6d5bb90606bc7f934258c8060d7ca5fade8da6a1aae288e8558bb4 +size 38390 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en.png index fe44b8941c..0a5082edbe 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8c422787b67d477d3b7c8d5dee8879f33d47153dc93dd29bb3883e4ed863a41 -size 25232 +oid sha256:2b14f8a5a50deb5dd4854665cd41511228f5ba47b0719bf35b4d1675d0f20ce1 +size 24527 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png index f5ff7856b2..6d872bf044 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8413aed02383572cfe8c481c6ba8b0db4cfb3402334c37f2d8b54a73fe4bf594 -size 37343 +oid sha256:841042eabcd85626a5182108edae46b4514f84a8f22c57e324c02430536acff2 +size 36738 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 c6e079dee2..03d5ad5880 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:0805bac4bf9e1c5bb16b4f81b004bcc952563eef98101d8c9c6e856a414977d0 -size 11219 +oid sha256:0dfea70e781debf7a293aee2967c3da314101020698fee97d3551e25f5f378d0 +size 10655 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 f21d99fffc..27f51b2778 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:070163694fe10b465f2903ce2cc88f9ffc67d9489aa5a4e204cd087fd02b8642 -size 11281 +oid sha256:62e127900d00756ecc806eb9d8efb6a11cd9cdcecae6b4bab643b7306a06be2b +size 10435 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png index 78e3e7db33..93e17f26b8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9aa5b37b57d1ef1f219e0c5213eab3eba3222bd0453988a5c708e15ba89d8fd4 -size 9772 +oid sha256:4c37d48eb1fde1eb67cb3130505414c97486d1b40b49be9a6c0770b0ff9e50da +size 9277 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png index af7347092d..d55e71d415 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e850f65631de21c8cb44965f66e8ffbf0b1eecf2ed6f91e6669f0dc89ec0e4b3 -size 9784 +oid sha256:4e283d48e8eb569f44576c158096ef0672146392411e2e768350ebaff9f71ee7 +size 9073 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en.png index 13b54d61f4..6fc398e5ba 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca4b2ddcebb957944522673d20aafb967ef118ac1a8564f33a0c8745f0f7caf5 -size 6268 +oid sha256:2a6797d1d45c1ef189dfffec805604b06dd7820976c834233a99fc803721b663 +size 6500 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en.png index 30475df2c4..b599a59788 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d56cc64425872a2dc1c12ab7d2e0d9fe43e89586e6f5f1805684350281baa6b8 -size 6744 +oid sha256:acc4553e995907ecfaaf74c4e7bfdd9fd8ccf5cd6ba8396b25c110211c21975e +size 6614 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Day_0_en.png index 81b127dc0b..1d334393b1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:160abf1659329b6ddb61e9f3bbe9cc5cf4630242429093a8d2d579e0b6efd78d -size 7687 +oid sha256:2f93df7decca6ced4efe9f739d6f877b2411be874c0cf011a146a66e0ee2fb69 +size 7790 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Night_0_en.png index 7ad44c9fd2..efe44c5f81 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUserRtl_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39817cc9c0bcb7ae058201c8bb9e7f68529142161019a23296087cd952667473 -size 8143 +oid sha256:7a52a67692a0fefcb499af2f3e0670b663b1df657ecc7b61e58773db9ea6615f +size 8057 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Day_0_en.png index 08ebefd43b..230de5c2ef 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40efbe8c661131800679fcdf18870d05cbd24a7f62c7c1adb998f28cef3896ea -size 7698 +oid sha256:b095f97e5ac7279fba15f7ea8dc1658c89e28e4f72b8f93b7c32a7b6d5bc4d23 +size 7807 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Night_0_en.png index b7d94eec19..d45e2d4b35 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SelectedUser_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:774bf98c634fef1339d95e8eaf5f5219535766f41f2ee8b4c124107f381bf052 -size 8167 +oid sha256:5a0960b2353e902b04682818cf598fad7ff4ccee9e9fe7aec13ad556653b702c +size 8091 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en.png index 25dae1f86b..82f7e36af6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ad5934da41af5f5f350adc3d5d754f1ed16e90546cb20a0874e3d069010167d -size 10117 +oid sha256:aa985c9b0211cb12e617e8da73669777cf3a5ec5b77b79f232ccdc6e0cf55373 +size 11760 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en.png index 491523e822..e38dfee86a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81de93c5c71bc1552dc93343bae9168ce35e0d4d4430a47311ff80b9cec6c3b6 -size 10633 +oid sha256:71bf90e818949065c7620bfa8e7148a8f9be295775e1b29cb251d2a00bd87853 +size 12173 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en.png index 7201e63c00..e3c16b4b40 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ec4038e9d1cd25d8ee27c54e10f9f3627bf6f8f4c83201b1bbc3fd73641f1d5 -size 10333 +oid sha256:68e990772361fd240fb20b664731613b5a2f187499f2db48e130673f16acb33b +size 11575 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en.png index 308066382b..f4bcc684a7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2a837de06ec9369c5a39629579c237b4f394a586a2ce85a5c5e15d444c98314 -size 10323 +oid sha256:05e2b62d4484990cdd837ff233a654cd6aa8d82d1c3965351bba86bcfcc1e1d0 +size 11776 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png index 1e4ce1ae37..5d59b52717 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_UnresolvedUserRow_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86d4aaa9a2ad499be90ed3a0d9a15fcd23cba4b40395aee53028168717c1fe9f -size 54739 +oid sha256:8a2d52c8f8903881357cd0590d5c1bfb85997068eded3813aad1bec4f31d853a +size 52452 From a27278da2075950801ecbc6c088aaac7d2967da7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 08:09:15 +0200 Subject: [PATCH 0357/1083] Update dependencyAnalysis to v3.10.0 (#6742) 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 c03d164728..581630c80d 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.9.0" +dependencyAnalysis = "3.10.0" # DI metro = "0.13.2" From 034916269483e875e9c8e564804e3fb40d029e7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 May 2026 09:50:00 +0200 Subject: [PATCH 0358/1083] More replacements --- .../suggestions/SuggestionsPickerView.kt | 3 +- .../previewutils/room/RoomMemberFixture.kt | 30 ++++++++++++------- .../previewutils/room/SpaceRoomFixture.kt | 3 +- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt index 678ef2ba56..3d18db12d9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt @@ -33,6 +33,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType.Ro import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.RoomAlias @@ -198,7 +199,7 @@ internal fun SuggestionsPickerViewPreview() { suggestions = persistentListOf( ResolvedSuggestion.AtRoom, ResolvedSuggestion.Member(roomMember), - ResolvedSuggestion.Member(roomMember.copy(userId = UserId("@bob:server.org"), displayName = "Bob")), + ResolvedSuggestion.Member(roomMember.copy(userId = UserId("@bob:server.org"), displayName = USER_NAME_BOB)), ResolvedSuggestion.Alias( roomAlias = anAlias, roomId = RoomId("!room:matrix.org"), diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt index 1b73ccea31..42fc527bb2 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt @@ -8,6 +8,16 @@ package io.element.android.libraries.previewutils.room +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB +import io.element.android.libraries.designsystem.preview.USER_NAME_CAROL +import io.element.android.libraries.designsystem.preview.USER_NAME_DAVID +import io.element.android.libraries.designsystem.preview.USER_NAME_EVE +import io.element.android.libraries.designsystem.preview.USER_NAME_JUSTIN +import io.element.android.libraries.designsystem.preview.USER_NAME_MALLORY +import io.element.android.libraries.designsystem.preview.USER_NAME_SUSIE +import io.element.android.libraries.designsystem.preview.USER_NAME_VICTOR +import io.element.android.libraries.designsystem.preview.USER_NAME_WALTER import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState @@ -38,27 +48,27 @@ fun aRoomMember( fun aRoomMemberList() = persistentListOf( anAlice(), aBob(), - aRoomMember(UserId("@carol:server.org"), "Carol"), - aRoomMember(UserId("@david:server.org"), "David"), - aRoomMember(UserId("@eve:server.org"), "Eve"), - aRoomMember(UserId("@justin:server.org"), "Justin"), - aRoomMember(UserId("@mallory:server.org"), "Mallory"), - aRoomMember(UserId("@susie:server.org"), "Susie"), + aRoomMember(UserId("@carol:server.org"), USER_NAME_CAROL), + aRoomMember(UserId("@david:server.org"), USER_NAME_DAVID), + aRoomMember(UserId("@eve:server.org"), USER_NAME_EVE), + aRoomMember(UserId("@justin:server.org"), USER_NAME_JUSTIN), + aRoomMember(UserId("@mallory:server.org"), USER_NAME_MALLORY), + aRoomMember(UserId("@susie:server.org"), USER_NAME_SUSIE), aVictor(), aWalter(), ) -fun anAlice() = aRoomMember(UserId("@alice:server.org"), "Alice", role = RoomMember.Role.Admin) -fun aBob() = aRoomMember(UserId("@bob:server.org"), "Bob", role = RoomMember.Role.Moderator) +fun anAlice() = aRoomMember(UserId("@alice:server.org"), USER_NAME_ALICE, role = RoomMember.Role.Admin) +fun aBob() = aRoomMember(UserId("@bob:server.org"), USER_NAME_BOB, role = RoomMember.Role.Moderator) fun aVictor() = aRoomMember( UserId("@victor:server.org"), - "Victor", + USER_NAME_VICTOR, membership = RoomMembershipState.INVITE ) fun aWalter() = aRoomMember( UserId("@walter:server.org"), - "Walter", + USER_NAME_WALTER, membership = RoomMembershipState.INVITE ) diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt index 4bf1d2501b..68825540a4 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.previewutils.room +import io.element.android.libraries.designsystem.preview.SPACE_NAME import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership @@ -19,7 +20,7 @@ import kotlinx.collections.immutable.toImmutableList fun aSpaceRoom( rawName: String? = null, - displayName: String = "Space name", + displayName: String = SPACE_NAME, avatarUrl: String? = null, canonicalAlias: RoomAlias? = null, childrenCount: Int = 0, From b19a2c5a443093462a381a49dfd90ed7ed7f431c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 May 2026 09:50:12 +0200 Subject: [PATCH 0359/1083] Use generic id for default --- .../libraries/matrix/ui/components/MatrixUserProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1b662ad7c1..639bafbcbf 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 @@ -44,7 +44,7 @@ fun aMatrixUser( displayName: String? = USER_NAME_ALICE, avatarUrl: String? = null, ) = MatrixUser( - userId = UserId(id ?: "@${displayName?.lowercase()?.replace(" ", "_") ?: "id_of_alice"}:server.org"), + userId = UserId(id ?: "@${displayName?.lowercase()?.replace(" ", "_") ?: "id"}:server.org"), displayName = displayName, avatarUrl = avatarUrl, ) From 4948497be29d2555235c0e9d03d7117b2bd94268 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 May 2026 09:53:33 +0200 Subject: [PATCH 0360/1083] More replacements --- .../features/home/impl/components/HomeTopBar.kt | 11 ++++++----- .../location/impl/common/ui/LocationShareRow.kt | 10 ++++++---- .../messages/impl/threads/list/ThreadsListView.kt | 6 ++++-- .../impl/timeline/components/MessageShieldView.kt | 3 ++- .../impl/timeline/components/TimelineItemEventRow.kt | 5 +++-- .../components/TimelineItemEventRowUtdPreview.kt | 8 +++++--- .../virtual/TimelineItemRoomBeginningView.kt | 5 +++-- .../messages/impl/topbars/MessagesViewTopBar.kt | 5 +++-- .../features/messages/impl/topbars/ThreadTopBar.kt | 7 ++++--- .../user/editprofile/EditUserProfileStateProvider.kt | 3 ++- .../userprofile/shared/UserProfileHeaderSection.kt | 5 +++-- .../impl/ui/VerificationUserProfileContent.kt | 3 ++- .../libraries/designsystem/components/LocationPin.kt | 3 ++- .../designsystem/components/avatar/DmAvatars.kt | 6 ++++-- .../matrix/ui/components/InviteSenderView.kt | 5 +++-- .../matrix/ui/components/OrganizationHeader.kt | 3 ++- .../libraries/matrix/ui/components/SpaceHeaderView.kt | 3 ++- 17 files changed, 56 insertions(+), 35 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt index 5c3075fc75..5f55beaf60 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt @@ -57,6 +57,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.backgroundVerticalGradient import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem @@ -65,8 +66,8 @@ import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.matrix.api.core.UserId 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.matrix.ui.model.getAvatarData import io.element.android.libraries.testtags.TestTags @@ -346,7 +347,7 @@ private fun AccountIcon( internal fun HomeTopBarPreview() = ElementPreview { HomeTopBar( selectedNavigationItem = HomeNavigationBarItem.Chats, - currentUserAndNeighbors = persistentListOf(MatrixUser(UserId("@id:domain"), "Alice")), + currentUserAndNeighbors = persistentListOf(aMatrixUser(id = "@id:domain", displayName = USER_NAME_ALICE)), showAvatarIndicator = false, areSearchResultsDisplayed = false, scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), @@ -367,7 +368,7 @@ internal fun HomeTopBarPreview() = ElementPreview { internal fun HomeTopBarSpaceFiltersSelectedPreview() = ElementPreview { HomeTopBar( selectedNavigationItem = HomeNavigationBarItem.Chats, - currentUserAndNeighbors = persistentListOf(MatrixUser(UserId("@id:domain"), "Alice")), + currentUserAndNeighbors = persistentListOf(aMatrixUser(id = "@id:domain", displayName = USER_NAME_ALICE)), showAvatarIndicator = false, areSearchResultsDisplayed = false, scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), @@ -388,7 +389,7 @@ internal fun HomeTopBarSpaceFiltersSelectedPreview() = ElementPreview { internal fun HomeTopBarSpacesPreview() = ElementPreview { HomeTopBar( selectedNavigationItem = HomeNavigationBarItem.Spaces, - currentUserAndNeighbors = persistentListOf(MatrixUser(UserId("@id:domain"), "Alice")), + currentUserAndNeighbors = persistentListOf(aMatrixUser(id = "@id:domain", displayName = USER_NAME_ALICE)), showAvatarIndicator = false, areSearchResultsDisplayed = false, scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), @@ -409,7 +410,7 @@ internal fun HomeTopBarSpacesPreview() = ElementPreview { internal fun HomeTopBarWithIndicatorPreview() = ElementPreview { HomeTopBar( selectedNavigationItem = HomeNavigationBarItem.Chats, - currentUserAndNeighbors = persistentListOf(MatrixUser(UserId("@id:domain"), "Alice")), + currentUserAndNeighbors = persistentListOf(aMatrixUser(id = "@id:domain", displayName = USER_NAME_ALICE)), showAvatarIndicator = true, areSearchResultsDisplayed = false, scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), 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 83db9a9c61..3d7b8df618 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 @@ -31,6 +31,8 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Text @@ -116,10 +118,10 @@ internal fun LocationShareRowPreview() = ElementPreview { LocationShareRow( item = LocationShareItem( userId = UserId("@alice:matrix.org"), - displayName = "Alice", + displayName = USER_NAME_ALICE, avatarData = AvatarData( id = "@alice:matrix.org", - name = "Alice", + name = USER_NAME_ALICE, url = null, size = AvatarSize.UserListItem, ), @@ -133,10 +135,10 @@ internal fun LocationShareRowPreview() = ElementPreview { LocationShareRow( item = LocationShareItem( userId = UserId("@bob:matrix.org"), - displayName = "Bob", + displayName = USER_NAME_BOB, avatarData = AvatarData( id = "@bob:matrix.org", - name = "Bob", + name = USER_NAME_BOB, url = null, size = AvatarSize.UserListItem, ), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt index c93af5c162..1beabcd3fa 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt @@ -43,6 +43,8 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.ROOM_NAME +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold @@ -303,7 +305,7 @@ internal fun ThreadsListViewPreview() { ThreadsListView( state = ThreadsListState( roomId = RoomId("!room-id:server"), - roomName = "Room name", + roomName = ROOM_NAME, roomAvatarUrl = null, threads = List(10) { aThreadListRowItem(threadId = ThreadId("\$thread-$it")) }.toImmutableList(), isRoomTombstoned = false, @@ -360,7 +362,7 @@ fun aThreadListItem( fun aThreadListItemEvent( threadId: ThreadId = ThreadId("\$a-thread-id"), senderId: UserId = UserId("@a-user-id:server"), - senderProfile: ProfileDetails = ProfileDetails.Ready(displayName = "Alice", displayNameAmbiguous = false, avatarUrl = null), + senderProfile: ProfileDetails = ProfileDetails.Ready(displayName = USER_NAME_ALICE, displayNameAmbiguous = false, avatarUrl = null), isOwn: Boolean = false, content: EventContent = MessageContent( body = "Hello world!", diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt index 096ab018e2..1859e66750 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageShieldView.kt @@ -26,6 +26,7 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.R import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.UserId @@ -162,7 +163,7 @@ internal fun MessageShieldViewPreview() { MessageShield.AuthenticityNotGuaranteed(false), forwarder = UserId("@alice:example.com"), forwarderProfile = ProfileDetails.Ready( - displayName = "Alice", + displayName = USER_NAME_ALICE, displayNameAmbiguous = false, avatarUrl = null, ), 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 f15d4d39a5..5785627564 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 @@ -92,6 +92,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.niceClickable import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.swipe.SwipeableActionsState import io.element.android.libraries.designsystem.swipe.rememberSwipeableActionsState import io.element.android.libraries.designsystem.text.toPx @@ -863,7 +864,7 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { ), senderId = UserId("@user:id"), senderProfile = ProfileDetails.Ready( - displayName = "Alice", + displayName = USER_NAME_ALICE, avatarUrl = null, displayNameAmbiguous = false, ), @@ -898,7 +899,7 @@ internal fun ThreadSummaryViewPreview() { ), senderId = UserId("@user:id"), senderProfile = ProfileDetails.Ready( - displayName = "Alice", + displayName = USER_NAME_ALICE, avatarUrl = null, displayNameAmbiguous = true, ), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowUtdPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowUtdPreview.kt index 49328ac025..abacc45ef8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowUtdPreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowUtdPreview.kt @@ -16,6 +16,8 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemGrou import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent import io.element.android.libraries.matrix.api.timeline.item.event.UtdCause @@ -25,7 +27,7 @@ internal fun TimelineItemEventRowUtdPreview() = ElementPreview { Column { ATimelineItemEventRow( event = aTimelineItemEvent( - senderDisplayName = "Alice", + senderDisplayName = USER_NAME_ALICE, isMine = false, content = TimelineItemEncryptedContent( data = UnableToDecryptContent.Data.MegolmV1AesSha2( @@ -39,7 +41,7 @@ internal fun TimelineItemEventRowUtdPreview() = ElementPreview { ) ATimelineItemEventRow( event = aTimelineItemEvent( - senderDisplayName = "Bob", + senderDisplayName = USER_NAME_BOB, isMine = false, content = TimelineItemEncryptedContent( data = UnableToDecryptContent.Data.MegolmV1AesSha2( @@ -54,7 +56,7 @@ internal fun TimelineItemEventRowUtdPreview() = ElementPreview { ATimelineItemEventRow( event = aTimelineItemEvent( - senderDisplayName = "Bob", + senderDisplayName = USER_NAME_BOB, isMine = false, content = TimelineItemEncryptedContent( data = UnableToDecryptContent.Data.MegolmV1AesSha2( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt index f812b40e61..d59526d8bb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt @@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.R import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.ROOM_NAME import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.allBooleans @@ -86,13 +87,13 @@ internal fun TimelineItemRoomBeginningViewPreview() = ElementPreview { ) TimelineItemRoomBeginningView( predecessorRoom = null, - roomName = "Room Name", + roomName = ROOM_NAME, isDm = isDm, onPredecessorRoomClick = {}, ) TimelineItemRoomBeginningView( predecessorRoom = PredecessorRoom(RoomId("!roomId:matrix.org")), - roomName = "Room Name", + roomName = ROOM_NAME, isDm = isDm, onPredecessorRoomClick = {}, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index b1a31da443..639092fc6c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -43,6 +43,7 @@ import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.ROOM_NAME import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text @@ -175,9 +176,9 @@ private fun RoomAvatarAndNameRow( internal fun MessagesViewTopBarPreview() = ElementPreview { @Composable fun AMessagesViewTopBar( - roomName: String? = "Room name", + roomName: String? = ROOM_NAME, roomAvatar: AvatarData = anAvatarData( - name = "Room name", + name = ROOM_NAME, size = AvatarSize.TimelineRoom, ), isTombstoned: Boolean = false, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt index 2247566531..e73b6b19b7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt @@ -31,6 +31,7 @@ import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.ROOM_NAME import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar @@ -96,9 +97,9 @@ internal fun ThreadTopBar( internal fun ThreadTopBarPreview() = ElementPreview { @Composable fun AThreadTopBar( - roomName: String? = "Room name", + roomName: String? = ROOM_NAME, roomAvatarData: AvatarData = anAvatarData( - name = "Room name", + name = ROOM_NAME, size = AvatarSize.TimelineRoom, ), isTombstoned: Boolean = false, @@ -123,7 +124,7 @@ internal fun ThreadTopBarPreview() = ElementPreview { HorizontalDivider() AThreadTopBar( roomAvatarData = anAvatarData( - name = "Room name", + name = ROOM_NAME, url = "https://some-avatar.jpg", size = AvatarSize.TimelineRoom, ), diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt index 13f69a7e1e..2f238f9935 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.preferences.impl.user.editprofile import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.designsystem.preview.USER_NAME_JOHN_DOE import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.permissions.api.PermissionsState @@ -28,7 +29,7 @@ open class EditUserProfileStateProvider : PreviewParameterProvider = emptyList(), saveButtonEnabled: Boolean = true, diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileHeaderSection.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileHeaderSection.kt index ac146a36a7..5ba0280b14 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileHeaderSection.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileHeaderSection.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.niceClickable import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.theme.components.ButtonSize import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text @@ -140,7 +141,7 @@ internal fun UserProfileHeaderSectionPreview() = ElementPreview { UserProfileHeaderSection( avatarUrl = null, userId = UserId("@alice:example.com"), - userName = "Alice", + userName = USER_NAME_ALICE, verificationState = UserProfileVerificationState.VERIFIED, openAvatarPreview = {}, onUserIdClick = {}, @@ -154,7 +155,7 @@ internal fun UserProfileHeaderSectionWithVerificationViolationPreview() = Elemen UserProfileHeaderSection( avatarUrl = null, userId = UserId("@alice:example.com"), - userName = "Alice", + userName = USER_NAME_ALICE, verificationState = UserProfileVerificationState.VERIFICATION_VIOLATION, openAvatarPreview = {}, onUserIdClick = {}, diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationUserProfileContent.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationUserProfileContent.kt index edaadc583d..c398d72ddd 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationUserProfileContent.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/ui/VerificationUserProfileContent.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.matrix.api.core.UserId @@ -86,7 +87,7 @@ internal fun VerificationUserProfileContentPreview() = ElementPreview( VerificationUserProfileContent( user = MatrixUser( userId = UserId("@alice:example.com"), - displayName = "Alice", + displayName = USER_NAME_ALICE, avatarUrl = "https://example.com/avatar.png", ) ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt index 9e783d605c..4940f2f965 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LocationPin.kt @@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData 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.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.utils.CommonDrawables private val PIN_WIDTH = 42.dp @@ -395,7 +396,7 @@ private object LocationPinRenderer { internal fun LocationPinPreview() = ElementPreview { val sampleAvatarData = AvatarData( id = "@alice:matrix.org", - name = "Alice", + name = USER_NAME_ALICE, url = null, size = AvatarSize.SelectedUser ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt index c5b870507b..f19796e053 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt @@ -29,6 +29,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.LayoutDirection import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup +import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.designsystem.text.toPx import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag @@ -116,12 +118,12 @@ internal fun DmAvatarsPreview() = ElementThemedPreview { DmAvatars( userAvatarData = anAvatarData( id = "Alice", - name = "Alice", + name = USER_NAME_ALICE, size = size, ), otherUserAvatarData = anAvatarData( id = "Bob", - name = "Bob", + name = USER_NAME_BOB, size = size, ), openAvatarPreview = {}, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/InviteSenderView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/InviteSenderView.kt index 13747a1a3d..12fa54add1 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/InviteSenderView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/InviteSenderView.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.ui.model.InviteSender @@ -57,10 +58,10 @@ internal fun InviteSenderViewPreview() = ElementPreview { InviteSenderView( inviteSender = InviteSender( userId = UserId("@bob:example.com"), - displayName = "Bob", + displayName = USER_NAME_BOB, avatarData = AvatarData( id = "@bob:example.com", - name = "Bob", + name = USER_NAME_BOB, url = null, size = AvatarSize.InviteSender, ), diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/OrganizationHeader.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/OrganizationHeader.kt index 374ebd7a1a..0a1e3bdc87 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/OrganizationHeader.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/OrganizationHeader.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.SPACE_NAME /** * Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=3643-2048&m=dev @@ -72,7 +73,7 @@ internal fun OrganizationHeaderPreview() = ElementPreview { url = "anUrl", size = AvatarSize.OrganizationHeader, ), - name = "Space name", + name = SPACE_NAME, numberOfSpaces = 9, numberOfRooms = 88, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt index 97aa6ea613..7aee62902f 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SpaceHeaderView.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.SPACE_NAME import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.designsystem.preview.USER_NAME_BOB import io.element.android.libraries.designsystem.preview.USER_NAME_CHARLIE @@ -119,7 +120,7 @@ internal fun SpaceHeaderViewPreview() = ElementPreview { size = AvatarSize.SpaceHeader, ), alias = RoomAlias("#spaceAlias:matrix.org"), - name = "Space name", + name = SPACE_NAME, topic = "Space topic: " + LoremIpsum(40).values.first(), topicMaxLines = 2, visibility = SpaceRoomVisibility.Public, From 861de339d8360da99ccfcb0fdceb9d916e779a65 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 7 May 2026 08:43:48 +0000 Subject: [PATCH 0361/1083] Update screenshots --- ...ponents.virtual_TimelineItemRoomBeginningView_Day_0_en.png | 4 ++-- ...nents.virtual_TimelineItemRoomBeginningView_Night_0_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_1_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_1_en.png | 4 ++-- ...eatures.preferences.impl.user_UserPreferences_Day_1_en.png | 4 ++-- ...tures.preferences.impl.user_UserPreferences_Night_1_en.png | 4 ++-- ...braries.matrix.ui.components_MatrixUserHeader_Day_1_en.png | 4 ++-- ...aries.matrix.ui.components_MatrixUserHeader_Night_1_en.png | 4 ++-- .../libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png | 4 ++-- ...ibraries.matrix.ui.components_MatrixUserRow_Night_1_en.png | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en.png index 5815548686..8d62522c1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abc1526f441c218d39e44ef3f146d4fee3bbb0628c4ece25fb2ae4ef7e4100b0 -size 48820 +oid sha256:13573edc4f14581b14a0238a66b6fdc040ccc02d49cd670c5e0ec1eb78b61bed +size 48621 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en.png index e01465633c..c61ea59d37 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20c52bb8f44c186d3104d457c5de9c0597d99f0a5be37a9d8680fb4be35d422f -size 53777 +oid sha256:d3153640c7d5f5be8bc66424cce167c44f48497bf5d91a25963a1e2d5e506d6f +size 53643 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 3ad13553de..b04da30f28 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:be4cbe72c73d76252f902e122bd62ba51ff89cf2cb20ddd61ed6615e983c65cf -size 25153 +oid sha256:0a6ddec2c9743976674657e454cb14bb479d774f1aa13882a34ceb89ff75b179 +size 24424 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 933a646f6b..a2d4d1b036 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:8d3a7ae9522da2911bf256273a4972020fc1677f026fbb9f17d27f549ab03ea3 -size 25978 +oid sha256:fa1a7c175f6551680b1a71ddaac14014f6503ccc2928d4ad97eced8a80626ed4 +size 25158 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 74bc9743d7..3a1ad156a2 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:b61c5a72e8e63a1775d20717c78d8e68e46c7c22b8e4ab8c24154dc3d48d7d0e -size 11428 +oid sha256:33482ad6e5033800e911dab44d4ba5bec15cfa58749102c5da4e2c57a8e760e8 +size 9783 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 9413b91e88..81d4ceda60 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:da4e1512cd7a58ede774755b6e3ac427e90c437bbbadaea8479506af776999c3 -size 11323 +oid sha256:e39bc143f7ee45c47ff57bfb53a773d7df2ba14568a9368643d8bab9dbbf4955 +size 9675 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 74bc9743d7..3a1ad156a2 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:b61c5a72e8e63a1775d20717c78d8e68e46c7c22b8e4ab8c24154dc3d48d7d0e -size 11428 +oid sha256:33482ad6e5033800e911dab44d4ba5bec15cfa58749102c5da4e2c57a8e760e8 +size 9783 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 9413b91e88..81d4ceda60 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:da4e1512cd7a58ede774755b6e3ac427e90c437bbbadaea8479506af776999c3 -size 11323 +oid sha256:e39bc143f7ee45c47ff57bfb53a773d7df2ba14568a9368643d8bab9dbbf4955 +size 9675 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png index 10d4beffb9..5174fbe9bf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a992addeb8525c7df4be04514c82e22c8c1269d7c14aa25497efaac50e844a8 -size 9410 +oid sha256:00a060c5b66ee6febd8bfe145548aa3b2fa43ed0852e4224ab08a4641cfdc6b5 +size 8075 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png index 38dc8e36ba..fa48ce852e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07b7d5515f0ca6e6634e8ff4b53c73f48b1170fe8d2488c7a8863d1568c52cdf -size 9420 +oid sha256:d23f245942d6353707c4252a05935b9d59a5a8ef380f351d0341b804413969ca +size 8101 From 61374bca4ef4b53f6fa048fc592f39879e1d0651 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 May 2026 18:24:25 +0200 Subject: [PATCH 0362/1083] Improve detection of configure PIN code. --- .../impl/biometric/BiometricAuthenticator.kt | 8 +++--- .../impl/pin/DefaultPinCodeManager.kt | 5 ++-- .../impl/storage/EncryptedPinCodeStorage.kt | 7 ----- .../storage/PreferencesLockScreenStore.kt | 6 ----- .../impl/DefaultLockScreenServiceTest.kt | 19 ++++++++----- .../biometric/FakeBiometricAuthenticator.kt | 2 +- .../pin/storage/InMemoryLockScreenStore.kt | 9 ------- libraries/cryptography/api/build.gradle.kts | 4 +++ .../cryptography/api/SecretKeyRepository.kt | 7 +++-- libraries/cryptography/impl/build.gradle.kts | 1 + .../impl/KeyStoreSecretKeyRepository.kt | 27 ++++++++++++++++--- libraries/cryptography/test/build.gradle.kts | 1 + .../test/SimpleSecretKeyRepository.kt | 25 ++++++++++++++--- 13 files changed, 77 insertions(+), 44 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt index a96c713ff2..d18d9b73b7 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt @@ -36,13 +36,13 @@ interface BiometricAuthenticator { } val isActive: Boolean - fun setup() + suspend fun setup() suspend fun authenticate(): AuthenticationResult } class NoopBiometricAuthentication : BiometricAuthenticator { override val isActive: Boolean = false - override fun setup() = Unit + override suspend fun setup() = Unit override suspend fun authenticate() = BiometricAuthenticator.AuthenticationResult.Failure() } @@ -58,7 +58,7 @@ class DefaultBiometricAuthentication( private var cryptoObject: CryptoObject? = null - override fun setup() { + override suspend fun setup() { try { val secretKey = ensureKey() val cipher = encryptionDecryptionService.createEncryptionCipher(secretKey) @@ -86,7 +86,7 @@ class DefaultBiometricAuthentication( } @Throws(KeyPermanentlyInvalidatedException::class) - private fun ensureKey() = secretKeyRepository.getOrCreateKey(keyAlias, true).also { + private suspend fun ensureKey() = secretKeyRepository.getOrCreateKey(keyAlias, true).also { encryptionDecryptionService.createEncryptionCipher(it) } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt index 091432044a..9a646461fa 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt @@ -18,7 +18,7 @@ import io.element.android.libraries.cryptography.api.SecretKeyRepository import kotlinx.coroutines.flow.Flow import java.util.concurrent.CopyOnWriteArrayList -private const val SECRET_KEY_ALIAS = "elementx.SECRET_KEY_ALIAS_PIN_CODE" +internal const val SECRET_KEY_ALIAS = "elementx.SECRET_KEY_ALIAS_PIN_CODE" @ContributesBinding(AppScope::class) @SingleIn(AppScope::class) @@ -38,7 +38,7 @@ class DefaultPinCodeManager( } override fun hasPinCode(): Flow { - return lockScreenStore.hasPinCode() + return secretKeyRepository.hasKey(SECRET_KEY_ALIAS) } override suspend fun getPinCodeSize(): Int { @@ -79,6 +79,7 @@ class DefaultPinCodeManager( override suspend fun deletePinCode() { lockScreenStore.deleteEncryptedPinCode() lockScreenStore.resetCounter() + secretKeyRepository.deleteKey(SECRET_KEY_ALIAS) callbacks.forEach { it.onPinCodeRemoved() } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt index c4558812de..b41e6a9578 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt @@ -8,8 +8,6 @@ package io.element.android.features.lockscreen.impl.storage -import kotlinx.coroutines.flow.Flow - /** * Should be implemented by any class that provides access to the encrypted PIN code. * All methods are suspending in case there are async IO operations involved. @@ -29,9 +27,4 @@ interface EncryptedPinCodeStorage { * Deletes the PIN code from some persistable storage. */ suspend fun deleteEncryptedPinCode() - - /** - * Returns whether the PIN code is stored or not. - */ - fun hasPinCode(): Flow } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt index 6b99d90592..98435f962d 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt @@ -70,12 +70,6 @@ class PreferencesLockScreenStore( } } - override fun hasPinCode(): Flow { - return dataStore.data.map { preferences -> - preferences[pinCodeKey] != null - } - } - override fun isBiometricUnlockAllowed(): Flow { return dataStore.data.map { preferences -> preferences[biometricUnlockKey] ?: false diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt index 9082f20a55..f906d0d6ba 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt @@ -14,9 +14,12 @@ import io.element.android.features.lockscreen.impl.biometric.BiometricAuthentica import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthenticatorManager import io.element.android.features.lockscreen.impl.fixtures.aLockScreenConfig import io.element.android.features.lockscreen.impl.pin.PinCodeManager +import io.element.android.features.lockscreen.impl.pin.SECRET_KEY_ALIAS import io.element.android.features.lockscreen.impl.pin.createDefaultPinCodeManager import io.element.android.features.lockscreen.impl.pin.storage.InMemoryLockScreenStore import io.element.android.features.lockscreen.impl.storage.LockScreenStore +import io.element.android.libraries.cryptography.api.SecretKeyRepository +import io.element.android.libraries.cryptography.test.SimpleSecretKeyRepository import io.element.android.libraries.sessionstorage.api.observer.SessionObserver import io.element.android.libraries.sessionstorage.test.observer.FakeSessionObserver import io.element.android.services.appnavstate.api.AppForegroundStateService @@ -38,18 +41,18 @@ class DefaultLockScreenServiceTest { @Test fun `when the pin is mandatory, isSetupRequired emits true`() = runTest { - val lockScreenStore = InMemoryLockScreenStore() + val secretKeyRepository = SimpleSecretKeyRepository() val sut = createDefaultLockScreenService( lockScreenConfig = aLockScreenConfig(isPinMandatory = true), - lockScreenStore = lockScreenStore, + secretKeyRepository = secretKeyRepository, ) sut.isSetupRequired().test { assertThat(awaitItem()).isTrue() // When the user configures the pin code, the setup is not required anymore - lockScreenStore.saveEncryptedPinCode("encryptedCode") + secretKeyRepository.getOrCreateKey(SECRET_KEY_ALIAS, true) assertThat(awaitItem()).isFalse() // Users deletes the pin code - lockScreenStore.deleteEncryptedPinCode() + secretKeyRepository.deleteKey("elementx.SECRET_KEY_ALIAS_PIN_CODE") assertThat(awaitItem()).isTrue() } } @@ -57,16 +60,16 @@ class DefaultLockScreenServiceTest { @Test fun `when the last session is deleted, the pin code is removed`() = runTest { val sessionObserver = FakeSessionObserver() - val lockScreenStore = InMemoryLockScreenStore() + val secretKeyRepository = SimpleSecretKeyRepository() val sut = createDefaultLockScreenService( lockScreenConfig = aLockScreenConfig(isPinMandatory = true), - lockScreenStore = lockScreenStore, + secretKeyRepository = secretKeyRepository, sessionObserver = sessionObserver, ) sut.isPinSetup().test { assertThat(awaitItem()).isFalse() // When the user configure the pin code, the setup is not required anymore - lockScreenStore.saveEncryptedPinCode("encryptedCode") + secretKeyRepository.getOrCreateKey(SECRET_KEY_ALIAS, true) assertThat(awaitItem()).isTrue() sessionObserver.onSessionDeleted("userId", wasLastSession = false) expectNoEvents() @@ -79,8 +82,10 @@ class DefaultLockScreenServiceTest { private fun TestScope.createDefaultLockScreenService( lockScreenConfig: LockScreenConfig = aLockScreenConfig(), lockScreenStore: LockScreenStore = InMemoryLockScreenStore(), + secretKeyRepository: SecretKeyRepository = SimpleSecretKeyRepository(), pinCodeManager: PinCodeManager = createDefaultPinCodeManager( lockScreenStore = lockScreenStore, + secretKeyRepository = secretKeyRepository, ), sessionObserver: SessionObserver = FakeSessionObserver(), appForegroundStateService: AppForegroundStateService = FakeAppForegroundStateService(), diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt index 073bdc799d..63729f941a 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt @@ -12,6 +12,6 @@ class FakeBiometricAuthenticator( override val isActive: Boolean = false, private val authenticateLambda: suspend () -> BiometricAuthenticator.AuthenticationResult = { BiometricAuthenticator.AuthenticationResult.Success }, ) : BiometricAuthenticator { - override fun setup() = Unit + override suspend fun setup() = Unit override suspend fun authenticate() = authenticateLambda() } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt index 61acf71cdd..312a33b7f1 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt @@ -15,12 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow private const val DEFAULT_REMAINING_ATTEMPTS = 3 class InMemoryLockScreenStore : LockScreenStore { - private val hasPinCode = MutableStateFlow(false) private var pinCode: String? = null - set(value) { - field = value - hasPinCode.value = value != null - } private var remainingAttempts: Int = DEFAULT_REMAINING_ATTEMPTS private var isBiometricUnlockAllowed = MutableStateFlow(false) @@ -48,10 +43,6 @@ class InMemoryLockScreenStore : LockScreenStore { pinCode = null } - override fun hasPinCode(): Flow { - return hasPinCode - } - override fun isBiometricUnlockAllowed(): Flow { return isBiometricUnlockAllowed } diff --git a/libraries/cryptography/api/build.gradle.kts b/libraries/cryptography/api/build.gradle.kts index 9ce26419d8..74fc5f6ecc 100644 --- a/libraries/cryptography/api/build.gradle.kts +++ b/libraries/cryptography/api/build.gradle.kts @@ -13,3 +13,7 @@ plugins { android { namespace = "io.element.android.libraries.cryptography.api" } + +dependencies { + implementation(libs.coroutines.core) +} diff --git a/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt b/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt index ba6c10dbe0..b210664d9f 100644 --- a/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt +++ b/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.cryptography.api +import kotlinx.coroutines.flow.Flow import javax.crypto.SecretKey /** @@ -15,16 +16,18 @@ import javax.crypto.SecretKey * Implementation should be able to store the generated key securely. */ interface SecretKeyRepository { + fun hasKey(alias: String): Flow + /** * Get or create a secret key for a given alias. * @param alias the alias to use * @param requiresUserAuthentication true if the key should be protected by user authentication */ - fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey + suspend fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey /** * Delete the secret key for a given alias. * @param alias the alias to use */ - fun deleteKey(alias: String) + suspend fun deleteKey(alias: String) } diff --git a/libraries/cryptography/impl/build.gradle.kts b/libraries/cryptography/impl/build.gradle.kts index 454432de6f..3a1f55126e 100644 --- a/libraries/cryptography/impl/build.gradle.kts +++ b/libraries/cryptography/impl/build.gradle.kts @@ -21,6 +21,7 @@ setupDependencyInjection() dependencies { implementation(projects.libraries.di) + implementation(libs.coroutines.core) api(projects.libraries.cryptography.api) testCommonDependencies(libs) diff --git a/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt b/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt index 46572ef047..dccba2a136 100644 --- a/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt +++ b/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt @@ -13,11 +13,16 @@ import android.security.keystore.KeyGenParameterSpec import android.security.keystore.KeyProperties import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn import io.element.android.libraries.cryptography.api.AESEncryptionSpecs import io.element.android.libraries.cryptography.api.SecretKeyRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import timber.log.Timber import java.security.KeyStore import java.security.KeyStoreException +import java.util.concurrent.ConcurrentHashMap import javax.crypto.KeyGenerator import javax.crypto.SecretKey @@ -25,13 +30,22 @@ import javax.crypto.SecretKey * Default implementation of [SecretKeyRepository] that uses the Android Keystore to store the keys. * The generated key uses AES algorithm, with a key size of 128 bits, and the GCM block mode. */ +@SingleIn(AppScope::class) @ContributesBinding(AppScope::class) class KeyStoreSecretKeyRepository( private val keyStore: KeyStore, ) : SecretKeyRepository { + private val hasKeyMap = ConcurrentHashMap>() + + override fun hasKey(alias: String): Flow { + return hasKeyMap.getOrPut(alias) { + MutableStateFlow(runCatching { keyStore.containsAlias(alias) }.getOrDefault(false)) + }.asStateFlow() + } + // False positive lint issue @SuppressLint("WrongConstant") - override fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { + override suspend fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { val secretKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.SecretKeyEntry) ?.secretKey return if (secretKeyEntry == null) { @@ -46,15 +60,22 @@ class KeyStoreSecretKeyRepository( .setUserAuthenticationRequired(requiresUserAuthentication) .build() generator.init(keyGenSpec) - generator.generateKey() + generator.generateKey().also { + hasKeyMap.getOrPut(alias) { + MutableStateFlow(true) + }.emit(true) + } } else { secretKeyEntry } } - override fun deleteKey(alias: String) { + override suspend fun deleteKey(alias: String) { try { keyStore.deleteEntry(alias) + hasKeyMap.getOrPut(alias) { + MutableStateFlow(false) + }.emit(false) } catch (e: KeyStoreException) { Timber.e(e) } diff --git a/libraries/cryptography/test/build.gradle.kts b/libraries/cryptography/test/build.gradle.kts index eaa621d53a..5cf04a9754 100644 --- a/libraries/cryptography/test/build.gradle.kts +++ b/libraries/cryptography/test/build.gradle.kts @@ -16,4 +16,5 @@ android { dependencies { api(projects.libraries.cryptography.api) + implementation(libs.coroutines.core) } diff --git a/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt b/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt index 0e301553ea..507325f45b 100644 --- a/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt +++ b/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt @@ -10,20 +10,39 @@ package io.element.android.libraries.cryptography.test import io.element.android.libraries.cryptography.api.AESEncryptionSpecs import io.element.android.libraries.cryptography.api.SecretKeyRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import java.util.concurrent.ConcurrentHashMap import javax.crypto.KeyGenerator import javax.crypto.SecretKey class SimpleSecretKeyRepository : SecretKeyRepository { private var secretKeyForAlias = HashMap() - override fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { + private val hasKeyMap = ConcurrentHashMap>() + + override fun hasKey(alias: String): Flow { + return hasKeyMap.getOrPut(alias) { + MutableStateFlow(false) + }.asStateFlow() + } + + override suspend fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { return secretKeyForAlias.getOrPut(alias) { - generateKey() + generateKey().also { + hasKeyMap.getOrPut(alias) { + MutableStateFlow(true) + }.emit(true) + } } } - override fun deleteKey(alias: String) { + override suspend fun deleteKey(alias: String) { secretKeyForAlias.remove(alias) + hasKeyMap.getOrPut(alias) { + MutableStateFlow(false) + }.emit(false) } private fun generateKey(): SecretKey { From 8799dda4719ecfac931e57cee7bf8c57203c9bf1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 10:36:00 +0200 Subject: [PATCH 0363/1083] Force sign out if PIN code store is corrupted. --- .../lockscreen/impl/pin/DefaultPinCodeManager.kt | 4 ++-- .../features/lockscreen/impl/pin/PinCodeManager.kt | 4 ++-- .../lockscreen/impl/unlock/PinUnlockPresenter.kt | 8 +++++++- .../features/lockscreen/impl/unlock/PinUnlockState.kt | 10 +++++++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt index 9a646461fa..2bda5759a8 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt @@ -41,8 +41,8 @@ class DefaultPinCodeManager( return secretKeyRepository.hasKey(SECRET_KEY_ALIAS) } - override suspend fun getPinCodeSize(): Int { - val encryptedPinCode = lockScreenStore.getEncryptedCode() ?: return 0 + override suspend fun getPinCodeSize(): Int? { + val encryptedPinCode = lockScreenStore.getEncryptedCode() ?: return null val secretKey = secretKeyRepository.getOrCreateKey(SECRET_KEY_ALIAS, false) val decryptedPinCode = encryptionDecryptionService.decrypt(secretKey, EncryptionResult.fromBase64(encryptedPinCode)) return decryptedPinCode.size diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt index 9282f3e7df..350631a233 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt @@ -51,9 +51,9 @@ interface PinCodeManager { fun hasPinCode(): Flow /** - * @return the size of the saved pin code. + * @return the size of the saved pin code. Return null if no pin code is saved. */ - suspend fun getPinCodeSize(): Int + suspend fun getPinCodeSize(): Int? /** * Creates a new encrypted pin code. diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt index 5429320fc7..05b4dbfe72 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt @@ -69,7 +69,13 @@ class PinUnlockPresenter( LaunchedEffect(Unit) { suspend { val pinCodeSize = pinCodeManager.getPinCodeSize() - PinEntry.createEmpty(pinCodeSize) + if (pinCodeSize == null) { + // No pin code set, deleted store? Force sign out + showSignOutPrompt = true + throw Exception("No pin code size found") + } else { + PinEntry.createEmpty(pinCodeSize) + } }.runCatchingUpdatingState(pinEntryState) } LaunchedEffect(biometricUnlock) { diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt index 2bbcbe335c..50d03045ab 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt @@ -25,9 +25,13 @@ data class PinUnlockState( val biometricUnlockResult: BiometricAuthenticator.AuthenticationResult?, val eventSink: (PinUnlockEvents) -> Unit ) { - val isSignOutPromptCancellable = when (remainingAttempts) { - is AsyncData.Success -> remainingAttempts.data > 0 - else -> true + val isSignOutPromptCancellable = if (pinEntry.isFailure()) { + false + } else { + when (remainingAttempts) { + is AsyncData.Success -> remainingAttempts.data > 0 + else -> true + } } val biometricUnlockErrorMessage = when { From 94d37c68d5559277bf932735d357ce93614e282d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 10:38:59 +0200 Subject: [PATCH 0364/1083] Use test extension. --- .../biometric/SetupBiometricPresenterTest.kt | 16 ++++------------ .../impl/setup/pin/SetupPinPresenterTest.kt | 8 ++------ .../impl/unlock/PinUnlockPresenterTest.kt | 16 ++++------------ 3 files changed, 10 insertions(+), 30 deletions(-) diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt index 3f87c1dccf..458cd295f6 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.lockscreen.impl.setup.biometric -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticator import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticatorManager @@ -18,6 +15,7 @@ import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthen import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthenticatorManager import io.element.android.features.lockscreen.impl.pin.storage.InMemoryLockScreenStore import io.element.android.features.lockscreen.impl.storage.LockScreenStore +import io.element.android.tests.testutils.test import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.Test @@ -30,9 +28,7 @@ class SetupBiometricPresenterTest { FakeBiometricAuthenticator(authenticateLambda = { BiometricAuthenticator.AuthenticationResult.Success }) }) val presenter = createSetupBiometricPresenter(lockScreenStore, fakeBiometricAuthenticatorManager) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() state.eventSink(SetupBiometricEvents.AllowBiometric) @@ -51,9 +47,7 @@ class SetupBiometricPresenterTest { FakeBiometricAuthenticator(authenticateLambda = { BiometricAuthenticator.AuthenticationResult.Failure() }) }) val presenter = createSetupBiometricPresenter(lockScreenStore, fakeBiometricAuthenticatorManager) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() state.eventSink(SetupBiometricEvents.AllowBiometric) @@ -66,9 +60,7 @@ class SetupBiometricPresenterTest { fun `present - skip flow`() = runTest { val lockScreenStore = InMemoryLockScreenStore() val presenter = createSetupBiometricPresenter(lockScreenStore) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() state.eventSink(SetupBiometricEvents.UsePin) diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt index 6a1d32e879..46591eb2af 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.lockscreen.impl.setup.pin -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.impl.LockScreenConfig import io.element.android.features.lockscreen.impl.fixtures.aLockScreenConfig @@ -24,6 +21,7 @@ import io.element.android.features.lockscreen.impl.setup.pin.validation.SetupPin import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.tests.testutils.awaitLastSequentialItem import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.test import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.test.runTest import org.junit.Test @@ -43,9 +41,7 @@ class SetupPinPresenterTest { } } val presenter = createSetupPinPresenter(callback) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> state.choosePinEntry.assertEmpty() state.confirmPinEntry.assertEmpty() diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt index f5bfb11818..197f45f0f8 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.lockscreen.impl.unlock -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticatorManager import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthenticatorManager @@ -25,6 +22,7 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -36,9 +34,7 @@ class PinUnlockPresenterTest { @Test fun `present - success verify flow`() = runTest { val presenter = createPinUnlockPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Uninitialized::class.java) assertThat(state.showWrongPinTitle).isFalse() @@ -73,9 +69,7 @@ class PinUnlockPresenterTest { @Test fun `present - failure verify flow`() = runTest { val presenter = createPinUnlockPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) @@ -102,9 +96,7 @@ class PinUnlockPresenterTest { val signOutLambda = lambdaRecorder {} val signOut = FakeLogoutUseCase(signOutLambda) val presenter = createPinUnlockPresenter(logoutUseCase = signOut) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) From bc60512e102da8544d0eaa5f4d44a1dfafd17fd6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 10:39:52 +0200 Subject: [PATCH 0365/1083] `LockScreenSettingsEvents` -> `LockScreenSettingsEvent` --- ...ettingsEvents.kt => LockScreenSettingsEvent.kt} | 10 +++++----- .../impl/settings/LockScreenSettingsPresenter.kt | 10 +++++----- .../impl/settings/LockScreenSettingsState.kt | 2 +- .../impl/settings/LockScreenSettingsView.kt | 8 ++++---- .../settings/LockScreenSettingsPresenterTest.kt | 14 +++++++------- 5 files changed, 22 insertions(+), 22 deletions(-) rename features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/{LockScreenSettingsEvents.kt => LockScreenSettingsEvent.kt} (62%) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvent.kt similarity index 62% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvent.kt index 2d62427e02..c7437912eb 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvent.kt @@ -8,9 +8,9 @@ package io.element.android.features.lockscreen.impl.settings -sealed interface LockScreenSettingsEvents { - data object OnRemovePin : LockScreenSettingsEvents - data object ConfirmRemovePin : LockScreenSettingsEvents - data object CancelRemovePin : LockScreenSettingsEvents - data object ToggleBiometricAllowed : LockScreenSettingsEvents +sealed interface LockScreenSettingsEvent { + data object OnRemovePin : LockScreenSettingsEvent + data object ConfirmRemovePin : LockScreenSettingsEvent + data object CancelRemovePin : LockScreenSettingsEvent + data object ToggleBiometricAllowed : LockScreenSettingsEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt index 589794bde0..83a0253f39 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt @@ -51,10 +51,10 @@ class LockScreenSettingsPresenter( val biometricUnlock = biometricAuthenticatorManager.rememberConfirmBiometricAuthenticator() - fun handleEvent(event: LockScreenSettingsEvents) { + fun handleEvent(event: LockScreenSettingsEvent) { when (event) { - LockScreenSettingsEvents.CancelRemovePin -> showRemovePinConfirmation = false - LockScreenSettingsEvents.ConfirmRemovePin -> { + LockScreenSettingsEvent.CancelRemovePin -> showRemovePinConfirmation = false + LockScreenSettingsEvent.ConfirmRemovePin -> { coroutineScope.launch { if (showRemovePinConfirmation) { showRemovePinConfirmation = false @@ -62,8 +62,8 @@ class LockScreenSettingsPresenter( } } } - LockScreenSettingsEvents.OnRemovePin -> showRemovePinConfirmation = true - LockScreenSettingsEvents.ToggleBiometricAllowed -> { + LockScreenSettingsEvent.OnRemovePin -> showRemovePinConfirmation = true + LockScreenSettingsEvent.ToggleBiometricAllowed -> { coroutineScope.launch { if (!isBiometricEnabled) { biometricUnlock.setup() diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt index a69d633508..62b8d6d4ee 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt @@ -13,5 +13,5 @@ data class LockScreenSettingsState( val isBiometricEnabled: Boolean, val showRemovePinConfirmation: Boolean, val showToggleBiometric: Boolean, - val eventSink: (LockScreenSettingsEvents) -> Unit + val eventSink: (LockScreenSettingsEvent) -> Unit ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt index fe5f20da0d..e78a5ee002 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt @@ -51,7 +51,7 @@ fun LockScreenSettingsView( }, style = ListItemStyle.Destructive, onClick = { - state.eventSink(LockScreenSettingsEvents.OnRemovePin) + state.eventSink(LockScreenSettingsEvent.OnRemovePin) } ) } @@ -61,7 +61,7 @@ fun LockScreenSettingsView( title = stringResource(id = R.string.screen_app_lock_settings_enable_biometric_unlock), isChecked = state.isBiometricEnabled, onCheckedChange = { - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } ) } @@ -72,10 +72,10 @@ fun LockScreenSettingsView( title = stringResource(id = R.string.screen_app_lock_settings_remove_pin_alert_title), content = stringResource(id = R.string.screen_app_lock_settings_remove_pin_alert_message), onSubmitClick = { - state.eventSink(LockScreenSettingsEvents.ConfirmRemovePin) + state.eventSink(LockScreenSettingsEvent.ConfirmRemovePin) }, onDismiss = { - state.eventSink(LockScreenSettingsEvents.CancelRemovePin) + state.eventSink(LockScreenSettingsEvent.CancelRemovePin) } ) } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt index ef3e94f27f..85eb4a37e7 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt @@ -43,19 +43,19 @@ class LockScreenSettingsPresenterTest { consumeItemsUntilPredicate { state -> state.showRemovePinOption }.last().also { state -> - state.eventSink(LockScreenSettingsEvents.OnRemovePin) + state.eventSink(LockScreenSettingsEvent.OnRemovePin) } awaitLastSequentialItem().also { state -> assertThat(state.showRemovePinConfirmation).isTrue() - state.eventSink(LockScreenSettingsEvents.CancelRemovePin) + state.eventSink(LockScreenSettingsEvent.CancelRemovePin) } awaitLastSequentialItem().also { state -> assertThat(state.showRemovePinConfirmation).isFalse() - state.eventSink(LockScreenSettingsEvents.OnRemovePin) + state.eventSink(LockScreenSettingsEvent.OnRemovePin) } awaitLastSequentialItem().also { state -> assertThat(state.showRemovePinConfirmation).isTrue() - state.eventSink(LockScreenSettingsEvents.ConfirmRemovePin) + state.eventSink(LockScreenSettingsEvent.ConfirmRemovePin) } consumeItemsUntilPredicate { it.showRemovePinOption.not() @@ -93,7 +93,7 @@ class LockScreenSettingsPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } awaitItem().also { state -> assertThat(state.isBiometricEnabled).isTrue() @@ -114,7 +114,7 @@ class LockScreenSettingsPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } } } @@ -137,7 +137,7 @@ class LockScreenSettingsPresenterTest { skipItems(1) awaitItem().also { state -> assertThat(state.isBiometricEnabled).isTrue() - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } awaitItem().also { state -> assertThat(state.isBiometricEnabled).isFalse() From 90918cbb9dba1f6124c569f8fc58125b0de36144 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 10:40:14 +0200 Subject: [PATCH 0366/1083] `SetupBiometricEvents` -> `SetupBiometricEvent` --- .../{SetupBiometricEvents.kt => SetupBiometricEvent.kt} | 6 +++--- .../impl/setup/biometric/SetupBiometricPresenter.kt | 6 +++--- .../lockscreen/impl/setup/biometric/SetupBiometricState.kt | 2 +- .../lockscreen/impl/setup/biometric/SetupBiometricView.kt | 6 +++--- .../impl/setup/biometric/SetupBiometricPresenterTest.kt | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) rename features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/{SetupBiometricEvents.kt => SetupBiometricEvent.kt} (68%) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvent.kt similarity index 68% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvent.kt index ab8b18642e..d4db46b731 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvent.kt @@ -8,7 +8,7 @@ package io.element.android.features.lockscreen.impl.setup.biometric -sealed interface SetupBiometricEvents { - data object AllowBiometric : SetupBiometricEvents - data object UsePin : SetupBiometricEvents +sealed interface SetupBiometricEvent { + data object AllowBiometric : SetupBiometricEvent + data object UsePin : SetupBiometricEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt index 3af2a28851..ce914320bc 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt @@ -35,16 +35,16 @@ class SetupBiometricPresenter( val coroutineScope = rememberCoroutineScope() val biometricUnlock = biometricAuthenticatorManager.rememberConfirmBiometricAuthenticator() - fun handleEvent(event: SetupBiometricEvents) { + fun handleEvent(event: SetupBiometricEvent) { when (event) { - SetupBiometricEvents.AllowBiometric -> coroutineScope.launch { + SetupBiometricEvent.AllowBiometric -> coroutineScope.launch { biometricUnlock.setup() if (biometricUnlock.authenticate() == BiometricAuthenticator.AuthenticationResult.Success) { lockScreenStore.setIsBiometricUnlockAllowed(true) isBiometricSetupDone = true } } - SetupBiometricEvents.UsePin -> coroutineScope.launch { + SetupBiometricEvent.UsePin -> coroutineScope.launch { lockScreenStore.setIsBiometricUnlockAllowed(false) isBiometricSetupDone = true } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt index 2843c028d1..db11b1dc30 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt @@ -10,5 +10,5 @@ package io.element.android.features.lockscreen.impl.setup.biometric data class SetupBiometricState( val isBiometricSetupDone: Boolean, - val eventSink: (SetupBiometricEvents) -> Unit + val eventSink: (SetupBiometricEvent) -> Unit ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt index 35b1ec76c0..70a1046e36 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt @@ -33,7 +33,7 @@ fun SetupBiometricView( modifier: Modifier = Modifier, ) { BackHandler { - state.eventSink(SetupBiometricEvents.UsePin) + state.eventSink(SetupBiometricEvent.UsePin) } HeaderFooterPage( modifier = modifier.padding(top = 80.dp), @@ -42,8 +42,8 @@ fun SetupBiometricView( }, footer = { SetupBiometricFooter( - onAllowClick = { state.eventSink(SetupBiometricEvents.AllowBiometric) }, - onSkipClick = { state.eventSink(SetupBiometricEvents.UsePin) } + onAllowClick = { state.eventSink(SetupBiometricEvent.AllowBiometric) }, + onSkipClick = { state.eventSink(SetupBiometricEvent.UsePin) } ) }, ) diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt index 458cd295f6..9dde220906 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt @@ -31,7 +31,7 @@ class SetupBiometricPresenterTest { presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() - state.eventSink(SetupBiometricEvents.AllowBiometric) + state.eventSink(SetupBiometricEvent.AllowBiometric) } awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isTrue() @@ -50,7 +50,7 @@ class SetupBiometricPresenterTest { presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() - state.eventSink(SetupBiometricEvents.AllowBiometric) + state.eventSink(SetupBiometricEvent.AllowBiometric) } } assertThat(lockScreenStore.isBiometricUnlockAllowed().first()).isFalse() @@ -63,7 +63,7 @@ class SetupBiometricPresenterTest { presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() - state.eventSink(SetupBiometricEvents.UsePin) + state.eventSink(SetupBiometricEvent.UsePin) } awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isTrue() From 668b03f8bc8e24754f4c97fd58b7b009a132927d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 10:40:32 +0200 Subject: [PATCH 0367/1083] `SetupPinEvents` -> `SetupPinEvent` --- .../impl/setup/pin/{SetupPinEvents.kt => SetupPinEvent.kt} | 6 +++--- .../features/lockscreen/impl/setup/pin/SetupPinPresenter.kt | 6 +++--- .../features/lockscreen/impl/setup/pin/SetupPinState.kt | 2 +- .../features/lockscreen/impl/setup/pin/SetupPinView.kt | 4 ++-- .../lockscreen/impl/setup/pin/SetupPinPresenterTest.kt | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) rename features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/{SetupPinEvents.kt => SetupPinEvent.kt} (74%) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvent.kt similarity index 74% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvent.kt index 276a94b2fc..f0dfdc33f0 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvent.kt @@ -8,7 +8,7 @@ package io.element.android.features.lockscreen.impl.setup.pin -sealed interface SetupPinEvents { - data class OnPinEntryChanged(val entryAsText: String, val fromConfirmationStep: Boolean) : SetupPinEvents - data object ClearFailure : SetupPinEvents +sealed interface SetupPinEvent { + data class OnPinEntryChanged(val entryAsText: String, val fromConfirmationStep: Boolean) : SetupPinEvent + data object ClearFailure : SetupPinEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt index ac5b5bd1cc..d780927d44 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt @@ -74,9 +74,9 @@ class SetupPinPresenter( } } - fun handleEvent(event: SetupPinEvents) { + fun handleEvent(event: SetupPinEvent) { when (event) { - is SetupPinEvents.OnPinEntryChanged -> { + is SetupPinEvent.OnPinEntryChanged -> { // Use the fromConfirmationStep flag from ui to avoid race condition. if (event.fromConfirmationStep) { confirmPinEntry = confirmPinEntry.fillWith(event.entryAsText) @@ -84,7 +84,7 @@ class SetupPinPresenter( choosePinEntry = choosePinEntry.fillWith(event.entryAsText) } } - SetupPinEvents.ClearFailure -> { + SetupPinEvent.ClearFailure -> { when (setupPinFailure) { is SetupPinFailure.PinsDoNotMatch -> { choosePinEntry = choosePinEntry.clear() diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt index 2d5124d440..cf65e63c1b 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt @@ -17,7 +17,7 @@ data class SetupPinState( val isConfirmationStep: Boolean, val setupPinFailure: SetupPinFailure?, val appName: String, - val eventSink: (SetupPinEvents) -> Unit + val eventSink: (SetupPinEvent) -> Unit ) { val activePinEntry = if (isConfirmationStep) { confirmPinEntry diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt index 5f2320db32..508d3c1fbb 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt @@ -107,7 +107,7 @@ private fun SetupPinContent( pinEntry = state.activePinEntry, isSecured = true, onValueChange = { entry -> - state.eventSink(SetupPinEvents.OnPinEntryChanged(entry, state.isConfirmationStep)) + state.eventSink(SetupPinEvent.OnPinEntryChanged(entry, state.isConfirmationStep)) }, modifier = Modifier .focusRequester(focusRequester) @@ -119,7 +119,7 @@ private fun SetupPinContent( title = state.setupPinFailure.title(), content = state.setupPinFailure.content(), onSubmit = { - state.eventSink(SetupPinEvents.ClearFailure) + state.eventSink(SetupPinEvent.ClearFailure) } ) } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt index 46591eb2af..9d63f9e26b 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt @@ -59,7 +59,7 @@ class SetupPinPresenterTest { awaitLastSequentialItem().also { state -> state.choosePinEntry.assertText(forbiddenPin) assertThat(state.setupPinFailure).isEqualTo(SetupPinFailure.ForbiddenPin) - state.eventSink(SetupPinEvents.ClearFailure) + state.eventSink(SetupPinEvent.ClearFailure) } awaitLastSequentialItem().also { state -> state.choosePinEntry.assertEmpty() @@ -78,7 +78,7 @@ class SetupPinPresenterTest { state.choosePinEntry.assertText(completePin) state.confirmPinEntry.assertText(mismatchedPin) assertThat(state.setupPinFailure).isEqualTo(SetupPinFailure.PinsDoNotMatch) - state.eventSink(SetupPinEvents.ClearFailure) + state.eventSink(SetupPinEvent.ClearFailure) } awaitLastSequentialItem().also { state -> state.choosePinEntry.assertEmpty() @@ -104,7 +104,7 @@ class SetupPinPresenterTest { } private fun SetupPinState.onPinEntryChanged(pinEntry: String) { - eventSink(SetupPinEvents.OnPinEntryChanged(pinEntry, isConfirmationStep)) + eventSink(SetupPinEvent.OnPinEntryChanged(pinEntry, isConfirmationStep)) } private fun createSetupPinPresenter( From 44baa4a383381ebfe97a7338a289c54c8e2d65ed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 10:41:02 +0200 Subject: [PATCH 0368/1083] `PinUnlockEvents` -> `PinUnlockEvent` --- .../{PinUnlockEvents.kt => PinUnlockEvent.kt} | 16 +++++----- .../impl/unlock/PinUnlockPresenter.kt | 16 +++++----- .../lockscreen/impl/unlock/PinUnlockState.kt | 2 +- .../lockscreen/impl/unlock/PinUnlockView.kt | 16 +++++----- .../impl/unlock/PinUnlockPresenterTest.kt | 30 +++++++++---------- 5 files changed, 40 insertions(+), 40 deletions(-) rename features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/{PinUnlockEvents.kt => PinUnlockEvent.kt} (61%) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvent.kt similarity index 61% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvent.kt index bd9043859f..aa96a2e115 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvent.kt @@ -10,12 +10,12 @@ package io.element.android.features.lockscreen.impl.unlock import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel -sealed interface PinUnlockEvents { - data class OnPinKeypadPressed(val pinKeypadModel: PinKeypadModel) : PinUnlockEvents - data class OnPinEntryChanged(val entryAsText: String) : PinUnlockEvents - data object OnForgetPin : PinUnlockEvents - data object ClearSignOutPrompt : PinUnlockEvents - data object SignOut : PinUnlockEvents - data object OnUseBiometric : PinUnlockEvents - data object ClearBiometricError : PinUnlockEvents +sealed interface PinUnlockEvent { + data class OnPinKeypadPressed(val pinKeypadModel: PinKeypadModel) : PinUnlockEvent + data class OnPinEntryChanged(val entryAsText: String) : PinUnlockEvent + data object OnForgetPin : PinUnlockEvent + data object ClearSignOutPrompt : PinUnlockEvent + data object SignOut : PinUnlockEvent + data object OnUseBiometric : PinUnlockEvent + data object ClearBiometricError : PinUnlockEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt index 05b4dbfe72..a6e35b6967 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt @@ -101,28 +101,28 @@ class PinUnlockPresenter( isUnlocked.value = true } - fun handleEvent(event: PinUnlockEvents) { + fun handleEvent(event: PinUnlockEvent) { when (event) { - is PinUnlockEvents.OnPinKeypadPressed -> { + is PinUnlockEvent.OnPinKeypadPressed -> { pinEntryState.value = pinEntry.process(event.pinKeypadModel) } - PinUnlockEvents.OnForgetPin -> showSignOutPrompt = true - PinUnlockEvents.ClearSignOutPrompt -> showSignOutPrompt = false - PinUnlockEvents.SignOut -> { + PinUnlockEvent.OnForgetPin -> showSignOutPrompt = true + PinUnlockEvent.ClearSignOutPrompt -> showSignOutPrompt = false + PinUnlockEvent.SignOut -> { if (showSignOutPrompt) { showSignOutPrompt = false coroutineScope.signOut(signOutAction) } } - PinUnlockEvents.OnUseBiometric -> { + PinUnlockEvent.OnUseBiometric -> { coroutineScope.launch { biometricUnlockResult = biometricUnlock.authenticate() } } - PinUnlockEvents.ClearBiometricError -> { + PinUnlockEvent.ClearBiometricError -> { biometricUnlockResult = null } - is PinUnlockEvents.OnPinEntryChanged -> { + is PinUnlockEvent.OnPinEntryChanged -> { pinEntryState.value = pinEntry.process(event.entryAsText) } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt index 50d03045ab..037aa87dec 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt @@ -23,7 +23,7 @@ data class PinUnlockState( val showBiometricUnlock: Boolean, val isUnlocked: Boolean, val biometricUnlockResult: BiometricAuthenticator.AuthenticationResult?, - val eventSink: (PinUnlockEvents) -> Unit + val eventSink: (PinUnlockEvent) -> Unit ) { val isSignOutPromptCancellable = if (pinEntry.isFailure()) { false diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt index 659f8c2966..465f015cdd 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt @@ -69,7 +69,7 @@ fun PinUnlockView( ) { OnLifecycleEvent { _, event -> when (event) { - Lifecycle.Event.ON_RESUME -> state.eventSink.invoke(PinUnlockEvents.OnUseBiometric) + Lifecycle.Event.ON_RESUME -> state.eventSink.invoke(PinUnlockEvent.OnUseBiometric) else -> Unit } } @@ -78,8 +78,8 @@ fun PinUnlockView( if (state.showSignOutPrompt) { SignOutPrompt( isCancellable = state.isSignOutPromptCancellable, - onSignOut = { state.eventSink(PinUnlockEvents.SignOut) }, - onDismiss = { state.eventSink(PinUnlockEvents.ClearSignOutPrompt) }, + onSignOut = { state.eventSink(PinUnlockEvent.SignOut) }, + onDismiss = { state.eventSink(PinUnlockEvent.ClearSignOutPrompt) }, ) } when (state.signOutAction) { @@ -95,7 +95,7 @@ fun PinUnlockView( if (state.showBiometricUnlockError) { ErrorDialog( content = state.biometricUnlockErrorMessage ?: "", - onSubmit = { state.eventSink(PinUnlockEvents.ClearBiometricError) } + onSubmit = { state.eventSink(PinUnlockEvent.ClearBiometricError) } ) } } @@ -125,10 +125,10 @@ private fun PinUnlockPage( modifier = Modifier.padding(top = 24.dp), showBiometricUnlock = state.showBiometricUnlock, onUseBiometric = { - state.eventSink(PinUnlockEvents.OnUseBiometric) + state.eventSink(PinUnlockEvent.OnUseBiometric) }, onForgotPin = { - state.eventSink(PinUnlockEvents.OnForgetPin) + state.eventSink(PinUnlockEvent.OnForgetPin) }, ) } @@ -144,7 +144,7 @@ private fun PinUnlockPage( pinEntry = pinEntry, isSecured = true, onValueChange = { - state.eventSink(PinUnlockEvents.OnPinEntryChanged(it)) + state.eventSink(PinUnlockEvent.OnPinEntryChanged(it)) }, modifier = Modifier .focusRequester(focusRequester) @@ -154,7 +154,7 @@ private fun PinUnlockPage( } else { PinKeypad( onClick = { - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(it)) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(it)) }, maxWidth = constraints.maxWidth, maxHeight = constraints.maxHeight, diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt index 197f45f0f8..4f93eba12e 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt @@ -46,17 +46,17 @@ class PinUnlockPresenterTest { awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) assertThat(state.remainingAttempts).isInstanceOf(AsyncData.Success::class.java) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('1'))) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('2'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('1'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('2'))) } skipItems(1) awaitItem().also { state -> state.pinEntry.assertText(halfCompletePin) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('3'))) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Back)) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Empty)) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('3'))) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('5'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('3'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Back)) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Empty)) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('3'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('5'))) } skipItems(4) awaitItem().also { state -> @@ -77,10 +77,10 @@ class PinUnlockPresenterTest { } val numberOfAttempts = initialState.remainingAttempts.dataOrNull() ?: 0 repeat(numberOfAttempts) { - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('1'))) - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('2'))) - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('3'))) - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('4'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('1'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('2'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('3'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('4'))) } skipItems(4 * numberOfAttempts + 2) awaitItem().also { state -> @@ -101,20 +101,20 @@ class PinUnlockPresenterTest { awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) assertThat(state.remainingAttempts).isInstanceOf(AsyncData.Success::class.java) - state.eventSink(PinUnlockEvents.OnForgetPin) + state.eventSink(PinUnlockEvent.OnForgetPin) } awaitItem().also { state -> assertThat(state.showSignOutPrompt).isTrue() assertThat(state.isSignOutPromptCancellable).isTrue() - state.eventSink(PinUnlockEvents.ClearSignOutPrompt) + state.eventSink(PinUnlockEvent.ClearSignOutPrompt) } awaitItem().also { state -> assertThat(state.showSignOutPrompt).isFalse() - state.eventSink(PinUnlockEvents.OnForgetPin) + state.eventSink(PinUnlockEvent.OnForgetPin) } awaitItem().also { state -> assertThat(state.showSignOutPrompt).isTrue() - state.eventSink(PinUnlockEvents.SignOut) + state.eventSink(PinUnlockEvent.SignOut) } skipItems(2) awaitItem().also { state -> From 5269b9787e087765bb038aa62928e2fd62240708 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 11:25:03 +0200 Subject: [PATCH 0369/1083] Fix quality issue. --- .../features/lockscreen/impl/unlock/PinUnlockPresenter.kt | 2 +- .../libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt index a6e35b6967..c8dd8916f9 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt @@ -72,7 +72,7 @@ class PinUnlockPresenter( if (pinCodeSize == null) { // No pin code set, deleted store? Force sign out showSignOutPrompt = true - throw Exception("No pin code size found") + error("No pin code size found") } else { PinEntry.createEmpty(pinCodeSize) } diff --git a/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt b/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt index dccba2a136..bcd38695c4 100644 --- a/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt +++ b/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt @@ -37,6 +37,7 @@ class KeyStoreSecretKeyRepository( ) : SecretKeyRepository { private val hasKeyMap = ConcurrentHashMap>() + @Suppress("RunCatchingNotAllowed") override fun hasKey(alias: String): Flow { return hasKeyMap.getOrPut(alias) { MutableStateFlow(runCatching { keyStore.containsAlias(alias) }.getOrDefault(false)) From d558371798d3fc97cfc08b3d14ce4d2d802cdb0d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 11:27:41 +0200 Subject: [PATCH 0370/1083] Add test. --- .../impl/unlock/PinUnlockPresenterTest.kt | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt index 4f93eba12e..fa7d05b5cb 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt @@ -16,6 +16,7 @@ import io.element.android.features.lockscreen.impl.pin.DefaultPinCodeManagerCall import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.features.lockscreen.impl.pin.model.assertText +import io.element.android.features.lockscreen.impl.pin.storage.InMemoryLockScreenStore import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel import io.element.android.features.logout.test.FakeLogoutUseCase import io.element.android.libraries.architecture.AsyncAction @@ -124,6 +125,28 @@ class PinUnlockPresenterTest { } } + @Test + fun `present - pin is configured, but deleted in store, sign out prompt will be shown`() = runTest { + val lockScreenStore = InMemoryLockScreenStore() + val pinCodeManager = aPinCodeManager( + lockScreenStore = lockScreenStore, + ) + val presenter = createPinUnlockPresenter( + pinCodeManager = pinCodeManager, + ) + // Delete the pin code from the store + lockScreenStore.deleteEncryptedPinCode() + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.pinEntry).isInstanceOf(AsyncData.Failure::class.java) + assertThat(state.showSignOutPrompt).isTrue() + assertThat(state.isSignOutPromptCancellable).isFalse() + assertThat(state.remainingAttempts.dataOrNull()).isEqualTo(3) + } + } + } + private fun AsyncData.assertText(text: String) { dataOrNull()?.assertText(text) } @@ -131,9 +154,10 @@ class PinUnlockPresenterTest { private suspend fun TestScope.createPinUnlockPresenter( biometricAuthenticatorManager: BiometricAuthenticatorManager = FakeBiometricAuthenticatorManager(), callback: PinCodeManager.Callback = DefaultPinCodeManagerCallback(), - logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase(logoutLambda = { "" }), + logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase(logoutLambda = {}), + pinCodeManager: PinCodeManager = aPinCodeManager() ): PinUnlockPresenter { - val pinCodeManager = aPinCodeManager().apply { + pinCodeManager.apply { addCallback(callback) createPinCode(completePin) } From d18b5292856ea04ab91630281f29440cba1a0633 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 12:08:33 +0200 Subject: [PATCH 0371/1083] Ensure that remaining pin code attempts is never bigger than the value in the config. --- .../lockscreen/impl/storage/PreferencesLockScreenStore.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt index 98435f962d..bce20b2418 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt @@ -82,5 +82,7 @@ class PreferencesLockScreenStore( } } - private fun Preferences.getRemainingPinCodeAttemptsNumber() = this[remainingAttemptsKey] ?: lockScreenConfig.maxPinCodeAttemptsBeforeLogout + private fun Preferences.getRemainingPinCodeAttemptsNumber() = + this[remainingAttemptsKey]?.coerceIn(0, lockScreenConfig.maxPinCodeAttemptsBeforeLogout) + ?: lockScreenConfig.maxPinCodeAttemptsBeforeLogout } From ae044607c73c2a31905039d111c3c3a782937453 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 May 2026 14:48:55 +0200 Subject: [PATCH 0372/1083] Add missing screenshot and improve UX when user enter wrong pin then correct pin. --- .../impl/unlock/PinUnlockStateProvider.kt | 13 +++-- .../lockscreen/impl/unlock/PinUnlockView.kt | 52 ++++++++++++------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt index 2beb8babe3..1b8166a8ac 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt @@ -20,7 +20,7 @@ open class PinUnlockStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aPinUnlockState(), - aPinUnlockState(pinEntry = PinEntry.createEmpty(4).fillWith("12")), + aPinUnlockState(pinEntry = AsyncData.Success(PinEntry.createEmpty(4).fillWith("12"))), aPinUnlockState(showWrongPinTitle = true), aPinUnlockState(showSignOutPrompt = true), aPinUnlockState(showBiometricUnlock = false), @@ -31,11 +31,18 @@ open class PinUnlockStateProvider : PreviewParameterProvider { BiometricUnlockError(BiometricPrompt.ERROR_LOCKOUT, "Biometric auth disabled") ) ), + aPinUnlockState(showSignOutPrompt = true, pinEntry = AsyncData.Failure(Exception("An error occurred"))), + // User enter wrong pin once, and then correct PIN. In this case, the error (with counter reset to 3) should not be displayed. + aPinUnlockState( + remainingAttempts = AsyncData.Success(2), + showWrongPinTitle = true, + isUnlocked = true, + ), ) } fun aPinUnlockState( - pinEntry: PinEntry = PinEntry.createEmpty(4), + pinEntry: AsyncData = AsyncData.Success(PinEntry.createEmpty(4)), remainingAttempts: AsyncData = AsyncData.Success(3), showWrongPinTitle: Boolean = false, showSignOutPrompt: Boolean = false, @@ -44,7 +51,7 @@ fun aPinUnlockState( isUnlocked: Boolean = false, signOutAction: AsyncAction = AsyncAction.Uninitialized, ) = PinUnlockState( - pinEntry = AsyncData.Success(pinEntry), + pinEntry = pinEntry, showWrongPinTitle = showWrongPinTitle, remainingAttempts = remainingAttempts, showSignOutPrompt = showSignOutPrompt, diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt index 465f015cdd..6749697b64 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt @@ -108,10 +108,10 @@ private fun PinUnlockPage( ) { BoxWithConstraints { val commonModifier = Modifier - .fillMaxSize() - .systemBarsPadding() - .imePadding() - .padding(all = 20.dp) + .fillMaxSize() + .systemBarsPadding() + .imePadding() + .padding(all = 20.dp) val header = @Composable { PinUnlockHeader( @@ -147,8 +147,8 @@ private fun PinUnlockPage( state.eventSink(PinUnlockEvent.OnPinEntryChanged(it)) }, modifier = Modifier - .focusRequester(focusRequester) - .fillMaxWidth() + .focusRequester(focusRequester) + .fillMaxWidth() ) } } else { @@ -217,8 +217,8 @@ private fun PinUnlockCompactView( } BoxWithConstraints( modifier = Modifier - .weight(1f) - .fillMaxHeight(), + .weight(1f) + .fillMaxHeight(), contentAlignment = Alignment.Center, ) { content() @@ -239,9 +239,9 @@ private fun PinUnlockExpandedView( header() BoxWithConstraints( modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(top = 40.dp), + .weight(1f) + .fillMaxWidth() + .padding(top = 40.dp), ) { content() } @@ -274,8 +274,8 @@ private fun PinDot( } Box( modifier = Modifier - .size(14.dp) - .background(backgroundColor, CircleShape) + .size(14.dp) + .background(backgroundColor, CircleShape) ) } @@ -311,14 +311,26 @@ private fun PinUnlockHeader( ) Spacer(Modifier.height(8.dp)) val remainingAttempts = state.remainingAttempts.dataOrNull() - val subtitle = if (remainingAttempts != null) { - if (state.showWrongPinTitle) { - pluralStringResource(id = R.plurals.screen_app_lock_subtitle_wrong_pin, count = remainingAttempts, remainingAttempts) - } else { - pluralStringResource(id = R.plurals.screen_app_lock_subtitle, count = remainingAttempts, remainingAttempts) + val subtitle = when { + state.isUnlocked -> { + // Hide any previous error + "" } - } else { - "" + remainingAttempts != null -> + if (state.showWrongPinTitle) { + pluralStringResource( + id = R.plurals.screen_app_lock_subtitle_wrong_pin, + count = remainingAttempts, + remainingAttempts, + ) + } else { + pluralStringResource( + id = R.plurals.screen_app_lock_subtitle, + count = remainingAttempts, + remainingAttempts, + ) + } + else -> "" } val subtitleColor = if (state.showWrongPinTitle) { ElementTheme.colors.textCriticalPrimary From 866c8375b305a90119a2bb713a66c32443638e84 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 7 May 2026 11:11:07 +0200 Subject: [PATCH 0373/1083] Make send event state UI easier to click (#6739) * Make send event state UI easier to click Make it so the whole timestamp view can be clicked * Update screenshots * Simplify `clickableModifier` --------- Co-authored-by: ElementBot --- .../components/TimelineEventTimestampView.kt | 53 +++++++++++++------ ...ts_TimelineEventTimestampView_Day_3_en.png | 2 +- ..._TimelineEventTimestampView_Night_3_en.png | 4 +- ...lineItemEventRowForDirectRoom_Day_0_en.png | 4 +- ...neItemEventRowForDirectRoom_Night_0_en.png | 4 +- ...ts_TimelineItemEventRowShield_Day_0_en.png | 4 +- ..._TimelineItemEventRowShield_Night_0_en.png | 4 +- ...mponents_TimelineItemEventRow_Day_0_en.png | 4 +- ...onents_TimelineItemEventRow_Night_0_en.png | 2 +- ...s.impl.timeline_TimelineView_Day_17_en.png | 4 +- ...es.impl.timeline_TimelineView_Day_2_en.png | 4 +- ...es.impl.timeline_TimelineView_Day_3_en.png | 4 +- ...es.impl.timeline_TimelineView_Day_9_en.png | 4 +- ...impl.timeline_TimelineView_Night_17_en.png | 4 +- ....impl.timeline_TimelineView_Night_2_en.png | 4 +- ....impl.timeline_TimelineView_Night_3_en.png | 4 +- ....impl.timeline_TimelineView_Night_9_en.png | 4 +- ...ures.messages.impl_MessagesViewA11y_en.png | 4 +- 18 files changed, 68 insertions(+), 49 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index 21ef7c5b09..25a53cec2d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -15,9 +15,12 @@ import androidx.compose.foundation.layout.Spacer 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.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -47,9 +50,39 @@ fun TimelineEventTimestampView( val isMessageEdited = event.content.isEdited() val isMessageRedacted = event.content.isRedacted() val tint = if (hasError || hasEncryptionCritical && !isMessageRedacted) ElementTheme.colors.textCriticalPrimary else ElementTheme.colors.textSecondary + + val shield = event.messageShield + val isVerifiedUserSendFailure = event.localSendState is LocalEventSendState.Failed.VerifiedUser + val onClickLabel = when { + shield != null -> stringResource(CommonStrings.a11y_view_details) + hasError && isVerifiedUserSendFailure -> stringResource(CommonStrings.action_open_context_menu) + else -> null + } + val clickableModifier = remember(shield, hasError) { + when { + shield != null -> { + Modifier.clickable( + onClickLabel = onClickLabel, + ) { + eventSink(TimelineEvent.ShowShieldDialog(shield)) + } + } + hasError -> Modifier + .clickable( + enabled = isVerifiedUserSendFailure, + onClickLabel = onClickLabel, + ) { + eventSink(TimelineEvent.ComputeVerifiedUserSendFailure(event)) + } + else -> Modifier + } + } Row( modifier = Modifier .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) + // For a better click target, make the corners rounded + .clip(RoundedCornerShape(8.dp)) + .then(clickableModifier) .then(modifier), verticalAlignment = Alignment.CenterVertically, ) { @@ -67,36 +100,22 @@ fun TimelineEventTimestampView( color = tint, ) if (hasError) { - val isVerifiedUserSendFailure = event.localSendState is LocalEventSendState.Failed.VerifiedUser Spacer(modifier = Modifier.width(2.dp)) Icon( imageVector = CompoundIcons.ErrorSolid(), contentDescription = stringResource(id = CommonStrings.common_sending_failed), tint = tint, - modifier = Modifier - .size(15.dp, 18.dp) - .clickable( - enabled = isVerifiedUserSendFailure, - onClickLabel = stringResource(CommonStrings.action_open_context_menu), - ) { - eventSink(TimelineEvent.ComputeVerifiedUserSendFailure(event)) - } + modifier = Modifier.size(15.dp, 18.dp), ) } if (!isMessageRedacted) { - event.messageShield?.let { shield -> + shield?.let { shield -> Spacer(modifier = Modifier.width(2.dp)) Icon( imageVector = shield.toIcon(), contentDescription = stringResource(id = CommonStrings.a11y_encryption_details), - modifier = Modifier - .size(15.dp) - .clickable( - onClickLabel = stringResource(CommonStrings.a11y_view_details), - ) { - eventSink(TimelineEvent.ShowShieldDialog(shield)) - }, + modifier = Modifier.size(15.dp), tint = shield.toIconColor(), ) Spacer(modifier = Modifier.width(4.dp)) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en.png index 2faf0a5bb2..e1f1510b5d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ef807d846ee06add8438e81ece8570cf688742268af87b6985551c3cb2a0faf +oid sha256:4bb4d59085cc26a284e1bd9c2e6fb7e982a1b32eae5f46282a4dde93b5d5ba1f size 5735 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en.png index fdbb4a4aae..b09b378502 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46b2bf1b4ed49f02ab2ff5218ad6bf2a7e0184e022af60d4cbeb8599646975c8 -size 5670 +oid sha256:e6cf51de97f040b1028bc32d167f7c4acdbd2717c3222e1a1d97929d666cacc0 +size 5669 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en.png index 592d4b0e0d..a0b392a659 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87b78e2a06bf592ac538eecfdca70a9c5ec51f69e397623edcdcad8daaa9bfe8 -size 293405 +oid sha256:495951c4763e1c3015a88964683d384b84dbfce1b9569630d81ff8578a7d13e2 +size 293410 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en.png index a84752536c..97826e6a68 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bccf822697a9710752ce5323c8b6481d7080d9eba7579d9679f451818ab71a6 -size 293202 +oid sha256:25d4838bf2587c2ccfffe83d53d556ec35ee7691e6eff91689d41dfcd538a324 +size 293209 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png index 4faa1f828a..90e9e72d8f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6982eb3368779c8e7fa602059d9af4119f450f9f2f7f384b0e1251080d286c1 -size 377103 +oid sha256:7684bb50d0012a7175957d0bbac28f68856573cea37f45697ef3b81235f1eafb +size 377102 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png index 14d9ae5907..c7a8f44df4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:add275ce7641fbeba7acca740b2d0d6df0ed06c1c3c5cbcd05a1ca474b086ccf -size 375878 +oid sha256:f6677e0cda28bab1973cc767606eedf86eae3a1ae111b552c6f284eae4fb2de2 +size 375875 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en.png index 480ae88643..cacc88a34c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2476a6e3d5beff4360a349adb831e63fbc05962b57bb0f551ec784e28b9495d1 -size 411656 +oid sha256:789dbfa4886cacdaf5bab7bd6e501d0dd6e31af965b398d9f61d7e46c653a8c9 +size 411661 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en.png index 75cdc28a3e..e85c9987f7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8cb2e25a8f461fbb9ca9082bf94571daae1d2c886d2cd33ecea14f955eb959b2 +oid sha256:a740b9d1af8d48d5b9f9bd47abab34ed37037c7c2646d92a05af139435f23d27 size 409955 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 72f4fa03b5..39bbd406ed 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:4a0827eb23b48bd03fde5078598cb7827459a213ff0a693890581628330f6939 -size 66845 +oid sha256:6f7e3f1cdaf18d7d529be07cde3bdc9100243780101e73dd53c3d78639775974 +size 66862 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png index 67aca77a8c..414db592da 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c94c770cbd1f41f0b50d0a64290c96e1a75bdcddbd0f850d097cd41e5f2a9cf5 -size 493537 +oid sha256:467e5aee42e9041db2672dc0d37e98fc1090c19207604a31247f3142d845f792 +size 493534 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png index dde5ade114..b9723dd5c4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d73c338dce5b27c718cffbbf7cb1fe8f5b9d72f0d335afd81526849190d4941 -size 488704 +oid sha256:723238ad84c9925eb0edbbf225b50a03bf29e5671777d9f03eba6b910ee00fcf +size 488705 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 adf8d255e3..6ff4840c57 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:a8fa43d296a984d242ed56f7879de4c38f3da94147c365c424248eba2c4ad61d -size 371263 +oid sha256:fbd5652457d495c3c6692c151be27c985cf47e95c8b89af9b6edc8c1b734acc8 +size 371265 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 3ad7246822..e5795401ce 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:bea070091132156a809da1c185e2f94333e62f8ea9ae7d6d1b789adffb869522 -size 55538 +oid sha256:06e2c25d3cbd111b22bd0188e2b1880729e023170c7bed972cdb3c34544ba55e +size 55547 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png index fa93db2f0d..c418921834 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c57dbc66342263c4ff1d47c18099dd2cc22b752f1b6bfc853566706dc0cf5110 -size 486435 +oid sha256:3bf788838a204acb53bceba268327e3c2a772447490a597ed4929487716bc6fb +size 486425 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png index 150b2b0c87..6ab414ab0b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d4fff1585f602d561a98bfbd907d3c7499e6717f488eee711e90f2b0f5df7b9 -size 481595 +oid sha256:80e198bd8cf523c785de4a66c4c22cecb22d1040377bdfd66eeed821a4281592 +size 481590 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 7b5512dcc7..825618ae17 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:bcd9e0934b5f6808d58a3d3506641f173c4b223d78c605de09832d3741e8834f -size 149300 +oid sha256:75ace43e27a0c8f9786b0494931c3ef5e12d903e7417dddecfb34c9526e74f3c +size 149314 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png index c214011ea7..631559cabc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23aabf96e5dc84257968a77ad406a8f3952b24fa8d8c03612bddfc08b6c990c6 -size 131751 +oid sha256:ee269e52306e048bbd0a06ea7c56f9080f37f37b00909c3d48a02a3a37bd57bc +size 131800 From 790c30ca1f210c9d38f4deb8cf1072da6a6f38a8 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 7 May 2026 09:20:09 +0000 Subject: [PATCH 0374/1083] Update screenshots --- ...ures.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png | 3 +++ ...ures.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png | 3 +++ ...es.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png | 3 +++ ...es.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png | 3 +++ .../features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png | 3 +++ .../features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png | 3 +++ ...eatures.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png | 3 +++ ...eatures.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png | 3 +++ 8 files changed, 24 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png new file mode 100644 index 0000000000..5669a59d24 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8665179304ccd2e0acf517ddcf369c4daae51c41732ee1b9618e3bedf38aeffc +size 31643 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png new file mode 100644 index 0000000000..265044a0b2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14300f3af0bc8c003ce94868665547ad439826b47cf416f1a062ffa4a1d7e793 +size 15782 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png new file mode 100644 index 0000000000..ff95140047 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88354d222679723cadfb76d2c4928fad78e17fec13514c0e4712e6f877b1a0c7 +size 29627 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png new file mode 100644 index 0000000000..4bc9f6653b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d505c4b2323dfc67c1b7e119960ede5b97b52d6c453610cdbb01efd485730aa5 +size 15369 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png new file mode 100644 index 0000000000..8b7fa8b77c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80246e3957a0e3f98bce55ddd6d8fe09b5f140eee3837d80ca20253f6bcfb876 +size 37738 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png new file mode 100644 index 0000000000..266dae3c81 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60dd90eb571f473b78ecc629573bcf2faca02819022bdf57f05cc8b0876f4ab8 +size 31440 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png new file mode 100644 index 0000000000..8a8d15acf9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d60a8caa2441ff0618636d307d32d0944bdb77fb3b579c0959dc951b0318ad72 +size 35429 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png new file mode 100644 index 0000000000..fe27573765 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfe8b59b8d5d7a1c33285072dec437060faae55bfa2a42687bd8895dd90409a6 +size 30310 From 80a46fdb3dabbcf57a667627a24d81bd9a16efdc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 May 2026 11:52:21 +0200 Subject: [PATCH 0375/1083] Fix test --- .../invitepeople/impl/DefaultInvitePeoplePresenterTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index e7fef11423..4ecd74a42f 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -320,7 +320,7 @@ internal class DefaultInvitePeoplePresenterTest { val initialState = awaitItemAsDefault() skipItems(1) - val selectedUser = aMatrixUser() + val selectedUser = aMatrixUser(displayName = "John Doe") initialState.eventSink(DefaultInvitePeopleEvents.ToggleUser(selectedUser)) @@ -358,7 +358,7 @@ internal class DefaultInvitePeoplePresenterTest { val initialState = awaitItemAsDefault() skipItems(1) - val selectedUser = aMatrixUser() + val selectedUser = aMatrixUser(displayName = "John Doe") // Given a query is made initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query") From 022d21b097630aad8c8249222bf6b579a1fc1a56 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 May 2026 11:54:27 +0200 Subject: [PATCH 0376/1083] Remove trailing spaces --- .../impl/developer/appsettings/AppDeveloperSettingsView.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt index f60eb2ac85..9b2a2aa3a9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsView.kt @@ -87,7 +87,6 @@ fun AppDeveloperSettingsView( onClick = onOpenShowkase ) } - RageshakePreferencesView( state = state.rageshakeState, ) From a6bee757b4e936fd2403db2d2412e3415ecd6f97 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 12:11:36 +0000 Subject: [PATCH 0377/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.7 --- 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 581630c80d..4a1e0c2f80 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.6" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.7" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 7e3acc03b9c6db92ee67da231b553166313424d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 7 May 2026 15:13:51 +0200 Subject: [PATCH 0378/1083] Fix API breaks --- .../matrix/impl/fixtures/factories/NotificationItem.kt | 2 ++ .../libraries/matrix/impl/fixtures/factories/SpaceRoom.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt index 82984c480d..63ad77238b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt @@ -67,6 +67,7 @@ internal fun aRustNotificationRoomInfo( joinedMembersCount: ULong = 2u, isEncrypted: Boolean? = true, isDirect: Boolean = false, + isDm: Boolean = false, joinRule: JoinRule? = null, isSpace: Boolean = false, serviceMembers: List = emptyList(), @@ -79,6 +80,7 @@ internal fun aRustNotificationRoomInfo( joinedMembersCount = joinedMembersCount, isEncrypted = isEncrypted, isDirect = isDirect, + isDm = isDm, joinRule = joinRule, isSpace = isSpace, serviceMembers = serviceMembers.map { it.value }, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt index 50115055c2..50e2f6168e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt @@ -19,6 +19,7 @@ import org.matrix.rustcomponents.sdk.SpaceRoom internal fun aRustSpaceRoom( roomId: RoomId = A_ROOM_ID, isDirect: Boolean = false, + isDm: Boolean = false, canonicalAlias: String? = null, rawName: String? = null, displayName: String = "", @@ -35,6 +36,7 @@ internal fun aRustSpaceRoom( ) = SpaceRoom( roomId = roomId.value, isDirect = isDirect, + isDm = isDm, canonicalAlias = canonicalAlias, rawName = rawName, displayName = displayName, From 95dac66869dd350c84f80d3c4af61caef75500d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 15:39:26 +0200 Subject: [PATCH 0379/1083] Update tspascoal/get-user-teams-membership action to v4 (#6747) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update tspascoal/get-user-teams-membership action to v4 * Point the commit to the right tag v4.0.0 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c8c0a98dea..9b4a5e3689 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Check membership if: github.event.pull_request.user.login != 'renovate[bot]' - uses: tspascoal/get-user-teams-membership@57e9f42acd78f4d0f496b3be4368fc5f62696662 # v3 + uses: tspascoal/get-user-teams-membership@b1480b119326dde04ceffbeccd98e41892539c74 # v4.0.0 id: teams with: username: ${{ github.event.pull_request.user.login }} From 0cb1a9fb145ee1879f923ffb50644944584917bc Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 May 2026 16:01:34 +0200 Subject: [PATCH 0380/1083] Setting version for the release 26.05.0 --- plugins/src/main/kotlin/Versions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index d6a2cbea3d..fa197e4a08 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -39,13 +39,13 @@ private const val versionYear = 26 * Month of the version on 2 digits. Value must be in [1,12]. * Do not update this value. it is updated by the release script. */ -private const val versionMonth = 4 +private const val versionMonth = 5 /** * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 4 +private const val versionReleaseNumber = 0 object Versions { /** From 63edcd69898a7adc4b2008365e718d48fc11a7b2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 May 2026 16:01:40 +0200 Subject: [PATCH 0381/1083] Adding fastlane file for version 26.05.0 --- fastlane/metadata/android/en-US/changelogs/202605000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202605000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202605000.txt b/fastlane/metadata/android/en-US/changelogs/202605000.txt new file mode 100644 index 0000000000..a4b397f1bb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202605000.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 245c30c18a9ba54dabd6df86a07138ff2cb11bd4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 May 2026 17:47:15 +0200 Subject: [PATCH 0382/1083] Changelog for version 26.05.0 --- CHANGES.md | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index df109d34a6..a57395b833 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,88 @@ +Changes in Element X v26.05.0 +============================= + + + +## What's Changed +### ✨ Features +* Add flag for automatic back pagination feature by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6637 +* Promote "history sharing on invite" out of developer options by @richvdh in https://github.com/element-hq/element-x-android/pull/6647 +* Remove RoomDirectorySearch feature flag — always enable the feature by @Copilot in https://github.com/element-hq/element-x-android/pull/6736 +### 🙌 Improvements +* Change native back button behavior in EC view (close settings in EC with os native back) by @toger5 in https://github.com/element-hq/element-x-android/pull/6642 +* Revert PR #6642 by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6724 +* Use 'Report a problem' string instead of 'Report bug' by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6735 +### 🐛 Bugfixes +* Remove distributed tracing of the 'timeline loading' flow by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6644 +* Set max lines for 'in reply to' view conditionally by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6612 +* Mention pill cut off by @bmarty in https://github.com/element-hq/element-x-android/pull/6651 +* Ensure that bottom sheet can scroll by @bmarty in https://github.com/element-hq/element-x-android/pull/6661 +* Remove legacy `mx-reply` from `toPlainText` formatted event contents by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6683 +* Fix ANRs when receiving push notifications by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6696 +* Mitigate a deadlock when loading room timelines by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6674 +* Fix calls on Huawei devices: skip addWebMessageListener on Chromium < 119 by @manfrommedan in https://github.com/element-hq/element-x-android/pull/6640 +* Allow cancelling room loading in Home screen by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6723 +* Let our Json parser accept comments and trailing comma. by @bmarty in https://github.com/element-hq/element-x-android/pull/6700 +* Fix low width image message by @krbns in https://github.com/element-hq/element-x-android/pull/6692 +* Make icons in the Chat screen top bar 16dp by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6733 +* Fix back button sometimes not working after exiting a thread by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6732 +* Make send event state UI easier to click by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6739 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6658 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6716 +### 🧱 Build +* Fix record screenshots action permissions by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6679 +* Fix dependency error by @bmarty in https://github.com/element-hq/element-x-android/pull/6697 +### 🚧 In development 🚧 +* [Link new device] Add missing screen to render digits that the user has to type on the other device by @bmarty in https://github.com/element-hq/element-x-android/pull/6680 +### Dependency upgrades +* Update dependency io.nlopez.compose.rules:detekt to v0.5.7 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6594 +* Update zizmorcore/zizmor-action action to v0.5.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6630 +* Update dependency io.sentry:sentry-android to v8.38.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6597 +* fix(deps): update camera to v1.6.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6514 +* Update dependency io.sentry:sentry-android to v8.39.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6648 +* Update dependency io.element.android:element-call-embedded to v0.19.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6662 +* Update dependencyAnalysis to v3.9.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6657 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.04.27 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6666 +* Update dependency io.sentry:sentry-android to v8.40.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6691 +* Update dependency org.jsoup:jsoup to v1.22.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6660 +* Update kotlin by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6687 +* Update dependency androidx.compose:compose-bom to v2026.04.01 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6693 +* Update dependency io.nlopez.compose.rules:detekt to v0.5.8 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6711 +* Update dependency com.posthog:posthog-android to v3.43.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6704 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6718 +* Update roborazzi to v1.60.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6722 +* Update dependency net.zetetic:sqlcipher-android to v4.15.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6727 +* Update dependency org.maplibre.gl:android-sdk to v13.1.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6731 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.6 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6734 +* Update dependencyAnalysis to v3.10.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6742 +* Update tspascoal/get-user-teams-membership action to v4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6747 +### Others +* devx: fix build sdk script options for macos by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6636 +* PR:Fix mention pill cut off by @krbns in https://github.com/element-hq/element-x-android/pull/6622 +* Update media viewer UI by @bmarty in https://github.com/element-hq/element-x-android/pull/6643 +* Strip formatting from media captions in room summary by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6670 +* Update error mappings for Link new device flow by @hughns in https://github.com/element-hq/element-x-android/pull/6677 +* Rename `OIDC` components and variables to `OAuth` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6686 +* [Link new device] Add missing error case "already signed in" by @bmarty in https://github.com/element-hq/element-x-android/pull/6688 +* Improve detection of completion for Link new device flow by @hughns in https://github.com/element-hq/element-x-android/pull/6681 +* Remove external call support by @bmarty in https://github.com/element-hq/element-x-android/pull/6668 +* [a11y] Fix a set of issues by @bmarty in https://github.com/element-hq/element-x-android/pull/6650 +* Add clipping to RoomSummaryRow by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6654 +* Fix media viewer flickering and crashing by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6715 +* Rename verification methods by @bmarty in https://github.com/element-hq/element-x-android/pull/6726 +* Add a way to tweak MAS url. by @bmarty in https://github.com/element-hq/element-x-android/pull/6682 +* Fix 2 x Crash the app in Developer Options - Update AppDeveloperSettingsView.kt by @escix in https://github.com/element-hq/element-x-android/pull/6708 +* Introduce UI sample by @bmarty in https://github.com/element-hq/element-x-android/pull/6740 + +## New Contributors +* @krbns made their first contribution in https://github.com/element-hq/element-x-android/pull/6622 +* @toger5 made their first contribution in https://github.com/element-hq/element-x-android/pull/6642 +* @manfrommedan made their first contribution in https://github.com/element-hq/element-x-android/pull/6640 +* @Copilot made their first contribution in https://github.com/element-hq/element-x-android/pull/6736 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.04.4...v26.05.0 + Changes in Element X v26.04.4 ============================= From 4a4b3e07ef1cc3989809fc9f2b1da15a7ec9a577 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 8 May 2026 11:17:30 +0200 Subject: [PATCH 0383/1083] Use just the other user's avatar for DM details (#6738) * Use just the other user's avatar for DM details. Remove `DmAvatars` component and other no longer needed data. * Improve selection indicator by clipping the avatar to a circle shape * Update screenshots --------- Co-authored-by: ElementBot --- .../roomdetails/impl/RoomDetailsPresenter.kt | 16 +- .../roomdetails/impl/RoomDetailsState.kt | 5 +- .../impl/RoomDetailsStateProvider.kt | 6 +- .../roomdetails/impl/RoomDetailsView.kt | 32 +++- .../impl/RoomDetailsPresenterTest.kt | 7 +- .../roomdetails/impl/RoomDetailsViewTest.kt | 12 +- .../components/avatar/DmAvatars.kt | 142 ------------------ ...es.roomdetails.impl_RoomDetailsA11y_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_0_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_10_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_11_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_12_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_13_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_14_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_15_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_16_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_17_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_18_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_1_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_20_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_21_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_22_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_2_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_3_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_4_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_6_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_7_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_8_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_9_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_0_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_10_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_11_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_12_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_13_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_14_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_15_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_16_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_17_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_1_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_20_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_21_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_22_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_2_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_3_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_4_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_6_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_7_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_8_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_9_en.png | 4 +- ...ponents.avatar_DmAvatarsRtl_Avatars_en.png | 3 - ...components.avatar_DmAvatars_Avatars_en.png | 3 - 56 files changed, 128 insertions(+), 286 deletions(-) delete mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt delete mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 5fd44076e6..2ba7b4fa4a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -47,7 +47,6 @@ import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomNotificationSettings -import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange import io.element.android.libraries.preferences.api.store.AppPreferencesStore @@ -99,9 +98,8 @@ class RoomDetailsPresenter( val canonicalAlias by remember { derivedStateOf { roomInfo.canonicalAlias } } val isEncrypted by remember { derivedStateOf { roomInfo.isEncrypted == true } } val dmMember by room.getDirectRoomMember(membersState) - val currentMember by room.getCurrentRoomMember(membersState) val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember) - val roomType = getRoomType(dmMember, currentMember) + val roomType = getRoomType(dmMember) val roomCallState = roomCallStatePresenter.present() val joinedMemberCount by remember { derivedStateOf { roomInfo.joinedMembersCount } } @@ -210,15 +208,9 @@ class RoomDetailsPresenter( } @Composable - private fun getRoomType( - dmMember: RoomMember?, - currentMember: RoomMember?, - ): RoomDetailsType = remember(dmMember, currentMember) { - if (dmMember != null && currentMember != null) { - RoomDetailsType.Dm( - me = currentMember, - otherMember = dmMember, - ) + private fun getRoomType(dmMember: RoomMember?): RoomDetailsType = remember(dmMember) { + if (dmMember != null) { + RoomDetailsType.Dm(otherMember = dmMember) } else { RoomDetailsType.Room } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index e74f71322d..90a912e86f 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -77,10 +77,7 @@ data class RoomDetailsState( @Immutable sealed interface RoomDetailsType { data object Room : RoomDetailsType - data class Dm( - val me: RoomMember, - val otherMember: RoomMember, - ) : RoomDetailsType + data class Dm(val otherMember: RoomMember) : RoomDetailsType } @Immutable diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index 7f3701a770..a8cd84be72 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -13,7 +13,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.aStandByCallState -import io.element.android.features.roomdetails.impl.members.aRoomMember import io.element.android.features.userprofile.api.UserProfileState import io.element.android.features.userprofile.api.UserProfileVerificationState import io.element.android.features.userprofile.shared.aUserProfileState @@ -179,10 +178,7 @@ fun aDmRoomDetailsState( roomName = roomName, isPublic = false, isEncrypted = isEncrypted, - roomType = RoomDetailsType.Dm( - me = aRoomMember(), - otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored), - ), + roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)), roomMemberDetailsState = aUserProfileState( isBlocked = AsyncData.Success(isDmMemberIgnored), verificationState = dmRoomMemberVerificationState, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index c48716db11..e877c24554 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -31,6 +32,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign @@ -52,7 +54,6 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType -import io.element.android.libraries.designsystem.components.avatar.DmAvatars import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.MainActionButton import io.element.android.libraries.designsystem.components.list.ListItemContent @@ -91,6 +92,7 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.compose.LocalAnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @Composable @@ -154,9 +156,9 @@ fun RoomDetailsView( } is RoomDetailsType.Dm -> { DmHeaderSection( - me = state.roomType.me, otherMember = state.roomType.otherMember, roomName = state.roomName, + isTombstoned = state.isTombstoned, openAvatarPreview = { name, avatarUrl -> openAvatarPreview(name, avatarUrl) }, @@ -417,6 +419,7 @@ private fun RoomHeaderSection( ), contentDescription = stringResource(CommonStrings.a11y_room_avatar), modifier = Modifier + .clip(CircleShape) .clickable( enabled = avatarUrl != null, onClickLabel = stringResource(CommonStrings.action_view), @@ -435,9 +438,9 @@ private fun RoomHeaderSection( @Composable private fun DmHeaderSection( - me: RoomMember, otherMember: RoomMember, roomName: String, + isTombstoned: Boolean, openAvatarPreview: (name: String, url: String) -> Unit, onSubtitleClick: (String) -> Unit, modifier: Modifier = Modifier @@ -448,11 +451,24 @@ private fun DmHeaderSection( .padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - DmAvatars( - userAvatarData = me.getAvatarData(size = AvatarSize.DmCluster), - otherUserAvatarData = otherMember.getAvatarData(size = AvatarSize.DmCluster), - openAvatarPreview = { url -> openAvatarPreview(me.getBestName(), url) }, - openOtherAvatarPreview = { url -> openAvatarPreview(roomName, url) }, + Avatar( + avatarData = AvatarData(otherMember.userId.value, roomName, otherMember.avatarUrl, AvatarSize.RoomDetailsHeader), + avatarType = AvatarType.Room( + heroes = persistentListOf( + otherMember.getAvatarData(size = AvatarSize.RoomDetailsHeader) + ), + isTombstoned = isTombstoned, + ), + contentDescription = stringResource(CommonStrings.a11y_room_avatar), + modifier = Modifier + .clip(CircleShape) + .clickable( + enabled = otherMember.avatarUrl != null, + onClickLabel = stringResource(CommonStrings.action_view), + ) { + openAvatarPreview(otherMember.getBestName(), otherMember.avatarUrl!!) + } + .testTag(TestTags.roomDetailAvatar) ) TitleAndSubtitle( title = roomName, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index d355010307..1b93a92884 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -206,12 +206,7 @@ class RoomDetailsPresenterTest { val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { val initialState = awaitItem() - assertThat(initialState.roomType).isEqualTo( - RoomDetailsType.Dm( - me = myRoomMember, - otherMember = otherRoomMember, - ) - ) + assertThat(initialState.roomType).isEqualTo(RoomDetailsType.Dm(otherMember = otherRoomMember)) cancelAndIgnoreRemainingEvents() } } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 50139e0149..5fe0130c73 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -126,10 +126,7 @@ class RoomDetailsViewTest { state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canInvite = true, - roomType = RoomDetailsType.Dm( - aRoomMember(UserId("@me:local.org")), - aRoomMember(UserId("@other:local.org")) - ), + roomType = RoomDetailsType.Dm(aRoomMember(UserId("@other:local.org"))), ), onJoinCallClick = callback, ) @@ -232,10 +229,7 @@ class RoomDetailsViewTest { fun `click on avatar test on DM`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aRoomDetailsState( - roomType = RoomDetailsType.Dm( - aRoomMember(), - aDmRoomMember(avatarUrl = "an_avatar_url"), - ), + roomType = RoomDetailsType.Dm(aDmRoomMember(avatarUrl = "an_avatar_url"),), roomName = "Daniel", eventSink = eventsRecorder, ) @@ -244,7 +238,7 @@ class RoomDetailsViewTest { state = state, openAvatarPreview = callback, ) - onNodeWithTag(TestTags.memberDetailAvatar.value).performClick() + onNodeWithTag(TestTags.roomDetailAvatar.value).performClick() callback.assertSuccess() } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt deleted file mode 100644 index f19796e053..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.designsystem.components.avatar - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.drawWithContent -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.BlendMode -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.CompositingStrategy -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.LayoutDirection -import io.element.android.libraries.designsystem.preview.ElementThemedPreview -import io.element.android.libraries.designsystem.preview.PreviewGroup -import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE -import io.element.android.libraries.designsystem.preview.USER_NAME_BOB -import io.element.android.libraries.designsystem.text.toPx -import io.element.android.libraries.testtags.TestTags -import io.element.android.libraries.testtags.testTag -import io.element.android.libraries.ui.strings.CommonStrings - -/** Ratio between the box size (120 on Figma) and the avatar size (75 on Figma). */ -private const val SIZE_RATIO = 1.6f - -/** - * https://www.figma.com/design/A2pAEvTEpJZBiOPUlcMnKi/Settings-%2B-Room-Details-(new)?node-id=1787-56333 - */ -@Composable -fun DmAvatars( - userAvatarData: AvatarData, - otherUserAvatarData: AvatarData, - openAvatarPreview: (url: String) -> Unit, - openOtherAvatarPreview: (url: String) -> Unit, - modifier: Modifier = Modifier, -) { - val boxSize = userAvatarData.size.dp * SIZE_RATIO - val boxSizePx = boxSize.toPx() - val otherAvatarRadius = otherUserAvatarData.size.dp.toPx() / 2 - val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl - Box( - modifier = modifier.size(boxSize), - ) { - // Draw user avatar and cut top end corner - Avatar( - avatarData = userAvatarData, - avatarType = AvatarType.User, - contentDescription = stringResource(CommonStrings.a11y_your_avatar), - modifier = Modifier - .align(Alignment.BottomStart) - .graphicsLayer { - compositingStrategy = CompositingStrategy.Offscreen - } - .drawWithContent { - drawContent() - val xOffset = if (isRtl) { - size.width - boxSizePx + otherAvatarRadius - } else { - boxSizePx - otherAvatarRadius - } - drawCircle( - color = Color.Black, - center = Offset( - x = xOffset, - y = size.height - (boxSizePx - otherAvatarRadius), - ), - radius = otherAvatarRadius / 0.9f, - blendMode = BlendMode.Clear, - ) - } - .clip(CircleShape) - .clickable( - enabled = userAvatarData.url != null, - onClickLabel = stringResource(CommonStrings.action_view), - ) { - userAvatarData.url?.let { openAvatarPreview(it) } - } - ) - // Draw other user avatar - Avatar( - avatarData = otherUserAvatarData, - avatarType = AvatarType.User, - contentDescription = stringResource(CommonStrings.a11y_other_user_avatar), - modifier = Modifier - .align(Alignment.TopEnd) - .clip(CircleShape) - .clickable( - enabled = otherUserAvatarData.url != null, - onClickLabel = stringResource(CommonStrings.action_view), - ) { - otherUserAvatarData.url?.let { openOtherAvatarPreview(it) } - } - .testTag(TestTags.memberDetailAvatar) - ) - } -} - -@Preview(group = PreviewGroup.Avatars) -@Composable -internal fun DmAvatarsPreview() = ElementThemedPreview { - val size = AvatarSize.DmCluster - DmAvatars( - userAvatarData = anAvatarData( - id = "Alice", - name = USER_NAME_ALICE, - size = size, - ), - otherUserAvatarData = anAvatarData( - id = "Bob", - name = USER_NAME_BOB, - size = size, - ), - openAvatarPreview = {}, - openOtherAvatarPreview = {}, - ) -} - -@Preview(group = PreviewGroup.Avatars) -@Composable -internal fun DmAvatarsRtlPreview() { - CompositionLocalProvider( - LocalLayoutDirection provides LayoutDirection.Rtl, - ) { - DmAvatarsPreview() - } -} diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png index 5f0cdd8eca..43a49f7320 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33d583fac967f383a3d3535c4ac38aaccdcbf4a1d48323ff375a239dbce81838 -size 83494 +oid sha256:34ce2f0451fb1681648c91771316256e67b1f295f4deb97f6115ae593d82f2ef +size 83472 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png index d674b1ad00..bb68ee4d65 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ad7b9331a5d504b8d2145c4428e6b64ed838b371f1aad5c288e5545f8a20f1f -size 45464 +oid sha256:eeb2355a693a7ac522028833fea4f0506e1b455e4aee888ed314c2700a9a87af +size 45454 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png index 2567512ca9..77bc91df06 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d74ede198f221b1138ed49bac7e02ee0fefbccd38735b09237fda95a78f6bd2 -size 44174 +oid sha256:b45d35b68d232fc5cbaf3b01156127a77618bcf2197375ad42f61bc7ad8ec400 +size 44161 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png index ee9fcd2088..9f23841e1d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3f483a9e05278928f806f9534720c121efa77bd11b93ea6afc8b543f51a6d7c -size 43171 +oid sha256:6a7efaa997737bfc6db898987b78077ec3c8039a6d0cce84d770bcabcbdc815e +size 43161 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png index 724a99374d..308c764795 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3045102b9695ce3c095ac81e3d3d26dbf182d433427903e280189613a74f2984 -size 44758 +oid sha256:a8de9a9297383ff1ec552304a49040c44236654dd16ba9ae5f54fddf3e14c617 +size 44764 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png index c62a4e99b7..13403ea92d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2bbbf23895558745ebe4fab7faee8ffb4acba07f48b652cc130c78ddf89bebef -size 44684 +oid sha256:ff4c856028887c1390df7b313462e37e0723ff98b9f92aa769b2fc9133ab6ec5 +size 44673 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png index f23e6e5532..59ac3c53af 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f72fb044fb52f226600ad2eb3344e8122edcce15c75800fb483f3b93a1c6e26 -size 45092 +oid sha256:162a9cd8b10b8ec7c33dc926c63d2d04986ca0e29a6cd036771ffc137176e28c +size 45079 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png index 47f40ccaab..9d934ba726 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14261c716c286b17ee2afcb652378f9703b39f67b219256f6ac3cde61cd50947 -size 45589 +oid sha256:fcd3e86c18e34e96a2b535340a27a8cb248d48697ce75d1c7c62cde27b3e2ccb +size 45577 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png index fd5b8fce76..cfd42f8af2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1b1c3f8db4dc58dcaab91f254da2906138c09c65d4e57a77a5be9af371aaa5d -size 44944 +oid sha256:d5a20887fa9a6dd7c96f328f24608e1fcea0326b60cf8a7b43e2387fa19595f5 +size 44932 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png index 5491a33e2a..b45fd6c6f1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5d3a4bd5c340c0d439ccd7d7e24f372d89255a775a9497e5d9b8847354cafb6 -size 44236 +oid sha256:8087a634dd7bf3893697d8ab599f9694169e878b4484b0d8e9821307a8423d63 +size 44243 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index e44f676f01..ddcd78552d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d9a464a1bc24dc76d1a10ae835fb24839b521ba446a1adad3e70f4ae5f17857 -size 42076 +oid sha256:f7b9375965be172b7a1a6b00be38c66dc5f73d7d76f6b07fd1cb8defbadae840 +size 41554 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 46bb9b0a89..669af01562 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29592dcede3af29136c857b03975c2697470682371ac5d606f2e6974f89ea268 -size 42030 +oid sha256:7890cc2fc8e722bfdee5e1c0cdda335c386a2e70a918b710a44a788457dd8497 +size 41507 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png index d58516f709..6b89622e9d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:676908cf3eabc3417f228dabd2663bb0aa3d903d1b6f0e2fe770bdd6fbb48af2 -size 40407 +oid sha256:e7b4d5f81f605a0858994e50d72fbd17d2f82e0b2e4673ff9baf6e25a103ef55 +size 40392 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png index 7cc47cba6d..b0a44326fd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c66ebe3c16933495fe33596036363f95e20654b6ef5ee822f594a34531ea640f -size 45211 +oid sha256:fef854b4c908e206ece79491c655fbf0fd5b51883f3d77045c579664331b9058 +size 45195 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png index 8d4880b59f..637549dfc7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de5ccdad3e08ed4fd4330697ad6c7085d5553cb889b7b7c12879aaaa6b34c1de -size 44953 +oid sha256:dde778a13f36958fefba950fe0d3470b7277d22fe4eac189c77b0838b3728ef3 +size 44940 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png index 52e66c38c8..cafc853f58 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e215296d864d34ceacaa53e7fec452643b63d72b253074eb50617bab50915ad1 -size 44670 +oid sha256:d5870cd12f6de78ecf72a9dc8e3716e0e3476ecf2f29647fc1eca900f5e030f9 +size 44652 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png index 2a765938ad..12efcf7526 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae13e58b01e0e43591c0374474b33fea60574a5d8b22cb57092d15637dc58baa -size 37920 +oid sha256:1281394671737e78232cb7d9785b57b8ef2ca50c125f0c0854d101d27efaa939 +size 37910 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png index 8a7f2e2d75..3d6f26c63c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0cc874a4ba2b8bd0f0b7e290d0ffc67e82d1222fd287360c3321143d5f87ad4 -size 42369 +oid sha256:ec2b5711ea9ffacc6aad4f7b16efdcc78603e9eaa9d33abfaa0d867db5aead67 +size 42355 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png index c8d3e8f6fa..90dd2364d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5bb345d25a8b90a34708123fc6ba72dd6aca2c09ade4c26b29e9168d65e18be -size 42466 +oid sha256:4adfa037ff619098067d03f252ba0af1c3c89553ea0c81dcda41f7f0b655baad +size 42450 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index cdb5f92f18..31daf341c2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1d4af8779d9869938b17f26b155c584c10d119479c62918d5b819a0db30acac -size 41720 +oid sha256:105399c3ca12de9e911ccf7b4aaebe87bffeba45b1740d067b5b8e67c5647952 +size 41196 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png index 1e0b3070ee..3309d53220 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fac98b00a99771b186e8146b98ab63602be7b4c5cc9febc3ca821c1d5cd6a1b -size 42700 +oid sha256:5da1fef365731946e08a38250187fe6f3108aff466d7771863c0ba52fb5b7728 +size 42254 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png index 478f3dcb3c..fc66173002 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cb0953ce6c69ad2e49213bf0dbff76a87505f88a092660b71d97ad1e75a5344 -size 45766 +oid sha256:0d5b8a9f7bc2e7f654b018b2f66b5971c21326dd6b64371f330299649daea4c0 +size 45755 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png index 37a67e7aa0..d4ff65b44f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0f655ed143e7b894e37d99fc64c75d44e6483e830055e04609a9da36830278c -size 44670 +oid sha256:2dd6b524bd146b4e66621fea59515e6784055f52f6d1d08c393b5be208e5f29a +size 44657 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png index b41099055e..4264857e69 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac26ca718f2118d88315704ce4bc7960983ab2ac0c394199da2c5b3feeec4438 -size 44688 +oid sha256:73a27b8df68182a3d0ae4872a14688ae10e5651ec85490c1e46186acc2c60028 +size 44671 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png index 836386fc75..f0751a53cd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a9c05a4ace7dc7013e4b02b5e652296399cb2f391ed4bacb2f74d06b68c4be4 -size 46436 +oid sha256:9bedc6d0b55d94586de728cb4039303c9ecbd8b3a090c401331ae1bf6e0ba426 +size 46396 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png index f3ee29437c..f5f4d4cf3c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:997444daf4024495291014f1cae1cee2ba389d160c0ccae706b120dcd908996e -size 45024 +oid sha256:d47a7207e83fe770d4925b91b4bb0eee6cb2c494c46b1f3d5d6d0720464392d6 +size 44992 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png index 5ccda85a79..54890aa7bd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:527d2c4574c8a5f6946ee94415e30152fdd9e153fd7651b5a40df789e8694d72 -size 43969 +oid sha256:605ea373238bbaa4d3820adf13bf3896d9a5c5b6ceb6c022a7f3b8ae817f921f +size 43927 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png index 60753106e7..385ca39bc9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7da6bfdf7bc9878e1850f8a443adae82a3a4b0aaa5574cec74081ba6f88b879e -size 45622 +oid sha256:c4dab72328925eb45cd529913972670587ea4257d2ff7affd708295d68e783d7 +size 45579 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png index 5549792942..064cfc5b27 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e253e47f998774da8443926990526105fd918b79040955a3d884558a110db8a -size 45538 +oid sha256:76cc029a07c0fb568d9e15864be667478cd9927095f66ec2f590a1466c58a291 +size 45497 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png index e5dac7dc72..3bcd7d1de4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60a989450ffb8ed428d5dd021573b821d238a06f5515f21f9d50b855889ad985 -size 46022 +oid sha256:42a8b9b5abe3a5a3fe61e27924ca75ea7925e857005d5de3cd3ceb81500f73c2 +size 45981 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png index d4143895a2..5dc96aaa2c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37e6049854cd5aaeb50f38c4604e631fb561f0f309d4c58d41becf69a01ca036 -size 46596 +oid sha256:19cc2df1da3b685668afe309bd305d5ac8447d0997c7ad902685d44daa26239f +size 46556 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png index 03bcda4666..2b4718d729 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05a841f7590a33ffea5b09ffc0975bc9090b03cace9e22c330965ce773431211 -size 45849 +oid sha256:5625bb01c24d969adeecdb536e145ba549ef1c10d99e16f7a68c3bd577fbefbc +size 45804 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png index 19d509d513..4f40cab65a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bc90cce90b0648a340e332276fe4395aec673408aaf938bd0d744d45c89dec2 -size 45396 +oid sha256:3bdd0b00fddd9fc62b5c9c97b5ff766591c0a1822730bd249059ed02508a65ee +size 45353 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index 8027c68a7b..74405c8661 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3ab8eeb4123df1feb35b4d9d9c7fbf166be943edfeb9fa23ac6549463763b10 -size 42853 +oid sha256:fef392cb892bf6dc746ed59f1279bf9558536ef439715d1834bd88260739949d +size 42441 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index 64acd4e843..dd6c6a993d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3eee4e61c8676a547c3ccbb1d6b9ea2ce0ae30286012de6b3a4f912b908d2e0 -size 42722 +oid sha256:c9b7c26c5f0638dbe7731e239fc16bb2ba4330986af7218688a3a12ede2bfd9d +size 42313 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png index ef06cd3451..02be5d5da0 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02c734eb60efab5050988331527aae294fc6baf0b110e3395103429a79ba059c -size 41424 +oid sha256:4dd437c614c904bf210e5b51fe017f26cf849e7572b09966e834ac6fd429d347 +size 41380 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png index 9462f1336b..7c037817b4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:389fcb65c5334f31b3d66731de2c65128d0a17e7380ca7c45be8a36023719732 -size 46097 +oid sha256:380fbdd2caa485b9fe84a331e64139ccb23998ce1d95158c6345364daa3810b8 +size 46048 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png index f1f9639eae..7b74e5750c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:567cefb525795b66704ccd1738bfe08247004814c947f6c60801588304c768c2 -size 45835 +oid sha256:c4610f8488c8c8edf05e2cd3e09470660b2c4db14650907c28367d2b38bce852 +size 45792 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png index fb830369a5..a2e1108c0c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f87512e18ca91237141d97ed03f4725a8a671268daf50f0a8049ee34bdc42a61 -size 45503 +oid sha256:efb795d2808d7ae5e38eda42105101dce377154c794844f752e4cb80dcabd681 +size 45462 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png index 25bcd31599..2d38f9d8b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ced1cdb2e11bff01ffce233ddf6cf826d6db266739abcd022f83b58d8bec012f -size 38785 +oid sha256:7dca0800e7e68e65bd27814b4c86123da40385d6e85153e003ba58ca7689b5f8 +size 38742 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png index a64f6a2843..1fc42278e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfd96490ce4509620efd7be72e6ecca219eafe73050417c0c3685339444457f1 -size 43060 +oid sha256:351183a1b0fb44dc42c790a625ee6aa5740b27fa95b138252b72bf67268f5a16 +size 43015 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png index 92b2b86922..da0c4a9dde 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db67d40bae68ec1ece950a06f618606fedc78aa997743b1804db4b69848ba65b -size 43381 +oid sha256:31f92cc4d97c7129bc37da51e6f0a10612d4f61803762b1709c5d72f1cda86f1 +size 43337 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index 8b143f6b5c..e6cae695cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cee9f291a3257f3960ea5d1490f3f219bb0d42b01109b9b398b941524b85971 -size 42383 +oid sha256:8d6a5102a9dd44a6a15dc6b40ec422a115a302506a2b3808a1df84ca34cb323e +size 41972 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png index 2f72417b73..a1947b9c2c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd455b5b492eb88bde4e985ca01ab97e23a337d7ac478782c09dbb10803960f2 -size 43430 +oid sha256:1538aa1f1313df1f6cbbc0ed7ef92d264c85b7de0080492a7cba19bbd235131d +size 43100 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png index a1071426b1..ae9d249cb2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79ac979bcc0339ed30c68c4617f082a9398edf657cc3aea1c80df04bd4b8bab2 -size 46724 +oid sha256:4e15030fc182998a37493228d91c888d6b499b6a684b1a4e15d402c9156a40ba +size 46678 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png index 36a3defc1f..214dee1111 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d71c5e3a8dd2defe2dd37fee1a22921f49bbc9a52a766e5ad082b6595c6ff75 -size 45577 +oid sha256:b773cce165a6410140afbf0daf3ec526233b97ea707811a3794e591704237398 +size 45536 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png index 6c4e522988..41946442cb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ada1e17913092a5e33b5f422a41826dd711102cfb5ab396d5d323e8e0f0b6589 -size 45590 +oid sha256:f28bec4fb21e827f3467bc08ab0f33e917cf76360903b6e7df6282a7589cae7e +size 45545 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png deleted file mode 100644 index b96321378c..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9dda468dafd8eb072ad7f3b731e55fbd1f8a4e11e8765f566b929b1d367fd0e0 -size 13693 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png deleted file mode 100644 index 097602787d..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:69e9858a04efe0160908bd0b85990dce8e983db33408ca58752bd4dc1eef6861 -size 13576 From 071d98c66b6e7b4e908b0ba25b4a81228c1a4e81 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 8 May 2026 17:30:32 +0300 Subject: [PATCH 0384/1083] Render media captions formatting in the media viewer (#6729) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Render media captions formatting in the media viewer * Update screenshots * Trigger actions * Remove unused imports and reformat code --------- Co-authored-by: ElementBot Co-authored-by: Jorge Martín --- .../messages/impl/MessagesFlowNode.kt | 1 + .../libraries/mediaviewer/api/MediaInfo.kt | 14 ++++ libraries/mediaviewer/impl/build.gradle.kts | 3 + .../impl/DefaultMediaViewerEntryPoint.kt | 1 + .../impl/datasource/EventItemFactory.kt | 6 ++ .../impl/local/AndroidLocalMediaFactory.kt | 1 + .../impl/viewer/MediaViewerStateProvider.kt | 80 +++++++++++++++++++ .../impl/viewer/MediaViewerView.kt | 42 +++++++--- .../TimelineMediaGalleryDataSourceTest.kt | 1 + .../mediaviewer/test/FakeLocalMediaFactory.kt | 1 + ....viewer_MediaViewerViewLandscape_17_en.png | 4 +- ....viewer_MediaViewerViewLandscape_18_en.png | 3 + ....viewer_MediaViewerViewLandscape_19_en.png | 3 + ....viewer_MediaViewerViewLandscape_20_en.png | 3 + ....viewer_MediaViewerViewLandscape_21_en.png | 3 + ....viewer_MediaViewerViewLandscape_22_en.png | 3 + ...l.viewer_MediaViewerViewLandscape_3_en.png | 4 +- ...l.viewer_MediaViewerViewLandscape_4_en.png | 4 +- ...ewer.impl.viewer_MediaViewerView_17_en.png | 4 +- ...ewer.impl.viewer_MediaViewerView_18_en.png | 3 + ...ewer.impl.viewer_MediaViewerView_19_en.png | 3 + ...ewer.impl.viewer_MediaViewerView_20_en.png | 3 + ...ewer.impl.viewer_MediaViewerView_21_en.png | 3 + ...ewer.impl.viewer_MediaViewerView_22_en.png | 3 + ...iewer.impl.viewer_MediaViewerView_3_en.png | 4 +- ...iewer.impl.viewer_MediaViewerView_4_en.png | 4 +- 26 files changed, 182 insertions(+), 22 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 7b0515a423..ff46ce0041 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 @@ -646,6 +646,7 @@ class MessagesFlowNode( filename = content.filename, fileSize = content.fileSize, caption = content.caption, + formattedCaption = content.formattedCaption, mimeType = content.mimeType, formattedFileSize = content.formattedFileSize, fileExtension = content.fileExtension, diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt index 74b479dc8c..fedf376a60 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt @@ -17,6 +17,7 @@ import kotlinx.parcelize.Parcelize data class MediaInfo( val filename: String, val caption: String?, + val formattedCaption: CharSequence? = null, val mimeType: String, val fileSize: Long?, val formattedFileSize: String, @@ -33,6 +34,7 @@ data class MediaInfo( fun anImageMediaInfo( senderId: UserId? = UserId("@alice:server.org"), caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -40,6 +42,7 @@ fun anImageMediaInfo( filename = "an image file.jpg", fileSize = 4 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Jpeg, formattedFileSize = "4MB", fileExtension = "jpg", @@ -54,6 +57,7 @@ fun anImageMediaInfo( fun aVideoMediaInfo( caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -62,6 +66,7 @@ fun aVideoMediaInfo( filename = "a video file.mp4", fileSize = 14 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Mp4, formattedFileSize = "14MB", fileExtension = "mp4", @@ -77,6 +82,7 @@ fun aVideoMediaInfo( fun aPdfMediaInfo( filename: String = "a pdf file.pdf", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -84,6 +90,7 @@ fun aPdfMediaInfo( filename = filename, fileSize = 23 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Pdf, formattedFileSize = "23MB", fileExtension = "pdf", @@ -105,6 +112,7 @@ fun anApkMediaInfo( filename = "an apk file.apk", fileSize = 50 * 1024 * 1024, caption = null, + formattedCaption = null, mimeType = MimeTypes.Apk, formattedFileSize = "50MB", fileExtension = "apk", @@ -120,6 +128,7 @@ fun anApkMediaInfo( fun anAudioMediaInfo( filename: String = "an audio file.mp3", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -129,6 +138,7 @@ fun anAudioMediaInfo( filename = filename, fileSize = 7 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Mp3, formattedFileSize = "7MB", fileExtension = "mp3", @@ -144,6 +154,7 @@ fun anAudioMediaInfo( fun aVoiceMediaInfo( filename: String = "a voice file.ogg", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -153,6 +164,7 @@ fun aVoiceMediaInfo( filename = filename, fileSize = 3 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Ogg, formattedFileSize = "3MB", fileExtension = "ogg", @@ -168,6 +180,7 @@ fun aVoiceMediaInfo( fun aTxtMediaInfo( filename: String = "a text file.txt", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -175,6 +188,7 @@ fun aTxtMediaInfo( filename = filename, fileSize = 2 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.PlainText, formattedFileSize = "2kB", fileExtension = "txt", diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index 9c2342ecd9..cd1579d50d 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -25,6 +25,9 @@ android { setupDependencyInjection() dependencies { + implementation(libs.matrix.richtexteditor.compose) + implementation(libs.matrix.richtexteditor) + implementation(projects.libraries.textcomposer.impl) implementation(libs.coroutines.core) implementation(libs.coil.compose) implementation(libs.androidx.media3.exoplayer) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt index e1e112ecfa..138f6382d2 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt @@ -32,6 +32,7 @@ class DefaultMediaViewerEntryPoint : MediaViewerEntryPoint { filename = filename, fileSize = null, caption = null, + formattedCaption = null, mimeType = mimeType, formattedFileSize = "", fileExtension = "", diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt index 379c70f960..898a29aa7a 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt @@ -98,6 +98,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -118,6 +119,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -139,6 +141,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -160,6 +163,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -181,6 +185,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -202,6 +207,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt index 05cbe40f36..83e8a17cf4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt @@ -97,6 +97,7 @@ class AndroidLocalMediaFactory( filename = fileName, fileSize = fileSize, caption = caption, + formattedCaption = null, formattedFileSize = calculatedFormattedFileSize, fileExtension = fileExtension, senderId = senderId, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index cb1da7b9b2..8cc14d6445 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -195,6 +195,86 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) ) }, + anImageMediaInfo( + senderName = "Bob", + dateSent = "22 NOV, 2024", + formattedCaption = "This is a bold caption", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Charlie", + dateSent = "23 NOV, 2024", + formattedCaption = "This is an italic caption", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Diana", + dateSent = "24 NOV, 2024", + formattedCaption = "This is a code caption", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Eve", + dateSent = "25 NOV, 2024", + formattedCaption = "
This is a quote caption
", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Frank", + dateSent = "26 NOV, 2024", + formattedCaption = "This caption has bold, italic, and code formatting.", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 3738f6643b..8bc5088187 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -31,8 +31,11 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -59,10 +62,12 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import androidx.core.text.toSpannable import coil3.compose.AsyncImage import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.viewfolder.api.TextFileViewer +import io.element.android.libraries.androidutils.text.safeLinkify import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.audio.api.AudioFocus import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo @@ -91,7 +96,9 @@ import io.element.android.libraries.mediaviewer.impl.local.LocalMediaView import io.element.android.libraries.mediaviewer.impl.local.PlayableState import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState import io.element.android.libraries.mediaviewer.impl.util.bgCanvasWithTransparency +import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.wysiwyg.compose.EditorStyledText import kotlinx.coroutines.delay import me.saket.telephoto.zoomable.OverzoomEffect import me.saket.telephoto.zoomable.ZoomSpec @@ -242,6 +249,7 @@ fun MediaViewerView( MediaViewerBottomBar( showDivider = dataForPage.mediaInfo.mimeType.isMimeTypeVideo(), caption = dataForPage.mediaInfo.caption, + formattedCaption = dataForPage.mediaInfo.formattedCaption, onHeightChange = { bottomPaddingInPixels = it }, ) } @@ -545,6 +553,7 @@ private fun MediaViewerTopBar( @Composable private fun MediaViewerBottomBar( caption: String?, + formattedCaption: CharSequence?, showDivider: Boolean, onHeightChange: (Int) -> Unit, modifier: Modifier = Modifier, @@ -557,7 +566,7 @@ private fun MediaViewerBottomBar( onHeightChange(it.height) }, ) { - if (caption != null) { + if (caption != null || formattedCaption != null) { if (showDivider) { HorizontalDivider() } @@ -568,15 +577,28 @@ private fun MediaViewerBottomBar( .fillMaxWidth() .heightIn(max = if (hasCompactHeightWindowSize()) maxCaptionHeightLandscape else maxCaptionHeightPortrait), ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .verticalScroll(scrollState) - .navigationBarsPadding(), - text = caption, - style = ElementTheme.typography.fontBodyLgRegular, - ) + val textToRender = when { + formattedCaption != null -> formattedCaption + caption != null -> caption.safeLinkify().toSpannable() + else -> null + } + if (textToRender != null) { + CompositionLocalProvider( + LocalContentColor provides ElementTheme.colors.textPrimary, + LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular + ) { + EditorStyledText( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .verticalScroll(scrollState) + .navigationBarsPadding(), + text = textToRender, + style = ElementRichTextEditorStyle.textStyle(), + releaseOnDetach = false, + ) + } + } if (showBottomShadow) { Box( modifier = Modifier diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt index 528fc1da70..88aefb842c 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt @@ -235,6 +235,7 @@ class TimelineMediaGalleryDataSourceTest { filename = "body.jpg", fileSize = 888L, caption = "body.jpg caption", + formattedCaption = "formatted", mimeType = MimeTypes.Jpeg, formattedFileSize = "888 Bytes", fileExtension = "jpg", diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt index faa27fd0e3..8dbee232df 100644 --- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt +++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt @@ -41,6 +41,7 @@ class FakeLocalMediaFactory( filename = safeName, fileSize = null, caption = null, + formattedCaption = null, mimeType = mimeType ?: fallbackMimeType, formattedFileSize = formattedFileSize ?: fallbackFileSize, fileExtension = fileExtensionExtractor.extractFromName(safeName), diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png index 36ecce8294..2e580e55a4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5aa3bca6cd248ac4725fb35aa11a465029dc534b8b167aedbf3e9bc240577e9c -size 654171 +oid sha256:4e8ce597c240a7e72b6811537b6fd24e1bd38714db0ce074377ab3f16eaf0436 +size 656958 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png new file mode 100644 index 0000000000..b18a209110 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46d390cfe8d41536cea5e90cb38aa547969ae24d82027c02cfb71c4fbc780247 +size 667948 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png new file mode 100644 index 0000000000..e22d5b8e72 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bd4f0133fc3a4a159e3eda1f715e4140464b7c67558c551216546d4688f21bc +size 669143 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png new file mode 100644 index 0000000000..1023508292 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:178de2176a3932665897486ecbee622083af2d5939f4f1f7f0bdc4667a61e36a +size 668061 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png new file mode 100644 index 0000000000..9fa3e43792 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc974dfc6206f389153477d287a69c401ddc154a529cb892227a743acee8ac50 +size 668212 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png new file mode 100644 index 0000000000..081ab9a80b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7ac632f2062aa4a13ee46fd2fef6d9e6be25270f4790247131231163670cbe6 +size 670668 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png index c63d5a9110..d122817b15 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd5b76aefb0fde0605556e78c7286bf8ee8dd465def0e3095ebc97ce3427eafa -size 666239 +oid sha256:21b8289db279172f042fa902bdbdb70d87104d342a1140357bb1ac2bc18f6590 +size 668482 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png index d404456119..797c1cb2cb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6870b9c1a5aad4257aa4bd7b13d0be5bea281778061d71c711495aadfaafdb8 -size 206057 +oid sha256:f72964447f2fa66e8df38fcff4a84ada1cf62e1646a2e8a00c61f8f151abfa8c +size 206507 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png index 5b167203f5..be398e06bf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bddbe3b0e66e0a2ce49b39321057c94427933de81663f680237a398e9929ba3 -size 442729 +oid sha256:2adfc04e0f7999ba861bf931b853f068067387558e81464e99caba1c2445a3a7 +size 444811 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png new file mode 100644 index 0000000000..057e117409 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0487a6dbc3a2f3bfb79a709c782fb692ef93f37607b4483095ce76f08954580e +size 396582 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png new file mode 100644 index 0000000000..bc7a7cc257 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29833e4103ecf4bd3e1c5da384d3bcc20031073a14261971825e97bc9f1dad23 +size 397593 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png new file mode 100644 index 0000000000..aa8d934627 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b544362587868c37edc424b675c6758e7ffcff359fa12c1cfcb874a0502e25de +size 397284 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png new file mode 100644 index 0000000000..26758e047f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51e183ca6d518d803471ad4eed0ee932397c32a4c1ffb064714b39f13ea2003f +size 396825 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png new file mode 100644 index 0000000000..7f34e6d53c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b6623e0e784a93d6a3aa220b620efe7d1f9e040aedac7f34d01b24262fe101b +size 401770 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png index 167467d515..7d1ba874a3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bd4a96daaa24c01b7d0007fdd14460dc80c65c13d0ccc7a887b04fd90e9fa99 -size 396805 +oid sha256:d56f08f1c37575de90a67ebfeadaf1c891c9ac9e4925af7d048922df9fec5aa9 +size 396815 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png index c44162b0ff..52f17795bb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0249f33aca3e50713c87a3826e71985991f0996998132c42a374c6169800023 -size 130728 +oid sha256:e3a148746b4f7428688a634f2b1299f0393bf669a665c94fa9af12d7839e72a0 +size 130834 From 0c657c258ad5fb4c9b234c7fc432722d1696dfe0 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 11 May 2026 09:37:59 +0200 Subject: [PATCH 0385/1083] Sync Strings from Localazy (#6761) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- .../src/main/res/values-pl/translations.xml | 32 +- .../src/main/res/values-uk/translations.xml | 10 + .../src/main/res/values-el/translations.xml | 6 +- .../src/main/res/values-et/translations.xml | 4 +- .../src/main/res/values-it/translations.xml | 6 +- .../src/main/res/values-pl/translations.xml | 6 +- .../src/main/res/values-uz/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 3 +- .../src/main/res/values-pl/translations.xml | 7 +- .../src/main/res/values-it/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 4 + .../src/main/res/values-uk/translations.xml | 4 + .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 19 + .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-el/translations.xml | 5 + .../src/main/res/values-et/translations.xml | 4 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-it/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 6 + .../src/main/res/values-uk/translations.xml | 5 + .../src/main/res/values-zh/translations.xml | 1 + .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 2 +- .../src/main/res/values-el/translations.xml | 9 +- .../src/main/res/values-fa/translations.xml | 2 + .../src/main/res/values-it/translations.xml | 3 +- .../src/main/res/values-pl/translations.xml | 13 +- .../src/main/res/values-uk/translations.xml | 11 +- .../src/main/res/values-fa/translations.xml | 16 +- .../src/main/res/values-pl/translations.xml | 26 +- .../src/main/res/values-sk/translations.xml | 10 +- .../src/main/res/values-uk/translations.xml | 4 +- .../src/main/res/values-fa/translations.xml | 8 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 5 + .../src/main/res/values-fa/translations.xml | 3 + .../src/main/res/values-it/translations.xml | 8 + .../src/main/res/values-pl/translations.xml | 9 + .../src/main/res/values-uk/translations.xml | 9 + .../src/main/res/values-fa/translations.xml | 1 + .../src/main/res/values-uk/translations.xml | 2 + .../src/main/res/values-fa/translations.xml | 20 +- .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-it/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 42 +- .../src/main/res/values-uk/translations.xml | 5 + .../src/main/res/values-zh/translations.xml | 1 + .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-be/translations.xml | 1 + .../src/main/res/values-bg/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-cy/translations.xml | 1 + .../src/main/res/values-da/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-es/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-eu/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 23 +- .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-hr/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-in/translations.xml | 1 + .../src/main/res/values-it/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 1 + .../src/main/res/values-ka/translations.xml | 1 + .../src/main/res/values-ko/translations.xml | 1 + .../src/main/res/values-lt/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 81 +- .../main/res/values-pt-rBR/translations.xml | 1 + .../src/main/res/values-pt/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values-sv/translations.xml | 1 + .../src/main/res/values-tr/translations.xml | 1 + .../src/main/res/values-uk/translations.xml | 15 + .../src/main/res/values-ur/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 1 + .../src/main/res/values-vi/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 1 + .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-uk/translations.xml | 2 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 4 +- .../src/main/res/values-fa/translations.xml | 12 +- .../src/main/res/values-pl/translations.xml | 31 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 43 +- .../src/main/res/values-uk/translations.xml | 6 + .../src/main/res/values-fa/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 12 + .../src/main/res/values-uk/translations.xml | 14 + .../src/main/res/values-fa/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 6 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 2 +- .../src/main/res/values-it/translations.xml | 2 + .../src/main/res/values-pl/translations.xml | 2 + .../src/main/res/values-uk/translations.xml | 2 + .../src/main/res/values-it/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 1 + .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 12 +- .../src/main/res/values-uk/translations.xml | 15 + .../src/main/res/values-be/translations.xml | 1 - .../src/main/res/values-bg/translations.xml | 1 - .../src/main/res/values-cs/translations.xml | 1 - .../src/main/res/values-cy/translations.xml | 1 - .../src/main/res/values-da/translations.xml | 1 - .../src/main/res/values-de/translations.xml | 1 - .../src/main/res/values-el/translations.xml | 9 +- .../src/main/res/values-es/translations.xml | 1 - .../src/main/res/values-et/translations.xml | 17 +- .../src/main/res/values-eu/translations.xml | 1 - .../src/main/res/values-fa/translations.xml | 7 +- .../src/main/res/values-fi/translations.xml | 1 - .../src/main/res/values-fr/translations.xml | 1 - .../src/main/res/values-hr/translations.xml | 1 - .../src/main/res/values-hu/translations.xml | 5 +- .../src/main/res/values-in/translations.xml | 1 - .../src/main/res/values-it/translations.xml | 19 +- .../src/main/res/values-ja/translations.xml | 1 - .../src/main/res/values-ka/translations.xml | 1 - .../src/main/res/values-ko/translations.xml | 1 - .../src/main/res/values-lt/translations.xml | 1 - .../src/main/res/values-nb/translations.xml | 1 - .../src/main/res/values-nl/translations.xml | 1 - .../src/main/res/values-pl/translations.xml | 90 +- .../main/res/values-pt-rBR/translations.xml | 1 - .../src/main/res/values-pt/translations.xml | 1 - .../src/main/res/values-ro/translations.xml | 2 +- .../src/main/res/values-ru/translations.xml | 1 - .../src/main/res/values-sk/translations.xml | 11 +- .../src/main/res/values-sv/translations.xml | 1 - .../src/main/res/values-tr/translations.xml | 1 - .../src/main/res/values-uk/translations.xml | 58 +- .../src/main/res/values-ur/translations.xml | 1 - .../src/main/res/values-uz/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 1 - .../main/res/values-zh-rTW/translations.xml | 1 - .../src/main/res/values-zh/translations.xml | 7 +- .../src/main/res/values/localazy.xml | 4 +- .../de/appnav.root_RootView_Day_0_de.png | 4 +- .../de/appnav.root_RootView_Day_1_de.png | 4 +- ...cline_AcceptDeclineInviteView_Day_1_de.png | 4 +- ...cline_AcceptDeclineInviteView_Day_2_de.png | 4 +- ...mpl.unlock_PinUnlockViewInApp_Day_8_de.png | 3 + ...mpl.unlock_PinUnlockViewInApp_Day_9_de.png | 3 + ...een.impl.unlock_PinUnlockView_Day_8_de.png | 3 + ...een.impl.unlock_PinUnlockView_Day_9_de.png | 3 + ...TimelineItemRoomBeginningView_Day_0_de.png | 4 +- ...ts_TimelineEventTimestampView_Day_3_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_17_de.png | 4 +- ...pl.topbars_MessagesViewTopBar_Day_0_de.png | 4 +- ...impl.root_PreferencesRootViewDark_0_de.png | 4 +- ...impl.root_PreferencesRootViewDark_1_de.png | 4 +- ...impl.root_PreferencesRootViewDark_2_de.png | 4 +- ...impl.root_PreferencesRootViewDark_3_de.png | 4 +- ...impl.root_PreferencesRootViewDark_4_de.png | 4 +- ...impl.root_PreferencesRootViewDark_5_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_0_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_1_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_2_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_3_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_4_de.png | 4 +- ...mpl.root_PreferencesRootViewLight_5_de.png | 4 +- ....api.crash_CrashDetectionView_Day_0_de.png | 4 +- ...ection_RageshakeDialogContent_Day_0_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_0_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_10_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_11_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_12_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_13_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_14_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_15_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_16_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_17_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_18_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_1_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_20_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_21_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_22_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_2_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_3_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_4_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_6_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_7_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_8_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_9_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_0_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_10_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_11_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_12_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_13_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_14_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_15_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_16_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_17_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_1_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_20_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_21_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_22_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_2_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_3_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_4_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_6_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_7_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_8_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_9_de.png | 4 +- ...nents_SearchMultipleUsersResultItem_de.png | 4 +- ...mponents_SearchSingleUserResultItem_de.png | 4 +- ...tchat.impl.root_StartChatView_Day_0_de.png | 4 +- ...tchat.impl.root_StartChatView_Day_1_de.png | 4 +- ...tchat.impl.root_StartChatView_Day_2_de.png | 4 +- ...tchat.impl.root_StartChatView_Day_3_de.png | 4 +- ...tchat.impl.root_StartChatView_Day_4_de.png | 4 +- ...tchat.impl.root_StartChatView_Day_5_de.png | 3 - ...rofile.shared_UserProfileView_Day_8_de.png | 4 +- ...mponents_CheckableUnresolvedUserRow_de.png | 4 +- ...eateDmConfirmationBottomSheet_Day_0_de.png | 4 +- ...eateDmConfirmationBottomSheet_Day_1_de.png | 4 +- ....components_SpaceRoomItemView_Day_2_de.png | 4 +- ....components_SpaceRoomItemView_Day_8_de.png | 4 +- ...rix.ui.components_UnresolvedUserRow_de.png | 4 +- screenshots/html/data.js | 2132 +++++++++-------- 248 files changed, 1988 insertions(+), 1448 deletions(-) create mode 100644 features/location/impl/src/main/res/values-el/translations.xml create mode 100644 features/location/impl/src/main/res/values-et/translations.xml create mode 100644 features/location/impl/src/main/res/values-pl/translations.xml create mode 100644 features/location/impl/src/main/res/values-uk/translations.xml create mode 100644 screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png create mode 100644 screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png create mode 100644 screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png create mode 100644 screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png delete mode 100644 screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png diff --git a/features/createroom/impl/src/main/res/values-pl/translations.xml b/features/createroom/impl/src/main/res/values-pl/translations.xml index 0164225ea2..b602cb13d8 100644 --- a/features/createroom/impl/src/main/res/values-pl/translations.xml +++ b/features/createroom/impl/src/main/res/values-pl/translations.xml @@ -3,14 +3,34 @@ "Nowy pokój" "Zaproś znajomych" "Wystąpił błąd w trakcie tworzenia pokoju" - "Tylko zaproszone osoby mogą dołączyć do tego pokoju. Wszystkie wiadomości są szyfrowane end-to-end." + "Nie udało się utworzyć przestrzeni z powodu nieznanego błędu. Spróbuj ponownie później." + "Dodaj nazwę…" + "Nowy pokój" + "Nowa przestrzeń" + "Dołączyć mogą tylko zaproszone osoby." + "Prywatny" "Każdy może znaleźć ten pokój. Możesz to zmienić w ustawieniach pokoju." - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę" - "Poproś o dołączenie" - "Każdy może dołączyć do tego pokoju" - "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju." - "Adres pokoju" + "Każdy może dołączyć." + "Publiczny" + "Każdy może poprosić o dołączenie, ale administrator lub moderator musi to zaakceptować." + "Zezwól na prośbę o dołączenie" + "Każdy w %1$s może dołączyć, ale wszyscy pozostali muszą poprosić o dostęp." + "Poproś o dołączenie" + "Dołączyć mogą tylko zaproszone osoby." + "Prywatny" + "Każdy może dołączyć." + "Publiczny" + "Każdy w %1$s może dołączyć." + "Standardowy" + "Kto ma dostęp" + "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, potrzebny jest adres pokoju." + "Adres" "Widoczność pomieszczenia" + "(brak przestrzeni)" + "Nie dodawaj do przestrzeni" + "Nie wybrano przestrzeni" + "Dodaj do przestrzeni" "Temat (opcjonalnie)" + "Dodaj opis…"
diff --git a/features/createroom/impl/src/main/res/values-uk/translations.xml b/features/createroom/impl/src/main/res/values-uk/translations.xml index d01da0dc35..a40a2b21a5 100644 --- a/features/createroom/impl/src/main/res/values-uk/translations.xml +++ b/features/createroom/impl/src/main/res/values-uk/translations.xml @@ -3,22 +3,32 @@ "Нова кімната" "Запросити людей" "Під час створення кімнати сталася помилка" + "Простір не вдалося створити через невідому помилку. Спробуйте ще раз пізніше." "Додати назву…" "Нова кімната" "Новий простір" "Можуть приєднатися лише запрошені люди." + "Приватний" "Будь-хто може знайти цю кімнату. Ви можете змінити це в будь-який час у налаштуваннях кімнати." "Приєднатися може будь-хто." + "Публічний" "Будь-хто може подати запит на приєднання, але адміністратор або модератор повинен схвалити запит." "Дозволити запит на приєднання" + "Будь-хто з %1$s може приєднатися, але всі інші повинні подати запит на доступ." + "Запит на приєднання" "Приєднатися можуть лише запрошені особи." + "Приватний" "Приєднатися може будь-хто." + "Публічний" "Приєднатися може будь-хто з %1$s." + "Стандартний" "Хто має доступ" "Вам знадобиться адреса, щоб зробити її видимою в загальнодоступному каталозі." "Адреса" "Видимість кімнати" + "(без пробілу)" + "Не додавати до простору" "Головна" "Додати до простору" "Тема (необов\'язково)" diff --git a/features/deactivation/impl/src/main/res/values-el/translations.xml b/features/deactivation/impl/src/main/res/values-el/translations.xml index ac645f3063..b6a359abbf 100644 --- a/features/deactivation/impl/src/main/res/values-el/translations.xml +++ b/features/deactivation/impl/src/main/res/values-el/translations.xml @@ -1,14 +1,14 @@ - "Παρακαλώ επιβεβαίωσε ότι θες να απενεργοποιήσεις τον λογαριασμό σου. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί." + "Επιβεβαιώστε ότι θέλετε να διαγράψετε τον λογαριασμό σας. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί." "Διαγραφή όλων των μηνυμάτων μου" "Προειδοποίηση: Οι μελλοντικοί χρήστες ενδέχεται να βλέπουν ελλιπείς συνομιλίες." - "Η απενεργοποίηση του λογαριασμού σας είναι %1$s, θα:" + "Η διαγραφή του λογαριασμού σας είναι %1$s, και θα:" "μη αναστρέψιμο" "%1$s τον λογαριασμό σου (δεν μπορείς να συνδεθείς ξανά και το αναγνωριστικό σου δεν μπορεί να επαναχρησιμοποιηθεί)." "Μόνιμη απενεργοποίηση" "Αποχώρησή σας από όλες τις αίθουσες συνομιλίας." "Διαγράψει τα στοιχεία του λογαριασμού σου από τον διακομιστή ταυτότητάς μας." "Τα μηνύματά σου θα εξακολουθούν να είναι ορατά στους εγγεγραμμένους χρήστες, αλλά δεν θα είναι διαθέσιμα σε νέους ή μη εγγεγραμμένους χρήστες εάν επιλέξεις να τα διαγράψεις." - "Απενεργοποίηση λογαριασμού" + "Διαγραφή λογαριασμού" diff --git a/features/deactivation/impl/src/main/res/values-et/translations.xml b/features/deactivation/impl/src/main/res/values-et/translations.xml index 95695fef16..1776e2de17 100644 --- a/features/deactivation/impl/src/main/res/values-et/translations.xml +++ b/features/deactivation/impl/src/main/res/values-et/translations.xml @@ -1,6 +1,6 @@ - "Palun kinnita uuesti, et soovid eemaldada oma konto kasutusest" + "Palun kinnita uuesti, et soovid kustutada oma kasutajakonto. Seda tegevust ei saa tagasi pöörata." "Kustuta kõik minu sõnumid" "Hoiatus: tulevased kasutajad võivad näha poolikuid vestlusi." "Sinu konto kasutusest eemaldamine on %1$s ja sellega:" @@ -10,5 +10,5 @@ "Sind logitakse välja kõikidest jututubadest." "Kustutatakse sinu andmed meie isikutuvastusserverist." "Sinu sõnumid on jätkuvalt nähtavad registreeritud kasutajatele, kuid kui otsustad sõnumid kustutada, siis nad nad pole nähtavad uutele ja registreerimata kasutajatele." - "Eemalda konto kasutusest" + "Kustuta kasutajakonto" diff --git a/features/deactivation/impl/src/main/res/values-it/translations.xml b/features/deactivation/impl/src/main/res/values-it/translations.xml index 7cd484d0e4..e3de1ec8bb 100644 --- a/features/deactivation/impl/src/main/res/values-it/translations.xml +++ b/features/deactivation/impl/src/main/res/values-it/translations.xml @@ -1,14 +1,14 @@ - "Conferma di voler disattivare il tuo account. Questa azione è irreversibile." + "Conferma di voler eliminare il tuo account. Questa azione è irreversibile." "Elimina tutti i miei messaggi" "Attenzione: gli utenti futuri potrebbero vedere conversazioni incomplete." - "La disattivazione del tuo account è %1$s , quindi:" + "L\'eliminazione del tuo account è %1$s, e comporterà:" "irreversibile" "%1$s il tuo account (non puoi riaccedere e il tuo ID non può essere riutilizzato)." "Disattiva permanentemente" "Ti rimuove da tutte le stanze di chat." "Elimina le informazioni del tuo account dal nostro server di identità." "I tuoi messaggi saranno ancora visibili agli utenti registrati, ma non saranno disponibili per gli utenti nuovi o non registrati se decidi di eliminarli." - "Disattivazione dell\'account" + "Elimina account" diff --git a/features/deactivation/impl/src/main/res/values-pl/translations.xml b/features/deactivation/impl/src/main/res/values-pl/translations.xml index bddb6a9037..5778123aa5 100644 --- a/features/deactivation/impl/src/main/res/values-pl/translations.xml +++ b/features/deactivation/impl/src/main/res/values-pl/translations.xml @@ -1,14 +1,14 @@ - "Potwierdź dezaktywacje konta. Tej akcji nie można cofnąć." + "Potwierdź usunięcie konta. Tej akcji nie można cofnąć." "Usuń wszystkie moje wiadomości" "Ostrzeżenie: Przyszli użytkownicy mogą zobaczyć niekompletne rozmowy." - "Dezaktywacja konta jest %1$s, zostanie:" + "Usunięcie konta jest %1$s, co spowoduje:" "nieodwracalna" "%1$s twoje konto (nie będziesz mógł się zalogować, a twoje ID przepadnie)." "Permanentnie wyłączy" "Usunie Ciebie ze wszystkich pokoi rozmów." "Usunięte wszystkie dane konta z naszego serwera tożsamości." "Twoje wiadomości wciąż będą widoczne dla zarejestrowanych użytkowników, ale nie będą dostępne dla nowych lub niezarejestrowanych użytkowników, jeśli je usuniesz." - "Dezaktywuj konto" + "Usuń konto" diff --git a/features/deactivation/impl/src/main/res/values-uz/translations.xml b/features/deactivation/impl/src/main/res/values-uz/translations.xml index d357f38186..e0dcfe59ef 100644 --- a/features/deactivation/impl/src/main/res/values-uz/translations.xml +++ b/features/deactivation/impl/src/main/res/values-uz/translations.xml @@ -10,4 +10,5 @@ "Sizni barcha chat xonalaridan olib tashlash." "Hisobingiz haqidagi axborotni identifikatsiya serverimizdan o‘chirib tashlang." "Xabarlaringiz ro‘yxatdan o‘tgan foydalanuvchilarga ko‘rinadi, lekin ularni o‘chirishni tanlasangiz, yangi yoki ro‘yxatdan o‘tmagan foydalanuvchilarga ko‘rinmaydi." + "Akkauntni o‘chirish" diff --git a/features/ftue/impl/src/main/res/values-pl/translations.xml b/features/ftue/impl/src/main/res/values-pl/translations.xml index 5d77c57994..45ca82ede6 100644 --- a/features/ftue/impl/src/main/res/values-pl/translations.xml +++ b/features/ftue/impl/src/main/res/values-pl/translations.xml @@ -2,8 +2,8 @@ "Nie możesz potwierdzić?" "Utwórz nowy klucz przywracania" - "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." - "Potwierdź, że to Ty" + "Wybierz sposób weryfikacji, aby skonfigurować bezpieczne wiadomości." + "Potwierdź swoją tożsamość cyfrową" "Użyj innego urządzenia" "Użyj klucza przywracania" "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." diff --git a/features/home/impl/src/main/res/values-et/translations.xml b/features/home/impl/src/main/res/values-et/translations.xml index c1f61bfa29..9d938ed941 100644 --- a/features/home/impl/src/main/res/values-et/translations.xml +++ b/features/home/impl/src/main/res/values-et/translations.xml @@ -7,7 +7,7 @@ "Oleme sinu helisid värskendanud" "Loo uus taastevõti, mida saad kasutada oma krüptitud sõnumite ajaloo taastamisel olukorras, kus kaotad ligipääsu oma seadmetele." "Seadista andmete taastamine" - "Seadista taastamine" + "Varunda oma vestlused" "Säilitamaks ligipääsu vestluste ja krüptovõtmete varukoopiale, palun sisesta kinnituseks oma taastevõti." "Sisesta oma taastevõti" "Kas unustasid oma taastevõtme?" diff --git a/features/home/impl/src/main/res/values-fa/translations.xml b/features/home/impl/src/main/res/values-fa/translations.xml index aec50309d8..b0c6a30bc4 100644 --- a/features/home/impl/src/main/res/values-fa/translations.xml +++ b/features/home/impl/src/main/res/values-fa/translations.xml @@ -4,7 +4,7 @@ "از کار انداختن بهینه سازی" "آگاهی‌ها نمی‌رسند؟" "بازگردانی تاریخچهٔ پیام‌ها و هویت رمزنگاشته‌تان با کلید بازیابی در صورت از دست دادن همهٔ افزاره‌های موجودتان." - "برپایی بازیابی" + "دریافت کلید بازیابی" "برپایی بازیابی" "کلید بازیابی خود را تأیید کنید تا دسترسی به حافظه کلیدها و تاریخچه پیام‌هایتان حفظ شود ." "ورود کلید بازیابیتان" @@ -25,6 +25,7 @@ "آغاز با پیام دادن به کسی." "هنوز گپی وجود ندارد." "علاقه‌مندی‌ها" + "می‌توانید در تنظیمات چت، یک چت را به موارد دلخواه خود اضافه کنید. فعلاً می‌توانید فیلترها را غیرفعال کنید تا چت‌های دیگر خود را ببینید." "هنوز هیچ گپ مورد علاقه‌ای ندارید" "دعوت‌ها" "هیچ دعوت منتظری ندارید." diff --git a/features/home/impl/src/main/res/values-pl/translations.xml b/features/home/impl/src/main/res/values-pl/translations.xml index 73e0b5e52e..0c1b07f27b 100644 --- a/features/home/impl/src/main/res/values-pl/translations.xml +++ b/features/home/impl/src/main/res/values-pl/translations.xml @@ -5,9 +5,9 @@ "Powiadomienia nie dochodzą?" "Sygnał powiadomień został zaktualizowany — jest wyraźniejszy, szybszy i mniej uciążliwy." "Odświeżyliśmy Twoje dźwięki" - "Wygeneruj nowy klucz przywracania, którego można użyć do przywrócenia historii wiadomości szyfrowanych w przypadku utraty dostępu do swoich urządzeń." - "Skonfiguruj przywracanie" - "Skonfiguruj przywracanie" + "Twoje czaty są automatycznie archiwizowane za pomocą szyfrowania end-to-end. Aby przywrócić tę kopię zapasową i swoją tożsamość cyfrową, wymagany będzie klucz przywracania." + "Uzyskaj klucz przywracania" + "Utwórz kopię zapasową swoich czatów" "Potwierdź klucz przywracania, aby zachować dostęp do magazynu kluczy i historii wiadomości." "Wprowadź klucz przywracania" "Zapomniałeś klucza przywracania?" @@ -50,6 +50,7 @@ Nie masz żadnych nieprzeczytanych wiadomości!"
"Oznacz jako przeczytane" "Oznacz jako nieprzeczytane" "Ten pokój został ulepszony" + "Twoje przestrzenie" "Wygląda na to, że używasz nowego urządzenia. Zweryfikuj się innym urządzeniem, aby uzyskać dostęp do zaszyfrowanych wiadomości." "Potwierdź, że to Ty" diff --git a/features/invitepeople/impl/src/main/res/values-it/translations.xml b/features/invitepeople/impl/src/main/res/values-it/translations.xml index 979e42de1b..82dc6126f1 100644 --- a/features/invitepeople/impl/src/main/res/values-it/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-it/translations.xml @@ -2,4 +2,8 @@ "Già membro" "Già invitato" + "Al momento non hai conversazioni con questi contatti. Conferma di invitarli in questa stanza prima di continuare." + "Al momento non hai converszioni con questo contatto. Conferma di invitarlo in questa stanza prima di continuare." + "Invita nuovi contatti in questa stanza?" + "Invitare un nuovo contatto in questa stanza?" diff --git a/features/invitepeople/impl/src/main/res/values-pl/translations.xml b/features/invitepeople/impl/src/main/res/values-pl/translations.xml index bfd537bb4b..3e8371c1ab 100644 --- a/features/invitepeople/impl/src/main/res/values-pl/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-pl/translations.xml @@ -2,4 +2,8 @@ "Jest już członkiem" "Już zaproszony" + "Obecnie nie prowadzisz żadnych czatów z tymi kontaktami. Potwierdź zaproszenie, zanim przejdziesz dalej." + "Obecnie nie posiadasz żadnych czatów z tym kontaktem. Potwierdź zaproszenie, zanim przejdziesz dalej." + "Zaprosić nowe kontakty do tego pokoju?" + "Zaprosić nowy kontakt do tego pokoju?" diff --git a/features/invitepeople/impl/src/main/res/values-uk/translations.xml b/features/invitepeople/impl/src/main/res/values-uk/translations.xml index da3ac9fe5b..b7bb3c95d9 100644 --- a/features/invitepeople/impl/src/main/res/values-uk/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-uk/translations.xml @@ -2,4 +2,8 @@ "Уже учасник" "Уже запрошені" + "Наразі у вас немає чатів із цими контактами. Підтвердьте запрошення їх до цієї кімнати, перш ніж продовжувати." + "Наразі у вас немає чатів із цим контактом. Підтвердьте запрошення до цієї кімнати, перш ніж продовжувати." + "Запросити нових контактів до цієї кімнати?" + "Запросити нового контакта до цієї кімнати?" diff --git a/features/joinroom/impl/src/main/res/values-uk/translations.xml b/features/joinroom/impl/src/main/res/values-uk/translations.xml index ec2a24950a..1a83a6ca8c 100644 --- a/features/joinroom/impl/src/main/res/values-uk/translations.xml +++ b/features/joinroom/impl/src/main/res/values-uk/translations.xml @@ -15,6 +15,7 @@ "Вам потрібно отримати запрошення, щоб приєднатися, інакше доступ може бути обмежений." "Забути" "Вам потрібне запрошення, щоб приєднатися" + "Запрошено користувачем" "Доєднатися" "Можливо, вам знадобиться отримати запрошення або стати учасником простору, щоб приєднатися." "Постукати, щоб приєднатися" diff --git a/features/leaveroom/api/src/main/res/values-fa/translations.xml b/features/leaveroom/api/src/main/res/values-fa/translations.xml index 167070891f..ec2cd89314 100644 --- a/features/leaveroom/api/src/main/res/values-fa/translations.xml +++ b/features/leaveroom/api/src/main/res/values-fa/translations.xml @@ -1,5 +1,6 @@ + "آیا مطمئنید که می‌خواهید این مکالمه را ترک کنید؟ این مکالمه عمومی نیست و بدون دعوت نمی‌توانید دوباره به آن بپیوندید." "مطمئنید که می‌خواهید این اتاق را ترک کنید؟ تنها فرد این‌جا هستید. در صورت ترک، هیچ‌کسی از جمله خودتان در آینده نخواهد توانست به آن بپیوندد." "مطمئنید که می‌خواهید این اتاق را ترک کنید؟ این اتاق عمومی نبوده قادر نخواهید بود بدون دعوت دوباره بپیوندید." "گزینش مالکان" diff --git a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml index 18b731a528..ced8955d1d 100644 --- a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml @@ -1,16 +1,33 @@ "Skanuj kod QR" + "Otwórz %1$s na laptopie lub komputerze stacjonarnym" "Zeskanuj kod QR za pomocą tego urządzenia" "Gotowy do skanowania" + "Otwórz %1$s na komputerze stacjonarnym, aby uzyskać kod QR" + "Liczby nie pasują do siebie" + "Wprowadź 2-cyfrowy kod" + "Pozwoli to sprawdzić, czy połączenie z drugim urządzeniem jest bezpieczne." + "Wprowadź numer wyświetlany na drugim urządzeniu" "Twój dostawca konta nie obsługuje %1$s." "%1$s nie jest wspierany" + "Twój dostawca konta nie wspiera logowania na nowym urządzeniu za pomocą kodu QR." "Kod QR nie jest wspierany" "Logowanie zostało anulowane na drugim urządzeniu." "Prośba o logowanie została anulowana" "Logowanie wygasło. Spróbuj ponownie." "Logowanie nie zostało ukończone na czas" + "Otwórz %1$s na drugim urządzeniu" "Wybierz %1$s" + "“Zaloguj się za pomocą kodu QR”" + "Zeskanuj kod QR pokazany tutaj za pomocą drugiego urządzenia" + "Otwórz %1$s na drugim urządzeniu" + "Komputer stacjonarny" + "Ładowanie kodu QR…" + "Urządzenie mobilne" + "Jakiego typu urządzenie chcesz powiązać?" + "Spróbuj ponownie i upewnij się, że 2-cyfrowy kod został wpisany prawidłowo. Jeśli liczby wciąż się nie zgadzają, skontaktuj się ze swoim dostawcą konta." + "Liczby nie pasują do siebie" "Nie udało się nawiązać bezpiecznego połączenia z nowym urządzeniem. Twoje istniejące urządzenia są nadal bezpieczne i nie musisz się o nie martwić." "Co teraz?" "Spróbuj zalogować się ponownie za pomocą kodu QR, jeśli byłby to problem z siecią" @@ -23,6 +40,8 @@ "Prośba o logowanie została anulowana" "Logowanie zostało odrzucone na drugim urządzeniu." "Logowanie odrzucone" + "Nie musisz już robić nic więcej." + "Twoje drugie urządzenie jest już zalogowane" "Logowanie wygasło. Spróbuj ponownie." "Logowanie nie zostało ukończone na czas" "Twoje drugie urządzenie nie wspiera logowania się do %s za pomocą kodu QR. diff --git a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml index fe5b1a7460..752b5ead3f 100644 --- a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml @@ -26,6 +26,7 @@ "Завантаження QR-коду…" "Мобільний пристрій" "Який тип пристрою ви хочете під\'єднати?" + "Спробуйте ще раз і переконайтеся, що ви правильно ввели двозначний код. Якщо цифри все одно не збігаються, зверніться до свого провайдера облікового запису." "Цифри не збігаються" "Не вдалося встановити безпечне з\'єднання з новим пристроєм. Ваші наявні пристрої досі в безпеці, і вам не потрібно про них турбуватися." "Що тепер?" diff --git a/features/location/impl/src/main/res/values-el/translations.xml b/features/location/impl/src/main/res/values-el/translations.xml new file mode 100644 index 0000000000..8ae7c58c74 --- /dev/null +++ b/features/location/impl/src/main/res/values-el/translations.xml @@ -0,0 +1,5 @@ + + + "Το ιστορικό ζωντανής τοποθεσίας σας θα αποθηκευτεί στην αίθουσα και θα είναι ορατό στα μέλη μετά το τέλος της συνεδρίας." + "Επιλέξτε για πόσο χρονικό διάστημα θα κοινοποιείτε την τρέχουσα τοποθεσία σας." + diff --git a/features/location/impl/src/main/res/values-et/translations.xml b/features/location/impl/src/main/res/values-et/translations.xml new file mode 100644 index 0000000000..53aede1bb2 --- /dev/null +++ b/features/location/impl/src/main/res/values-et/translations.xml @@ -0,0 +1,4 @@ + + + "Vali, kui kaua tahad oma reaalajas jagada." + diff --git a/features/location/impl/src/main/res/values-hu/translations.xml b/features/location/impl/src/main/res/values-hu/translations.xml index b89965485f..0ccb2a2413 100644 --- a/features/location/impl/src/main/res/values-hu/translations.xml +++ b/features/location/impl/src/main/res/values-hu/translations.xml @@ -2,4 +2,5 @@ "Az élő helymeghatározás története a szobában lesz tárolva, és a munkamenet befejezése után is látható marad a tagok számára." "Válassza ki, mennyi ideig szeretné megosztani az aktuális tartózkodási helyét." + "Nincs jogosultsága az élő tartózkodási helyének megosztására ebben a szobában." diff --git a/features/location/impl/src/main/res/values-it/translations.xml b/features/location/impl/src/main/res/values-it/translations.xml index 235a9eba4a..44adc1e3c5 100644 --- a/features/location/impl/src/main/res/values-it/translations.xml +++ b/features/location/impl/src/main/res/values-it/translations.xml @@ -2,4 +2,5 @@ "La cronologia delle tue posizioni in tempo reale verrà archiviata nella stanza e sarà visibile ai membri al termine della sessione." "Scegli per quanto tempo condividere la tua posizione in tempo reale." + "Non hai l\'autorizzazione per condividere la tua posizione in tempo reale in questa stanza" diff --git a/features/location/impl/src/main/res/values-pl/translations.xml b/features/location/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..c480d0f43b --- /dev/null +++ b/features/location/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,6 @@ + + + "Twoja historia lokalizacji na żywo zostanie zapisana w pokoju i będzie widoczna dla członków po zakończeniu sesji." + "Wybierz, jak długo chcesz udostępniać swoją lokalizację na żywo." + "Nie masz uprawnień do udostępniania swojej lokalizacji na żywo w tym pokoju" + diff --git a/features/location/impl/src/main/res/values-uk/translations.xml b/features/location/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..3c8155817a --- /dev/null +++ b/features/location/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,5 @@ + + + "Ваша історія поточного місцезнаходження зберігатиметься у кімнаті та буде доступна учасникам після завершення сеансу." + "Виберіть, як довго ділитися своїм місцезнаходженням." + diff --git a/features/location/impl/src/main/res/values-zh/translations.xml b/features/location/impl/src/main/res/values-zh/translations.xml index 6837d3a1eb..563bba593f 100644 --- a/features/location/impl/src/main/res/values-zh/translations.xml +++ b/features/location/impl/src/main/res/values-zh/translations.xml @@ -2,4 +2,5 @@ "你实时位置历史将存储在房间中,并于会话结束后对其他成员可见。" "选择共享实时位置的时长。" + "你无权在此房内共享实时位置。" diff --git a/features/location/impl/src/main/res/values/localazy.xml b/features/location/impl/src/main/res/values/localazy.xml index ac2ff4b2a0..975bb3c6ea 100644 --- a/features/location/impl/src/main/res/values/localazy.xml +++ b/features/location/impl/src/main/res/values/localazy.xml @@ -2,4 +2,5 @@ "Your live location history will be stored in the room and visible to members after the session ends." "Choose how long to share your live location." + "You do not have permissions to share your live location in this room" diff --git a/features/lockscreen/impl/src/main/res/values-fa/translations.xml b/features/lockscreen/impl/src/main/res/values-fa/translations.xml index bd2000b94d..0575f22221 100644 --- a/features/lockscreen/impl/src/main/res/values-fa/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-fa/translations.xml @@ -23,7 +23,7 @@ "لطفاً یک پین را دو بار وارد کنید" "پین‌ها مطابق نیستند" "برای ادامه باید دوباره وارد شده و پینی جدید ایجاد کنید" - "دارید خارج می‌شوید" + "این دستگاه در حال حذف شدن است" "شما %1$d تلاش برای باز کردن قفل دارید" "شما %1$d تلاش برای باز کردن قفل دارید" diff --git a/features/lockscreen/impl/src/main/res/values-pl/translations.xml b/features/lockscreen/impl/src/main/res/values-pl/translations.xml index 5d61ecb7c6..29691987f6 100644 --- a/features/lockscreen/impl/src/main/res/values-pl/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-pl/translations.xml @@ -23,7 +23,7 @@ Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz ten PIN, zostaniesz wyl "Wprowadź ten sam kod PIN dwa razy" "PIN\'y nie pasują do siebie" "Aby kontynuować, zaloguj się ponownie i utwórz nowy kod PIN" - "Trwa wylogowywanie" + "Trwa usuwanie urządzenia" "Masz %1$d próbę, żeby odblokować" "Masz %1$d próby, żeby odblokować" @@ -36,5 +36,5 @@ Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz ten PIN, zostaniesz wyl "Użyj biometrii" "Użyj kodu PIN" - "Wylogowywanie…" + "Usuwam urządzenie…" diff --git a/features/lockscreen/impl/src/main/res/values-sk/translations.xml b/features/lockscreen/impl/src/main/res/values-sk/translations.xml index 0cfb2e88cd..14687f9272 100644 --- a/features/lockscreen/impl/src/main/res/values-sk/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-sk/translations.xml @@ -36,5 +36,5 @@ Vyberte si niečo zapamätateľné. Ak tento kód PIN zabudnete, budete z aplik "Použiť biometrické údaje" "Použiť PIN" - "Prebieha odhlasovanie…" + "Odoberanie zariadenia…" diff --git a/features/lockscreen/impl/src/main/res/values-uk/translations.xml b/features/lockscreen/impl/src/main/res/values-uk/translations.xml index 5c19889282..25e96003c8 100644 --- a/features/lockscreen/impl/src/main/res/values-uk/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-uk/translations.xml @@ -36,5 +36,5 @@ "Використати біометрію" "Використати PIN-код" - "Вихід…" + "Видалення пристрою…" diff --git a/features/login/impl/src/main/res/values-el/translations.xml b/features/login/impl/src/main/res/values-el/translations.xml index 85640698f3..045465902b 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -28,7 +28,7 @@ "Ποια είναι η διεύθυνση του διακομιστή σου;" "Επέλεξε το διακομιστή σου" "Δημιουργία λογαριασμού" - "Αυτός ο λογαριασμός έχει απενεργοποιηθεί." + "Αυτός ο λογαριασμός έχει διαγραφεί." "Λανθασμένο όνομα χρήστη ή κωδικός πρόσβασης" "Αυτό δεν είναι έγκυρο αναγνωριστικό χρήστη. Αναμενόμενη μορφή: \'@χρήστης:homeserver.org\'" "Αυτός ο διακομιστής έχει ρυθμιστεί ώστε να χρησιμοποιεί διακριτικά ανανέωσης. Αυτά δεν υποστηρίζονται όταν χρησιμοποιείς σύνδεση μέσω κωδικού πρόσβασης." @@ -37,6 +37,13 @@ "Το Matrix είναι ένα ανοιχτό δίκτυο για ασφαλή, αποκεντρωμένη επικοινωνία." "Καλωσόρισες ξανά!" "Συνδέσου στο %1$s" + "Άνοιγμα του Element Classic" + "Ανοίξτε το Element Classic στη συσκευή σας." + "Μεταβείτε στις Ρυθμίσεις > Ασφάλεια και Απόρρητο" + "Στη Διαχείριση κλειδιών κρυπτογράφησης, επιλέξτε Ανάκτηση κρυπτογραφημένων μηνυμάτων" + "Ακολουθήστε τις οδηγίες για να ενεργοποιήσετε την αποθήκευση κλειδιών" + "Επιστρέψτε στο %1$s" + "Ενεργοποιήστε την αποθήκευση κλειδιών σας πριν προχωρήσετε στο %1$s" "Έκδοση %1$s" "Σύνδεση χειροκίνητα" "Συνδέσου στο %1$s" diff --git a/features/login/impl/src/main/res/values-fa/translations.xml b/features/login/impl/src/main/res/values-fa/translations.xml index d903103c1b..c28c891c9a 100644 --- a/features/login/impl/src/main/res/values-fa/translations.xml +++ b/features/login/impl/src/main/res/values-fa/translations.xml @@ -15,6 +15,7 @@ "تغییر فراهم کنندهٔ حساب" "پلی گپگل" "ما نتوانستیم به این کارساز خانگی برسیم. لطفاً بررسی کنید که URL کارساز اصلی را به درستی وارد کرده اید. اگر URL صحیح است، برای کمک بیشتر با مدیر کارساز خانگی خود تماس بگیرید." + "سرور به دلیل مشکلی در فایل .well-known در دسترس نیست: %1$s" "نشانی کارساز خانگی" "ورود نشانی دامنه." "نشانی کارسازتان چیست؟" @@ -23,6 +24,7 @@ "این حساب حذف شده است." "نام کاربری یا گذرواژه نامعتبر است" "این یک شناسه کاربری معتبر نیست. قالب صحیح: ‪«@user:homeserver.or" + "این سرور برای استفاده از توکن‌های به‌روزرسانی پیکربندی شده است. این توکن‌ها هنگام استفاده از ورود مبتنی بر رمز عبور پشتیبانی نمی‌شوند." "کارساز اصلی انتخاب شده از رمز عبور یا ورود OAuth پشتیبانی نمی کند. لطفا با مدیر خود تماس بگیرید یا یک کارساز خانگی دیگر را انتخاب کنید." "جزییاتتان را وارد کنید" "ماتریکس شبکه‌ای بار برای ارتباطات نامتمرکز و امن است." diff --git a/features/login/impl/src/main/res/values-it/translations.xml b/features/login/impl/src/main/res/values-it/translations.xml index 3753d58390..1f1b51cda8 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -28,7 +28,7 @@ "Qual è l\'indirizzo del tuo server?" "Seleziona il tuo server" "Crea account" - "Questo account è stato disattivato." + "Questo account è stato eliminato." "Nome utente e/o password errati" "Questo non è un identità utente valida. il formato atteso é: \'@user:homeserver.org\'" "Questo server è configurato per usare i token di aggiornamento. Non sono supportati quando si usa l\'accesso basato su password." @@ -45,6 +45,7 @@ "Torna a %1$s" "Abilita l\'archivio delle chiavi prima di procedere con %1$s" "Versione %1$s" + "Verifica dell\'account" "Accedi manualmente" "Accedi a %1$s" "Accedi con codice QR" diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index b134395adf..ca0d035fe0 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -28,7 +28,7 @@ "Jaki jest adres Twojego serwera?" "Wybierz swój serwer" "Utwórz konto" - "To konto zostało dezaktywowane." + "To konto zostało usunięte." "Nieprawidłowa nazwa użytkownika i/lub hasło" "To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \'@user:homeserver.org\'" "Ten serwer został skonfigurowany do korzystania z tokenów odświeżania. Nie są one obsługiwane, gdy korzystasz z hasła." @@ -37,11 +37,20 @@ "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." "Witaj ponownie!" "Zaloguj się do %1$s" + "Otwórz Element Classic" + "Otwórz Element Classic na swoim urządzeniu" + "Przejdź do Ustawienia > Bezpieczeństwo i prywatność" + "W Zarządzaniu kluczami kryptograficznymi wybierz przywracanie wiadomości szyfrowanych" + "Aby włączyć magazyn kluczy, postępuj zgodnie z instrukcjami" + "Wróć do %1$s" + "Włącz magazyn kluczy zanim przejdziesz do %1$s" "Wersja %1$s" + "Sprawdzanie konta" "Zaloguj się ręcznie" "Zaloguj się do %1$s" "Zaloguj się za pomocą kodu QR" "Utwórz konto" + "Witamy ponownie" "Witamy w %1$s. Szybszy i prostszy niż kiedykolwiek." "Witamy w %1$s. Doładowany, dla szybkości i prostoty." "Be in your element" @@ -60,6 +69,8 @@ "Prośba o logowanie została anulowana" "Logowanie zostało odrzucone na drugim urządzeniu." "Logowanie odrzucone" + "Nie musisz już robić nic więcej." + "Twoje drugie urządzenie jest już zalogowane" "Logowanie wygasło. Spróbuj ponownie." "Logowanie nie zostało ukończone na czas" "Twoje drugie urządzenie nie wspiera logowania się do %s za pomocą kodu QR. diff --git a/features/login/impl/src/main/res/values-uk/translations.xml b/features/login/impl/src/main/res/values-uk/translations.xml index 0d8eca42cf..17632cc4fc 100644 --- a/features/login/impl/src/main/res/values-uk/translations.xml +++ b/features/login/impl/src/main/res/values-uk/translations.xml @@ -28,7 +28,7 @@ "Яка адреса вашого сервера?" "Виберіть свій сервер" "Створити обліковий запис" - "Цей обліковий запис було деактивовано." + "Цей обліковий запис було видалено." "Неправильне ім\'я користувача та/або пароль" "Це недійсний ідентифікатор користувача. Очікуваний формат: \'@user:homeserver.org\'" "Цей сервер налаштований на використання оновлюваних токенів. Вони не підтримуються, якщо використовується вхід за допомогою основі пароля." @@ -37,11 +37,20 @@ "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації." "З поверненням!" "Увійти в %1$s" + "Відкрити Element Classic" + "Відкрийте Element Classic на своєму пристрої" + "Перейдіть до «Налаштування» > «Безпека та конфіденційність»" + "У розділі «Управління криптографічними ключами» виберіть «Відновлення зашифрованих повідомлень»" + "Дотримуйтесь інструкцій, щоб увімкнути сховище ключів" + "Повернутися до %1$s" + "Увімкніть сховище ключів, перш ніж переходити до %1$s" "Версія %1$s" + "Перевірка облікового запису" "Увійти вручну" "Увійти в %1$s" "Увійти за допомогою QR-коду" "Створити обліковий запис" + "З поверненням!" "Ласкаво просимо до найшвидшого %1$s. Заряджений для швидкості та простоти." "Ласкаво просимо до %1$s. Заряджений, для швидкості та простоти." "Будьте у своєму element" diff --git a/features/logout/impl/src/main/res/values-fa/translations.xml b/features/logout/impl/src/main/res/values-fa/translations.xml index d286ded539..a540b9be37 100644 --- a/features/logout/impl/src/main/res/values-fa/translations.xml +++ b/features/logout/impl/src/main/res/values-fa/translations.xml @@ -4,15 +4,15 @@ "برداشتن این افزاره" "برداشتن این افزاره" "برداشتن افزاره…" - "دارید از واپسین نشستتان خارج می‌شوید. اگر اکنون خارج شوید پیام‌های رمزنگاشته‌تان را از دست خواهید داد." - "پشتیبان را خاموش کرده‌اید" - "در هنگامی که آفلاین شدید، کلیدهای شما هنوز در حال پشتیبان‌گیری بودند. دوباره متصل شوید ، تا قبل از خروج از کلیدهایتان نسخه پشتیبان‌ گرفته شود." + "این تنها دستگاه شماست. اگر آن را جدا کنید، برای تأیید هویت دیجیتال خود و بازیابی چت‌های رمزگذاری شده‌تان در دفعه بعد که وارد سیستم می‌شوید، به یک کلید بازیابی نیاز خواهید داشت." + "شما در درحال از دست دادن دسترسی به چت‌های رمزگذاری‌شده‌تان هستید." + "وقتی آفلاین شدید، کلیدهای شما هنوز در حال پشتیبان‌گیری بودند. دوباره متصل شوید تا قبل از جدا کردن این دستگاه، از کلیدهایتان پشتیبان‌گیری شود." "کلیدهایتان هنوز در حال پشتیبان گیریند" - "لطفاً پیش از خروج منتظر پایانش شوید." + "لطفاً قبل از خروج از این دستگاه، منتظر بمانید تا این مراحل تکمیل شود." "کلیدهایتان هنوز در حال پشتیبان گیریند" "برداشتن این افزاره" - "شما در آستانه خروج از آخرین جلسه خود هستید. اگر اکنون از سیستم خارج شوید، دسترسی به پیام های رمزگذاری شده تان را از دست خواهید داد." - "بازگردانی برپا نشده" - "دارید از واپسین نشستتان خارج می‌شوید. اگر اکنون خارج شوید ممکن است پیام‌های رمزنگاشته‌تان را از دست بدهید." - "کلید بازیابیتان را ذخیره کرده‌اید؟" + "این تنها دستگاه شماست. اگر آن را جدا کنید، برای تأیید هویت دیجیتال خود و بازیابی چت‌های رمزگذاری شده‌تان در دفعه بعد که وارد سیستم می‌شوید، به یک کلید بازیابی نیاز خواهید داشت." + "شما در حال از دست دادن دسترسی به چت‌های رمزگذاری‌شده‌تان هستید." + "این تنها دستگاه شماست. اگر آن را جدا کنید، برای تأیید هویت دیجیتال خود و بازیابی چت‌های رمزگذاری شده‌تان در دفعه بعد که وارد سیستم می‌شوید، به یک کلید بازیابی نیاز خواهید داشت." + "قبل از حذف این دستگاه، مطمئن شوید که به کلید بازیابی خود دسترسی دارید." diff --git a/features/logout/impl/src/main/res/values-pl/translations.xml b/features/logout/impl/src/main/res/values-pl/translations.xml index 46a5c2d6bd..691255f434 100644 --- a/features/logout/impl/src/main/res/values-pl/translations.xml +++ b/features/logout/impl/src/main/res/values-pl/translations.xml @@ -1,18 +1,18 @@ - "Czy na pewno chcesz się wylogować?" - "Wyloguj" - "Wyloguj" - "Wylogowywanie…" - "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." - "Wyłączyłeś backup" - "Twoje klucze były nadal archiwizowane po przejściu w tryb offline. Połącz się ponownie, aby zapisać w chmurze przed wylogowaniem." + "Czy na pewno chcesz usunąć to urządzenie?" + "Usuń to urządzenie" + "Usuń to urządzenie" + "Usuwam urządzenie…" + "To jest twoje jedyne urządzenie. Jeśli je usuniesz, będziesz potrzebować klucza przywracania, aby potwierdzić swoją tożsamość cyfrową i przywrócić zaszyfrowane czaty przy następnym logowaniu." + "Zamierzasz utracić dostęp do swoich zaszyfrowanych czatów" + "Twoje klucze były nadal archiwizowane po przejściu w tryb offline. Połącz się ponownie, aby zapisać je w chmurze przed usunięciem urządzenia." "Twoje klucze są nadal archiwizowane" - "Zanim się wylogujesz, poczekaj na zakończenie operacji." + "Poczekaj na zakończenie procesu, zanim usuniesz to urządzenie." "Twoje klucze są nadal archiwizowane" - "Wyloguj" - "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." - "Nie ustawiono przywracania" - "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." - "Czy zapisałeś swój klucz przywracania?" + "Usuń to urządzenie" + "To jest twoje jedyne urządzenie. Jeśli je usuniesz, będziesz potrzebować klucza przywracania, aby potwierdzić swoją tożsamość cyfrową i przywrócić zaszyfrowane czaty przy następnym logowaniu." + "Zamierzasz utracić dostęp do swoich zaszyfrowanych czatów" + "To jest twoje jedyne urządzenie. Jeśli je usuniesz, będziesz potrzebować klucza przywracania, aby potwierdzić swoją tożsamość cyfrową i przywrócić zaszyfrowane czaty przy następnym logowaniu." + "Upewnij się, że posiadasz dostęp do klucza przywracania przed usunięciem urządzenia" diff --git a/features/logout/impl/src/main/res/values-sk/translations.xml b/features/logout/impl/src/main/res/values-sk/translations.xml index 39301437fb..4fe07b2fa7 100644 --- a/features/logout/impl/src/main/res/values-sk/translations.xml +++ b/features/logout/impl/src/main/res/values-sk/translations.xml @@ -1,16 +1,16 @@ - "Ste si istí, že sa chcete odhlásiť?" - "Odhlásiť sa" - "Odhlásiť sa" - "Prebieha odhlasovanie…" + "Naozaj chcete odstrániť toto zariadenie?" + "Odstrániť toto zariadenie" + "Odstrániť toto zariadenie" + "Odoberanie zariadenia…" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, stratíte prístup k svojim šifrovaným správam." "Vypli ste zálohovanie" "Keď ste sa odpojili od internetu, vaše kľúče sa ešte stále zálohovali. Pripojte sa znova k internetu, aby sa vaše kľúče mohli zálohovať pred odhlásením." "Vaše kľúče sa ešte stále zálohujú" "Pred odhlásením počkajte, kým sa to dokončí." "Vaše kľúče sa ešte stále zálohujú" - "Odhlásiť sa" + "Odstrániť toto zariadenie" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, stratíte prístup k svojim šifrovaným správam." "Obnovenie nie je nastavené" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, môžete stratiť prístup k svojim šifrovaným správam." diff --git a/features/logout/impl/src/main/res/values-uk/translations.xml b/features/logout/impl/src/main/res/values-uk/translations.xml index 7e23189dc6..f012603533 100644 --- a/features/logout/impl/src/main/res/values-uk/translations.xml +++ b/features/logout/impl/src/main/res/values-uk/translations.xml @@ -1,9 +1,9 @@ - "Ви впевнені, що бажаєте вийти?" + "Ви впевнені, що хочете видалити цей пристрій?" "Вийти" "Вийти" - "Вихід…" + "Видалення пристрою…" "Ви збираєтеся вийти зі свого останнього сеансу. Якщо ви вийдете зараз, ви втратите доступ до своїх зашифрованих повідомлень." "Ви вимкнули резервне копіювання" "Коли ви вийшли з мережі, резервна копія ваших ключів все ще створювалася. Повторно під\'єднайтеся, щоб зберегти резервну копію ключів перед виходом." diff --git a/features/messages/impl/src/main/res/values-fa/translations.xml b/features/messages/impl/src/main/res/values-fa/translations.xml index dcac058d2f..19f55a5559 100644 --- a/features/messages/impl/src/main/res/values-fa/translations.xml +++ b/features/messages/impl/src/main/res/values-fa/translations.xml @@ -56,5 +56,13 @@ "این اتاق جایگزین شده و دیگر فعّال نیست" "دیدن پیام‌های قدیمی" "این اتاق ادامهٔ اتاقی دیگر است" + + "%1$s، %2$s و %3$d سایر" + "%1$s، %2$s و %3$d موارد دیگر" + + + "%1$s در حال تایپ است" + "%1$s در حال تایپ هستند" + "%1$s و %2$s" diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index 18a8af6cb0..0085e1d4ee 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -35,7 +35,7 @@ "Nagraj film" "Załącznik" "Zdjęcia i filmy" - "Lokalizacja" + "Udostępnij lokalizację" "Ankieta" "Formatowanie tekstu" "Historia wiadomości jest obecnie niedostępna." diff --git a/features/messages/impl/src/main/res/values-sk/translations.xml b/features/messages/impl/src/main/res/values-sk/translations.xml index 4f267d8552..d2022c4882 100644 --- a/features/messages/impl/src/main/res/values-sk/translations.xml +++ b/features/messages/impl/src/main/res/values-sk/translations.xml @@ -35,7 +35,7 @@ "Nahrať video" "Príloha" "Knižnica fotografií a videí" - "Poloha" + "Zdieľať polohu" "Anketa" "Formátovanie textu" "História správ v tejto miestnosti nie je momentálne k dispozícii" diff --git a/features/messages/impl/src/main/res/values-uk/translations.xml b/features/messages/impl/src/main/res/values-uk/translations.xml index c51744a408..a3035e9e08 100644 --- a/features/messages/impl/src/main/res/values-uk/translations.xml +++ b/features/messages/impl/src/main/res/values-uk/translations.xml @@ -35,7 +35,7 @@ "Записати відео" "Вкладення" "Бібліотека фото та відео" - "Розташування" + "Поділитися місцеперебуванням" "Опитування" "Форматування тексту" "Історія повідомлень наразі недоступна." diff --git a/features/preferences/impl/src/main/res/values-et/translations.xml b/features/preferences/impl/src/main/res/values-et/translations.xml index 4e7ba1c26e..c9094f1d31 100644 --- a/features/preferences/impl/src/main/res/values-et/translations.xml +++ b/features/preferences/impl/src/main/res/values-et/translations.xml @@ -11,6 +11,11 @@ "Peida jututubade kutsetest tunnuspildid" "Peida meedia eelvaated ajajoonel" "Katsed" + "Rakenduse seadistused" + + "Iga %1$d meeter" + "Iga %1$d meetrit" + "Sellega laadid fotosid ja videoid kiiremini üles ning vähendad andmemahtu" "Optimeeri meedia kvaliteeti" "Modereerimine ja ohutus" diff --git a/features/preferences/impl/src/main/res/values-fa/translations.xml b/features/preferences/impl/src/main/res/values-fa/translations.xml index 05e73febb4..1a832ca54c 100644 --- a/features/preferences/impl/src/main/res/values-fa/translations.xml +++ b/features/preferences/impl/src/main/res/values-fa/translations.xml @@ -19,12 +19,15 @@ "فراهم کنندهٔ آگاهی‌های ارسالی" "از کار انداختن ویرایشگر متن غنی یا نوشتن دستی مارک‌دون." "رسید‌های خواندن" + "اگر خاموش باشد، رسیدهای خوانده شدن شما برای کسی ارسال نمی‌شود. شما همچنان رسیدهای خوانده شدن را از سایر کاربران دریافت خواهید کرد." "هم‌رسانی حضور" + "اگر خاموش باشد، نمی‌توانید رسیدهای خوانده شدن یا اعلان‌های تایپ را ارسال یا دریافت کنید." "نهفتن همیشگی" "نمایش همیشگی" "در اتاق‌های خصوصی" "رسانه‌های نهفته همواره خواهند توانست با زدن رویشان نمایان شوند" "نمایش رسانه در خط زمانی" + "گزینه مشاهده منبع پیام در جدول زمانی را فعال کنید." "هیچ کاربر مسدودی ندارید" "رفع انسداد" "قادر خواهید بود دوباره همهٔ پیام‌هایش را ببینید." diff --git a/features/preferences/impl/src/main/res/values-it/translations.xml b/features/preferences/impl/src/main/res/values-it/translations.xml index a10dcc9594..7872a2d47d 100644 --- a/features/preferences/impl/src/main/res/values-it/translations.xml +++ b/features/preferences/impl/src/main/res/values-it/translations.xml @@ -11,6 +11,14 @@ "Nascondi gli avatar nelle richieste di invito alle stanze" "Nascondi le anteprime dei media nelle conversazioni" "Labs" + "La distanza che devi percorrere per attivare un aggiornamento." + "Assicurati che l\'opzione \"Posizione precisa\" sia abilitata per questa app. Per modificare l\'autorizzazione, vai in %1$s." + "Impostazioni app" + "Aggiornamenti posizione in tempo reale" + + "Ogni %1$d metro" + "Ogni %1$d metri" + "Carica foto e video più velocemente e riduci l\'utilizzo dei dati" "Ottimizza la qualità dei contenuti multimediali" "Moderazione e Sicurezza" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index 9e2c56e580..606a79df0d 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -11,6 +11,15 @@ "Ukryj awatary w prośbach o dołączenie do pokoju" "Ukryj podglądy multimediów na osi czasu" "Laboratoria" + "Odległość, jaką należy pokonać, aby uruchomić aktualizację." + "Upewnij się, że \"Dokładna lokalizacja\" jest włączona dla tej aplikacji. Aby zmienić to uprawnienie, przejdź do %1$s." + "Ustawienia aplikacji" + "Aktualizacje lokalizacji na żywo" + + "Co %1$d metr" + "Co %1$d metry" + "Co %1$d metrów" + "Przesyłaj zdjęcia i filmy szybciej, zmniejszając zużycie danych" "Optymalizuj jakość multimediów" "Moderacja i bezpieczeństwo" diff --git a/features/preferences/impl/src/main/res/values-uk/translations.xml b/features/preferences/impl/src/main/res/values-uk/translations.xml index d145724af8..eeffc97328 100644 --- a/features/preferences/impl/src/main/res/values-uk/translations.xml +++ b/features/preferences/impl/src/main/res/values-uk/translations.xml @@ -11,6 +11,15 @@ "Сховати аватари у запитах на запрошення до кімнат" "Сховати попередній перегляд медіа у стрічці" "Лабораторії" + "Відстань, яку потрібно пройти, щоб ініціювати оновлення." + "Переконайтеся, що для цього додатка увімкнено функцію «Точна геолокація». Щоб змінити дозвіл, перейдіть на сторінку %1$s." + "Налаштування додатка" + "Оновлення місцезнаходження в реальному часі" + + "Кожен %1$d метр" + "Кожні %1$d метри" + "Кожні %1$d метрів" + "Швидше завантажуйте фотографії та відео та зменшуйте використання даних" "Оптимізуйте медіаякість" "Модерування й безпека" diff --git a/features/rageshake/impl/src/main/res/values-fa/translations.xml b/features/rageshake/impl/src/main/res/values-fa/translations.xml index ba5ab756db..2e27f97ba6 100644 --- a/features/rageshake/impl/src/main/res/values-fa/translations.xml +++ b/features/rageshake/impl/src/main/res/values-fa/translations.xml @@ -7,6 +7,7 @@ "لطفاً مشکل را شرح دهید. چه‌کار کردید؟ انتظار داشتید چه بشود؟ ولی چه شد؟ لطفاً‌تا جای ممکن وارد جزییات شوید." "شرح مشکل…" "ترجیحاً توضیحات را به زبان انگلیسی بنویسید." + "توضیحات خیلی کوتاه است، لطفاً جزئیات بیشتری در مورد آنچه اتفاق افتاده ارائه دهید. متشکرم!" "ارسال رخدادنگارهای خطا" "اجازه به گزارش‌ها" "ارسال تصویر صفحه" diff --git a/features/rageshake/impl/src/main/res/values-uk/translations.xml b/features/rageshake/impl/src/main/res/values-uk/translations.xml index 3999133537..c29306b9bf 100644 --- a/features/rageshake/impl/src/main/res/values-uk/translations.xml +++ b/features/rageshake/impl/src/main/res/values-uk/translations.xml @@ -14,5 +14,7 @@ "Надіслати знімок екрана" "Журнали будуть додані до вашого повідомлення, щоб переконатися, що все працює належним чином. Щоб надіслати повідомлення без журналів, вимкніть це налаштування." "Стався збій %1$s під час останнього користування. Хочете поділитися з нами звітом про збій?" + "Якщо у вас виникають проблеми зі сповіщеннями, надсилання нам правил push-сповіщень допоможе нам визначити першопричину. Зверніть увагу, що ці правила можуть містити приватну інформацію, таку як ваше ім’я користувача або ключові слова, за якими ви отримували сповіщення." + "Налаштування сповіщень" "Переглянути журнали" diff --git a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml index 2bd79bddd2..4bcb764219 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml @@ -1,14 +1,14 @@ - "فقط مدیران" + "ادمین" "تحریم افراد" - "برداشتن پیام‌ها" - "هرکسی" - "دعوت افراد و پذیرش درخواست‌های پیوستن" - "نظارت اعضا" + "حذف پیام‌ها" + "عضو" + "دعوت کاربران" + "مدیریت اعضا" "پیام‌ها و محتوا" - "مدیرن و ناظران" - "برداشتن افراد و رد درخواست‌های پیوستن" + "ناظم" + "حذف افراد" "تغییر چهرک اتاق" "ویرایش جزییات" "تغییر نام اتاق" @@ -44,8 +44,8 @@ "تحریم نکردن از اتاق" "محروم" "اعضا" - "فقط مدیران" - "مدیرن و ناظران" + "ادمین" + "ناظم" "مالک" "اعضای اتاق" "رفع تحریم %1$s" @@ -62,5 +62,5 @@ "بازنشانی اجازه‌ها؟" "نقش‌ها" "جزییات اتاق" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" diff --git a/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml index e44a1dba21..9c88a2f20e 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml @@ -6,6 +6,7 @@ "Üzenetek eltávolítása" "Tag" "Emberek meghívása" + "Valós idejű hely megosztása" "Tér kezelése" "Szobák kezelése" "Tagok kezelése" diff --git a/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml index b1dea12151..ac1366d988 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml @@ -6,6 +6,7 @@ "Rimuovi messaggi" "Membro" "Invita persone" + "Condividi posizione in tempo reale" "Gestire lo spazio" "Gestisci le stanze" "Gestisci membri" diff --git a/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml index 44659c47cd..9b570f5261 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml @@ -1,17 +1,24 @@ - "Tylko administratorzy" + "Administrator" "Banowanie osób" + "Zmień ustawienia" "Usuń wiadomości" - "Zapraszanie osób i akceptowanie próśb o dołączenie" + "Członek" + "Zaproś osoby" + "Udostępnij lokalizację na żywo" + "Zarządzaj przestrzeniami" + "Zarządzaj pokojami" + "Zarządzaj członkami" "Wiadomości i zawartość" - "Administratorzy i moderatorzy" - "Usuwanie osób i odrzucanie próśb o dołączenie" + "Moderator" + "Usuń osoby" "Zmień awatar pokoju" - "Edytuj pokój" + "Edytuj szczegóły" "Zmień nazwę pokoju" "Zmień temat pokoju" "Wysyłanie wiadomości" + "Uprawnienia" "Edytuj administratorów" "Tej akcji nie będzie można cofnąć. Promujesz użytkownika, który będzie posiadał takie same uprawnienia jak Ty." "Dodać administratora?" @@ -21,7 +28,7 @@ "Nie będzie można cofnąć tej zmiany, jeśli się zdegradujesz. Jeśli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju, nie będziesz w stanie odzyskać uprawnień." "Zdegradować siebie?" "%1$s (Oczekujące)" - "(Oczekujący)" + "(Oczekujące)" "Administratorzy automatycznie mają uprawnienia moderatora" "Właściciele automatycznie mają uprawnienia administratora." "Edytuj moderatorów" @@ -31,7 +38,14 @@ "Członków" "Masz niezapisane zmiany." "Zapisać zmiany?" - "W tym pokoju nie ma zbanowanych użytkowników." + "Nie ma zbanowanych użytkowników." + + "%1$d zbanowany" + "%1$d zbanowanych" + "%1$d zbanowanych" + + "Sprawdź pisownię lub wyszukaj ponownie" + "Brak wyników dla “%1$s”" "%1$d osoba" "%1$d osoby" @@ -44,8 +58,14 @@ "Odbanuj z pokoju" "Zbanowanych" "Członków" - "Tylko administratorzy" - "Administratorzy i moderatorzy" + + "%1$d zaproszony" + "%1$d zaproszonych" + "%1$d zaproszonych" + + "Oczekuje" + "Administrator" + "Moderator" "Właściciel" "Członkowie pokoju" "Odbanowanie %1$s" @@ -58,10 +78,12 @@ "Wiadomości i zawartość" "Moderatorzy" "Właściciele" - "Resetuj uprawnienia" + "Uprawnienia" + "Zresetuj uprawnienia" "Po zresetowaniu uprawnień utracisz bieżące ustawienia." "Zresetować uprawnienia?" "Role" "Szczegóły pokoju" + "Szczegóły przestrzeni" "Role i uprawnienia" diff --git a/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml index 7ce3e78387..99f21bb403 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml @@ -38,6 +38,11 @@ "У вас є не збережені зміни." "Зберегти зміни?" "Немає заблокованих користувачів." + + "%1$d Заблокований" + "%1$d Заблоковано" + "%1$d Заблоковано" + "Перевірте правопис або спробуйте новий пошук" "Немає результатів за запитом «%1$s»" diff --git a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml index b28cf8e524..53edd50a6d 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml @@ -6,6 +6,7 @@ "移除消息" "成员" "邀请人员" + "共享实时位置" "管理空间" "管理房间" "管理成员" diff --git a/features/rolesandpermissions/impl/src/main/res/values/localazy.xml b/features/rolesandpermissions/impl/src/main/res/values/localazy.xml index e5ab3f1cd7..dc89095786 100644 --- a/features/rolesandpermissions/impl/src/main/res/values/localazy.xml +++ b/features/rolesandpermissions/impl/src/main/res/values/localazy.xml @@ -6,6 +6,7 @@ "Remove messages" "Member" "Invite people" + "Share live location" "Manage space" "Manage rooms" "Manage members" diff --git a/features/roomdetails/impl/src/main/res/values-be/translations.xml b/features/roomdetails/impl/src/main/res/values-be/translations.xml index 9b89f2cef0..5bd33fef17 100644 --- a/features/roomdetails/impl/src/main/res/values-be/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-be/translations.xml @@ -43,6 +43,7 @@ "Не атрымалася адключыць гук у гэтым пакоі, паўтарыце спробу." "Не ўдалося ўключыць гук у гэтым пакоі. Паўтарыце спробу." "Запрасіць карыстальнікаў" + "Запрасіць" "Пакінуць размову" "Пакінуць пакой" "Уласныя" diff --git a/features/roomdetails/impl/src/main/res/values-bg/translations.xml b/features/roomdetails/impl/src/main/res/values-bg/translations.xml index 55bce6cd12..2c797cb74e 100644 --- a/features/roomdetails/impl/src/main/res/values-bg/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-bg/translations.xml @@ -33,6 +33,7 @@ "Неуспешно заглушаване на тази стая, моля, опитайте отново." "Неуспешно раззаглушаване на тази стая, моля, опитайте отново." "Поканване на хора" + "Поканване" "Напускане на разговора" "Напускане на стаята" "Медия и файлове" diff --git a/features/roomdetails/impl/src/main/res/values-cs/translations.xml b/features/roomdetails/impl/src/main/res/values-cs/translations.xml index eaf787e4e3..d47a1c709b 100644 --- a/features/roomdetails/impl/src/main/res/values-cs/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cs/translations.xml @@ -56,6 +56,7 @@ "Nezavírejte aplikaci, dokud neskončíte." "Příprava pozvánek…" "Pozvat přátele" + "Pozvat" "Opustit konverzaci" "Opustit místnost" "Média a soubory" diff --git a/features/roomdetails/impl/src/main/res/values-cy/translations.xml b/features/roomdetails/impl/src/main/res/values-cy/translations.xml index be8ab00639..b8ec88e51a 100644 --- a/features/roomdetails/impl/src/main/res/values-cy/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cy/translations.xml @@ -53,6 +53,7 @@ "Peidiwch â chau\'r ap nes ei fod wedi gorffen." "Wrthi\'n paratoi gwahoddiadau…" "Gwahodd pobl" + "Gwahodd" "Gadael y sgwrs" "Gadael yr ystafell" "Cyfryngau a ffeiliau" diff --git a/features/roomdetails/impl/src/main/res/values-da/translations.xml b/features/roomdetails/impl/src/main/res/values-da/translations.xml index 2217e0b9c6..9f3b3436f0 100644 --- a/features/roomdetails/impl/src/main/res/values-da/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-da/translations.xml @@ -56,6 +56,7 @@ "Luk ikke appen, før den er færdig." "Forbereder invitationer…" "Invitér andre" + "Invitér" "Forlad samtalen" "Forlad rum" "Medier og filer" diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml index d810ca0919..c1487d7d98 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -56,6 +56,7 @@ "Schließ die App erst, wenn du fertig bist." "Einladungen werden vorbereitet…" "Nutzer einladen" + "Einladen" "Unterhaltung verlassen" "Verlassen" "Medien und Dateien" diff --git a/features/roomdetails/impl/src/main/res/values-el/translations.xml b/features/roomdetails/impl/src/main/res/values-el/translations.xml index c1b108a524..c1be20d7f5 100644 --- a/features/roomdetails/impl/src/main/res/values-el/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-el/translations.xml @@ -56,6 +56,7 @@ "Μην κλείσετε την εφαρμογή μέχρι να τελειώσει." "Προετοιμασία προσκλήσεων…" "Πρόσκληση ατόμων" + "Πρόσκληση" "Αποχώρηση από τη συζήτηση" "Αποχώρηση από την αίθουσα" "Πολυμέσα και αρχεία" diff --git a/features/roomdetails/impl/src/main/res/values-es/translations.xml b/features/roomdetails/impl/src/main/res/values-es/translations.xml index 716e3ed32a..6b92e48884 100644 --- a/features/roomdetails/impl/src/main/res/values-es/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-es/translations.xml @@ -47,6 +47,7 @@ "No se ha podido silenciar esta sala, inténtalo de nuevo." "Error al dejar de silenciar esta sala, por favor inténtalo de nuevo." "Invitar personas" + "Invitar" "Salir de la conversación" "Salir de la sala" "Medios y archivos" diff --git a/features/roomdetails/impl/src/main/res/values-et/translations.xml b/features/roomdetails/impl/src/main/res/values-et/translations.xml index d5d3af8563..f0c8c58b1f 100644 --- a/features/roomdetails/impl/src/main/res/values-et/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-et/translations.xml @@ -56,6 +56,7 @@ "Ära sulge rakendust enne, kui tegevus on lõppenud." "Valmistan kutseid ette…" "Kutsu osalejaid" + "Kutsu" "Lahku vestlusest" "Lahku jututoast" "Meedia ja failid" diff --git a/features/roomdetails/impl/src/main/res/values-eu/translations.xml b/features/roomdetails/impl/src/main/res/values-eu/translations.xml index 7fb07cf2a4..f299131852 100644 --- a/features/roomdetails/impl/src/main/res/values-eu/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-eu/translations.xml @@ -44,6 +44,7 @@ "Ezin izan da gela mututu; saiatu berriro." "Ezin izan da gela mututzeari utzi; saiatu berriro." "Gonbidatu jendea" + "Gonbidatu" "Utzi elkarrizketa" "Atera gelatik" "Multimedia eta fitxategiak" diff --git a/features/roomdetails/impl/src/main/res/values-fa/translations.xml b/features/roomdetails/impl/src/main/res/values-fa/translations.xml index 364c94c6f2..bb7cb490b8 100644 --- a/features/roomdetails/impl/src/main/res/values-fa/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fa/translations.xml @@ -4,15 +4,15 @@ "هنگام به‌روز کردن تنظیمات آگاهی خطایی رخ داد." "کارساز خانگیتان از این گزینه در اتاق‌های رمز شده پشتیبانی نمی‌کند. ممکن است در برخی اتاق‌ها آگاه نشوید." "نظرسنجی‌ها" - "فقط مدیران" + "ادمین" "تحریم افراد" - "برداشتن پیام‌ها" - "هرکسی" - "دعوت افراد و پذیرش درخواست‌های پیوستن" - "نظارت اعضا" + "حذف پیام‌ها" + "عضو" + "دعوت کاربران" + "مدیریت اعضا" "پیام‌ها و محتوا" - "مدیرن و ناظران" - "برداشتن افراد و رد درخواست‌های پیوستن" + "ناظم" + "حذف افراد" "تغییر چهرک اتاق" "ویرایش جزییات" "تغییر نام اتاق" @@ -51,6 +51,7 @@ "کاره را تا زمان پایانش نبندید." "آماده سازی دعوت‌ها…" "دعوت افراد" + "دعوت" "ترک گفت‌وگو" "ترک اتاق" "رسانه‌ها و پرونده‌ها" @@ -60,7 +61,7 @@ "پیام‌های سنجاق شده" "نمایه" "درخواست‌های پیوستن" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" "امنیت و محرمانگی" "امنیت" "هم‌رسانی اتاق" @@ -79,8 +80,8 @@ "تحریم نکردن از اتاق" "محروم" "اعضا" - "فقط مدیران" - "مدیرن و ناظران" + "ادمین" + "ناظم" "مالک" "اعضای اتاق" "رفع تحریم %1$s" @@ -111,7 +112,7 @@ "بازنشانی اجازه‌ها؟" "نقش‌ها" "جزییات اتاق" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" "افزودن نشانی اتاق" "درخواست دعوت" "بله. به کار انداختن رمزنگاری" diff --git a/features/roomdetails/impl/src/main/res/values-fi/translations.xml b/features/roomdetails/impl/src/main/res/values-fi/translations.xml index 110790fac1..0d07ff4eae 100644 --- a/features/roomdetails/impl/src/main/res/values-fi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fi/translations.xml @@ -56,6 +56,7 @@ "Älä sulje sovellusta ennen kuin se on valmis." "Valmistellaan kutsuja…" "Kutsu henkilöitä" + "Kutsu" "Poistu keskustelusta" "Poistu huoneesta" "Media ja tiedostot" diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 0fad68c934..3d4283145c 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -56,6 +56,7 @@ "Ne fermez pas l’application avant que l’opération soit terminée." "Préparation des invitations…" "Inviter des amis" + "Inviter" "Quitter la discussion" "Quitter le salon" "Médias et fichiers" diff --git a/features/roomdetails/impl/src/main/res/values-hr/translations.xml b/features/roomdetails/impl/src/main/res/values-hr/translations.xml index 1bc264ca10..73b6866249 100644 --- a/features/roomdetails/impl/src/main/res/values-hr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hr/translations.xml @@ -56,6 +56,7 @@ "Ne zatvarajte aplikaciju dok se ne završi." "Priprema pozivnica…" "Pozovi osobe" + "Pozovi" "Napusti razgovor" "Napusti sobu" "Mediji i datoteke" diff --git a/features/roomdetails/impl/src/main/res/values-hu/translations.xml b/features/roomdetails/impl/src/main/res/values-hu/translations.xml index 1dc523f319..937c91b68d 100644 --- a/features/roomdetails/impl/src/main/res/values-hu/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hu/translations.xml @@ -56,6 +56,7 @@ "Ne zárja be az alkalmazást, amíg nem végzett." "Meghívók előkészítése…" "Ismerősök meghívása" + "Meghívás" "Beszélgetés elhagyása" "Szoba elhagyása" "Média és fájlok" diff --git a/features/roomdetails/impl/src/main/res/values-in/translations.xml b/features/roomdetails/impl/src/main/res/values-in/translations.xml index 41bf3d2826..2cce124321 100644 --- a/features/roomdetails/impl/src/main/res/values-in/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-in/translations.xml @@ -53,6 +53,7 @@ "Jangan tutup aplikasi tunggu hingga selesai." "Mempersiapkan undangan…" "Undang orang-orang" + "Undang" "Tinggalkan percakapan" "Tinggalkan ruangan" "Media dan berkas" diff --git a/features/roomdetails/impl/src/main/res/values-it/translations.xml b/features/roomdetails/impl/src/main/res/values-it/translations.xml index 22ec99f2b5..044721c345 100644 --- a/features/roomdetails/impl/src/main/res/values-it/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-it/translations.xml @@ -56,6 +56,7 @@ "Non chiudere l\'app fino al completamento." "Preparazione degli inviti…" "Invita persone" + "Invita" "Abbandona la conversazione" "Esci dalla stanza" "File e contenuti multimediali" diff --git a/features/roomdetails/impl/src/main/res/values-ja/translations.xml b/features/roomdetails/impl/src/main/res/values-ja/translations.xml index 70b3255437..b6c7608793 100644 --- a/features/roomdetails/impl/src/main/res/values-ja/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ja/translations.xml @@ -56,6 +56,7 @@ "終了するまでアプリを閉じないでください。" "招待を準備中…" "ユーザーを招待" + "招待" "会話を退出" "ルームを退出" "ファイルとメディア" diff --git a/features/roomdetails/impl/src/main/res/values-ka/translations.xml b/features/roomdetails/impl/src/main/res/values-ka/translations.xml index 3ffc962603..317f62313d 100644 --- a/features/roomdetails/impl/src/main/res/values-ka/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ka/translations.xml @@ -39,6 +39,7 @@ "ამ ოთახის დადუმება ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა." "ამ ოთახის დადუმების მოხსნა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა." "ხალხის მოწვევა" + "მოწვევა" "საუბრის დატოვება" "ოთახის დატოვება" "მორგებული" diff --git a/features/roomdetails/impl/src/main/res/values-ko/translations.xml b/features/roomdetails/impl/src/main/res/values-ko/translations.xml index 2c6462c4a7..8c0db6eefd 100644 --- a/features/roomdetails/impl/src/main/res/values-ko/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ko/translations.xml @@ -56,6 +56,7 @@ "작업이 완료될 때까지 앱을 닫지 마세요." "초대 준비중…" "사람 초대하기" + "초대" "대화에서 나가기" "방 떠나기" "미디어 및 파일" diff --git a/features/roomdetails/impl/src/main/res/values-lt/translations.xml b/features/roomdetails/impl/src/main/res/values-lt/translations.xml index 84f74042da..9bdaeb86e5 100644 --- a/features/roomdetails/impl/src/main/res/values-lt/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-lt/translations.xml @@ -8,6 +8,7 @@ "Žinutės yra užrakintos. Tik Jūs ir gavėjai turite unikalius raktus joms atrakinti." "Įjungtas žinučių šifravimas" "Pakviesti žmonių" + "Kviesti" "Palikti pokalbį" "Išeiti iš kambario" "Pasirinktinis" diff --git a/features/roomdetails/impl/src/main/res/values-nb/translations.xml b/features/roomdetails/impl/src/main/res/values-nb/translations.xml index e522f5cd79..52ea87bc3d 100644 --- a/features/roomdetails/impl/src/main/res/values-nb/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nb/translations.xml @@ -56,6 +56,7 @@ "Ikke lukk appen før den er ferdig." "Forbereder invitasjoner…" "Inviter folk" + "Inviter" "Forlat samtalen" "Forlat rommet" "Medier og filer" diff --git a/features/roomdetails/impl/src/main/res/values-nl/translations.xml b/features/roomdetails/impl/src/main/res/values-nl/translations.xml index 9234921c35..e9f03d3a57 100644 --- a/features/roomdetails/impl/src/main/res/values-nl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nl/translations.xml @@ -43,6 +43,7 @@ "Het dempen van deze kamer is mislukt. Probeer het opnieuw." "Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw." "Mensen uitnodigen" + "Uitnodigen" "Gesprek verlaten" "Kamer verlaten" "Media en bestanden" diff --git a/features/roomdetails/impl/src/main/res/values-pl/translations.xml b/features/roomdetails/impl/src/main/res/values-pl/translations.xml index e22636290b..7af5d8e557 100644 --- a/features/roomdetails/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pl/translations.xml @@ -1,19 +1,24 @@ - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" + "Nowi członkowie nie widzą historii" + "Nowi członkowie widzą historię" + "Każdy może przeglądać historię" + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Edytuj adres" "Wystąpił błąd podczas aktualizacji ustawienia powiadomień." "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi." "Ankiety" - "Tylko administratorzy" + "Administrator" "Banowanie osób" "Usuń wiadomości" - "Zapraszanie osób i akceptowanie próśb o dołączenie" + "Członek" + "Zaproś osoby" + "Zarządzaj członkami" "Wiadomości i zawartość" - "Administratorzy i moderatorzy" - "Usuwanie osób i odrzucanie próśb o dołączenie" + "Moderator" + "Usuń osoby" "Zmień awatar pokoju" - "Edytuj pokój" + "Edytuj szczegóły" "Zmień nazwę pokoju" "Zmień temat pokoju" "Wysyłanie wiadomości" @@ -26,7 +31,7 @@ "Nie będzie można cofnąć tej zmiany, jeśli się zdegradujesz. Jeśli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju, nie będziesz w stanie odzyskać uprawnień." "Zdegradować siebie?" "%1$s (Oczekujące)" - "(Oczekujący)" + "(Oczekujące)" "Administratorzy automatycznie mają uprawnienia moderatora" "Właściciele automatycznie mają uprawnienia administratora." "Edytuj moderatorów" @@ -40,7 +45,7 @@ "Szyfrowany" "Nieszyfrowany" "Pokój publiczny" - "Edytuj pokój" + "Edytuj szczegóły" "Wystąpił nieznany błąd i nie można było zmienić informacji." "Nie można zaktualizować pokoju" "Wiadomości są zabezpieczone kłódkami. Tylko Ty i odbiorcy macie unikalne klucze do ich odblokowania." @@ -51,6 +56,7 @@ "Nie zamykaj aplikacji przed zakończeniem." "Przygotowywanie zaproszeń…" "Zaproś znajomych" + "Zaproś" "Opuść rozmowę" "Opuść pokój" "Media i pliki" @@ -61,13 +67,21 @@ "Profil" "Prośby o dołączenie" "Role i uprawnienia" + "Nazwa" "Bezpieczeństwo i prywatność" "Bezpieczeństwo" "Udostępnij pokój" "Informacje pokoju" "Temat" "Aktualizuję pokój…" - "W tym pokoju nie ma zbanowanych użytkowników." + "Nie ma zbanowanych użytkowników." + + "%1$d zbanowany" + "%1$d zbanowanych" + "%1$d zbanowanych" + + "Sprawdź pisownię lub wyszukaj ponownie" + "Brak wyników dla “%1$s”" "%1$d osoba" "%1$d osoby" @@ -80,8 +94,14 @@ "Odbanuj z pokoju" "Zbanowanych" "Członków" - "Tylko administratorzy" - "Administratorzy i moderatorzy" + + "%1$d zaproszony" + "%1$d zaproszonych" + "%1$d zaproszonych" + + "Oczekuje" + "Administrator" + "Moderator" "Właściciel" "Członkowie pokoju" "Odbanowanie %1$s" @@ -108,15 +128,18 @@ "Wiadomości i zawartość" "Moderatorzy" "Właściciele" - "Resetuj uprawnienia" + "Uprawnienia" + "Zresetuj uprawnienia" "Po zresetowaniu uprawnień utracisz bieżące ustawienia." "Zresetować uprawnienia?" "Role" "Szczegóły pokoju" "Role i uprawnienia" - "Dodaj adres pokoju" - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić żądanie." + "Dodaj adres" + "Każdy w autoryzowanych przestrzeniach może dołączyć, ale wszyscy inni muszą poprosić o dostęp." + "Każdy musi poprosić o dostęp." "Poproś o dołączenie" + "Każdy w %1$s może dołączyć, ale wszyscy pozostali muszą poprosić o dostęp." "Tak, włącz szyfrowanie" "Po włączeniu szyfrowanie pokoju nie może zostać wyłączone, a historia wiadomości będzie widoczna tylko dla członków od momentu, w którym dołączyli lub zostali zaproszeni. Nikt poza członkami pokoju nie będzie mógł czytać wiadomości. Może to wpłynąć na prawidłowe działanie botów lub mostków. @@ -125,23 +148,31 @@ Odradzamy włączanie szyfrowania dla pokoi, które każdy może znaleźć i do "Po włączeniu szyfrowania nie można wyłączyć." "Szyfrowanie" "Włącz szyfrowanie end-to-end" - "Każdy może znaleźć i dołączyć" + "Każdy może dołączyć." "Każdy" - "Tylko osoby z zaproszeniem mogą dołączyć" - "Tylko zaproszenie" - "Dostęp do pokoju" + "Wybierz, którzy członkowie przestrzeni mogą dołączyć do tego pokoju bez zaproszenia. %1$s" + "Zarządzaj przestrzeniami" + "Tylko zaproszone osoby mogą dołączyć" + "Tylko na zaproszenie" + "Dostęp" + "Każdy w autoryzowanych przestrzeniach może dołączyć." + "Każdy w %1$s może dołączyć." + "Członkowie przestrzeni" "Przestrzenie nie są obecnie wspierane" - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Adres" "Zezwól na znalezienie tego pokoju wyszukując %1$s w katalogu pokoi publicznych" + "Zezwól, by inni mogli Cię znaleźć, przeszukując katalog publiczny." "Widoczny w katalogu pokoi publicznych" - "Ktokolwiek" + "Każdy (historia jest publiczna)" + "Zmiany nie zmienią przeszłych wiadomości, tylko nowe. %1$s" "Kto może czytać historię" - "Od momentu kiedy członkowie zostali zaproszeni" - "Członkowie od momentu włączenia tej opcji" + "Członkowie od kiedy zostali zaproszeni" + "Członkowie (cała historia)" "Adresy pokoju umożliwiają łatwe znalezienie i dołączenie do pokojów. Również możesz się zdecydować na upublicznienie Twojego serwera w katalogu pokoi publicznych." "Publikowanie pokoju" - "Widoczność pokoju" + "Adresy pokoi pomagają w znalezieniu i dołączeniu do pokoi i przestrzeni. Umożliwiają również łatwe udostępnianie ich innym." + "Widoczność" "Bezpieczeństwo i prywatność" diff --git a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml index ddbbe0f601..da98e7bd5a 100644 --- a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml @@ -53,6 +53,7 @@ "Não feche o aplicativo até terminar." "Preparando convites…" "Convidar pessoas" + "Convidar" "Sair da conversa" "Sair da sala" "Mídia e arquivos" diff --git a/features/roomdetails/impl/src/main/res/values-pt/translations.xml b/features/roomdetails/impl/src/main/res/values-pt/translations.xml index 592cba34f6..c5a9be9a4c 100644 --- a/features/roomdetails/impl/src/main/res/values-pt/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt/translations.xml @@ -53,6 +53,7 @@ "Não feches a aplicação até concluir." "A preparar convites…" "Convidar pessoas" + "Convidar" "Sair da conversa" "Sair da sala" "Multimédia e ficheiros" diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml index 2eac873575..0374c64314 100644 --- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml @@ -53,6 +53,7 @@ "Nu închideți aplicația până nu se termină." "Se pregătesc invitațiile…" "Invitați prieteni" + "Invitați" "Părăsiți conversația" "Părăsiți camera" "Media și fișiere" diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index 7ad44fff9d..bd683009ad 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -56,6 +56,7 @@ "Не закрывайте приложение, пока не закончите." "Подготовка приглашений…" "Пригласить в комнату" + "Пригласить" "Покинуть беседу" "Покинуть комнату" "Медиа и файлы" diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 225dcedac3..6a27e375ee 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -53,6 +53,7 @@ "Nezatvárajte aplikáciu, kým sa neukončí pozývanie." "Príprava pozvánok…" "Pozvať ľudí" + "Pozvať" "Opustiť konverzáciu" "Opustiť miestnosť" "Médiá a súbory" diff --git a/features/roomdetails/impl/src/main/res/values-sv/translations.xml b/features/roomdetails/impl/src/main/res/values-sv/translations.xml index 795dc97106..02574e77e9 100644 --- a/features/roomdetails/impl/src/main/res/values-sv/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sv/translations.xml @@ -53,6 +53,7 @@ "Stäng inte appen förrän det är klart." "Förbereder inbjudningar …" "Bjud in personer" + "Bjud in" "Lämna konversation" "Lämna rum" "Media och filer" diff --git a/features/roomdetails/impl/src/main/res/values-tr/translations.xml b/features/roomdetails/impl/src/main/res/values-tr/translations.xml index 16137ce753..8d11b8035a 100644 --- a/features/roomdetails/impl/src/main/res/values-tr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-tr/translations.xml @@ -46,6 +46,7 @@ "Bu odayı sessize alma başarısız oldu, lütfen tekrar deneyin." "Bu odanın sesi açılamadı, lütfen tekrar deneyin." "Kişileri davet et" + "Davet et" "Sohbeti bırak" "Odadan ayrıl" "Medya ve dosyalar" diff --git a/features/roomdetails/impl/src/main/res/values-uk/translations.xml b/features/roomdetails/impl/src/main/res/values-uk/translations.xml index 46adfa54d5..1565e0ec48 100644 --- a/features/roomdetails/impl/src/main/res/values-uk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uk/translations.xml @@ -1,5 +1,8 @@ + "Нові учасники не бачать історії" + "Нові учасники бачать історію" + "Будь-хто може переглянути історію" "Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі." "Змінити адресу" "Під час оновлення налаштувань сповіщень сталася помилка." @@ -53,6 +56,7 @@ "Не закривайте застосунок доки не завершите." "Приготування запрошень…" "Запросити людей" + "Запросити" "Залишити розмову" "Вийти з кімнати" "Медіа та файли" @@ -71,6 +75,11 @@ "Тема" "Оновлення кімнати…" "Немає заблокованих користувачів." + + "%1$d Заблокований" + "%1$d Заблоковано" + "%1$d Заблоковано" + "Перевірте правопис або спробуйте новий пошук" "Немає результатів за запитом «%1$s»" @@ -127,8 +136,10 @@ "Деталі кімнати" "Ролі та дозволи" "Додати адресу" + "Будь-хто в авторизованих просторах може приєднатися, але всі інші повинні подати запит на доступ." "Усі повинні запитувати доступ." "Запит на приєднання" + "Будь-хто з %1$s може приєднатися, але всі інші повинні подати запит на доступ." "Так, увімкнути шифрування" "Після ввімкнення шифрування кімнати, його неможливо вимкнути, історію повідомлень бачитимуть лише учасники кімнати, яких було запрошено або які приєдналися до кімнати. Ніхто, крім учасників кімнати, не зможе прочитати повідомлення. Це може перешкоджати коректній роботі ботів і мостів. @@ -144,11 +155,14 @@ "Приєднатися можуть лише запрошені люди." "Лише запрошені" "Доступ" + "Долучитися може будь-хто, хто має доступ до авторизованих просторів." "Долучитися може будь-хто з %1$s." + "Учасники простору" "Простори наразі не підтримуються" "Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі." "Адреса" "Дозвольте, щоб цю кімнату можна було знайти за допомогою пошуку в каталозі загальнодоступних кімнат %1$s " + "Дозвольте знаходити вас за допомогою пошуку в публічному каталозі." "Видима в загальному каталозі" "Будь-хто (загальнодоступна історія)" "Зміни не вплинуть на попередні повідомлення, лише на нові. %1$s" @@ -158,6 +172,7 @@ "Адреси кімнат — це спосіб знайти кімнату та отримати до неї доступ. Це також гарантує, що ви можете легко поділитися своєю кімнатою з іншими. Ви можете опублікувати свою кімнату в каталозі загальнодоступних кімнат вашого домашнього сервера." "Публікація в кімнаті" + "Адреси — це спосіб знаходити кімнати та простори та отримувати до них доступ. Це також гарантує, що ви зможете легко ділитися ними з іншими." "Видимість" "Безпека й приватність" diff --git a/features/roomdetails/impl/src/main/res/values-ur/translations.xml b/features/roomdetails/impl/src/main/res/values-ur/translations.xml index 3715bb91ff..d5ab09dd18 100644 --- a/features/roomdetails/impl/src/main/res/values-ur/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ur/translations.xml @@ -43,6 +43,7 @@ "اس کمرے کو خاموش کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔" "اس کمرے کو غیر خاموش کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔" "لوگوں کو مدعو کریں" + "مدعو کریں" "گفتگو چھوڑیں" "کمرہ چھوڑ دیں" "حسب ضرورت" diff --git a/features/roomdetails/impl/src/main/res/values-uz/translations.xml b/features/roomdetails/impl/src/main/res/values-uz/translations.xml index 1b4718ee44..fa9408b3ba 100644 --- a/features/roomdetails/impl/src/main/res/values-uz/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uz/translations.xml @@ -56,6 +56,7 @@ "Tugallanmaguncha ilovani yopmang." "Taklifnomalar tayyorlanmoqda…" "Odamlarni taklif qiling" + "Taklif qilish" "Suhbatni tark etish" "Xonani tark etish" "Media va fayllar" diff --git a/features/roomdetails/impl/src/main/res/values-vi/translations.xml b/features/roomdetails/impl/src/main/res/values-vi/translations.xml index ac37e6fcfa..5e25014c88 100644 --- a/features/roomdetails/impl/src/main/res/values-vi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-vi/translations.xml @@ -46,6 +46,7 @@ "Không thể tắt tiếng phòng này, vui lòng thử lại." "Không thể bật tiếng cho phòng này. Vui lòng thử lại." "Mời ai đó" + "Mời" "Rời khỏi cuộc trò chuyện" "Rời phòng" "Tùy chỉnh" diff --git a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml index 1cbabe0e54..04ccc56adb 100644 --- a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml @@ -56,6 +56,7 @@ "完成前請勿關閉應用程式。" "正在準備邀請……" "邀請夥伴" + "邀請" "離開對話" "離開聊天室" "媒體與檔案" diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index 267cdf5c04..1fef5583a3 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -56,6 +56,7 @@ "完成之前请勿关闭 app。" "正在准备邀请…" "邀请人员" + "邀请" "离开聊天" "离开房间" "媒体与文件" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 6275b2837e..d7092af70e 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -56,6 +56,7 @@ "Don\'t close the app until finished." "Preparing invitations…" "Invite people" + "Invite" "Leave conversation" "Leave room" "Media and files" diff --git a/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml index c676ff46ed..25be496204 100644 --- a/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml @@ -1,6 +1,6 @@ - "Edytuj pokój" + "Edytuj szczegóły" "Wystąpił nieznany błąd i nie można było zmienić informacji." "Nie można zaktualizować pokoju" "Aktualizuję pokój…" diff --git a/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml b/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml index f17660f418..6ddb482189 100644 --- a/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml @@ -9,7 +9,7 @@ "در صورت دعوت می‌تواند دوباره به اتاق بپیوندد." "مطمئنید می‌خواهید این عضو را بردارید؟" "دیدن نمایه" - "برداشتن از اتاق" + "حذف کاربر" "برداشتن عضو و تحریم پیوستن در آینده؟" "برداشتن %1$s…" "تحریم نکردن از اتاق" diff --git a/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml b/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml index 20246af787..40ea1f099a 100644 --- a/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml @@ -4,12 +4,14 @@ "Zbanuj" "Nie będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." "Czy na pewno chcesz zbanować tego członka?" + "Nie będą mogli ponownie dołączyć do tej przestrzeni, nawet jeśli zostaną zaproszeni, zachowają jednak członkostwo w pokojach lub podprzestrzeniach." "Banowanie %1$s" "Usuń" "Będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." "Czy na pewno chcesz usunąć tego członka?" + "Będą mogli ponownie dołączyć do tej przestrzeni, jeśli zostaną zaproszeni, zachowując jednocześnie członkostwo w pokojach lub podprzestrzeniach." "Wyświetl profil" - "Usuń z pokoju" + "Usuń użytkownika" "Usunąć członka i zablokować możliwość dołączenia w przyszłości?" "Usuwanie %1$s…" "Odbanuj z pokoju" diff --git a/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml b/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml index cd6dd40e55..0ddc115f7d 100644 --- a/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml @@ -4,10 +4,12 @@ "Заблокувати" "Він не зможе приєднатися до цієї кімнати знову, якщо його запросять." "Ви точно хочете заблокувати цього користувача?" + "Вони не зможуть знову приєднатися до цього простору, навіть якщо їх запросять, але збережуть своє членство в будь-яких кімнатах або підпросторах." "Блокування %1$s" "Вилучити" "Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять." "Ви дійсно хочете вилучити цього учасника?" + "Вони зможуть знову приєднатися до цього простору, якщо їх запросять, і збережуть своє членство в будь-яких кімнатах або підпросторах." "Переглянути профіль" "Вилучити користувача" "Вилучити учасника та заборонити приєднання в майбутньому?" diff --git a/features/securebackup/impl/src/main/res/values-el/translations.xml b/features/securebackup/impl/src/main/res/values-el/translations.xml index ca9adbc5ac..0f4584271c 100644 --- a/features/securebackup/impl/src/main/res/values-el/translations.xml +++ b/features/securebackup/impl/src/main/res/values-el/translations.xml @@ -12,6 +12,7 @@ "Εισαγωγή κλειδιού ανάκτησης" "Ο αποθηκευτικός χώρος κλειδιών σου δεν είναι συγχρονισμένος αυτήν τη στιγμή." "Λήψη κλειδιού ανάκτησης" + "Οι συνομιλίες σας αποθηκεύονται αυτόματα με κρυπτογράφηση από άκρο σε άκρο. Για να επαναφέρετε αυτό το αντίγραφο ασφαλείας και να διατηρήσετε την ψηφιακή σας ταυτότητα όταν χάσετε την πρόσβαση σε όλες τις συσκευές σας, θα χρειαστείτε το κλειδί ανάκτησης. " "Άνοιγμα %1$s σε συσκευή υπολογιστή" "Συνδέσου ξανά στο λογαριασμό σου" "Όταν σου ζητηθεί να επαληθεύσεις τη συσκευή σου, επέλεξε %1$s" diff --git a/features/securebackup/impl/src/main/res/values-et/translations.xml b/features/securebackup/impl/src/main/res/values-et/translations.xml index 987fd88190..c3d849f37b 100644 --- a/features/securebackup/impl/src/main/res/values-et/translations.xml +++ b/features/securebackup/impl/src/main/res/values-et/translations.xml @@ -61,9 +61,9 @@ "Seadista andmete taastamine" "Jah, lähtesta nüüd" "See tegevus on tagasipöördumatu." - "Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?" + "Kas sa oled kindel, et soovid oma võrguidentiteeti lähtestada?" "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti." "Sisesta…" - "Palun kinnita, et soovid oma andmete krüptimist lähtestada." + "Palun kinnita, et soovid oma võrguidentiteedi lähtestada." "Jätkamaks sisesta oma kasutajakonto salasõna" diff --git a/features/securebackup/impl/src/main/res/values-fa/translations.xml b/features/securebackup/impl/src/main/res/values-fa/translations.xml index c16e5bd1d8..bd7a43ffba 100644 --- a/features/securebackup/impl/src/main/res/values-fa/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fa/translations.xml @@ -9,7 +9,7 @@ "تغییر کلید بازیابی" "ورود کلید بازیابی" "ذخیره‌ساز کلیدتان از هم‌گام بودن در آمده." - "برپایی بازیابی" + "دریافت کلید بازیابی" "گشودن %1$s در افزارهٔ میزکار" "ورود دوباره به حسابتان" "گزینش %1$s هنگام درخواست تأیید افزاره‌تان" @@ -23,10 +23,10 @@ "لازم است دوباره همهٔ آشنایان و افزاره‌های موجودتان را تأیید کنید" "فقط اگر به افزاره‌ای وارد شده از پیش دسترسی ندارید و کلید بازیابیتان را گم کرده‌اید بازنشانی کنید." "نمی‌توانید تأیید کنید؟ لازم است هویتتان را بازنشانی کنید." - "خاموش کردن" - "اگر از سیستم همه دستگاه ها خارج شده باشید، پیام های رمزگذاری شده خود را از دست خواهید داد." - "مطمئنید که می‌خواهید پشتیبان گیری را خاموش کنید؟" - "حذف فضای ذخیره سازی کلید، هویت رمزنگاری و کلیدهای پیام شما را از کارساز حذف می کند و ویژگی های امنیتی زیر را خاموش می کند:" + "حذف" + "اگر از تمام دستگاه‌هایتان خارج شوید، تاریخچه چت رمزگذاری‌شده خود را از دست خواهید داد و باید هویت دیجیتال خود را مجدداً تنظیم کنید." + "آیا مطمئن هستید که می‌خواهید کلید ذخیره‌سازی را حذف کنید؟" + "حذف محل ذخیره‌سازی کلید، کلیدهای هویت دیجیتال و پیام شما را از سرور حذف کرده و ویژگی‌های امنیتی زیر را غیرفعال می‌کند:" "سابقه پیام رمزگذاری شده در دستگاه های جدید نخواهید داشت" "اگر از %1$s در همه جا خارج شده باشید، دسترسی به پیام های رمزگذاری شده خود را از دست خواهید داد" "مطمئنید که می‌خواهید فضای ذخیره سازی کلید را خاموش کرده و آن را حذف کنید؟" @@ -56,7 +56,7 @@ "تولید کلید بازیابیتان" "با کسی هم‌رسانیش نکنید!" "برپایی بازیابی موفّق بود" - "برپایی بازیابی" + "دریافت کلید بازیابی" "بله. اکنون بازنشانی شود" "این فرایند بازگشت‌ناپذیر است." "ورود…" diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index fb30d786c0..f2f44e10f3 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -2,33 +2,34 @@ "Wyłącz backup" "Włącz backup" - "Bezpiecznie przechowuj swoją tożsamość kryptograficzną i klucze wiadomości na serwerze. Umożliwi to przeglądanie historii wiadomości na każdym nowym urządzeniu. %1$s" + "Umożliwi Ci to przeglądanie historii czatów na nowych urządzeniach i jest wymagane do tworzenia kopii zapasowych i tożsamości cyfrowej. %1$s." "Magazyn kluczy" - "Magazyn kluczy musi być włączony, aby włączyć przywracanie." + "Magazyn kluczy musi być włączony, aby włączyć archiwizowanie czatów." "Prześlij klucze z tego urządzenia" "Zezwól na magazynowanie kluczy" "Zmień klucz przywracania" - "Odzyskaj swoją tożsamość kryptograficzną i historię wiadomości za pomocą klucza przywracania, jeśli utraciłeś dostęp do wszystkich swoich urządzeń." + "Twoje czaty są automatycznie archiwizowane za pomocą szyfrowania end-to-end. Aby przywrócić tę kopię zapasową i swoją tożsamość cyfrową, wymagany będzie klucz przywracania." "Wprowadź klucz przywracania" "Magazyn kluczy nie jest zsynchronizowany." - "Skonfiguruj przywracanie" + "Uzyskaj klucz przywracania" + "Twoje czaty są automatycznie archiwizowane za pomocą szyfrowania end-to-end. Aby przywrócić tę kopię zapasową i swoją tożsamość cyfrową, wymagany będzie klucz przywracania." "Otwórz %1$s na urządzeniu stacjonarnym" "Zaloguj się ponownie na swoje konto" "Gdy pojawi się prośba o weryfikację urządzenia, wybierz %1$s" - "“Resetuj wszystko”" + "“Zresetuj wszystko”" "Postępuj zgodnie z instrukcjami, aby utworzyć nowy klucz przywracania" "Zapisz nowy klucz przywracania w menedżerze haseł lub notatce szyfrowanej" - "Resetuj szyfrowanie swojego konta za pomocą drugiego urządzenia" + "Zresetuj szyfrowanie swojego konta za pomocą drugiego urządzenia" "Kontynuuj resetowanie" "Szczegóły konta, kontakty, preferencje i lista czatów zostaną zachowane" "Utracisz istniejącą historię wiadomości" "Wymagana będzie ponowna weryfikacja istniejących urządzeń i kontaktów" - "Zresetuj swoją tożsamość tylko wtedy, gdy nie jesteś zalogowany na żadnym urządzeniu i straciłeś swój klucz przywracania." - "Zresetuj swoją tożsamość, jeśli nie możesz jej potwierdzić w inny sposób" - "Wyłącz" - "Jeśli wylogujesz się ze wszystkich urządzeń, stracisz wszystkie wiadomości szyfrowane." - "Czy na pewno chcesz wyłączyć backup?" - "Wyłączenie backupu spowoduje usunięcie kopii klucza szyfrowania i wyłączenie innych funkcji bezpieczeństwa. W takim przypadku będziesz:" + "Zresetuj swoją tożsamość tylko wtedy, gdy nie posiadasz dostępu do żadnego innego zweryfikowanego urządzenia i straciłeś swój klucz przywracania." + "Nie możesz potwierdzić? Zresetuj swoją tożsamość cyfrową." + "Usuń" + "Jeśli usuniesz wszystkie swoje urządzenia, stracisz zaszyfrowaną historię wiadomości i będziesz musiał zresetować swoją tożsamość cyfrową." + "Czy na pewno chcesz usunąć magazyn kluczy?" + "Usunięcie magazynu kluczy usunie Twoją tożsamość cyfrową i klucze wiadomości z serwera, wyłączając następujące funkcje bezpieczeństwa:" "Posiadał historii wiadomości szyfrowanych na nowych urządzeniach" "Utracisz dostęp do wiadomości szyfrowanych, jeśli zostaniesz wszędzie wylogowany z %1$s" "Czy na pewno chcesz wyłączyć backup?" @@ -58,12 +59,12 @@ "Wygeneruj klucz przywracania" "Nie udostępniaj tego nikomu!" "Skonfigurowano przywracanie pomyślnie" - "Skonfiguruj przywracanie" + "Uzyskaj klucz przywracania" "Tak, zresetuj teraz" "Tego procesu nie można odwrócić." - "Czy na pewno chcesz zresetować szyfrowanie?" + "Czy na pewno chcesz zresetować swoją tożsamość cyfrową?" "Wystąpił nieznany błąd. Sprawdź, czy hasło jest poprawne i spróbuj ponownie." "Wprowadź…" - "Potwierdź, że chcesz zresetować szyfrowanie." + "Potwierdź, że chcesz zresetować swoją tożsamość cyfrową." "Wprowadź hasło, aby kontynuować" diff --git a/features/securebackup/impl/src/main/res/values-sk/translations.xml b/features/securebackup/impl/src/main/res/values-sk/translations.xml index b02d5ecfbb..3e92a39df0 100644 --- a/features/securebackup/impl/src/main/res/values-sk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sk/translations.xml @@ -26,7 +26,7 @@ "Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie." "Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom" "Vypnúť" - "Stratíte prístup k svojim zašifrovaným správam, ak sa odhlásite zo všetkých zariadení" + "Ak odstránite všetky svoje zariadenia, stratíte svoju zašifrovanú históriu správ a budete si musieť obnoviť svoju digitálnu identitu." "Ste si istí, že chcete vypnúť zálohovanie?" "Vypnutím zálohovania sa odstráni aktuálna záloha šifrovacích kľúčov a vypnú sa ďalšie bezpečnostné funkcie. V tomto prípade:" "Na nových zariadeniach nebudete mať zašifrovanú históriu správ" diff --git a/features/securebackup/impl/src/main/res/values-uk/translations.xml b/features/securebackup/impl/src/main/res/values-uk/translations.xml index 218e6d64fd..82a96fcab9 100644 --- a/features/securebackup/impl/src/main/res/values-uk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uk/translations.xml @@ -12,6 +12,7 @@ "Введіть ключ відновлення" "Сховище ключів наразі не синхронізовано." "Налаштувати відновлення" + "Ваші чати автоматично резервуються з використанням наскрізного шифрування. Щоб відновити цю резервну копію та зберегти свою цифрову ідентичність у разі втрати доступу до всіх своїх пристроїв, вам знадобиться ключ відновлення." "Відкрийте %1$s на комп\'ютері" "Увійдіть до вашого облікового запису знову" "Коли вас попросять підтвердити пристрій, виберіть %1$s" diff --git a/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml b/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml index c62c4f2af4..60415c2288 100644 --- a/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml @@ -1,10 +1,17 @@ - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" - "Dodaj adres pokoju" - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić żądanie." + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Edytuj adres" + "Przestrzenie, których członkowie mogą dołączyć do pokoju bez zaproszenia." + "Zarządzaj przestrzeniami" + "(Nieznana przestrzeń)" + "Inne przestrzenie, których nie jesteś członkiem" + "Twoje przestrzenie" + "Dodaj adres" + "Każdy w autoryzowanych przestrzeniach może dołączyć, ale wszyscy inni muszą poprosić o dostęp." + "Każdy musi poprosić o dostęp." "Poproś o dołączenie" + "Każdy w %1$s może dołączyć, ale wszyscy pozostali muszą poprosić o dostęp." "Tak, włącz szyfrowanie" "Po włączeniu szyfrowanie pokoju nie może zostać wyłączone, a historia wiadomości będzie widoczna tylko dla członków od momentu, w którym dołączyli lub zostali zaproszeni. Nikt poza członkami pokoju nie będzie mógł czytać wiadomości. Może to wpłynąć na prawidłowe działanie botów lub mostków. @@ -13,23 +20,31 @@ Odradzamy włączanie szyfrowania dla pokoi, które każdy może znaleźć i do "Po włączeniu szyfrowania nie można wyłączyć." "Szyfrowanie" "Włącz szyfrowanie end-to-end" - "Każdy może znaleźć i dołączyć" + "Każdy może dołączyć." "Każdy" - "Tylko osoby z zaproszeniem mogą dołączyć" - "Tylko zaproszenie" - "Dostęp do pokoju" + "Wybierz, którzy członkowie przestrzeni mogą dołączyć do tego pokoju bez zaproszenia. %1$s" + "Zarządzaj przestrzeniami" + "Tylko zaproszone osoby mogą dołączyć" + "Tylko na zaproszenie" + "Dostęp" + "Każdy w autoryzowanych przestrzeniach może dołączyć." + "Każdy w %1$s może dołączyć." + "Członkowie przestrzeni" "Przestrzenie nie są obecnie wspierane" - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Adres" "Zezwól na znalezienie tego pokoju wyszukując %1$s w katalogu pokoi publicznych" + "Zezwól, by inni mogli Cię znaleźć, przeszukując katalog publiczny." "Widoczny w katalogu pokoi publicznych" - "Ktokolwiek" + "Każdy (historia jest publiczna)" + "Zmiany nie zmienią przeszłych wiadomości, tylko nowe. %1$s" "Kto może czytać historię" - "Od momentu kiedy członkowie zostali zaproszeni" - "Członkowie od momentu włączenia tej opcji" + "Członkowie od kiedy zostali zaproszeni" + "Członkowie (cała historia)" "Adresy pokoju umożliwiają łatwe znalezienie i dołączenie do pokojów. Również możesz się zdecydować na upublicznienie Twojego serwera w katalogu pokoi publicznych." "Publikowanie pokoju" - "Widoczność pokoju" + "Adresy pokoi pomagają w znalezieniu i dołączeniu do pokoi i przestrzeni. Umożliwiają również łatwe udostępnianie ich innym." + "Widoczność" "Bezpieczeństwo i prywatność" diff --git a/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml b/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml index f8b96ee6c5..0921887ccb 100644 --- a/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml @@ -8,8 +8,10 @@ "Інші простори, учасником яких ви не є" "Ваші простори" "Додати адресу" + "Будь-хто в авторизованих просторах може приєднатися, але всі інші повинні подати запит на доступ." "Усі повинні запитувати доступ." "Запит на приєднання" + "Будь-хто з %1$s може приєднатися, але всі інші повинні подати запит на доступ." "Так, увімкнути шифрування" "Після ввімкнення шифрування кімнати, його неможливо вимкнути, історію повідомлень бачитимуть лише учасники кімнати, яких було запрошено або які приєдналися до кімнати. Ніхто, крім учасників кімнати, не зможе прочитати повідомлення. Це може перешкоджати коректній роботі ботів і мостів. @@ -25,11 +27,14 @@ "Приєднатися можуть лише запрошені люди." "Лише запрошені" "Доступ" + "Долучитися може будь-хто, хто має доступ до авторизованих просторів." "Долучитися може будь-хто з %1$s." + "Учасники простору" "Простори наразі не підтримуються" "Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі." "Адреса" "Дозвольте, щоб цю кімнату можна було знайти за допомогою пошуку в каталозі загальнодоступних кімнат %1$s " + "Дозвольте знаходити вас за допомогою пошуку в публічному каталозі." "Видима в загальному каталозі" "Будь-хто (загальнодоступна історія)" "Зміни не вплинуть на попередні повідомлення, лише на нові. %1$s" @@ -39,6 +44,7 @@ "Адреси кімнат — це спосіб знайти кімнату та отримати до неї доступ. Це також гарантує, що ви можете легко поділитися своєю кімнатою з іншими. Ви можете опублікувати свою кімнату в каталозі загальнодоступних кімнат вашого домашнього сервера." "Публікація в кімнаті" + "Адреси — це спосіб знаходити кімнати та простори та отримувати до них доступ. Це також гарантує, що ви зможете легко ділитися ними з іншими." "Видимість" "Безпека й приватність" diff --git a/features/space/impl/src/main/res/values-fa/translations.xml b/features/space/impl/src/main/res/values-fa/translations.xml index dcab5c912a..d8f377c0b2 100644 --- a/features/space/impl/src/main/res/values-fa/translations.xml +++ b/features/space/impl/src/main/res/values-fa/translations.xml @@ -8,6 +8,6 @@ "تنها مدیر %1$s هستید" "دیدن اعضا" "ترک فضا" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" "امنیت و محرمانگی" diff --git a/features/space/impl/src/main/res/values-pl/translations.xml b/features/space/impl/src/main/res/values-pl/translations.xml index f1a964c6e3..9c3097b75f 100644 --- a/features/space/impl/src/main/res/values-pl/translations.xml +++ b/features/space/impl/src/main/res/values-pl/translations.xml @@ -9,9 +9,21 @@ "Wybierz pokoje, które chcesz opuścić, a których nie jesteś jedynym administratorem:" "Aby opuścić tę przestrzeń, musisz przypisać do niej innego administratora." + "Jesteś jedynym właścicielem %1$s. Musisz przenieść własność zanim odejdziesz." "Nie zostaniesz usunięty z następujących pokoi, ponieważ jesteś ich jedynym administratorem:" "Opuścić %1$s?" "Jesteś jedynym administratorem %1$s" + "Przenieś własność" + "Pokój" + "Dodanie pokoju nie wpłynie na dostęp do niego. Aby zmienić ustawienia dostępu, przejdź do Ustawienia pokoju > Bezpieczeństwo i prywatność." + "Dodaj swój pierwszy pokój" + "Zobacz członków" + "Usunięcie pokoju nie wpłynie na dostęp do niego. Aby zmienić ustawienia dostępu, przejdź do Ustawienia pokoju > Bezpieczeństwo i prywatność." + + "Usuń %1$d pokój z %2$s" + "Usuń %1$d pokoje z %2$s" + "Usuń %1$d pokoi z %2$s" + "Opuść przestrzeń" "Role i uprawnienia" "Bezpieczeństwo i prywatność" diff --git a/features/space/impl/src/main/res/values-uk/translations.xml b/features/space/impl/src/main/res/values-uk/translations.xml index e124f72826..df4b4fb922 100644 --- a/features/space/impl/src/main/res/values-uk/translations.xml +++ b/features/space/impl/src/main/res/values-uk/translations.xml @@ -2,14 +2,28 @@ "Оберіть власників" "%1$s (Адміністратор)" + + "Залишити %1$d кімнату та простір" + "Залишити %1$d кімнату та простори" + "Залишити %1$d кімнат та просторів" + "Виберіть кімнати, з яких ви хочете вийти, і в них ви не єдиний адміністратор:" "Перш ніж ви зможете вийти, вам потрібно призначити іншого адміністратора для цього простору." + "Ви єдиний власник %1$s. Перш ніж піти, вам потрібно передати право володіння комусь іншому." "Вас не буде видалено з цих кімнат, оскільки ви єдиний адміністратор:" "Вийти з %1$s?" "Ви єдиний адміністратор у %1$s" + "Передача права володіння" "Кімната" + "Додавання кімнати не вплине на доступ до неї. Щоб змінити доступ, перейдіть до «Налаштування кімнати» > «Безпека та конфіденційність»." "Додайте свою першу кімнату" "Переглянути учасників" + "Видалення кімнати не вплине на доступ до неї. Щоб змінити доступ, перейдіть до розділу «Налаштування кімнати» > «Безпека та конфіденційність»." + + "Видалити %1$d кімнату з %2$s" + "Видалити %1$d кімнати з %2$s" + "Видалити %1$d кімнат з %2$s" + "Вийти з простору" "Ролі та дозволи" "Безпека й приватність" diff --git a/features/verifysession/impl/src/main/res/values-fa/translations.xml b/features/verifysession/impl/src/main/res/values-fa/translations.xml index aa902a94e1..3447c07a7d 100644 --- a/features/verifysession/impl/src/main/res/values-fa/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fa/translations.xml @@ -13,6 +13,7 @@ "يه چيزي درست به نظر نمياد یا زمان درخواست به پایان رسید یا درخواست رد شد." "تأیید تطابق شکلک‌های زیر با شکلک‌های نشان داده شده روی افزارهٔ دیگرتان." "مقایسهٔ شکلک‌ها" + "تأیید کنید که اعداد زیر با اعداد نشان داده شده در جلسه دیگر شما مطابقت دارند." "مقایسهٔ اعداد" "اکنون می‌توانید روی افزارهٔ دیگرتان با امنیت پیام فرستاده و بخوانید." "افزاره تأیید شده" diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml index 92b0572d08..39ce9f6fa3 100644 --- a/features/verifysession/impl/src/main/res/values-pl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml @@ -2,8 +2,8 @@ "Nie możesz potwierdzić?" "Utwórz nowy klucz przywracania" - "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." - "Potwierdź, że to Ty" + "Wybierz sposób weryfikacji, aby skonfigurować bezpieczne wiadomości." + "Potwierdź swoją tożsamość cyfrową" "Użyj innego urządzenia" "Użyj klucza przywracania" "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." @@ -50,5 +50,5 @@ "Po zaakceptowaniu będziesz mógł kontynuować weryfikację." "Zaakceptuj prośbę o rozpoczęcie procesu weryfikacji w innej sesji, aby kontynuować." "Oczekiwanie na zaakceptowanie prośby" - "Wylogowywanie…" + "Usuwam urządzenie…" diff --git a/features/verifysession/impl/src/main/res/values-sk/translations.xml b/features/verifysession/impl/src/main/res/values-sk/translations.xml index 932b8555fc..d4e6f60402 100644 --- a/features/verifysession/impl/src/main/res/values-sk/translations.xml +++ b/features/verifysession/impl/src/main/res/values-sk/translations.xml @@ -50,5 +50,5 @@ "Po prijatí budete môcť pokračovať v overovaní." "Ak chcete pokračovať, prijmite žiadosť o spustenie procesu overenia vo vašej druhej relácii." "Čaká sa na prijatie žiadosti" - "Prebieha odhlasovanie…" + "Odoberanie zariadenia…" diff --git a/features/verifysession/impl/src/main/res/values-uk/translations.xml b/features/verifysession/impl/src/main/res/values-uk/translations.xml index 1967fef383..03fe318d13 100644 --- a/features/verifysession/impl/src/main/res/values-uk/translations.xml +++ b/features/verifysession/impl/src/main/res/values-uk/translations.xml @@ -50,5 +50,5 @@ "Після погодження ви зможете продовжити верифікацію." "Щоб продовжити, прийміть запит на початок процесу верифікації в іншому сеансі." "Очікування на прийняття запиту" - "Вихід…" + "Видалення пристрою…" diff --git a/libraries/matrixui/src/main/res/values-it/translations.xml b/libraries/matrixui/src/main/res/values-it/translations.xml index 439d61337e..913c45867c 100644 --- a/libraries/matrixui/src/main/res/values-it/translations.xml +++ b/libraries/matrixui/src/main/res/values-it/translations.xml @@ -3,5 +3,7 @@ "Invia invito" "Vuoi iniziare una conversazione con%1$s?" "Inviare invito?" + "Al momento non hai alcuna conversazione con questa persona. Conferma l\'invito prima di continuare." + "Vuoi avviare una conversazione con questo nuovo contatto?" "%1$s (%2$s) ti ha invitato" diff --git a/libraries/matrixui/src/main/res/values-pl/translations.xml b/libraries/matrixui/src/main/res/values-pl/translations.xml index caa2c0e07d..bd31d7edb4 100644 --- a/libraries/matrixui/src/main/res/values-pl/translations.xml +++ b/libraries/matrixui/src/main/res/values-pl/translations.xml @@ -3,5 +3,7 @@ "Wyślij zaproszenie" "Czy chcesz rozpocząć czat z %1$s?" "Wysłać zaproszenie?" + "Obecnie nie posiadasz żadnych czatów z tą osobą. Potwierdź zaproszenie, zanim przejdziesz dalej." + "Rozpocząć czat z nowym kontaktem?" "%1$s (%2$s) zaprosił Cię" diff --git a/libraries/matrixui/src/main/res/values-uk/translations.xml b/libraries/matrixui/src/main/res/values-uk/translations.xml index 324bb96086..4d2063fbd2 100644 --- a/libraries/matrixui/src/main/res/values-uk/translations.xml +++ b/libraries/matrixui/src/main/res/values-uk/translations.xml @@ -3,5 +3,7 @@ "Надіслати запрошення" "Хочете розпочати бесіду з %1$s?" "Надіслати запрошення?" + "Наразі у вас немає чатів із цим користувачем. Підтвердьте запрошення, перш ніж продовжити." + "Розпочати чат із цим новим контактом?" "%1$s (%2$s) запрошує вас" diff --git a/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml index 72701194fc..913329122e 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml @@ -16,6 +16,7 @@ "Nome del file" "Nessun altro file da mostrare" "Non ci sono più contenuti multimediali da mostrare" + "Informazioni sul file" "Caricato da" "Caricato il" diff --git a/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml index c398123873..a1f7a3bdf9 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml @@ -16,6 +16,7 @@ "Nazwa pliku" "Brak plików do pokazania" "Brak mediów do pokazania" + "Informacje pliku" "Przesłane przez" "Przesłane w dniu" diff --git a/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml index 45e1e1703b..ddc316fb4b 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml @@ -16,6 +16,7 @@ "Назва файлу" "Більше немає файлів для показу" "Більше немає медіа для показу" + "Інформація про файл" "Вивантажено користувачем" "Вивантажено" diff --git a/libraries/push/impl/src/main/res/values-pl/translations.xml b/libraries/push/impl/src/main/res/values-pl/translations.xml index b9ae289507..d8a4077d05 100644 --- a/libraries/push/impl/src/main/res/values-pl/translations.xml +++ b/libraries/push/impl/src/main/res/values-pl/translations.xml @@ -15,7 +15,14 @@ "%d powiadomienia" "%d powiadomień" + "Nie udało się zarejestrować dystrybutora powiadomień Push, przez co nie będziesz już otrzymywać powiadomień. Sprawdź ustawienia powiadomień aplikacji i status dystrybutora powiadomień Push." "Masz nowe wiadomości." + + "Masz %d nową wiadomość." + "Masz %d nowe wiadomości." + "Masz %d nowych wiadomości." + + "📞 Połączenie przychodzące" "📹 Połączenie przychodzące" "** Nie udało się wysłać - proszę otworzyć pokój" "Dołącz" @@ -41,12 +48,15 @@ "%1$s zaprosił Cię do pokoju" "Ja" "%1$s wspomniał lub odpowiedział" + "Zaprosił Cię do dołączenia do przestrzeni" + "%1$s zaprosił Cię do dołączenia do przestrzeni" "Wyświetlasz powiadomienie! Kliknij mnie!" + "Wątek w %1$s" "%1$s: %2$s" "%1$s: %2$s %3$s" "%d nieprzeczytana wiadomość" - "%d nieprzeczytane wiadomość" + "%d nieprzeczytane wiadomości" "%d nieprzeczytanych wiadomości" "%1$s i %2$s" diff --git a/libraries/push/impl/src/main/res/values-uk/translations.xml b/libraries/push/impl/src/main/res/values-uk/translations.xml index d3aee22165..9c5f74605f 100644 --- a/libraries/push/impl/src/main/res/values-uk/translations.xml +++ b/libraries/push/impl/src/main/res/values-uk/translations.xml @@ -15,7 +15,14 @@ "%d сповіщення" "%d сповіщень" + "Розподільник сповіщень UnifiedPush не вдалося зареєструвати, тому ви більше не отримуватимете сповіщень. Перевірте налаштування сповіщень у додатку та статус розподільника push-сповіщень." "У вас є нові повідомлення." + + "У вас %d нове повідомлення." + "У вас %d нових повідомлення." + "У вас %d нових повідомлень." + + "📞 Вхідний дзвінок" "📹 Вхідний виклик" "** Не вдалося надіслати - відкрийте кімнату" "Доєднатися" @@ -41,6 +48,7 @@ "%1$s запросив вас приєднатися до кімнати" "Я" "%1$s згадували або відповідали" + "Вас запросили приєднатися до простору" "%1$s запрошує вас приєднатися до простору" "Ви переглядаєте сповіщення! Натисніть тут!" "Гілка в %1$s" @@ -62,11 +70,18 @@ "Фонова синхронізація" "Сервіси Google" "Не знайдено дійсних сервісів Google Play. Сповіщення можуть не працювати належним чином." + "Перевірка заблокованих користувачів" "Переглянути заблокованих користувачів" "Немає заблокованих користувачів" + + "Ви заблокували %1$d користувача. Ви не отримуватимете сповіщення для цього користувача." + "Ви заблокували %1$d користувачів. Ви не отримуватимете сповіщення для цих користувачів." + "Ви заблокували %1$d користувачів. Ви не отримуватимете сповіщення для цих користувачів." + "Заблоковані користувачі" "Отримує назву поточного постачальника." "Постачальників push-сповіщень не вибрано." + "Поточний провайдер push-повідомлень: %1$s та поточний дистриб\'ютор: %2$s. Але дистриб\'ютор %3$s не знайдено. Можливо, додаток було видалено?" "Поточний постачальник push-сповіщень: %1$s, але дистриб\'юторів не налаштовано." "Поточний постачальник: %1$s." "Поточний постачальник push-сповіщень: %1$s (%2$s)" diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 4011474193..f106b46e6c 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -244,7 +244,6 @@ "Ключ аднаўлення" "Абнаўленне…" "Адказвае на %1$s" - "Паведаміць пра памылку" "Паведаміць аб праблеме" "Скарга прынята" "Рэдактар фарматаванага тэксту" diff --git a/libraries/ui-strings/src/main/res/values-bg/translations.xml b/libraries/ui-strings/src/main/res/values-bg/translations.xml index 94e050727d..596b7b3e34 100644 --- a/libraries/ui-strings/src/main/res/values-bg/translations.xml +++ b/libraries/ui-strings/src/main/res/values-bg/translations.xml @@ -231,7 +231,6 @@ "%1$d отговора" "В отговор на %1$s" - "Съобщаване за грешка" "Съобщаване за проблем" "Докладът е изпратен" "Редактор на богат текст" diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 4343f2980b..e177c23957 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -324,7 +324,6 @@ Důvod: %1$s." "%1$d odpovědí" "Odpověď na %1$s" - "Nahlásit chybu" "Nahlásit problém" "Zpráva odeslána" "Editor formátovaného textu" diff --git a/libraries/ui-strings/src/main/res/values-cy/translations.xml b/libraries/ui-strings/src/main/res/values-cy/translations.xml index 9c4b04b9d5..98538f517d 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -309,7 +309,6 @@ Rheswm: %1$s."
"%1$d ateb" "Yn ymateb i %1$s" - "Adrodd ar wall" "Adrodd am broblem" "Adroddiad wedi ei gyflwyno" "Golygydd testun cyfoethog" diff --git a/libraries/ui-strings/src/main/res/values-da/translations.xml b/libraries/ui-strings/src/main/res/values-da/translations.xml index f1ff7ec747..1769a5d223 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -323,7 +323,6 @@ "%1$d svar" "Svarer til %1$s" - "Rapportér en fejl" "Anmeld et problem" "Anmeldelsen er indsendt" "Rich text editor" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 739d003f88..e6332b9df2 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -316,7 +316,6 @@ Grund: %1$s." "%1$d Antworten" "%1$s antworten" - "Einen Fehler melden" "Ein Problem melden" "Bericht eingereicht" "Rich-Text-Editor" diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml index beb97c54d1..a12122b00b 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -120,6 +120,7 @@ "Αποχώρηση από τον χώρο" "Φόρτωσε περισσότερα" "Διαχείριση λογαριασμού" + "Διαχείριση λογαριασμού και συσκευών" "Διαχείριση συσκευών" "Διαχείριση αίθουσών" "Στείλε" @@ -170,6 +171,7 @@ "Ξανά από την αρχή" "Έναρξη επαλήθευσης" "Πάτα για φόρτωση χάρτη" + "Διακοπή" "Τράβηξε φωτογραφία" "Πάτα για επιλογές" "Μετάφραση" @@ -224,6 +226,7 @@ "Κενό αρχείο" "Κρυπτογράφηση" "Η κρυπτογράφηση ενεργοποιήθηκε" + "Τελειώνει στις %1$s" "Εισήγαγε το PIN σου" "Σφάλμα" "Παρουσιάστηκε σφάλμα, ενδέχεται να μην λαμβάνεις ειδοποιήσεις για νέα μηνύματα. Αντιμετώπισε το πρόβλημα με τις ειδοποιήσεις από τις ρυθμίσεις. @@ -250,6 +253,8 @@ "Η γραμμή αντιγράφηκε στο πρόχειρο" "Ο σύνδεσμος αντιγράφηκε στο πρόχειρο" "Σύνδεση νέας συσκευής" + "Ζωντανή τοποθεσία" + "Η ζωντανή τοποθεσία έληξε" "Φόρτωση…" "Φόρτωση περισσότερων…" @@ -311,7 +316,6 @@ "%1$d απαντήσεις" "Απάντηση σε %1$s" - "Αναφορά σφάλματος" "Αναφορά προβλήματος" "Η αναφορά υποβλήθηκε" "Επεξεργαστής εμπλουτισμένου κειμένου" @@ -346,6 +350,7 @@ "Ρυθμίσεις" "Κοινή χρήση χώρου" "Τα νέα μέλη βλέπουν το ιστορικό" + "Κοινόχρηστη ζωντανή τοποθεσία" "Κοινόχρηστη τοποθεσία" "Κοινόχρηστος χώρος" "Αφαίρεση συσκευής" @@ -368,6 +373,7 @@ "Κείμενο" "Ειδοποιήσεις τρίτων" "Νήμα" + "Νήματα" "Θέμα" "Τι αφορά αυτή η αίθουσα;" "Δεν είναι δυνατή η αποκρυπτογράφηση" @@ -398,6 +404,7 @@ "Φωνητικό μήνυμα" "Αναμονή…" "Αναμονή για αυτό το μήνυμα" + "Αναμονή για ζωντανή τοποθεσία…" "Οποιοσδήποτε μπορεί να δει το ιστορικό" "Εσύ" "%1$s (%2$s) μοιράστηκε αυτό το μήνυμα, καθώς δεν ήσασταν στην αίθουσα όταν στάλθηκε." diff --git a/libraries/ui-strings/src/main/res/values-es/translations.xml b/libraries/ui-strings/src/main/res/values-es/translations.xml index fa0bc700cb..1dc69b127c 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -251,7 +251,6 @@ Motivo: %1$s." "Clave de recuperación" "Recargando…" "Respondiendo a %1$s" - "Informar de un error" "Informar de un problema" "Informe enviado" "Editor de texto enriquecido" diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index beedf175bd..e76e3153e1 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -69,6 +69,7 @@ "Helista" "Loobu" "Hetkel jäta tegemata" + "Vali fail" "Vali foto" "Selge" "Sulge" @@ -88,12 +89,15 @@ "Eemalda konto kasutusest" "Keeldu" "Keeldu ja blokeeri" + "Kustuta" + "Kustuta kasutajakonto" "Kustuta küsitlus" "Eemalda kõik valikud" "Lülita välja" "Loobu" "Lõpeta" "Valmis" + "Laadi alla" "Muuda" "Muuda selgitust" "Muuda küsitlust" @@ -201,7 +205,9 @@ "Beetaversioon" "Blokeeritud kasutajad" "Mullid" + "Osapool keeldus kõnest" "Kõne algas" + "Sa keeldusid kõnest" "Vestluse varukoopia" "Kopeeritud lõikelauale" "Autoriõigused" @@ -253,6 +259,8 @@ Põhjus: %1$s." "Rida on kopeeritud lõikelauale" "Link on kopeeritud lõikelauale" "Seo uus seade" + "Asukoha jagamine reaalajas" + "Reaalajas asukoha jagamine on lõppenud" "Laadime…" "Laadime veel…" @@ -279,6 +287,7 @@ Põhjus: %1$s." "Võrgust väljas" "Avatud lähtekoodiga litsentsid" "või" + "Muud valikud" "Salasõna" "Inimesed" "Püsilink" @@ -313,7 +322,6 @@ Põhjus: %1$s." "%1$d vastust" "Vastates kasutajale %1$s" - "Teata veast" "Teata veast" "Veateade on saadetud" "Vormindatud teksti toimeti" @@ -401,6 +409,7 @@ Põhjus: %1$s." "Häälsõnum" "Ootame…" "Ootame selle sõnumi dekrüptimisvõtit" + "Ootan asukoha jagamist reaalajas…" "Kõik võivad ajalugu näha" "Sina" "Kuna sind polnud saatmise ajal jututoas, siis %1$s (%2$s) jagas seda sõnumit sinuga." @@ -461,6 +470,11 @@ Kas sa oled kindel, et soovid jätkata?" "Seadistused" "Mitte keegi ei jaga oma asukohta" "Asukoht on jagamisel reaalajas" + + "%1$d isik" + "%1$d isikut" + + "Kaardil" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Siia lisamiseks vajuta sõnumil ja vali „%1$s“." "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile" @@ -485,6 +499,7 @@ Kas sa oled kindel, et soovid jätkata?" "Sõnum jututoas %1$s" "Näita rohkem" "Näita vähem" + "Asukoht on jagamisel reaalajas" "Sa juba vaatad seda jututuba!" "%1$s / %2$s" "%1$s esiletõstetud sõnumit" diff --git a/libraries/ui-strings/src/main/res/values-eu/translations.xml b/libraries/ui-strings/src/main/res/values-eu/translations.xml index bef5f1a4b5..7e9d3a05fe 100644 --- a/libraries/ui-strings/src/main/res/values-eu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-eu/translations.xml @@ -256,7 +256,6 @@ Arrazoia: %1$s." "Berreskuratze-gakoa" "Freskatzen…" "%1$s(r)i erantzuten" - "Eman akats baten berri" "Eman arazo baten berri" "Salaketa bidali da" "Testu aberatsaren editorea" diff --git a/libraries/ui-strings/src/main/res/values-fa/translations.xml b/libraries/ui-strings/src/main/res/values-fa/translations.xml index 872493f7de..418ca96419 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -146,7 +146,7 @@ "نمایش" "ورود دوباره" "برداشتن این افزاره" - "خروج به هر صورت" + "به هر حال این دستگاه را حذف کنید" "پرش" "آغاز" "آغاز گپ" @@ -225,6 +225,10 @@ "پیوند در تخته‌گیره رونوشت شد" "بار کردن…" "بار کردن بیش‌تر…" + + "%d دیگر" + "%d دیگران" + "%1$d عضو" "%1$d عضو" @@ -270,7 +274,6 @@ "کلید بازیابی" "تازه سازی…" "پاسخ دادن به %1$s" - "گزارش یک اشکال" "گزارش مشکل" "گزارش ثبت شد" "ویرایشگر متن غنی" diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index 48601352ba..e35ef5c2e1 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -317,7 +317,6 @@ Syy: %1$s." "%1$d vastausta" "Vastataan käyttäjälle %1$s" - "Ilmoita virheestä" "Ilmoita ongelmasta" "Ilmoitus lähetetty" "Rikastettu tekstieditori" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 7e0c4e9481..7617571f17 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -324,7 +324,6 @@ Raison : %1$s." "%1$d réponses" "En réponse à %1$s" - "Signaler un problème" "Remonter un problème" "Rapport soumis" "Éditeur de texte enrichi" diff --git a/libraries/ui-strings/src/main/res/values-hr/translations.xml b/libraries/ui-strings/src/main/res/values-hr/translations.xml index 2382eafc1a..7c3cfbd83b 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -330,7 +330,6 @@ Razlog: %1$s ." "%1$d odgovora" "Odgovara korisniku %1$s" - "Prijavi pogrešku" "Prijavi problem" "Prijava je podnesena" "Uređivač obogaćenog teksta" diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index f6498f228f..8973ebc4f6 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -71,6 +71,7 @@ "Hívás" "Mégse" "Egyelőre nem" + "Fájl kiválasztása" "Fénykép kiválasztása" "Törlés" "Bezárás" @@ -323,7 +324,6 @@ Ok: %1$s." "%1$d válasz" "Válasz %1$s számára" - "Hiba jelentése" "Probléma jelentése" "A jelentés elküldve" "Formázott szöveges szerkesztő" @@ -466,6 +466,9 @@ Biztos, hogy folytatja?" "Elnézést, hiba történt" "🔐️ Csatlakozz hozzám itt: %1$s" "Beszélgessünk itt: %1$s, %2$s" + "Élő földrajzi hely megosztása" + "Helymegosztás folyamatban" + "Élő hely: %1$s" "%1$s Android" "Az eszköz rázása a hibajelentéshez" "Képernyőkép" diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index 77e405e1c8..ec5a582838 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -275,7 +275,6 @@ Alasan: %1$s." "%1$d balasan" "Membalas %1$s" - "Laporkan kutu" "Laporkan masalah" "Laporan terkirim" "Penyunting teks kaya" diff --git a/libraries/ui-strings/src/main/res/values-it/translations.xml b/libraries/ui-strings/src/main/res/values-it/translations.xml index 824b9f6441..ba0d6f022c 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -14,6 +14,7 @@ "Dettagli sulla crittografia" "Allarga il campo di testo del messaggio" "Nascondi password" + "Info" "Entra in chiamata" "Vai alla fine" "Sposta la mappa sulla mia posizione" @@ -48,6 +49,7 @@ "Invia file" "Posizione del mittente" "Azione richiesta a tempo limitato, hai un minuto per la verifica" + "Impostazioni, azione richiesta" "Mostra password" "Avvia una chiamata" "Avvia una videochiamata" @@ -69,6 +71,7 @@ "Chiama" "Annulla" "Annulla per ora" + "Scegli il file" "Scegli foto" "Cancella" "Chiudi" @@ -88,12 +91,15 @@ "Disattiva account" "Rifiuta" "Rifiuta e blocca" + "Elimina" + "Elimina account" "Elimina sondaggio" "Deseleziona tutti" "Disabilita" "Annulla" "Chiudi" "Fine" + "Scarica" "Modifica" "Modifica didascalia" "Modifica sondaggio" @@ -201,7 +207,9 @@ "Beta" "Utenti bloccati" "Fumetti" + "Chiamata rifiutata" "Chiamata avviata" + "Hai rifiutato una chiamata" "Backup della chat" "Copiato negli appunti" "Copyright" @@ -317,7 +325,6 @@ Motivo:. %1$s" "%1$d risposte" "Risposta a %1$s" - "Segnala un problema" "Segnala un problema" "Segnalazione inviata" "Editor di testo avanzato" @@ -460,6 +467,8 @@ Sei sicuro di voler continuare?" "Siamo spiacenti, si è verificato un errore" "🔐️ Unisciti a me su %1$s" "Ehi, parliamo su %1$s: %2$s" + "Condivisione della posizione in corso" + "%1$s Posizione in tempo reale" "%1$s Android" "Scuoti per segnalare un problema" "Istantanea schermo" @@ -467,6 +476,13 @@ Sei sicuro di voler continuare?" "Risposte" "Rimuovi %1$s" "Impostazioni" + "Nessuno sta condividendo la propria posizione" + "Condivisione posizione in tempo reale" + + "%1$d persona" + "%1$d persone" + + "Sulla mappa" "Selezione del file multimediale fallita, riprova." "Premi su un messaggio e scegli “%1$s” per includerlo qui." "Fissa i messaggi importanti così che possano essere trovati facilmente" @@ -491,6 +507,7 @@ Sei sicuro di voler continuare?" "Messaggio in %1$s" "Espandi" "Riduci" + "Condivisione posizione in tempo reale" "Stai già visualizzando questa stanza!" "%1$s di %2$s" "%1$s Messaggi fissati" diff --git a/libraries/ui-strings/src/main/res/values-ja/translations.xml b/libraries/ui-strings/src/main/res/values-ja/translations.xml index 1c022f850f..b7a33d4dfd 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -319,7 +319,6 @@ "%1$d 件の返信" "%1$s に返信" - "バグを報告" "問題を報告" "報告は送信されました" "リッチテキストエディター" diff --git a/libraries/ui-strings/src/main/res/values-ka/translations.xml b/libraries/ui-strings/src/main/res/values-ka/translations.xml index b7a8819391..aa7659dde2 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -186,7 +186,6 @@ "განახლება…" "პასუხი %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 6a87870658..4f594f002b 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -310,7 +310,6 @@ "%1$d 답변" "%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 280209f6a5..da5281212e 100644 --- a/libraries/ui-strings/src/main/res/values-lt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-lt/translations.xml @@ -126,7 +126,6 @@ "Reakcijos" "Atnaujinama…" "Atsakant %1$s" - "Pranešti apie klaidą" "Skundas pateiktas" "Kambario pavadinimas" "pvz., jūsų projekto pavadinimas" diff --git a/libraries/ui-strings/src/main/res/values-nb/translations.xml b/libraries/ui-strings/src/main/res/values-nb/translations.xml index fc641df34d..a0bb1b1a16 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -309,7 +309,6 @@ "%1$d svar" "Svar til %1$s" - "Rapporter en feil" "Rapporter et problem" "Rapport sendt inn" "Redigeringsprogram for rik tekst" diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml index 6e136e7d77..ab39365f8e 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -250,7 +250,6 @@ Reden: %1$s." "%1$d antwoorden" "Reageren op %1$s" - "Een fout melden" "Meld een probleem" "Melding ingediend" "Uitgebreide tekstverwerker" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index 6812885c9c..30f2c383b6 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -15,6 +15,7 @@ "Szczegóły szyfrowania" "Powiększ pole tekstowe wiadomości" "Ukryj hasło" + "Informacje" "Dołącz do połączenia" "Przejdź na dół" "Przesuń mapę do mojej lokalizacji" @@ -30,8 +31,10 @@ "Pole PIN" "Przypięta lokalizacja" "Odtwórz" + "Prędkość odtwarzania" "Ankieta" "Zakończona ankieta" + "Kod QR" "Zareaguj z %1$s" "Zareaguj innym emoji" "Odczytane przez %1$s i %2$s" @@ -46,9 +49,13 @@ "Usuń reakcję z %1$s" "Awatar pokoju" "Wyślij pliki" + "Lokalizacja nadawcy" "Wymagane jest działanie ograniczone czasowo, została jedna minuta" + "Ustawienia, wymagane działanie" "Pokaż hasło" "Rozpocznij rozmowę" + "Rozpocznij rozmowę wideo" + "Rozpocznij połączenie głosowe" "Pokój nagrobkowy" "Awatar użytkownika" "Menu użytkownika" @@ -60,11 +67,13 @@ "Twój awatar" "Akceptuj" "Dodaj opis" + "Dodaj istniejące pokoje" "Dodaj do osi czasu" "Wróć" "Zadzwoń" "Anuluj" "Anuluj na razie" + "Wybierz plik" "Wybierz zdjęcie" "Wyczyść" "Zamknij" @@ -79,26 +88,32 @@ "Kopiuj tekst" "Utwórz" "Utwórz pokój" + "Utwórz przestrzeń" "Dezaktywuj" "Dezaktywuj konto" "Odrzuć" "Odrzuć i zablokuj" + "Usuń" + "Usuń konto" "Usuń ankietę" "Odznacz wszystko" "Wyłącz" "Odrzuć" "Zamknij" "Gotowe" + "Pobierz" "Edytuj" "Edytuj opis" "Edytuj ankietę" "Włącz" "Zakończ ankietę" "Wprowadź PIN" + "Przeglądaj przestrzenie publiczne" "Zakończ" "Nie pamiętasz hasła?" "Przekaż dalej" "Wróć" + "Przejdź do ról i uprawnień" "Przejdź do ustawień" "Ignoruj" "Zaproś" @@ -114,7 +129,9 @@ "Opuść przestrzeń" "Załaduj więcej" "Zarządzaj kontem" + "Zarządzaj kontem i urządzeniami" "Zarządzaj urządzeniami" + "Zarządzaj pokojami" "Wiadomość" "Minimalizuj" "Dalej" @@ -139,7 +156,7 @@ "Zgłoś treść" "Zgłoś rozmowę" "Zgłoś pokój" - "Resetuj" + "Zresetuj" "Zresetuj tożsamość" "Spróbuj ponownie" "Ponów próbę odszyfrowania" @@ -152,18 +169,21 @@ "Wyślij wiadomość głosową" "Wyślij" "Wyślij link" + "Udostępnij lokalizację na żywo" "Pokaż" "Zaloguj się ponownie" - "Wyloguj" - "Wyloguj mimo to" + "Usuń to urządzenie" + "Usuń urządzenie mimo to" "Pomiń" "Rozpocznij" "Rozpocznij chat" "Zacznij od nowa" "Rozpocznij weryfikację" "Stuknij, aby załadować mapę" + "Zatrzymaj" "Zrób zdjęcie" "Stuknij, by wyświetlić opcje" + "Przetłumacz" "Spróbuj ponownie" "Odepnij" "Wyświetl" @@ -181,6 +201,7 @@ "Ustawienia zaawansowane" "obraz" "Dane analityczne" + "Synchronizuję powiadomienia…" "Opuściłeś pokój" "Zostałeś wylogowany z sesji" "Wygląd" @@ -188,11 +209,14 @@ "Beta" "Zablokowani użytkownicy" "Bąbelki" + "Połączenie odrzucone" "Rozpoczęto rozmowę" + "Odrzuciłeś połączenie" "Backup czatu" "Skopiowano do schowka" "Prawa autorskie" "Tworzenie pokoju…" + "Tworzenie przestrzeni…" "Anulowano żądanie" "Opuszczono pokój" "Opuścił przestrzeń" @@ -213,6 +237,7 @@ "Pusty plik" "Szyfrowanie" "Szyfrowanie włączone" + "Kończy się o %1$s" "Wprowadź kod PIN" "Błąd" "Wystąpił błąd, możesz nie otrzymać powiadomień nowych wiadomości. Spróbuj naprawić powiadomienia w ustawieniach. @@ -238,6 +263,9 @@ Powód: %1$s." "Jasny" "Wiersz skopiowany do schowka" "Link został skopiowany do schowka" + "Powiąż nowe urządzenie" + "Lokalizacja na żywo" + "Zakończono udostępnianie lokalizacji na żywo" "Ładowanie…" "Ładuję więcej…" @@ -252,10 +280,12 @@ Powód: %1$s." "Wiadomość" "Akcje wiadomości" + "Nie udało się wysłać wiadomości" "Układ wiadomości" "Wiadomość usunięta" "Nowoczesny" "Wycisz" + "Nazwa" "%1$s (%2$s)" "Brak wyników" "Brak nazwy pokoju" @@ -264,6 +294,7 @@ Powód: %1$s." "Offline" "Licencje open-source" "lub" + "Inne opcje" "Hasło" "Osoby" "Link bezpośredni" @@ -282,8 +313,10 @@ Powód: %1$s." "Przygotowuję…" "Polityka prywatności" + "Prywatny" "Pokój prywatny" "Prywatna przestrzeń" + "Publiczny" "Pokój publiczny" "Przestrzeń publiczna" "Reakcja" @@ -291,19 +324,20 @@ Powód: %1$s." "Powód" "Klucz przywracania" "Odświeżanie…" + "Usuwanie…" "%1$d odpowiedź" "%1$d odpowiedzi" "%1$d odpowiedzi" "Odpowiadanie do %1$s" - "Zgłoś błąd" "Zgłoś problem" "Zgłoszenie wysłane" "Bogaty edytor tekstu" + "Rola" "Pokój" "Nazwa pokoju" - "np. nazwa projektu" + "np. nazwa twojego projektu" "%1$d Pokój" "%1$d Pokoje" @@ -317,6 +351,11 @@ Powód: %1$s." "Bezpieczeństwo" "Wyświetlone przez" "Wybierz konto" + + "%1$d zaznaczony" + "%1$d zaznaczone" + "%1$d zaznaczonych" + "Wyślij do" "Wysyłanie…" "Błąd wysyłania" @@ -327,12 +366,16 @@ Powód: %1$s." "Adres URL serwera" "Ustawienia" "Udostępnij przestrzeń" + "Nowi członkowie widzą historię" + "Udostępniona lokalizacja na żywo" "Udostępniona lokalizacja" "Udostępniona przestrzeń" - "Wylogowywanie" + "Usuwanie urządzenia" "Coś poszło nie tak" "Napotkaliśmy problem. Spróbuj ponownie." "Przestrzeń" + "Członkowie przestrzeni" + "O czym jest ta przestrzeń?" "%1$d Przestrzeń" "%1$d Przestrzenie" @@ -341,12 +384,14 @@ Powód: %1$s." "Rozpoczynanie czatu…" "Naklejka" "Sukces" + "Polecane" "Sugestie" "Synchronizuję" "System" "Tekst" "Informacje stron trzecich" "Wątek" + "Wątki" "Temat" "O czym jest ten pokój?" "Nie można odszyfrować" @@ -377,13 +422,19 @@ Powód: %1$s." "Wiadomość głosowa" "Oczekiwanie…" "Oczekiwanie na tę wiadomość" + "Czekam na lokalizację na żywo…" + "Każdy może zobaczyć historię" "Ty" - "Tożsamość %1$s została zresetowana. %2$s" + "%1$s (%2$s) udostępnił tę wiadomość, kiedy nie było Cię w pokoju, gdy została wysłana." + "%1$s udostępnił tę wiadomość, kiedy nie było Cię w pokoju, gdy została wysłana." + "Ten pokój został skonfigurowany tak, aby nowi członkowie mogli czytać historię czatu. %1$s" + "Tożsamość cyfrowa %1$s została zresetowana. %2$s" "Tożsamość %1$s %2$s została zresetowana. %3$s" "(%1$s)" - "Tożsamość %1$s została zresetowana" - "Tożsamość %1$s %2$s została zresetowana. %3$s" + "Tożsamość %1$s została zresetowana." + "Tożsamość %1$s %2$s została zresetowana. %3$s" "Wycofaj weryfikację" + "Zezwól na dostęp" "Link %1$s prowadzi Cię do innej witryny %2$s Czy na pewno chcesz kontynuować?" @@ -413,6 +464,7 @@ Czy na pewno chcesz kontynuować?" "%1$s nie mógł uzyskać dostępu do Twojej lokalizacji. Spróbuj ponownie później." "Nie udało się przesłać Twojej wiadomości głosowej." "Pokój już nie istnieje lub zaproszenie nie jest już ważne." + "Włącz GPS, aby uzyskać dostęp do funkcji opartych na lokalizacji." "Nie znaleziono wiadomości" "%1$s nie uzyskało uprawnienia do dostępu do twojej lokalizacji. Możesz włączyć dostęp w Ustawieniach." "%1$s nie ma uprawnień dostępu do Twojej lokalizacji. Włącz dostęp poniżej." @@ -424,6 +476,9 @@ Czy na pewno chcesz kontynuować?" "Przepraszamy, wystąpił błąd" "🔐️ Dołącz do mnie na %1$s" "Hej, porozmawiajmy na %1$s: %2$s" + "Udostępnianie lokalizacji na żywo" + "Udostępnianie lokalizacji w toku" + "Lokalizacja na żywo %1$s" "%1$s Android" "Wstrząśnij gniewnie, aby zgłosić błąd" "Zrzut ekranu" @@ -431,6 +486,14 @@ Czy na pewno chcesz kontynuować?" "Opcje" "Usuń %1$s" "Ustawienia" + "Nikt nie udostępnia swojej lokalizacji" + "Udostępnianie lokalizacji na żywo" + + "%1$d osoba" + "%1$d osoby" + "%1$d osób" + + "Na mapie" "Nie udało się wybrać multimediów. Spróbuj ponownie." "Naciśnij wiadomość i wybierz “%1$s”, aby dołączyć tutaj." "Przypinaj ważne wiadomości, aby można było je łatwo znaleźć" @@ -456,6 +519,7 @@ Czy na pewno chcesz kontynuować?" "Wiadomość w %1$s" "Rozwiń" "Zmniejsz" + "Udostępnianie lokalizacji na żywo" "Już oglądasz ten pokój!" "%1$s z %2$s" "%1$s przypiętych wiadomości" @@ -467,11 +531,15 @@ Czy na pewno chcesz kontynuować?" "Otwórz w Apple Maps" "Otwórz w Google Maps" "Otwórz w OpenStreetMap" - "Udostępnij tę lokalizację" + "Udostępnij wybraną lokalizację" + "Opcje udostępniania" "Przestrzenie, które stworzyłeś lub do których dołączyłeś." "%1$s • %2$s" + "Utwórz przestrzeń, aby organizować pokoje" "Przestrzeń %1$s" "Przestrzenie" + "Udostępnianie %1$s" + "Na mapie" "Wiadomość nie została wysłana, ponieważ tożsamość %1$s została zresetowana." "Wiadomość nie została wysłana, ponieważ %1$s nie zweryfikował wszystkich urządzeń." "Wiadomość nie została wysłana, ponieważ nie zweryfikowałeś jednego lub więcej swoich urządzeń." @@ -482,5 +550,5 @@ Czy na pewno chcesz kontynuować?" "Musisz zweryfikować to urządzenie, aby uzyskać dostęp do historii wiadomości" "Nie masz uprawnień do tej wiadomości" "Nie można odszyfrować wiadomości" - "Wiadomość została zablokowana, ponieważ urządzenie nie zostało zweryfikowane lub nadawca musi zweryfikować Twoją tożsamość." + "Ta wiadomość została zablokowana, ponieważ urządzenie nie zostało zweryfikowane lub nadawca musi zweryfikować Twoją tożsamość." diff --git a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml index 49351c6b64..68035e0cc2 100644 --- a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml @@ -300,7 +300,6 @@ Motivo:​ %1$s." "%1$d respostas" "Respondendo a %1$s" - "Denunciar um bug" "Relatar um problema" "Relatório enviado" "Editor de rich text" diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index dd15875590..d82855223d 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -291,7 +291,6 @@ Razão: %1$s." "%1$d respostas" "Em resposta a %1$s" - "Comunicar falha" "Comunicar um problema" "Denúncia submetida" "Editor de texto rico" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index f47d43b47e..33a39278a4 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -1,6 +1,7 @@ "Adăugați o reacție: %1$s" + "Adresă" "Imagine de profil" "Micșorați câmpul mesajului" "Ștergere" @@ -300,7 +301,6 @@ Motiv:%1$s." "%1$d răspunsuri" "Răspuns pentru %1$s" - "Raportați o eroare" "Raportați o problemă" "Raport trimis" "Editor text avansat" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index bb423b5b10..a691d1d69b 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -323,7 +323,6 @@ "%1$d ответов" "Отвечает %1$s" - "Сообщить об ошибке" "Сообщить о проблеме" "Отчет отправлен" "Форматирование" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index e154093ddb..208016e363 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -1,6 +1,7 @@ "Pridať reakciu: %1$s" + "Adresa" "Obrázok" "Minimalizovať textové pole správy" "Vymazať" @@ -27,6 +28,7 @@ "Pozastaviť" "Hlasová správa, dĺžka:%1$s, aktuálna pozícia: %2$s" "Pole PIN" + "Pripnuté miesto" "Prehrať" "Anketa" "Ukončená anketa" @@ -47,6 +49,8 @@ "Vyžaduje sa časovo obmedzená akcia, na overenie máte jednu minútu" "Zobraziť heslo" "Začať hovor" + "Začať videohovor" + "Začať hlasový hovor" "Opustená miestnosť" "Profilový obrázok" "Používateľské menu" @@ -157,8 +161,8 @@ "Zdieľať odkaz" "Zobraziť" "Prihláste sa znova" - "Odhlásiť sa" - "Napriek tomu sa odhlásiť" + "Odstrániť toto zariadenie" + "Napriek tomu odstrániť toto zariadenie" "Preskočiť" "Spustiť" "Začať konverzáciu" @@ -306,7 +310,6 @@ Dôvod: %1$s." "%1$d odpovedí" "Odpoveď na %1$s" - "Nahlásiť chybu" "Nahlásiť problém" "Nahlásenie bolo odoslané" "Rozšírený textový editor" @@ -487,7 +490,7 @@ Naozaj chcete pokračovať?" "Otvoriť v Apple Maps" "Otvoriť v Mapách Google" "Otvoriť v OpenStreetMap" - "Zdieľajte túto polohu" + "Zdieľajte vybranú polohu" "Priestory, ktoré ste vytvorili alebo ku ktorým ste sa pripojili." "%1$s • %2$s" "Vytvorte priestory na usporiadanie miestností" diff --git a/libraries/ui-strings/src/main/res/values-sv/translations.xml b/libraries/ui-strings/src/main/res/values-sv/translations.xml index dfcd514209..afc58de8a5 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -281,7 +281,6 @@ Anledning:%1$s." "%1$d svar" "Svarar till %1$s" - "Rapportera en bugg" "Rapportera ett problem" "Rapport inskickad" "Riktextredigerare" diff --git a/libraries/ui-strings/src/main/res/values-tr/translations.xml b/libraries/ui-strings/src/main/res/values-tr/translations.xml index d92daa6527..a6d0b3e198 100644 --- a/libraries/ui-strings/src/main/res/values-tr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-tr/translations.xml @@ -264,7 +264,6 @@ Neden: %1$s." "Kurtarma anahtarı" "Yenileniyor…" "Cevaplamak için %1$s" - "Hata bildir" "Sorun bildir" "Rapor gönderildi" "Zengin metin editörü" diff --git a/libraries/ui-strings/src/main/res/values-uk/translations.xml b/libraries/ui-strings/src/main/res/values-uk/translations.xml index 835ded33f9..db0fa31804 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -1,6 +1,7 @@ "Додати реакцію: %1$s" + "Адреса" "Аватар" "Згорнути поле тексту повідомлення" "Видалити" @@ -14,6 +15,7 @@ "Подробиці шифрування" "Розгорнути текстове поле повідомлення" "Cховати пароль" + "Інформація" "Приєднатися до виклику" "Перейти вниз" "Перемістити карту до мого місця перебування" @@ -27,9 +29,12 @@ "Пауза" "Голосове повідомлення, тривалість: %1$s, поточна позиція: %2$s" "Поле PIN-коду" + "Закріплена локація" "Відтворити" + "Швидкість програвання" "Опитування" "Опитування завершено" + "QR-код" "Реагувати з%1$s" "Відреагувати іншими смайликами" "Прочитано %1$s та %2$s" @@ -44,9 +49,13 @@ "Прибрати реакцію %1$s" "Аватар кімнати" "Надіслати файли" + "Локація відправника" "Необхідно виконати дію, обмежену в часі, у вас є одна хвилина для верифікації" + "Налаштування, потрібні дії" "Показати пароль" "Розпочати виклик" + "Розпочати відеодзвінок" + "Розпочати голосовий дзвінок" "Кімната більше не використовується" "Аватар користувача" "Меню користувача" @@ -64,6 +73,7 @@ "Зателефонувати" "Скасувати" "Скасувати наразі" + "Вибрати файл" "Вибрати фото" "Очистити" "Закрити" @@ -83,18 +93,22 @@ "Деактивувати обліковий запис" "Відхилити" "Відхилити та заблокувати" + "Видалити" + "Видалити обліковий запис" "Видалити опитування" "Скасувати вибір усіх" "Вимкнути" "Відкинути" "Відхилити" "Готово" + "Завантажити" "Редагувати" "Редагувати підпис" "Редагувати опитування" "Увімкнути" "Завершити опитування" "Введіть PIN-код" + "Дізнатися про публічні простори" "Завершити" "Забули пароль?" "Переслати" @@ -115,6 +129,7 @@ "Вийти з простору" "Завантажити ще" "Керування обліковим записом" + "Керування обліковим записом і пристроями" "Керування пристроями" "Керувати кімнатами" "Написати" @@ -154,6 +169,7 @@ "Надіслати голосове повідомлення" "Поділитися" "Поділитися посиланням" + "Ділитися місцезнаходженням у реальному часі" "Показати" "Увійдіть знову" "Вийти" @@ -164,6 +180,7 @@ "Почати спочатку" "Почати верифікацію" "Натисніть, щоб завантажити мапу" + "Зупинити" "Зробити фото" "Торкніться, щоб переглянути параметри" "Перекласти" @@ -184,6 +201,7 @@ "Додаткові налаштування" "зображення" "Аналітика" + "Синхронізація сповіщень…" "Ви вийшли з кімнати" "Ви вийшли з сеансу" "Тема" @@ -191,7 +209,9 @@ "Бета-версія" "Заблоковані користувачі" "Бульбашки" + "Дзвінок відхилено" "Виклик розпочато" + "Ви відхилили дзвінок" "Резервне копіювання бесіди" "Скопійовано до буферу обміну" "Авторське право" @@ -199,6 +219,7 @@ "Створення простору…" "Запит скасовано" "Виходить з кімнати" + "Вийшов із простору" "Запрошення відхилено" "Темна" "Помилка розшифрування" @@ -216,6 +237,7 @@ "Порожній файл" "Шифрування" "Шифрування ввімкнено" + "Завершується о %1$s" "Введіть свій PIN-код" "Помилка" "Сталася помилка, ви можете не отримувати сповіщення про нові повідомлення. Усуньте неполадки зі сповіщеннями в налаштуваннях. @@ -242,6 +264,8 @@ "Рядок скопійовано до буфера обміну" "Посилання скопійовано в буфер обміну" "Під\'єднати новий пристрій" + "Місцезнаходження в реальному часі" + "Показ місцеперебування наживо завершено" "Завантаження" "Завантаження наступних…" @@ -270,6 +294,7 @@ "Не в мережі" "Ліцензії відкритого коду" "або" + "Інші варіанти" "Пароль" "Люди" "Постійне посилання" @@ -288,8 +313,10 @@ "Приготування…" "Політика конфіденційності" + "Приватний" "Приватна кімната (тільки за запрошенням)" "Приватний простір" + "Публічний" "Загальнодоступна кімната" "Загальнодоступний простір" "Реакція" @@ -304,7 +331,6 @@ "%1$d відповідей" "Відповідь %1$s" - "Повідомити про ваду" "Повідомити про проблему" "Звіт подано" "Багатоформатний текстовий редактор" @@ -325,6 +351,11 @@ "Безпека" "Переглянули" "Вибрати обліковий запис" + + "%1$d вибраний" + "%1$d вибрані" + "%1$d вибрано" + "Надіслати до" "Надсилання…" "Не вдалося надіслати" @@ -334,12 +365,16 @@ "Сервер недоступний" "URL-адреса сервера" "Налаштування" + "Поділитися простором" "Нові учасники бачать історію" + "Поділитися місцезнаходженням в реальному часі" "Поширене розташування" + "Простір спільного користування" "Вихід" "Щось пішло не так" "Ми зіткнулися з проблемою. Будь ласка, повторіть спробу." "Простір" + "Учасники простору" "Про що цей простір?" "%1$d простір" @@ -349,12 +384,14 @@ "Початок бесіди…" "Наліпка" "Успіх" + "Запропоновано" "Пропозиції" "Синхронізація" "Системна" "Текст" "Повідомлення третіх сторін" "Гілка" + "Гілки" "Тема" "Про що ця кімната?" "Неможливо розшифрувати" @@ -385,14 +422,19 @@ "Голосове повідомлення" "Очікування…" "Чекаємо на це повідомлення" + "Очікування геолокації…" "Будь-хто може переглянути історію" "Ви" + "%1$s (%2$s) поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали." + "%1$s поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали." + "Згідно із налаштувань цієї кімнати, нові учасники можуть переглядати історію. %1$s" "Ідентичність %1$s скинуто. %2$s" "Ідентичність %1$s %2$s скинуто. %3$s" "(%1$s)" "Ідентичність %1$s скинуто." "Ідентичність %1$s %2$s скинуто. %3$s" "Відкликати верифікацію" + "Надати доступ" "Посилання %1$s спрямовує вас на інший сайт %2$s Ви впевнені, що хочете продовжити?" @@ -422,6 +464,7 @@ "%1$s не вдалося отримати доступ до вашого розташування. Повторіть спробу пізніше." "Не вдалося завантажити голосове повідомлення." "Кімната більше не існує або запрошення не чинне." + "Будь ласка, увімкніть GPS, щоб отримати доступ до функцій, що використовують геолокацію." "Повідомлення не знайдено" "%1$s не має дозволу на доступ до вашого розташування. Увімкнути доступ можна в Налаштуваннях." "%1$s не має дозволу на доступ до вашого розташування. Увімкніть доступ нижче." @@ -440,6 +483,14 @@ "Варіанти" "Вилучити %1$s" "Налаштування" + "Ніхто не ділиться своєю геопозицією" + "Обмін геопозицією" + + "%1$d особа" + "%1$d осіб" + "%1$d осіб" + + "На карті" "Не вдалося вибрати медіафайл, спробуйте ще раз." "Натисніть на повідомлення і виберіть \"%1$s\", щоб додати його сюди." "Закріпіть важливі повідомлення, щоб їх можна було легко знайти" @@ -465,6 +516,7 @@ "Повідомлення в %1$s" "Розгорнути" "Згорнути" + "Спільний доступ до місцезнаходження у реальному часі" "Уже переглядаєте цю кімнату!" "%1$s із %2$s" "%1$s закріплених повідомлень" @@ -477,10 +529,14 @@ "Відкрити в Картах Google" "Відкрити в OpenStreetMap" "Поділитися цим місцем перебування" + "Налаштування обміну геопозицією" "Простори, які ви створили або до яких приєдналися." "%1$s • %2$s" + "Створіть простори для організації кімнат" "Простір %1$s" "Простори" + "Надано доступ %1$s" + "На карті" "Повідомлення не надіслано, оскільки підтверджену особистість %1$s скинуто." "Повідомлення не надіслано, оскільки %1$s перевірив не всі пристрої." "Повідомлення не надіслано, оскільки ви не підтвердили один або кілька своїх пристроїв." diff --git a/libraries/ui-strings/src/main/res/values-ur/translations.xml b/libraries/ui-strings/src/main/res/values-ur/translations.xml index 8e9c0fb3be..7bf138deb5 100644 --- a/libraries/ui-strings/src/main/res/values-ur/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ur/translations.xml @@ -212,7 +212,6 @@ "بازیابی کی کلید" "تاکہ کر رہا ہے…" "%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 2542de084e..304a044e0b 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -317,7 +317,6 @@ Sababi:%1$s." "%1$d ta javob" "%1$sga Javob berilmoqda" - "Xato haqida xabar bering" "Muammo haqida xabar bering" "Hisobot topshirildi" "Boy matn muharriri" @@ -410,6 +409,7 @@ Sababi:%1$s." "Tarixni hamma ko‘rishi mumkin" "Siz" "%1$s (%2$s) bu xabarni ulashdi, chunki u yuborilganda siz xonada emas edingiz." + "%1$s bu xabar yuborilgan paytda siz xonada bo‘lmaganingiz uchun uni ulashdi." "Siz yuborgan xabarlar bu xonaga taklif qilingan yangi a’zolarga ulashiladi. %1$s" "%1$sning raqamli identifikatori qayta tiklandi.%2$s" "%1$sning%2$s raqamli identifikatsiya qayta tiklandi.%3$s" diff --git a/libraries/ui-strings/src/main/res/values-vi/translations.xml b/libraries/ui-strings/src/main/res/values-vi/translations.xml index 9a450117ac..2db0ce1dae 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -310,7 +310,6 @@ Lý do: %1$s ." "%1$d trả lời" "Đang trả lời cho %1$s" - "Báo cáo lỗi" "Báo cáo sự cố" "Đã gửi báo cáo" "Trình soạn thảo văn bản nâng cao" diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index 11eb111b49..819c993bb1 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 @@ -311,7 +311,6 @@ "%1$d 個回覆" "正在回覆%1$s" - "回報程式錯誤" "回報問題" "已遞交報告" "格式化文字編輯器" diff --git a/libraries/ui-strings/src/main/res/values-zh/translations.xml b/libraries/ui-strings/src/main/res/values-zh/translations.xml index 974e91b530..00bb686f78 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -13,6 +13,7 @@ "加密详情" "展开消息文本框" "隐藏密码" + "信息" "加入通话" "跳转到底部" "将地图移动到我的位置" @@ -67,6 +68,7 @@ "通话" "取消" "暂时取消" + "选择文件" "选择照片" "清除" "关闭" @@ -125,7 +127,7 @@ "管理账户与设备" "管理设备" "管理房间" - "发送消息给" + "发送消息" "最小化" "下一步" "否" @@ -316,7 +318,6 @@ "%1$d 个回复" "正在回复 %1$s" - "报告 bug" "报告问题" "报告已提交" "富文本编辑器" @@ -456,6 +457,8 @@ "抱歉,发生了错误" "🔐️ 在 %1$s 中与我一起" "嗨!请通过 %1$s 与我联系:%2$s" + "正在共享实时位置" + "位置共享正在进行" "%1$s Android" "摇一摇以报告 bug" "屏幕截图" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index cdb3c52e6a..656ec50569 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -325,7 +325,6 @@ Reason: %1$s." "%1$d replies" "Replying to %1$s" - "Report a bug" "Report a problem" "Report submitted" "Rich text editor" @@ -468,6 +467,9 @@ Are you sure you want to continue?" "Sorry, an error occurred" "🔐️ Join me on %1$s" "Hey, talk to me on %1$s: %2$s" + "Live Location Sharing" + "Location sharing in progress" + "%1$s Live Location" "%1$s Android" "Rageshake to report bug" "Screenshot" diff --git a/screenshots/de/appnav.root_RootView_Day_0_de.png b/screenshots/de/appnav.root_RootView_Day_0_de.png index 7f70b90751..2d0d9fab03 100644 --- a/screenshots/de/appnav.root_RootView_Day_0_de.png +++ b/screenshots/de/appnav.root_RootView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa11b2165af4a12cd518fb3f9a06b91d9ce87b468705efc7a962bf34a8278fac -size 26284 +oid sha256:c3082552bf96131ddba157697bb254e22d6277537759c32dfabb56a2e99a9138 +size 27116 diff --git a/screenshots/de/appnav.root_RootView_Day_1_de.png b/screenshots/de/appnav.root_RootView_Day_1_de.png index e1796d211b..6d1c994b27 100644 --- a/screenshots/de/appnav.root_RootView_Day_1_de.png +++ b/screenshots/de/appnav.root_RootView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35a9ac561c2546fd94121cb0c80e1f5be1fe147f425be4d087b647ae0f204afd -size 29986 +oid sha256:f9231272736124f1e54a3422310d2dd5c7ad81e850548886062df61de36165c4 +size 30868 diff --git a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png index 79a282bf32..5fb0408a49 100644 --- a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png +++ b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:141bf23853b7ba97cffd4d54e9e0a48843d0a49e7f6d6a91c41f110d2df1c7dd -size 24180 +oid sha256:d20416987d2485431b66ebb29af1f03efa2e04da7ef5875eda62d7c5e187052b +size 24828 diff --git a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png index bc89b471f2..4aa0388c8a 100644 --- a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png +++ b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a39d0a1c752533bfb097ad1d2c59978123545ee76259e26efe6e3fbae209db69 -size 31441 +oid sha256:62d531d6b01266019e2fa686321e93d64bcffd5b1786f7ad4efac83fcc2a2fc5 +size 32141 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png new file mode 100644 index 0000000000..048facf45b --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b4ead892d27f2eb5fd7c9319e3c954ab2ae57c68180e08b30c07741c53cadda +size 35383 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png new file mode 100644 index 0000000000..af1fe3af55 --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b481b2bafe288542d25c301aa568fdbd9d63170b1c59b01fdacacc69d0395b3 +size 17352 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png new file mode 100644 index 0000000000..28afdb624e --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6f6d2946d194ba97c64e6749b1f9d8bf4ce52e685d06631cf22b47e156791d1 +size 41526 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png new file mode 100644 index 0000000000..9c540f1299 --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b74c5fd9cb084ca2c391ea65dea23ecc027d1206510841ada0d28d5f6674995 +size 32940 diff --git a/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png index 67fec85a88..b3f6706cda 100644 --- a/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68d468cf24f004f75b5f0d0ab21e4576941749b32a6780b074fce5ba6e7e06c0 -size 56172 +oid sha256:29fb6c5ccbc3fc1196fbccc4ce18d10668ae47733ecfcc454354ff231cac0f10 +size 56030 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png index 72c99d1da9..3ece744fcb 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b10f43a24d80689ee7c929eb5c530b544891cb0dce63ab9bbb4618f999fbd3cd -size 6226 +oid sha256:cbc7e8874d0a3c25aa0e6036c1ffc365c5407d79b011e5321821691315e98d3a +size 6223 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png index 75eb3ccc78..abb112a538 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68cef5541309a99a95f5004cbdcb4d091a70f68c142de2ff78deb710c521ea30 -size 69820 +oid sha256:4c119e44d9f51d0b4786f06092d3d0138ef69b363c43303164b0aac0629b324e +size 69840 diff --git a/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png b/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png index 99f0c161e8..2190897314 100644 --- a/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png +++ b/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d23534a940951085437a3c739b58d515a968869227db794a149b5066abe21800 -size 58473 +oid sha256:f952ad332aea788e87445b304894f0acf77a6ca5498d67584ab4e727cbb16eb4 +size 58055 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png index 99f738df12..9827329bbd 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe130f936313191f602331d5b1a08dd025da47a66ce23dd71cee0665e951a3ac -size 44506 +oid sha256:ece0f3e49ca489a67aa7a489bc2d7e4f35a99cff4e4f2df3f7ab480965b3f972 +size 44150 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png index 47113e66d0..28e4e403fe 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1228309dd9c2dbaa340f1b941ca9da17067c619a8645e870f20bf39db7c9ba25 -size 27560 +oid sha256:2b8741879622a799c9cae5ba7ecb0f83700cdfca52dd9e6b281bfa0cc31267b3 +size 26817 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png index 12791633f9..2f7d54a7ac 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b095c101503364437c57050c56fbcc56e8187a697921364eee4ae0807ad684e -size 38449 +oid sha256:61958e2bf98bcc380bca8622d53ea8d46ec466de6e8da134a9b01ea1605eca6c +size 38040 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png index edfa967da9..61aba383d1 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:128e6931b4ac3fbc02138fba8a67e22f60e722acddd8db26b1b031102bcbb198 -size 28060 +oid sha256:3e8275f65773690627383ef7f030f270c7f93639af5dff40ca46ee0c2d5e0316 +size 27628 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png index efb26f07c5..672f329d0d 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc9e3439b97efbd490030a7fdae43bccd60193b18c658f4ced99959550fc77bd -size 29481 +oid sha256:3efe6d5c4b5f02679eddf9be90af0ee0648a576a4488c021d9d7601aac3c71ab +size 29060 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png index 01f0712a7a..5d238d5c65 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ca99f565a56588d126e357df4417469e39ff196d21d41cdbff05166b8356da1 -size 21419 +oid sha256:17f591ce8aa0dc3c79dd450dc58b84194625f1eee1b8fb3d5dbd67b3b1e07966 +size 21035 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png index 2b260ff9f6..ba560e522f 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3b21d14f077ebcaa11ac2dca31fb08f9dc21f26a4847c6d1c623f0ec953cdc2 -size 45806 +oid sha256:7fff1e6cc2fe7ae2fe3dc81ee1f13f096245c238f3ca946ba4a353e693d0ecb8 +size 45468 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png index a584834ca9..893d7a086f 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bff3f28233c7b1be7c3524f06258dfcf27dffa4251279beb2bacb883c3c86c41 -size 28576 +oid sha256:e335a7132330e2c5dfb3f4cc015e25fdf67af2030474b347df2e0cca343b1c74 +size 27763 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png index bd510c21a9..7a2abd7f42 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f3ff8d40a465f3d73143de0d66566c0129a794cdba9556bb54423b2110375c8 -size 39033 +oid sha256:645d02f8d4503edfc2e5fb756050ed1ddb8a692d715d06b84b232e744379d613 +size 38820 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png index bc7f862d77..3b526c2fc1 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a7aab1f7cc5a26672666fab13a36fd7bb47d524b9ffa172bac322c1ad1c3b40 -size 28583 +oid sha256:4df58e4d7f0baeb0bfd0225302ed8e69eba1edc0ef37ae6cb8b86ffdd057b924 +size 28414 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png index 7cd952fef4..57bed01c00 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4743cbd8f565d114a74024455bddd999df95fba4c0ca346b32203cf6fb6f7550 -size 30203 +oid sha256:1a24be625e8a7d6eeb46f0066247bc22bd367b0e035802b54a663478392f4289 +size 29980 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png index 9cbde40654..4537f0ff7f 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a7e61a79e28968dfe2f57b75b88125471fecccdf4af670c7f2ca238019fc31c -size 21527 +oid sha256:f7a69722f7e5f6373a266116e7d97bef5e620b136deb2cea30409c41ec8d4180 +size 21310 diff --git a/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png b/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png index 29240c9037..6fe8d49af7 100644 --- a/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png +++ b/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d34090b6d2a05946f81c205b40dba420f49c19063b8f4bf2d0f55afe31886e7 -size 24441 +oid sha256:225e3ea78d7f1bf3bb9c2c56c128bdb6994b22df3f7c010837ef37bbcdc34997 +size 25170 diff --git a/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png b/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png index 39aa8e9965..c78691eca9 100644 --- a/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png +++ b/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2e6807ba4b85c71cca8aebaf34a22c836c6d53ebf8caaa42790594d3066956c -size 27850 +oid sha256:7546c33148ccc5d46e112c2488c6aecce925a9a0d729cc9c029c9dac2578e2a7 +size 28753 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index 759f942a33..c39909cf49 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:088e737cec6fb5fbd624a16dbbcca45a8815441b93ef4d949acbaea9d9c52c3c -size 49472 +oid sha256:10355aa4b00cbaa5ccded1d03d23db71907f9943ebd40dfec50545c046991b61 +size 49461 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 10ad61fad0..7e18f43981 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2f53b1fbc09307314ad92c688ef26490520de7380d27cab1ca67aca6e34a655 -size 47718 +oid sha256:7a2132a405f40d577a61420b4ad2d7bb9f55f67b5fe1b07b4ddb0daff10b8b89 +size 47704 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index e95dd4de1d..4cd5290a7c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bab8c4a37f2d9fbd4b29cdd729db9a84216fcfae3023facbfb979ecdf4645b6 -size 46428 +oid sha256:e3003b423f3fa7504581ecf60cfbb82452eb17267bbc44f3b9439642da0ff096 +size 46416 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 32193ce5f1..0086307ec6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6a11d9f2402b756b61a5ab3bb766bf19404fb24b306f86634650b070554268b -size 48264 +oid sha256:5bca6f953108331e512e3b0bca6086be207c1b1d2835d1dc220673098f5e3a9d +size 48263 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index a29bbd09cb..0a99e31a52 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b37442dd675bf8ce133b57484ec8dc11c695df69907ead762fa4b79c7c978663 -size 48172 +oid sha256:494b1135a849734bce082b30aaeb491aebdb95cd67e6150be7334b55fe9fc0eb +size 48159 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index 0fd4f66fcc..110a14531d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa879e0d1483b07c3127ed07da87b8aabcc38c51db6e158ff29039e3b1886745 -size 49071 +oid sha256:2e147c903449a6c5ba6fa5041f73217c29965c2b4c2a165a96d36aebd2e2691e +size 49059 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 6100b21322..469a77a49a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05db3b3e42f59515ffad1c522496ebff6092bd458297ca92eba25b321d8be0ca -size 49564 +oid sha256:5590f66df4e26885e4b4776de840a9b1e4877a579f34769fe652172d01f5e374 +size 49554 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index 63eb0980b8..7235a7a8e9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5662df69d4f1c66bb47019096df83031b190d7bc8e0b354c06f09d7c25d3773f -size 48454 +oid sha256:bbcc418cc648fe137d32a0455af4c0235c5c9269c49826c28dcdb22e7997638e +size 48441 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index 44c943a262..6389db0432 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81ac09d41d5f08d8f4714f070c3661e0628a0d28f32d58eb0a1460eacb1be8d0 -size 47752 +oid sha256:a8d7ee825e1e2cb28babc26bdd2de3747c99bff0b95f6c7e4d8a2b2dd9f9dd49 +size 47758 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index cf0d675e49..89c1174fd0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dadbbe0ad65da59d7599f782e3893375867821ba0b8309c61a94f530cd58965 -size 44846 +oid sha256:2e6f13ca775952d7a06d82c41519a5f480f156eabd015a2020e0a5cf9d435765 +size 44694 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index 3b5b87ac98..456f8db66c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d8648c9c6297f2e8ec87b334e1e885555e921faa7d98dda70fffb902ebe2688 -size 44828 +oid sha256:c84a92f1c008dffb95cf4aa1337a35ba208d3702decf912e084937665079d947 +size 44674 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index c418b7d0b4..2f9e2bc268 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc469282e83bb5e88a173fc8a4500f8260f37ffc8afb20449e1126aa50631693 -size 43177 +oid sha256:29f45a3272a173614152dd6e7b0d3dc08de6d3b1f86c9683b267e97db773fb19 +size 43163 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index 8360619979..fb90141dde 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a0a8cafff67aa2fd2991ce4320ed412cfebed0208b2d1c4e8bc0f45e7977e6b -size 48534 +oid sha256:cc70b1f6c6152f0f57b4f8586d781938c12af8bc61b517a232b779739eea6c72 +size 48521 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index d0a134673b..10f31671ce 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e1625ee06b9ae0025bf798705c8919b405f9cd917d85056623618fe0223e736 -size 48450 +oid sha256:8e5d32aea59c328b24d0a56bede3110e5b4a1d90a9b5eeb9bffffd30de5a41b6 +size 48437 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index 720c2eeae6..2a3f4a388a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0aaf88dcf5e06d6c409318447e154b9d0b33775ad3e3aa8d8e3fe2b85aedd816 -size 48017 +oid sha256:ddddf06d51977bcd997e3680d2fe3ff4f9d8102848980cf88b4d2ef08e37d5f9 +size 48004 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index e95f8da31b..28f7d63b1a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae9087dda9b2c6e160aa14dbb45e8ab614f2c315158c5bfc48d5c67058ebb63c -size 42639 +oid sha256:b5ffb5c4bb36e659d6650acfc43c560d6c6cfc26f7b663e6de036c8d210c3c53 +size 42627 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index ac8ea4aa9b..b945a5f082 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d1c6f0c3898e000774de48cd7590c44bc11c297163735f16cc2dccaaf23e538 -size 45428 +oid sha256:cd4f6d16dbb22cd3968e4fb3a1408ee6387bb3f7d81388b18e4b4d7cdc24a2b8 +size 45416 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index aeb6c18836..291e381783 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff3ddf54027d1f77d8e1e1f5cc063f1c13fc2725447d7cb6475c2ebb6c84b529 -size 47002 +oid sha256:19e656cf990a24bb08da6b7205a5fc1d39c76bbec967781cf0ea2a55bf7d11ab +size 46989 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index a600833dc2..8ad5518a4c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c99f882e777e43d1689ffa80a5396583426d987725424c779eff019f96d1c1bb -size 44444 +oid sha256:df3eb3ec43a8219be6e5fb27ae316222bf049d73d897712e9e4981c7cd482f66 +size 44290 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index a4d831a49c..2524ad82a5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35aab3535b161bb3b111a9a352f510b43a25f9c98a7e5648aa3a380cd8402063 -size 45969 +oid sha256:babe700b98176da34b30db8fcd367f13b26eb0b8216f8a486d0462dccdbe3068 +size 44782 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index 9d4d6b35bf..d3fe3eeec7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d637a9ab06a5eb79bbee7d141be92563d1c6d4acbb301b61a8c02db53e89132 -size 49078 +oid sha256:e78510f867c14a8cc9e98d6bf36880136f36cdf08cf8940b9a5f54e327a1f115 +size 49064 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index 0884641063..ae3e083f08 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f45315776c2e841043aabdef8b72a8cd4e485270ada198b28f92de8f55bc7ca -size 48392 +oid sha256:627f61625aadbd1801d38dec33a107c72d9c2bc10057ab85ed15207557fb8343 +size 48379 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index 82093102db..e52d7bbc87 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:401e526ee8c3e27e90d34a9cb86561789172a9b91b5b5a6f5955aa4b001dfb1a -size 47658 +oid sha256:d3da232ee647be1a9722a00d4884f6f559cddc83f642aa07c3cbc4fb35746028 +size 47649 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index d7778998b9..a825b90d21 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f7fd6001307e447476310fc91cfe2eab0bddd8d0bc137a9a35698320f30f706 -size 50559 +oid sha256:3b17db5e3de5f2a7cd8ab5adb998b9343993aeb4ca7e072287e0f60064638155 +size 50517 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index 777eaaf717..1e506d9628 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17c582d1666c5c7b6040b007a13f0c6367eccd07d2a35847e4751bf8e5de7ed6 -size 48691 +oid sha256:e9165fa335486aa0463e9ee43b9e7c581a1c9bcd81f605a193d217fac58bff01 +size 48642 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index c59448b50d..15456d858a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:673f1524b9a0e8284600cdcc5536bdf98574424c31a8a35552a75cbdd404424d -size 47490 +oid sha256:66d934f6d2fb764fd8d856e19671a47eb96bf79d1904222f12ba2c04ff815472 +size 47449 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index f0c70fc293..759eda79f1 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7aff67290ac05d786c65cdc2dabc4bc6dbf60a802d0b77ae8c8404fd05e1bb7 -size 49256 +oid sha256:f6dfedba8b70af6389b88143e0c1c59dc9dbacba06b985fb791f9d5ef6b76d65 +size 49222 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index 4c43697ac5..b50b33e08a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec0e7d344810f5fa43b9bc05c41116501350e3daedabd33c97782082264369ab -size 49157 +oid sha256:114059cd1d74d7e67039fdab4f4a37306badb38b2811b7cb494fd47a3de7dd52 +size 49118 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index f0d89fc365..09a418c30b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a012a170cbd17e1fe588c27e41e531baa12097830ed205ac5c9c51c5bd62e003 -size 50108 +oid sha256:319b86e201bbcf3efb4ca2cceef15e7bba83800202c110439b5bab58d94aaa9d +size 50069 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index 865602ac62..9bb6b27c92 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f734bad723be9fada8b38763321ea63778f0ebfd65567472432ac32634d7b67 -size 50695 +oid sha256:0ddeb573fd6c83a7b0d9e00947a1f1b87c27eda69796285c7b9a6cee487ccbb1 +size 50653 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index 1a59d9ec17..8c769eb3c2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a3c70bad40927fcd45902da33a3fe12fa50057e278c6009b1ed5befe4512182 -size 49470 +oid sha256:9a092056f5ae3f2bf40db0e1727afd191bf19b2bffea9bbeaa9cd5822b2235af +size 49426 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index 1c01af3450..b7e8d5e7da 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9e7f2edac607fcd372a991078a4d9d92e01e148ddebce2785174dbf877e14bf -size 49045 +oid sha256:f300dbb1b0868fa619edef30e43231b5c2cb777bee2af56a8f3dfe42253db318 +size 48999 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index aa64291503..602a4de377 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:755919c37c18cac3fe595975847620ce4a0b836b01546fbbfd3cdd1693ad5435 -size 45945 +oid sha256:2b7f04ee27a8cdc0b9cde949d6167f013cbf2cbfcf591a54262ca697fd54ab57 +size 46011 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 1cb9dd897b..0bb73f7526 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:735d92a8a39f4ec22ab51830cc0a5877697d028a12ba4cec2c2cce0475cddea5 -size 45888 +oid sha256:1d39a3067e1df646444276e13c1709e5c0ab0b27bb313531bdedde43fa056d6c +size 45947 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 1d527ce0e6..286ac63579 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c9e86d87f93e3e96ee25b6090b0f989baf173a189a3c2274dc2cdd06dd566e1 -size 44223 +oid sha256:62ec3e5198b9d783cc7dcff94c39dec2ddd7edabbcbf1e272418e5446ec6d854 +size 44182 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index c6e83dd003..673cdd0c30 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ed0a0e971a25574d13b6bbc5e0137f8a3f2bb1909d6149d16e09199dce3c25a -size 49535 +oid sha256:60c1951da07af010cd27d8622dcef6f953d369df9143a6c09e479bd26ea3aea9 +size 49487 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index dd2ebef37e..49483a49d7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd5dcb36fc1e9cb675d461850e88f80402d30e43c6f8709ab3274326ad4a42b5 -size 49454 +oid sha256:951b4ed6186db857355229f9518aab6e72d0e6089e750eb58f1d21c23af54a58 +size 49415 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index 9c0a4282b1..e49a2edf1b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b24f32d9a8640b7d1ef5a2b77d6198d3dbfabcab7a9cf46af8a0b24e23655eeb -size 48999 +oid sha256:9036a65f211de57afb08e2a8a1edc679690286063855146616d1a9205f5e92ba +size 48963 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index 24966de76f..037c1a51b9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e92a8647bc6be119cb6dd401267f3369ad0ffa61372efc21d8e1752350c37a54 -size 43617 +oid sha256:c42fc0297235872ed4a405cbf73dbe68646b4ba2f2d8b4ab2a2c759372aedff5 +size 43575 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index 95c8bffb80..c7dd2f7b1a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39e4eab91f3d07daff1437991ec74005e7c79eed3f9b4ff71c154d68bbce3e71 -size 46400 +oid sha256:36df2a8757b8fea88e4d03150b7c9f1349e4112b1c7172224818cf394eb8755f +size 46360 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index 5c5bc77cb2..731d5599be 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ce073c24e1d2b0cfcc6fc64cc62042c5bb9260e7636441827fdc746964aefbe -size 48017 +oid sha256:73a5e4314e7d2cfffff54c1181aab1fb95227172758299c06754e97b59a58bba +size 47972 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index 0a07cb8799..fb6a42fde4 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19fa23046e80df108a9d9cabe2b34d713e12d74127b3c4a320b5770e286429ea -size 45506 +oid sha256:9dec4b40543155b80a9d1db51a97f269d6188c0ea84384abf37e7c32a953a4c3 +size 45565 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 71787b6f1f..6ce7d985b9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb164e2c9796a1d12a0146b3fb67d29813be54d42b0628d17a323a525b866177 -size 47065 +oid sha256:2d575f4e716de7fc5e1d376a8225f69bcf5375ea8a1555baa8d27d0481b45d4b +size 46038 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index a9ebd612f5..28cb1f210b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d764589c800027ef6f34660324d980c6525475b0a65d7f1e7b4afa4f4f19aaa -size 50155 +oid sha256:8a4d42087d391ecc107d9f485e97499a9952f85c7555ac4428d36f4565c75dba +size 50112 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index 9a167dc9b8..8c515e1bfe 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3784f50878f750bc04b45ca657ccb89d74343164ef7b0aa06fb43260f46ef72 -size 49429 +oid sha256:a5b97717f51c11b13b760cdb6922587db19d962f1f47c7c45bb39de2fc7880af +size 49374 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index b2f44c24d5..04877ee746 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91302b37b756a39cae34160110d2f7bb3fd67129343cde63ae22b109861299c7 -size 48671 +oid sha256:29a2b72b3ab467665c819763eee041fe349d26d9d2b6b724677a071dfcb84450 +size 48626 diff --git a/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png b/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png index 34d3e5d494..e86f031a8e 100644 --- a/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png +++ b/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:993191e7db24d10111a3b7c22c0e192e28e9a3e170edb57de14ec205de73cf15 -size 95383 +oid sha256:fa263cc9cfb7cc47dacfa4ea65a9f4e8660e1a17df61e357d5cf76928dd89100 +size 90714 diff --git a/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png b/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png index 8d1aac76c6..3eff580ee8 100644 --- a/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png +++ b/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93b60fdeb5bd6fbf7f3ab3eca81f2109b02101bec9a8c812ceb02ac8d19840e2 -size 51866 +oid sha256:caa936c590efb400eec2e3d238bec4e48b81883371057f34badf0abb1644554c +size 49654 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png index 502b87bbdb..1230b616fd 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7884a15f505913ba13dcd99320b1b9d26cbf1e8f15eb051e65d8fbedc1a828c -size 27673 +oid sha256:fa14bce431debf9d9a64c4a47bed9d89730fb21d480af186dc2ac53a9e52f1af +size 31785 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png index 33479d694d..14b7d796bc 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8cea006dcb900e70cc9f4be90b9144e340768e7d23d90932c99422eaf8ea96fb -size 21203 +oid sha256:0f4fe803d3318a31919099958d793ecb4f5eae7109596712de23c89e6c982ea4 +size 20145 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png index e4c6ad93ff..358883997e 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41ddc90c4f22013037b7786f2b91e35dd2db7329d43f12cb72f8cd1474e89d3c -size 31725 +oid sha256:a99cb9da94e1ea3050ccb1e9c32380fde1b5e55ea806c4c2aa5f7bc8c5d0b0fd +size 30750 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png index 3e3fcc2526..fc81f7c584 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a17fadc85a373556a338cd4c9ceaf35432b1853e06641237e6d3f4bf7cd0979 -size 51495 +oid sha256:af238ae63b675069702e65b52c1e4b272294aa0a2c971a3394a67535ee89e45c +size 51165 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png index 75e7c2f592..3bbed27e43 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44855b0887ce9ccd5a0302c8d11ba6bf556badaefd33f897c5635d49cb44a99e -size 45071 +oid sha256:26cbf2c908b89e8cd2daa1a35cfd58dcea951e03a2ecc2334af7d8241d038254 +size 41339 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png deleted file mode 100644 index 1230b616fd..0000000000 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa14bce431debf9d9a64c4a47bed9d89730fb21d480af186dc2ac53a9e52f1af -size 31785 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png index ebf998ba32..5b11ec067d 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa5d7bb68d549eab01750a043f0c844cf9ff2609e813fa6be5170f7e47da04f4 -size 36872 +oid sha256:35ac4bfa2e7bffba17448459c52098400f421fc3af55a7de16c24f3f293d0d42 +size 36464 diff --git a/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png b/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png index 88e163b840..5fc8b4a8fe 100644 --- a/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4d6fb36f1340276b3f525505e8a51245f63a1fbe8637ad33c9c3c2ef793679d -size 114204 +oid sha256:81e2d991659061d40047373c3b3aedff5a4bc2b42c2b1355448b73784891b2f5 +size 109822 diff --git a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png index 74fca61a42..6b49ae7f1a 100644 --- a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9da4a0d12b26e2bf2bc3c6a0b032d462ccce782ee6ed5a62c7c32a7c2d4e0a2 -size 28400 +oid sha256:4484ff8dbba915c439270cbebab45c503d94dc82c7641a674153d88aa2aa3143 +size 28017 diff --git a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png index 6e9497454b..752973ddb4 100644 --- a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d365fb5ebb274cdf830763e8354e5fb532929f590f9ae93259c823fa66a64a5 -size 39239 +oid sha256:402ca214ecc34d4a5a5faf7583a879ab26e6c64b86904034dfa050a27a7b7a2d +size 38789 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png index 169e0d2b10..f89e8cf1c5 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:622e92307a1aae1a9feb420709f74d9cef063cdfd8e9f562e65655cb54ee804f -size 9991 +oid sha256:f02b4fe30d6ab57d618c925d3a110b5ca8f299717032b1380d91437acda62b7b +size 11633 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png index e2acbcc89c..6aee76799c 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ad1db5f211ed3df04d31e973297a82685168834ee6b629ce10c3b9e82c226c9 -size 10512 +oid sha256:1dde928940515398c089e258787afca156fd1dceb9b80559c339e94e97864f12 +size 12052 diff --git a/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png b/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png index 250826b00d..25ad5c2356 100644 --- a/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png +++ b/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7179346d56f1c4772169e344f1e5f01b42a5cbb86093dc6e14728f970f5fc6b -size 72739 +oid sha256:76955fb8324747c81687727bbced594f00d2c2610d91474123ecd6ced14394a4 +size 70297 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 2cd7772aff..eea6b4b636 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,99 +1,100 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",0,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20581,], ["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_0_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20573,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20573,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20581,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20581,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], -["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20573,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20573,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20581,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20581,], ["features.messages.impl.actionlist_ActionListViewContent_Day_0_en","features.messages.impl.actionlist_ActionListViewContent_Night_0_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20581,], ["features.messages.impl.actionlist_ActionListViewContent_Day_1_en","features.messages.impl.actionlist_ActionListViewContent_Night_1_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20573,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20581,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20581,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20573,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20573,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20573,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20573,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20573,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20581,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20581,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20581,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20581,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20581,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20573,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20573,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20573,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20573,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20581,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20581,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20581,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20581,], ["libraries.designsystem.components.async_AsyncActionView_Day_0_en","libraries.designsystem.components.async_AsyncActionView_Night_0_en",0,], -["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20573,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20581,], ["libraries.designsystem.components.async_AsyncActionView_Day_2_en","libraries.designsystem.components.async_AsyncActionView_Night_2_en",0,], -["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20573,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20581,], ["libraries.designsystem.components.async_AsyncActionView_Day_4_en","libraries.designsystem.components.async_AsyncActionView_Night_4_en",0,], -["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20573,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20581,], ["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20573,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20581,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_0_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_0_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_1_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_1_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_2_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_2_en",0,], @@ -103,19 +104,19 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20581,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en",0,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20573,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20581,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.matrix.ui.components_AvatarPickerSizes_Day_0_en","libraries.matrix.ui.components_AvatarPickerSizes_Night_0_en",0,], ["libraries.matrix.ui.components_AvatarPickerViewRtl_Day_0_en","libraries.matrix.ui.components_AvatarPickerViewRtl_Night_0_en",0,], @@ -145,22 +146,22 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20573,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20581,], ["libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en","libraries.designsystem.atomic.atoms_BetaLabel_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20581,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20573,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20581,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -171,141 +172,141 @@ export const screenshots = [ ["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20573,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20573,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20581,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20581,], ["features.messages.impl.timeline.components_CallMenuItem_Day_5_en","features.messages.impl.timeline.components_CallMenuItem_Night_5_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20573,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20581,], ["features.messages.impl.timeline.components_CallMenuItem_Day_7_en","features.messages.impl.timeline.components_CallMenuItem_Night_7_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20573,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20573,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20573,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20573,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20573,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20581,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20581,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20581,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20581,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20581,], ["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_5_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_5_en",0,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20581,], ["features.login.impl.changeserver_ChangeServerView_Day_0_en","features.login.impl.changeserver_ChangeServerView_Night_0_en",0,], -["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20573,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20581,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20573,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20581,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20573,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20573,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20581,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20581,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], -["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20577,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20581,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20573,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20581,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20581,], ["libraries.textcomposer_ComposerModeView_Day_1_en","libraries.textcomposer_ComposerModeView_Night_1_en",0,], ["libraries.textcomposer_ComposerModeView_Day_2_en","libraries.textcomposer_ComposerModeView_Night_2_en",0,], ["libraries.textcomposer_ComposerModeView_Day_3_en","libraries.textcomposer_ComposerModeView_Night_3_en",0,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20573,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20573,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20573,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20581,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20581,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20581,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20581,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicator_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicator_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_CounterAtom_Day_0_en","libraries.designsystem.atomic.atoms_CounterAtom_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20573,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20573,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20573,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20573,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20573,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20573,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20573,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20573,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20573,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20573,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20573,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20581,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20581,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20581,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20581,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20581,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20581,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20581,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20581,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20581,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20581,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20581,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_1_en",0,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20573,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20573,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20581,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_0_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_0_en",0,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20573,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20573,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20573,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20581,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20581,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20581,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_4_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_4_en",0,], -["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20573,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20581,], ["features.licenses.impl.details_DependenciesDetailsView_Day_0_en","features.licenses.impl.details_DependenciesDetailsView_Night_0_en",0,], -["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20573,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20573,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20573,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20573,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20573,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20573,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20573,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20581,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20581,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20581,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20581,], ["libraries.designsystem.theme.components_DialogWithDestructiveButton_Dialog_with_destructive_button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithOnlyMessageAndOkButton_Dialog_with_only_message_and_ok_button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithThirdButton_Dialog_with_third_button_Dialogs_en","",0,], @@ -314,26 +315,24 @@ export const screenshots = [ ["libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en","",0,], ["features.messages.impl.messagecomposer_DisabledComposerView_Day_0_en","features.messages.impl.messagecomposer_DisabledComposerView_Night_0_en",0,], -["libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en","",0,], -["libraries.designsystem.components.avatar_DmAvatars_Avatars_en","",0,], ["libraries.designsystem.text_DpScale_0_75f__en","",0,], ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20573,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20581,], ["libraries.matrix.ui.components_EditableOrgAvatarRtl_Day_0_en","libraries.matrix.ui.components_EditableOrgAvatarRtl_Night_0_en",0,], ["libraries.matrix.ui.components_EditableOrgAvatar_Day_0_en","libraries.matrix.ui.components_EditableOrgAvatar_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_Night_0_en",0,], @@ -341,29 +340,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20573,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20573,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20581,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20581,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_2_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_2_en",0,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_3_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_3_en",0,], ["libraries.ui.common.nodes_EmptyView_Day_0_en","libraries.ui.common.nodes_EmptyView_Night_0_en",0,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20573,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20573,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20577,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20581,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20581,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.designsystem.components_ExpandableBottomSheetLayout_en","",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], @@ -383,49 +382,49 @@ export const screenshots = [ ["features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en","features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20573,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20573,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20573,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20581,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20581,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20581,], ["features.messages.impl.timeline.components_FocusedEvent_Day_0_en","features.messages.impl.timeline.components_FocusedEvent_Night_0_en",0,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.forward.impl_ForwardMessagesView_Day_0_en","features.forward.impl_ForwardMessagesView_Night_0_en",0,], ["features.forward.impl_ForwardMessagesView_Day_1_en","features.forward.impl_ForwardMessagesView_Night_1_en",0,], ["features.forward.impl_ForwardMessagesView_Day_2_en","features.forward.impl_ForwardMessagesView_Night_2_en",0,], -["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20573,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20573,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20581,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20581,], ["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_0_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_0_en",0,], -["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20573,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20581,], ["libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Night_0_en",0,], ["libraries.designsystem.components.button_GradientFloatingActionButton_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButton_Night_0_en",0,], ["features.messages.impl.timeline.components.group_GroupHeaderView_Day_0_en","features.messages.impl.timeline.components.group_GroupHeaderView_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPage_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPage_Night_0_en",0,], -["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20573,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20573,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20573,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20573,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20573,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20581,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20581,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20581,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20581,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20581,], ["features.home.impl.components_HomeTopBarSpaces_Day_0_en","features.home.impl.components_HomeTopBarSpaces_Night_0_en",0,], -["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20573,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20573,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20581,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20581,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20573,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20573,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20581,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20581,], ["features.home.impl_HomeView_Day_11_en","features.home.impl_HomeView_Night_11_en",0,], ["features.home.impl_HomeView_Day_12_en","features.home.impl_HomeView_Night_12_en",0,], -["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20573,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20573,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20573,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20573,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20573,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20573,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20573,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20573,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20573,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20573,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20573,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20573,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20573,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20581,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20581,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20581,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20581,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20581,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20581,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20581,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20581,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20581,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20581,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20581,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20581,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20581,], ["libraries.designsystem.theme.components_HorizontalDivider_Dividers_en","",0,], ["libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en","libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en",0,], ["libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en","libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en",0,], @@ -440,8 +439,8 @@ export const screenshots = [ ["appicon.element_Icon_en","",0,], ["libraries.designsystem.icons_IconsOther_Day_0_en","libraries.designsystem.icons_IconsOther_Night_0_en",0,], ["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_0_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_0_en",0,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20573,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20573,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20581,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20581,], ["libraries.mediaviewer.impl.gallery.ui_ImageItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_ImageItemView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en",0,], @@ -449,119 +448,119 @@ export const screenshots = [ ["libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20573,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20581,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20573,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20581,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en",0,], -["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20573,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20573,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20581,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20581,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20581,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], ["libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Day_0_en","libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Night_0_en",0,], -["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20573,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20581,], ["features.invitepeople.impl_InvitePeopleView_Day_11_en","features.invitepeople.impl_InvitePeopleView_Night_11_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20581,], ["features.invitepeople.impl_InvitePeopleView_Day_2_en","features.invitepeople.impl_InvitePeopleView_Night_2_en",0,], ["features.invitepeople.impl_InvitePeopleView_Day_3_en","features.invitepeople.impl_InvitePeopleView_Night_3_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20581,], ["features.invitepeople.impl_InvitePeopleView_Day_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20573,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20581,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20581,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], -["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20581,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20573,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20573,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20581,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20581,], ["features.leaveroom.impl_LeaveRoomView_Day_0_en","features.leaveroom.impl_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20581,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress_Indicators_en","",0,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20581,], ["features.messages.impl.link_LinkView_Day_0_en","features.messages.impl.link_LinkView_Night_0_en",0,], -["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20573,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20581,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ListDialog_Day_0_en","libraries.designsystem.components.dialogs_ListDialog_Night_0_en",0,], ["libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en","",0,], @@ -616,45 +615,45 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20573,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20581,], ["libraries.designsystem.components_LocationPin_Day_0_en","libraries.designsystem.components_LocationPin_Night_0_en",0,], ["features.location.impl.common.ui_LocationShareRow_Day_0_en","features.location.impl.common.ui_LocationShareRow_Night_0_en",0,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20573,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20573,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20573,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20581,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20581,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20581,], ["appnav.loggedin_LoggedInView_Day_0_en","appnav.loggedin_LoggedInView_Night_0_en",0,], -["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20573,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20573,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20573,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20573,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20573,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20573,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20573,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20573,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20573,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20573,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20573,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20573,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20573,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20573,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20573,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20573,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20573,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20573,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20573,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20573,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20573,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20573,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20573,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20573,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20573,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20573,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20573,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20581,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20581,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20581,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20581,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20581,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20581,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20581,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20581,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20581,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20581,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20581,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20581,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20581,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20581,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20581,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20581,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20581,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20581,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20581,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20581,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20581,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20581,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20581,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20581,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20581,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20581,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20581,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20573,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20573,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20573,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20573,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20581,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20581,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20581,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20581,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -667,26 +666,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20573,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20573,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20581,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20581,], ["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",0,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20581,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -694,15 +693,20 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20573,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -712,15 +716,20 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20573,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_18_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_19_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_20_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_21_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_22_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -734,7 +743,7 @@ export const screenshots = [ ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], ["libraries.designsystem.theme.components.previews_Menu_Menus_en","",0,], ["features.messages.impl.messagecomposer_MessageComposerViewVoice_Day_0_en","features.messages.impl.messagecomposer_MessageComposerViewVoice_Night_0_en",0,], -["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20573,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20581,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_1_en","features.messages.impl.timeline.components_MessageEventBubble_Night_1_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_2_en","features.messages.impl.timeline.components_MessageEventBubble_Night_2_en",0,], @@ -743,7 +752,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_5_en","features.messages.impl.timeline.components_MessageEventBubble_Night_5_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_6_en","features.messages.impl.timeline.components_MessageEventBubble_Night_6_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20573,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20581,], ["features.messages.impl.timeline.components_MessageStateEventContainer_Day_0_en","features.messages.impl.timeline.components_MessageStateEventContainer_Night_0_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButtonAdd_Day_0_en","features.messages.impl.timeline.components_MessagesReactionButtonAdd_Night_0_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButtonExtra_Day_0_en","features.messages.impl.timeline.components_MessagesReactionButtonExtra_Night_0_en",0,], @@ -752,23 +761,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20573,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20573,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20573,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20573,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20573,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20573,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20573,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20573,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20573,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20573,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20573,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20573,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20573,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20573,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20573,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20581,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20581,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20581,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20581,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20581,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20581,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20581,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20581,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20581,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20581,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20581,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20581,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20581,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20581,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20581,], ["features.migration.impl_MigrationView_Day_0_en","features.migration.impl_MigrationView_Night_0_en",0,], -["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20573,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20581,], ["features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en","features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en",0,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], @@ -779,113 +788,117 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20573,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20573,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20581,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20581,], ["features.linknewdevice.impl.screens.number.component_NumberTextField_Day_0_en","features.linknewdevice.impl.screens.number.component_NumberTextField_Night_0_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20581,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], -["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20573,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20581,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_12_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_12_en",0,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_13_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_13_en",0,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20581,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonSmall_Buttons_en","",0,], -["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20573,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20573,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20573,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20573,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20573,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20573,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20581,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20581,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20581,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20581,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20581,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20581,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], ["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20584,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20581,], ["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_PlaybackSpeedButton_Day_0_en","libraries.designsystem.atomic.atoms_PlaybackSpeedButton_Night_0_en",0,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20573,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20581,], ["features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Night_0_en",0,], ["features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Night_0_en",0,], -["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20573,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20581,], ["features.poll.api.pollcontent_PollTitleView_Day_0_en","features.poll.api.pollcontent_PollTitleView_Night_0_en",0,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], @@ -899,225 +912,225 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20581,], ["features.messages.impl.timeline.components.event_ProgressButton_Day_0_en","features.messages.impl.timeline.components.event_ProgressButton_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20573,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20581,], ["libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20573,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20573,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20573,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20581,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20581,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20581,], ["libraries.qrcode_QrCodeView_en","",0,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20573,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20573,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20581,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20581,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], ["features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Night_0_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20581,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], ["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,], -["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20573,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20573,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20581,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20581,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20581,], ["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en",0,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20573,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20573,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20573,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20581,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20581,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20581,], ["libraries.matrix.ui.room.address_RoomAddressField_Day_0_en","libraries.matrix.ui.room.address_RoomAddressField_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20573,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20573,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20581,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20581,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20573,], -["features.roomdetails.impl_RoomDetails_0_en","",20573,], -["features.roomdetails.impl_RoomDetails_10_en","",20573,], -["features.roomdetails.impl_RoomDetails_11_en","",20573,], -["features.roomdetails.impl_RoomDetails_12_en","",20573,], -["features.roomdetails.impl_RoomDetails_13_en","",20573,], -["features.roomdetails.impl_RoomDetails_14_en","",20573,], -["features.roomdetails.impl_RoomDetails_15_en","",20573,], -["features.roomdetails.impl_RoomDetails_16_en","",20573,], -["features.roomdetails.impl_RoomDetails_17_en","",20573,], -["features.roomdetails.impl_RoomDetails_18_en","",20573,], -["features.roomdetails.impl_RoomDetails_19_en","",20573,], -["features.roomdetails.impl_RoomDetails_1_en","",20573,], -["features.roomdetails.impl_RoomDetails_20_en","",20573,], -["features.roomdetails.impl_RoomDetails_21_en","",20573,], -["features.roomdetails.impl_RoomDetails_22_en","",20573,], -["features.roomdetails.impl_RoomDetails_2_en","",20573,], -["features.roomdetails.impl_RoomDetails_3_en","",20573,], -["features.roomdetails.impl_RoomDetails_4_en","",20573,], -["features.roomdetails.impl_RoomDetails_5_en","",20573,], -["features.roomdetails.impl_RoomDetails_6_en","",20573,], -["features.roomdetails.impl_RoomDetails_7_en","",20573,], -["features.roomdetails.impl_RoomDetails_8_en","",20573,], -["features.roomdetails.impl_RoomDetails_9_en","",20573,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20573,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20573,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20573,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20573,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20573,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20581,], +["features.roomdetails.impl_RoomDetails_0_en","",20581,], +["features.roomdetails.impl_RoomDetails_10_en","",20581,], +["features.roomdetails.impl_RoomDetails_11_en","",20581,], +["features.roomdetails.impl_RoomDetails_12_en","",20581,], +["features.roomdetails.impl_RoomDetails_13_en","",20581,], +["features.roomdetails.impl_RoomDetails_14_en","",20581,], +["features.roomdetails.impl_RoomDetails_15_en","",20581,], +["features.roomdetails.impl_RoomDetails_16_en","",20581,], +["features.roomdetails.impl_RoomDetails_17_en","",20581,], +["features.roomdetails.impl_RoomDetails_18_en","",20581,], +["features.roomdetails.impl_RoomDetails_19_en","",20581,], +["features.roomdetails.impl_RoomDetails_1_en","",20581,], +["features.roomdetails.impl_RoomDetails_20_en","",20581,], +["features.roomdetails.impl_RoomDetails_21_en","",20581,], +["features.roomdetails.impl_RoomDetails_22_en","",20581,], +["features.roomdetails.impl_RoomDetails_2_en","",20581,], +["features.roomdetails.impl_RoomDetails_3_en","",20581,], +["features.roomdetails.impl_RoomDetails_4_en","",20581,], +["features.roomdetails.impl_RoomDetails_5_en","",20581,], +["features.roomdetails.impl_RoomDetails_6_en","",20581,], +["features.roomdetails.impl_RoomDetails_7_en","",20581,], +["features.roomdetails.impl_RoomDetails_8_en","",20581,], +["features.roomdetails.impl_RoomDetails_9_en","",20581,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20581,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20581,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20581,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20581,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20581,], ["features.home.impl.components_RoomListContentView_Day_2_en","features.home.impl.components_RoomListContentView_Night_2_en",0,], -["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20573,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20573,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20573,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20577,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20577,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20577,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20577,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20577,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20577,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20573,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20573,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20581,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20581,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20581,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20581,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20581,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20581,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20581,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20581,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20581,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20581,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20581,], ["features.home.impl.search_RoomListSearchContent_Day_0_en","features.home.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20573,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20581,], ["features.roommembermoderation.impl_RoomMemberModerationView_Day_9_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20581,], ["libraries.designsystem.atomic.atoms_RoomPreviewAliasAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoomPreviewAliasAtom_Night_0_en",0,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20581,], ["features.home.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.home.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_0_en","features.home.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_10_en","features.home.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -1140,16 +1153,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20581,], ["features.home.impl.components_RoomSummaryRow_Day_36_en","features.home.impl.components_RoomSummaryRow_Night_36_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20581,], ["features.home.impl.components_RoomSummaryRow_Day_38_en","features.home.impl.components_RoomSummaryRow_Night_38_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_3_en","features.home.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_4_en","features.home.impl.components_RoomSummaryRow_Night_4_en",0,], @@ -1158,119 +1171,119 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_7_en","features.home.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_8_en","features.home.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_9_en","features.home.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20573,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20581,], ["features.login.impl.screens.classic.root_RootView_Day_0_en","features.login.impl.screens.classic.root_RootView_Night_0_en",0,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20573,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20573,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20581,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20581,], ["appicon.element_RoundIcon_en","",0,], ["appicon.enterprise_RoundIcon_en","",0,], ["libraries.designsystem.atomic.atoms_RoundedIconAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoundedIconAtom_Night_0_en",0,], -["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20573,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20573,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20573,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20581,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20581,], ["libraries.designsystem.theme.components_SearchBarActiveNoneQuery_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithContent_Search_views_en","",0,], -["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20573,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20581,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchFieldsDark_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchFieldsLight_Search_views_en","",0,], -["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20573,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20573,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20573,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20581,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20581,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20581,], ["libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_0_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_1_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_1_en",0,], @@ -1293,35 +1306,35 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20573,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20573,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20573,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20573,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20573,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20573,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20573,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20573,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20573,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20573,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20581,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20581,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20581,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20581,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20581,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20581,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20581,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20581,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20581,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20581,], ["features.share.impl_ShareView_Day_0_en","features.share.impl_ShareView_Night_0_en",0,], ["features.share.impl_ShareView_Day_1_en","features.share.impl_ShareView_Night_1_en",0,], ["features.share.impl_ShareView_Day_2_en","features.share.impl_ShareView_Night_2_en",0,], -["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20573,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20573,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20573,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20573,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20573,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20573,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20573,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20573,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20573,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20573,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20573,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20581,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20581,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20581,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20581,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20581,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20581,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20581,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20581,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20581,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20581,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20581,], ["libraries.designsystem.components_SimpleModalBottomSheet_Day_0_en","libraries.designsystem.components_SimpleModalBottomSheet_Night_0_en",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], @@ -1331,107 +1344,106 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single_selection_List_item_-_no_selection,_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20573,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20581,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20573,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20573,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20573,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20573,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20573,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20581,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20581,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20581,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20581,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20581,], ["libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Day_0_en","libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Night_0_en",0,], ["libraries.matrix.ui.components_SpaceMembersView_Day_0_en","libraries.matrix.ui.components_SpaceMembersView_Night_0_en",0,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20573,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20573,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20573,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20573,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20573,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20573,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20573,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20573,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20573,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20581,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20581,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20581,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20581,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20581,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20581,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20581,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20581,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20581,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20581,], ["libraries.designsystem.modifiers_SquareSizeModifierInsideSquare_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], -["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20573,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20573,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20573,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20573,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20573,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20573,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20573,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20581,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20581,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20581,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20581,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20581,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20581,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], -["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20573,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20581,], ["libraries.designsystem.atomic.pages_SunsetPage_Day_0_en","libraries.designsystem.atomic.pages_SunsetPage_Night_0_en",0,], ["libraries.designsystem.components.button_SuperButton_Day_0_en","libraries.designsystem.components.button_SuperButton_Night_0_en",0,], ["libraries.designsystem.theme.components_Surface_en","",0,], ["libraries.designsystem.theme.components_Switch_Toggles_en","",0,], -["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20573,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20581,], ["libraries.designsystem.components.avatar.internal_TextAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonSmall_Buttons_en","",0,], -["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20573,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20573,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20573,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20573,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20573,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20573,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20573,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20573,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20573,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20573,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20573,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20581,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20581,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20581,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20581,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20581,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20581,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20581,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20581,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20581,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20581,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20581,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], -["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20573,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20573,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20581,], ["libraries.designsystem.components.list_TextFieldListItemEmpty_Text_field_List_item_-_empty_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItemTextFieldValue_Text_field_List_item_-_textfieldvalue_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItem_Text_field_List_item_-_text_List_items_en","",0,], @@ -1444,17 +1456,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20573,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20573,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20581,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20581,], ["features.messages.impl.threads.list_ThreadsListView_Day_0_en","features.messages.impl.threads.list_ThreadsListView_Night_0_en",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20573,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20573,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20573,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20581,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_0_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_1_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_2_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20573,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20573,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20581,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20581,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_7_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_7_en",0,], @@ -1464,18 +1476,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20581,], ["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_0_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_1_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowLongSenderName_en","",0,], @@ -1483,18 +1495,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,], @@ -1503,44 +1515,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20573,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20581,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20581,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemInformativeView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemInformativeView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20581,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20573,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20581,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemReactionsView_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsView_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20573,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20581,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_0_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_0_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_1_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_1_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_2_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_2_en",0,], @@ -1549,8 +1561,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_5_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_5_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_6_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_6_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_7_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_7_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20573,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20581,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemStateEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemStateEventRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStateView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStateView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStickerView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStickerView_Night_0_en",0,], @@ -1565,8 +1577,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_4_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_5_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20581,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_2_en",0,], @@ -1589,84 +1601,84 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20573,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20581,], ["features.messages.impl.timeline_TimelineView_Day_2_en","features.messages.impl.timeline_TimelineView_Night_2_en",0,], ["features.messages.impl.timeline_TimelineView_Day_3_en","features.messages.impl.timeline_TimelineView_Night_3_en",0,], -["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20581,], ["features.messages.impl.timeline_TimelineView_Day_5_en","features.messages.impl.timeline_TimelineView_Night_5_en",0,], -["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20581,], ["features.messages.impl.timeline_TimelineView_Day_7_en","features.messages.impl.timeline_TimelineView_Night_7_en",0,], ["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",0,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.components.avatar.internal_TombstonedRoomAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TopAppBarStr_App_Bars_en","",0,], ["libraries.designsystem.theme.components_TopAppBar_App_Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20581,], ["features.messages.impl.typing_TypingNotificationView_Day_0_en","features.messages.impl.typing_TypingNotificationView_Night_0_en",0,], -["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20581,], ["features.messages.impl.typing_TypingNotificationView_Day_7_en","features.messages.impl.typing_TypingNotificationView_Night_7_en",0,], ["features.messages.impl.typing_TypingNotificationView_Day_8_en","features.messages.impl.typing_TypingNotificationView_Night_8_en",0,], ["libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Night_0_en",0,], -["libraries.matrix.ui.components_UnresolvedUserRow_en","",20573,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20581,], ["libraries.designsystem.components.avatar.internal_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar.internal_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20573,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20573,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20573,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20573,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20581,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20581,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20581,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20581,], ["features.startchat.impl.components_UserListView_Day_3_en","features.startchat.impl.components_UserListView_Night_3_en",0,], ["features.startchat.impl.components_UserListView_Day_4_en","features.startchat.impl.components_UserListView_Night_4_en",0,], ["features.startchat.impl.components_UserListView_Day_5_en","features.startchat.impl.components_UserListView_Night_5_en",0,], ["features.startchat.impl.components_UserListView_Day_6_en","features.startchat.impl.components_UserListView_Night_6_en",0,], -["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20573,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20581,], ["features.startchat.impl.components_UserListView_Day_8_en","features.startchat.impl.components_UserListView_Night_8_en",0,], -["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20573,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20581,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20573,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20573,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20573,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20573,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20573,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20573,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20573,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20573,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20573,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20573,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20573,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20573,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20573,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20581,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20581,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20581,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20581,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20581,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20581,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20581,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20581,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20581,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20581,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20581,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20581,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20581,], ["features.verifysession.impl.ui_VerificationUserProfileContent_Day_0_en","features.verifysession.impl.ui_VerificationUserProfileContent_Night_0_en",0,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_1_en",0,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20573,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20573,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20581,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20581,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_2_en","features.viewfolder.impl.file_ViewFileView_Night_2_en",0,], -["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20573,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20581,], ["features.viewfolder.impl.file_ViewFileView_Day_4_en","features.viewfolder.impl.file_ViewFileView_Night_4_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_5_en","features.viewfolder.impl.file_ViewFileView_Night_5_en",0,], ["features.viewfolder.impl.folder_ViewFolderView_Day_0_en","features.viewfolder.impl.folder_ViewFolderView_Night_0_en",0,], From e49e183178d84de9e2d95b75492c2f409a8b13e9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 11 May 2026 10:19:28 +0200 Subject: [PATCH 0386/1083] Feature : share live location (#6741) * First live location sharing sending implementation * Simplify logic around canStop sharing * Add some debug logs around LiveLocationSharingService * Add LiveLocationException * Expose beaconId to identify the current share * Throttle live location instead of debouncing * Keep sync alive when sharing live location * Improve LiveLocation sharing * Show LiveLocationDisclaimer * Read minDistanceUpdate in LiveLocationSharingService * Set minDistanceUpdate in AdvancedSettings * Display banner in room when sharing live location * Fix tests around LiveLocationSharing * Ensure shares are properly restarted/stopped when app is re-launched * Ensure LLS data is cleared when session is removed * Update and fix LLS tests * Handle Start LLS in ui * Add check LLS permissions * Remove hardcoded strings * Fix quality and format * Create DeviceLocationProvider so we can share location data between sources (presenter/live location service) * Update screenshots * Fix warning * Do not try to stop if it was not sharing * Revert "Create DeviceLocationProvider so we can share location data between sources (presenter/live location service)" This reverts commit ba12bd968e82941cc231bdbb449310b24c97c5b8. * Tweak location provider config values * Address PR review remarks * Fix ktlint * Update screenshots * Fix some tests after merging develop * Adjust TimelineItemLocationView ui to match figma * Update screenshots * Documentation and cleanup * Remove temporary resource --------- Co-authored-by: ElementBot Co-authored-by: Benoit Marty Co-authored-by: Benoit Marty --- .../android/appnav/LoggedInFlowNode.kt | 4 +- .../android/appnav/di/SyncOrchestrator.kt | 10 +- features/location/api/build.gradle.kts | 1 + .../location/api/LiveLocationSharingBanner.kt | 100 ++++ .../live/ActiveLiveLocationShareManager.kt | 43 ++ features/location/impl/build.gradle.kts | 9 + .../impl/src/main/AndroidManifest.xml | 10 + .../impl/common/LocationConstraintsCheck.kt | 4 + .../common/SendLiveLocationPermissions.kt | 34 ++ .../common/ui/LocationConstraintsDialog.kt | 7 + .../impl/common/ui/LocationShareRow.kt | 25 +- .../impl/common/ui/UserLocationPuck.kt | 8 +- .../location/impl/di/LocationBindings.kt | 17 + .../DefaultActiveLiveLocationShareManager.kt | 227 ++++++++ .../location/impl/live/LiveLocationStore.kt | 94 ++++ .../LiveLocationSharingNotificationCreator.kt | 61 +++ .../impl/live/service/LiveLocationReceiver.kt | 14 + .../service/LiveLocationSharingCoordinator.kt | 98 ++++ .../service/LiveLocationSharingService.kt | 125 +++++ .../location/impl/share/ShareLocationEvent.kt | 3 +- .../impl/share/ShareLocationPresenter.kt | 62 ++- .../location/impl/share/ShareLocationState.kt | 3 + .../impl/share/ShareLocationStateProvider.kt | 15 + .../location/impl/share/ShareLocationView.kt | 58 ++- .../location/impl/show/ShowLocationEvent.kt | 1 + .../impl/show/ShowLocationPresenter.kt | 13 +- .../location/impl/show/ShowLocationState.kt | 5 +- .../impl/show/ShowLocationStateProvider.kt | 2 + .../location/impl/show/ShowLocationView.kt | 1 + .../common/LocationConstraintsCheckTest.kt | 22 +- ...faultActiveLiveLocationShareManagerTest.kt | 488 ++++++++++++++++++ .../LiveLocationSharingCoordinatorTest.kt | 115 +++++ .../DefaultShareLocationEntryPointTest.kt | 14 +- .../impl/share/ShareLocationPresenterTest.kt | 247 ++++++++- .../impl/share/ShareLocationViewTest.kt | 32 ++ .../show/DefaultShowLocationEntryPointTest.kt | 5 +- .../show/LiveLocationShareComparatorTest.kt | 14 +- .../impl/show/ShowLocationPresenterTest.kt | 27 +- .../impl/store/LiveLocationStoreTest.kt | 129 +++++ .../FakeActiveLiveLocationShareManager.kt | 46 ++ .../features/messages/impl/MessagesEvent.kt | 2 + .../messages/impl/MessagesFlowNode.kt | 8 + .../messages/impl/MessagesNavigator.kt | 1 + .../features/messages/impl/MessagesNode.kt | 5 + .../messages/impl/MessagesPresenter.kt | 18 + .../features/messages/impl/MessagesState.kt | 1 + .../messages/impl/MessagesStateProvider.kt | 3 + .../features/messages/impl/MessagesView.kt | 82 +-- .../actionlist/ActionListStateProvider.kt | 5 +- .../impl/threads/ThreadedMessagesNode.kt | 6 + .../impl/timeline/TimelinePresenter.kt | 6 +- .../components/TimelineItemEventRow.kt | 2 +- .../event/TimelineItemLocationView.kt | 17 +- .../di/FakeTimelineItemPresenterFactories.kt | 8 + .../event/TimelineItemContentFactory.kt | 1 + .../event/TimelineItemEventContentProvider.kt | 4 +- .../event/TimelineItemLocationContent.kt | 3 +- .../TimelineItemLocationContentProvider.kt | 50 +- .../messages/impl/FakeMessagesNavigator.kt | 5 + .../messages/impl/MessagesPresenterTest.kt | 37 ++ .../messages/impl/MessagesViewTest.kt | 38 ++ .../impl/timeline/TimelinePresenterTest.kt | 3 + .../impl/advanced/AdvancedSettingsEvents.kt | 1 + .../impl/advanced/AdvancedSettingsNode.kt | 6 +- .../advanced/AdvancedSettingsPresenter.kt | 20 + .../impl/advanced/AdvancedSettingsState.kt | 1 + .../advanced/AdvancedSettingsStateProvider.kt | 2 + .../impl/advanced/AdvancedSettingsView.kt | 97 +++- .../advanced/AdvancedSettingsPresenterTest.kt | 69 ++- .../impl/advanced/AdvancedSettingsViewTest.kt | 2 + .../libraries/matrix/api/MatrixClient.kt | 2 + .../matrix/api/room/location/BeaconId.kt | 12 + .../api/room/location/BeaconInfoUpdate.kt | 16 + .../room/location/LiveLocationException.kt | 14 + .../api/room/location/LiveLocationShare.kt | 2 + .../libraries/matrix/impl/RustMatrixClient.kt | 12 + .../matrix/impl/room/JoinedRustRoom.kt | 12 + .../impl/room/location/BeaconInfoUpdates.kt | 21 + .../room/location/LiveLocationException.kt | 19 + .../room/location/LiveLocationSharesFlow.kt | 10 +- .../TimedLiveLocationSharesFlowTest.kt | 27 +- .../libraries/matrix/test/FakeMatrixClient.kt | 2 + .../matrix/test/room/FakeJoinedRoom.kt | 2 +- .../test/room/location/LiveLocationFixture.kt | 38 ++ .../api/store/AppPreferencesStore.kt | 3 + libraries/preferences/impl/build.gradle.kts | 3 + .../impl/store/DefaultAppPreferencesStore.kt | 14 + .../store/DefaultAppPreferencesStoreTest.kt | 57 ++ .../test/InMemoryAppPreferencesStore.kt | 10 + .../notifications/NotificationIdProvider.kt | 1 + .../test/observer/FakeSessionObserver.kt | 5 +- .../api/AppForegroundStateService.kt | 4 + .../impl/DefaultAppForegroundStateService.kt | 6 + .../test/FakeAppForegroundStateService.kt | 7 + ...api_LiveLocationSharingBanner_Day_0_en.png | 3 + ...i_LiveLocationSharingBanner_Night_0_en.png | 3 + ...pl.common.ui_LocationShareRow_Day_0_en.png | 4 +- ....common.ui_LocationShareRow_Night_0_en.png | 4 +- ....impl.share_ShareLocationView_Day_6_en.png | 4 +- ....impl.share_ShareLocationView_Day_7_en.png | 3 + ....impl.share_ShareLocationView_Day_8_en.png | 3 + ...mpl.share_ShareLocationView_Night_6_en.png | 4 +- ...mpl.share_ShareLocationView_Night_7_en.png | 3 + ...mpl.share_ShareLocationView_Night_8_en.png | 3 + ...vent_TimelineItemLocationView_Day_1_en.png | 4 +- ...vent_TimelineItemLocationView_Day_2_en.png | 4 +- ...vent_TimelineItemLocationView_Day_3_en.png | 4 +- ...nt_TimelineItemLocationView_Night_1_en.png | 4 +- ...nt_TimelineItemLocationView_Night_2_en.png | 4 +- ...nt_TimelineItemLocationView_Night_3_en.png | 4 +- ...s.messages.impl_MessagesView_Day_10_en.png | 4 +- ...s.messages.impl_MessagesView_Day_11_en.png | 3 + ...es.messages.impl_MessagesView_Day_8_en.png | 4 +- ...es.messages.impl_MessagesView_Day_9_en.png | 4 +- ...messages.impl_MessagesView_Night_10_en.png | 4 +- ...messages.impl_MessagesView_Night_11_en.png | 3 + ....messages.impl_MessagesView_Night_8_en.png | 4 +- ....messages.impl_MessagesView_Night_9_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_0_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_1_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_2_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_3_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_4_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_5_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_6_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_7_en.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_8_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_0_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_1_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_2_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_3_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_4_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_5_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_6_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_7_en.png | 4 +- ...advanced_AdvancedSettingsViewDark_8_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_0_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_1_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_2_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_3_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_4_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_5_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_6_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_7_en.png | 4 +- ...dvanced_AdvancedSettingsViewLight_8_en.png | 4 +- 145 files changed, 2913 insertions(+), 278 deletions(-) create mode 100644 features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt create mode 100644 features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt create mode 100644 features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt create mode 100644 libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 70376ffcb9..f2120038a6 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -54,6 +54,7 @@ import io.element.android.features.ftue.api.state.FtueService import io.element.android.features.ftue.api.state.FtueState import io.element.android.features.home.api.HomeEntryPoint import io.element.android.features.linknewdevice.api.LinkNewDeviceEntryPoint +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorContainer @@ -151,6 +152,7 @@ class LoggedInFlowNode( private val analyticsService: AnalyticsService, private val analyticsRoomListStateWatcher: AnalyticsRoomListStateWatcher, private val createRoomEntryPoint: CreateRoomEntryPoint, + private val activeLiveLocationShareManager: ActiveLiveLocationShareManager, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Placeholder, @@ -211,6 +213,7 @@ class LoggedInFlowNode( super.onBuilt() lifecycleScope.launch { sessionEnterpriseService.init() + activeLiveLocationShareManager.setup() } lifecycle.subscribe( onCreate = { @@ -219,7 +222,6 @@ class LoggedInFlowNode( loggedInFlowProcessor.observeEvents(sessionCoroutineScope) matrixClient.sessionVerificationService.setListener(verificationListener) mediaPreviewConfigMigration() - sessionCoroutineScope.launch { // Wait for the network to be connected before pre-fetching the max file upload size networkMonitor.connectivity.first { networkStatus -> networkStatus == NetworkStatus.Connected } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt b/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt index 9b1bbd1b81..1ce423a569 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt @@ -89,16 +89,14 @@ class SyncOrchestrator( @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun observeStates() = coroutineScope.launch { Timber.tag(tag).d("start observing the app and network state") - - val isAppActiveFlow = combine( + val isAppActiveFlows = listOf( appForegroundStateService.isInForeground, appForegroundStateService.isInCall, appForegroundStateService.isSyncingNotificationEvent, appForegroundStateService.hasRingingCall, - ) { isInForeground, isInCall, isSyncingNotificationEvent, hasRingingCall -> - isInForeground || isInCall || isSyncingNotificationEvent || hasRingingCall - } - + appForegroundStateService.isSharingLiveLocation + ) + val isAppActiveFlow = combine(isAppActiveFlows) { actives -> actives.any { it } } combine( // small debounce to avoid spamming startSync when the state is changing quickly in case of error. syncService.syncState.debounce(100.milliseconds), diff --git a/features/location/api/build.gradle.kts b/features/location/api/build.gradle.kts index ab85e37594..f8377389f1 100644 --- a/features/location/api/build.gradle.kts +++ b/features/location/api/build.gradle.kts @@ -71,6 +71,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.uiStrings) implementation(libs.coil.compose) + implementation(libs.datetime) testCommonDependencies(libs) } diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt new file mode 100644 index 0000000000..8c53550737 --- /dev/null +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.api + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun LiveLocationSharingBanner( + onClick: () -> Unit, + onStopClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .background(ElementTheme.colors.bgCanvasDefault) + .drawBannerBorder(ElementTheme.colors.separatorPrimary) + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = CompoundIcons.LocationPinSolid(), + contentDescription = null, + tint = ElementTheme.colors.iconAccentPrimary, + modifier = Modifier.size(24.dp), + ) + Text( + text = stringResource(CommonStrings.screen_room_live_location_banner), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + Button( + text = stringResource(CommonStrings.action_stop), + onClick = onStopClick, + destructive = true, + size = ButtonSize.Small, + ) + } +} + +private fun Modifier.drawBannerBorder(borderColor: Color): Modifier = drawBehind { + val strokeWidth = 1.dp.toPx() + val bottomY = size.height - strokeWidth / 2 + drawLine( + color = borderColor, + start = Offset(0f, strokeWidth / 2), + end = Offset(size.width, strokeWidth / 2), + strokeWidth = strokeWidth, + ) + drawLine( + color = borderColor, + start = Offset(0f, bottomY), + end = Offset(size.width, bottomY), + strokeWidth = strokeWidth, + ) +} + +@PreviewsDayNight +@Composable +internal fun LiveLocationSharingBannerPreview() = ElementPreview { + LiveLocationSharingBanner( + onClick = {}, + onStopClick = {}, + ) +} diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt new file mode 100644 index 0000000000..cd6b8731c1 --- /dev/null +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.api.live + +import io.element.android.libraries.core.coroutine.mapState +import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.coroutines.flow.StateFlow +import kotlin.time.Duration + +interface ActiveLiveLocationShareManager { + /** All rooms currently sharing live location on this device. */ + val sharingRoomIds: StateFlow> + + /** + * Initializes the manager. + * This will restart or stop current location sharing and set the listener on the SDK + * and the session manager. + */ + suspend fun setup() + + /** + * Starts live location sharing in the given room. + * Calls room.startLiveLocationShare() on the SDK, registers the share, + * and starts the foreground GPS service if not already running. + */ + suspend fun startShare(roomId: RoomId, duration: Duration): Result + + /** + * Stops live location sharing in the given room. + * Calls room.stopLiveLocationShare() on the SDK, removes the share, + * and stops the foreground service if no shares remain. + */ + suspend fun stopShare(roomId: RoomId): Result +} + +fun ActiveLiveLocationShareManager.isCurrentlySharing(roomId: RoomId): StateFlow { + return sharingRoomIds.mapState { roomId in it } +} diff --git a/features/location/impl/build.gradle.kts b/features/location/impl/build.gradle.kts index 0da54a1394..165c32b7c5 100644 --- a/features/location/impl/build.gradle.kts +++ b/features/location/impl/build.gradle.kts @@ -37,10 +37,16 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.matrixui) implementation(projects.services.analytics.api) + implementation(projects.services.appnavstate.api) implementation(libs.accompanist.permission) implementation(projects.libraries.uiStrings) implementation(projects.libraries.featureflag.api) implementation(projects.libraries.dateformatter.api) + implementation(projects.libraries.preferences.api) + implementation(projects.libraries.push.api) + implementation(projects.libraries.sessionStorage.api) + implementation(libs.androidx.datastore.preferences) + implementation(libs.datetime) testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) @@ -50,4 +56,7 @@ dependencies { testImplementation(projects.services.analytics.test) testImplementation(projects.features.messages.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.preferences.test) + testImplementation(projects.libraries.sessionStorage.test) + testImplementation(projects.features.location.test) } diff --git a/features/location/impl/src/main/AndroidManifest.xml b/features/location/impl/src/main/AndroidManifest.xml index ae728c09e1..e92ca68077 100644 --- a/features/location/impl/src/main/AndroidManifest.xml +++ b/features/location/impl/src/main/AndroidManifest.xml @@ -9,4 +9,14 @@ + + + + + + + diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt index a0b0cd4734..f90793b775 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt @@ -16,13 +16,16 @@ sealed interface LocationConstraintsCheck { data object PermissionRationale : LocationConstraintsCheck data object PermissionDenied : LocationConstraintsCheck data object LocationServiceDisabled : LocationConstraintsCheck + data object NotEnoughPowerLevel : LocationConstraintsCheck } fun checkLocationConstraints( permissionsState: PermissionsState, locationActions: LocationActions, + sendLiveLocationPermissions: SendLiveLocationPermissions, ): LocationConstraintsCheck { return when { + !sendLiveLocationPermissions.hasAll -> LocationConstraintsCheck.NotEnoughPowerLevel permissionsState.isAnyGranted -> { if (locationActions.isLocationEnabled()) { LocationConstraintsCheck.Success @@ -41,5 +44,6 @@ fun LocationConstraintsCheck.toDialogState(): LocationConstraintsDialogState { LocationConstraintsCheck.PermissionRationale -> LocationConstraintsDialogState.PermissionRationale LocationConstraintsCheck.PermissionDenied -> LocationConstraintsDialogState.PermissionDenied LocationConstraintsCheck.LocationServiceDisabled -> LocationConstraintsDialogState.LocationServiceDisabled + LocationConstraintsCheck.NotEnoughPowerLevel -> LocationConstraintsDialogState.NotEnoughPowerLevel } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt new file mode 100644 index 0000000000..d1a9e32026 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common + +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +/** + * Permissions to send beacon and beacon_info events in the room. + */ +data class SendLiveLocationPermissions( + val canSendBeacon: Boolean, + val canSendBeaconInfo: Boolean, +) { + val hasAll = canSendBeaconInfo && canSendBeacon + + companion object { + val DEFAULT = SendLiveLocationPermissions(canSendBeacon = false, canSendBeaconInfo = false) + val GRANTED = SendLiveLocationPermissions(canSendBeacon = true, canSendBeaconInfo = true) + } +} + +fun RoomPermissions.sendLiveLocationPermissions(): SendLiveLocationPermissions { + return SendLiveLocationPermissions( + canSendBeaconInfo = canOwnUserSendState(StateEventType.BeaconInfo), + canSendBeacon = canOwnUserSendMessage(MessageEventType.Beacon), + ) +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt index 95f5129f91..334aebaee6 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt @@ -10,6 +10,8 @@ package io.element.android.features.location.impl.common.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.res.stringResource +import io.element.android.features.location.impl.R +import io.element.android.libraries.designsystem.components.dialogs.AlertDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.ui.strings.CommonStrings @@ -42,6 +44,10 @@ fun LocationConstraintsDialog( onDismiss = onDismiss, submitText = stringResource(CommonStrings.action_continue), ) + LocationConstraintsDialogState.NotEnoughPowerLevel -> AlertDialog( + content = stringResource(R.string.screen_share_location_live_location_missing_permissions), + onDismiss = onDismiss + ) } } @@ -51,4 +57,5 @@ sealed interface LocationConstraintsDialogState { data object PermissionRationale : LocationConstraintsDialogState data object PermissionDenied : LocationConstraintsDialogState data object LocationServiceDisabled : LocationConstraintsDialogState + data object NotEnoughPowerLevel : LocationConstraintsDialogState } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt index 3d7b8df618..24476e3c66 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -44,6 +45,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun LocationShareRow( item: LocationShareItem, onShareClick: () -> Unit, + onStopClick: () -> Unit, modifier: Modifier = Modifier, ) { Row( @@ -101,11 +103,24 @@ fun LocationShareRow( ) } } + if (item.canStopSharing) { + IconButton( + onClick = onStopClick, + colors = IconButtonDefaults.iconButtonColors( + containerColor = ElementTheme.colors.bgCriticalPrimary, + contentColor = ElementTheme.colors.iconOnSolidPrimary, + ) + ) { + Icon( + imageVector = CompoundIcons.Stop(), + contentDescription = stringResource(CommonStrings.action_stop), + ) + } + } IconButton(onClick = onShareClick) { Icon( imageVector = CompoundIcons.ShareAndroid(), contentDescription = stringResource(CommonStrings.action_share), - tint = ElementTheme.colors.iconPrimary, ) } } @@ -128,8 +143,10 @@ internal fun LocationShareRowPreview() = ElementPreview { formattedTimestamp = "Shared 1 min ago", isLive = true, assetType = AssetType.SENDER, - location = Location(0.0, 0.0) + location = Location(0.0, 0.0), + isOwnUser = true, ), + onStopClick = {}, onShareClick = {}, ) LocationShareRow( @@ -145,8 +162,10 @@ internal fun LocationShareRowPreview() = ElementPreview { isLive = false, assetType = AssetType.PIN, formattedTimestamp = "Shared 5 hours ago", - location = Location(0.0, 0.0) + location = Location(0.0, 0.0), + isOwnUser = false ), + onStopClick = {}, onShareClick = {}, ) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt index 8b89f77be4..589ed87c6f 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt @@ -23,7 +23,7 @@ import org.maplibre.compose.location.UserLocationState import org.maplibre.compose.location.rememberAndroidLocationProvider import org.maplibre.compose.location.rememberNullLocationProvider import org.maplibre.compose.location.rememberUserLocationState -import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds @Composable fun UserLocationPuck( @@ -72,9 +72,9 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState rememberNullLocationProvider() } else { rememberAndroidLocationProvider( - updateInterval = 1.minutes, - desiredAccuracy = DesiredAccuracy.Balanced, - minDistanceMeters = 50f, + updateInterval = 5.seconds, + desiredAccuracy = DesiredAccuracy.High, + minDistanceMeters = 5f, ) } return rememberUserLocationState(locationProvider) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt new file mode 100644 index 0000000000..ee70936160 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt @@ -0,0 +1,17 @@ +/* + * 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.di + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesTo +import io.element.android.features.location.impl.live.service.LiveLocationSharingService + +@ContributesTo(AppScope::class) +interface LocationBindings { + fun inject(service: LiveLocationSharingService) +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt new file mode 100644 index 0000000000..fd16bea515 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn +import dev.zacsweers.metro.binding +import io.element.android.features.location.api.Location +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.features.location.impl.live.service.LiveLocationReceiver +import io.element.android.features.location.impl.live.service.LiveLocationSharingCoordinator +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.location.BeaconId +import io.element.android.libraries.matrix.api.room.location.LiveLocationException +import io.element.android.libraries.sessionstorage.api.observer.SessionListener +import io.element.android.libraries.sessionstorage.api.observer.SessionObserver +import io.element.android.services.toolbox.api.systemclock.SystemClock +import kotlinx.coroutines.Job +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.getAndUpdate +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import timber.log.Timber +import java.util.concurrent.ConcurrentHashMap +import kotlin.concurrent.atomics.AtomicBoolean +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlin.time.Duration +import kotlin.time.Instant + +@OptIn(ExperimentalAtomicApi::class) +@SingleIn(SessionScope::class) +@ContributesBinding(SessionScope::class, binding = binding()) +class DefaultActiveLiveLocationShareManager( + private val matrixClient: MatrixClient, + private val coordinator: LiveLocationSharingCoordinator, + private val liveLocationStore: LiveLocationStore, + private val clock: SystemClock, + private val sessionObserver: SessionObserver, +) : ActiveLiveLocationShareManager, LiveLocationReceiver { + private val isSetup = AtomicBoolean(false) + private val cachedRooms = ConcurrentHashMap() + private val timeoutJobs = ConcurrentHashMap() + private val syncedActiveShareIds = MutableStateFlow>(emptySet()) + private val localSharingRoomIds = MutableStateFlow>(emptySet()) + override val sharingRoomIds: StateFlow> = localSharingRoomIds + + override suspend fun setup() = withContext(NonCancellable) { + if (isSetup.compareAndSet(expectedValue = false, newValue = true)) { + Timber.d("ActiveLiveLocationShareManager setup manager.") + + recoverPersistedShares() + + matrixClient.ownBeaconInfoUpdates + .onEach { update -> + Timber.d("Received beaconInfoUpdate:$update") + // First cancel the local share in this room if any. + if (update.roomId in localSharingRoomIds.value) { + stopLocalShare(roomId = update.roomId) + } + syncedActiveShareIds.update { + if (update.isLive) { + it + update.beaconId + } else { + it - update.beaconId + } + } + } + .launchIn(matrixClient.sessionCoroutineScope) + + sessionObserver.addListener(sessionListener) + } + } + + private val sessionListener: SessionListener = object : SessionListener { + override suspend fun onSessionDeleted(userId: String, wasLastSession: Boolean) { + if (matrixClient.sessionId.value == userId) { + clear() + } + } + } + + override suspend fun startShare(roomId: RoomId, duration: Duration): Result = withContext(NonCancellable) { + Timber.d("ActiveLiveLocationShareManager starting share for room $roomId with duration ${duration.inWholeSeconds}s") + val room = cachedRooms.getOrPut(roomId) { + matrixClient.getJoinedRoom(roomId) ?: return@withContext Result.failure(IllegalStateException("No room found for $roomId")) + } + // Before starting a new location share, stop the current one if any is active. + room.stopLiveLocationShare() + + room.startLiveLocationShare(duration.inWholeMilliseconds) + .onSuccess { beaconId -> + Timber.d("ActiveLiveLocationShareManager wait remote echo of $beaconId") + syncedActiveShareIds.first { beaconIds -> beaconIds.contains(beaconId) } + val expiresAt = Instant.fromEpochMilliseconds(clock.epochMillis() + duration.inWholeMilliseconds) + startLocalShare(roomId, expiresAt) + } + .onFailure { + Timber.e(it, "ActiveLiveLocationShareManager failed to start share for room $roomId") + stopLocalShare(roomId) + } + .map { } + } + + override suspend fun stopShare(roomId: RoomId): Result = withContext(NonCancellable) { + Timber.d("ActiveLiveLocationShareManager stopping share for room $roomId") + val room = cachedRooms.getOrPut(roomId) { + matrixClient.getJoinedRoom(roomId) ?: return@withContext Result.failure(IllegalStateException("No room found for $roomId")) + } + room.stopLiveLocationShare() + .onSuccess { + Timber.d("ActiveLiveLocationShareManager share stopped successfully for room $roomId") + } + .onFailure { + Timber.e(it, "ActiveLiveLocationShareManager failed to stop share for room $roomId") + } + .also { + stopLocalShare(roomId) + } + } + + override suspend fun onLocationUpdate(location: Location) { + val activeSharesCount = localSharingRoomIds.value.size + Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)") + localSharingRoomIds.value.forEach { roomId -> + Timber.d("ActiveLiveLocationShareManager sending location to room $roomId") + sendLiveLocation(roomId, location) + .onFailure { + Timber.e(it, "ActiveLiveLocationShareManager failed to send location to room $roomId") + } + } + } + + private suspend fun sendLiveLocation(roomId: RoomId, location: Location): Result { + val room = cachedRooms.getOrPut(roomId) { + matrixClient.getJoinedRoom(roomId) ?: return Result.failure(IllegalStateException("No room found for $roomId")) + } + return room.sendLiveLocation(location.toGeoUri()) + .recoverCatching { exception -> + when (exception) { + is LiveLocationException.NotLive -> { + stopLocalShare(roomId) + throw exception + } + else -> throw exception + } + } + } + + private suspend fun startLocalShare(roomId: RoomId, expiresAt: Instant) { + val wasEmpty = localSharingRoomIds.value.isEmpty() + Timber.d("ActiveLiveLocationShareManager share started successfully for room $roomId (wasEmpty=$wasEmpty)") + localSharingRoomIds.update { it + roomId } + liveLocationStore.setLiveLocationExpiry(roomId, expiresAt) + scheduleTimeout(roomId, expiresAt) + if (wasEmpty) { + Timber.d("ActiveLiveLocationShareManager registering with coordinator for session ${matrixClient.sessionId}") + coordinator.register(matrixClient.sessionId, this@DefaultActiveLiveLocationShareManager) + } + } + + private suspend fun recoverPersistedShares() { + val now = Instant.fromEpochMilliseconds(clock.epochMillis()) + liveLocationStore.getLiveLocationExpiries().forEach { (roomId, expiresAt) -> + if (expiresAt > now) { + // Only starts locally as the share is already started remotely + startLocalShare(roomId, expiresAt) + } else { + // Explicitly stop the share on the server. + stopShare(roomId) + } + } + } + + private fun scheduleTimeout(roomId: RoomId, expiresAt: Instant) { + timeoutJobs.remove(roomId)?.cancel() + val delayMillis = expiresAt.toEpochMilliseconds() - clock.epochMillis() + timeoutJobs[roomId] = matrixClient.sessionCoroutineScope.launch { + delay(delayMillis) + stopShare(roomId) + .onFailure { error -> + Timber.e(error, "ActiveLiveLocationShareManager failed to stop timed out share for room $roomId") + } + } + } + + private suspend fun stopLocalShare(roomId: RoomId) { + Timber.d("ActiveLiveLocationShareManager stop local share in $roomId") + timeoutJobs.remove(roomId)?.cancel() + val wasSharing = localSharingRoomIds.getAndUpdate { it - roomId }.isNotEmpty() + cachedRooms.remove(roomId)?.close() + liveLocationStore.removeLiveLocationExpiry(roomId) + if (wasSharing && localSharingRoomIds.value.isEmpty()) { + Timber.d("ActiveLiveLocationShareManager unregistering from coordinator for session ${matrixClient.sessionId}") + coordinator.unregister(matrixClient.sessionId) + } + } + + private suspend fun clear() { + Timber.d("ActiveLiveLocationShareManager clear state") + sessionObserver.removeListener(sessionListener) + coordinator.unregister(matrixClient.sessionId) + liveLocationStore.clear() + for (room in cachedRooms.values) { + room.close() + timeoutJobs[room.roomId]?.cancel() + } + timeoutJobs.clear() + cachedRooms.clear() + localSharingRoomIds.value = emptySet() + syncedActiveShareIds.value = emptySet() + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt new file mode 100644 index 0000000000..417d9d423a --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringSetPreferencesKey +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.androidutils.hash.hash +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import kotlinx.coroutines.flow.first +import timber.log.Timber +import kotlin.time.Instant + +private const val LIVE_LOCATION_EXPIRY_VALUE_SEPARATOR = "=" + +@Inject +@SingleIn(SessionScope::class) +class LiveLocationStore( + preferenceDataStoreFactory: PreferenceDataStoreFactory, + sessionId: SessionId, +) { + private val store = preferenceDataStoreFactory.create("location_${sessionId.value.hash().take(16)}") + private val acceptedLiveLocationDisclaimerKey = booleanPreferencesKey("live_location_disclaimer_accepted") + private val liveLocationExpiriesKey = stringSetPreferencesKey("live_location_expiries") + + suspend fun hasAcceptedLiveLocationDisclaimer(): Boolean = runCatchingExceptions { + store.data.first()[acceptedLiveLocationDisclaimerKey] ?: false + }.getOrDefault(false) + + suspend fun setAcceptedLiveLocationDisclaimer(): Result = runCatchingExceptions { + store.edit { prefs -> + prefs[acceptedLiveLocationDisclaimerKey] = true + } + } + + suspend fun getLiveLocationExpiries(): Map = runCatchingExceptions { + val serialized = store.data.first()[liveLocationExpiriesKey].orEmpty() + decodeLiveLocationExpiries(serialized) + }.onFailure { error -> + Timber.e(error, "Failed to decode live location expiry payload") + }.getOrDefault(emptyMap()) + + suspend fun setLiveLocationExpiry(roomId: RoomId, expiresAt: Instant): Result = runCatchingExceptions { + store.edit { prefs -> + val current = decodeLiveLocationExpiries(prefs[liveLocationExpiriesKey].orEmpty()) + prefs[liveLocationExpiriesKey] = encodeLiveLocationExpiries(current + (roomId to expiresAt)) + } + } + + suspend fun removeLiveLocationExpiry(roomId: RoomId): Result = runCatchingExceptions { + store.edit { prefs -> + val current = decodeLiveLocationExpiries(prefs[liveLocationExpiriesKey].orEmpty()) + val updated = current - roomId + if (updated.isEmpty()) { + prefs.remove(liveLocationExpiriesKey) + } else { + prefs[liveLocationExpiriesKey] = encodeLiveLocationExpiries(updated) + } + } + } + + private fun decodeLiveLocationExpiries(serialized: Set): Map { + return runCatchingExceptions { + serialized + .map { it.split(LIVE_LOCATION_EXPIRY_VALUE_SEPARATOR) } + .associate { values -> + val roomId = RoomId(values[0]) + val expiresAtMillis = values[1].toLong() + roomId to Instant.fromEpochMilliseconds(expiresAtMillis) + } + }.getOrDefault(emptyMap()) + } + + private fun encodeLiveLocationExpiries(expiries: Map): Set { + return expiries.entries.map { (roomId, expiresAt) -> + "${roomId.value}$LIVE_LOCATION_EXPIRY_VALUE_SEPARATOR${expiresAt.toEpochMilliseconds()}" + }.toSet() + } + + suspend fun clear() { + store.edit { prefs -> prefs.clear() } + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt new file mode 100644 index 0000000000..9d4c461b0e --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.notification + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import androidx.annotation.ChecksSdkIntAtLeast +import androidx.annotation.RequiresApi +import androidx.core.app.NotificationCompat +import dev.zacsweers.metro.Inject +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.ui.strings.CommonStrings + +@Inject +class LiveLocationSharingNotificationCreator( + @ApplicationContext private val context: Context, + private val buildMeta: BuildMeta, +) { + companion object { + const val CHANNEL_ID = "LIVE_LOCATION_SHARING" + } + + fun createNotification(): Notification { + if (supportNotificationChannels()) { + ensureChannelExists() + } + return NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(android.R.drawable.ic_menu_mylocation) + .setContentTitle(context.getString(CommonStrings.live_location_sharing_foreground_service_title_android, buildMeta.applicationName)) + .setContentText(context.getString(CommonStrings.live_location_sharing_foreground_service_message_android)) + .setOngoing(true) + .build() + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun ensureChannelExists() { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) { + notificationManager.createNotificationChannel( + NotificationChannel( + CHANNEL_ID, + context.getString(CommonStrings.live_location_sharing_foreground_service_channel_title_android) + .ifEmpty { "Live Location Sharing" }, + NotificationManager.IMPORTANCE_LOW, + ) + ) + } + } + + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O) + private fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt new file mode 100644 index 0000000000..adba75730c --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.service + +import io.element.android.features.location.api.Location + +fun interface LiveLocationReceiver { + suspend fun onLocationUpdate(location: Location) +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt new file mode 100644 index 0000000000..e39acb14e8 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.service + +import android.content.Context +import android.content.Intent +import androidx.core.content.ContextCompat +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn +import io.element.android.features.location.api.Location +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.services.toolbox.api.systemclock.SystemClock +import timber.log.Timber +import java.util.concurrent.ConcurrentHashMap +import kotlin.concurrent.atomics.AtomicLong +import kotlin.concurrent.atomics.AtomicReference +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlin.time.Duration.Companion.seconds + +private val THROTTLE_WINDOW = 3.seconds + +@OptIn(ExperimentalAtomicApi::class) +@SingleIn(AppScope::class) +class LiveLocationSharingCoordinator internal constructor( + private val startService: () -> Unit, + private val stopService: () -> Unit, + private val nowMillis: () -> Long, +) { + @Inject + constructor(@ApplicationContext context: Context, clock: SystemClock) : this( + startService = { + ContextCompat.startForegroundService(context, Intent(context, LiveLocationSharingService::class.java)) + }, + stopService = { + context.stopService(Intent(context, LiveLocationSharingService::class.java)) + }, + nowMillis = clock::epochMillis + ) + + private val receivers = ConcurrentHashMap() + + private val lastDispatchMillis = AtomicLong(0L) + private val lastKnownLocation = AtomicReference(null) + + suspend fun register(sessionId: SessionId, receiver: LiveLocationReceiver) { + val wasEmpty = receivers.isEmpty() + Timber.d("LiveLocationSharingCoordinator registering receiver for session $sessionId (wasEmpty=$wasEmpty)") + receivers[sessionId] = receiver + if (wasEmpty) { + Timber.d("LiveLocationSharingCoordinator starting service") + runCatchingExceptions(startService).onFailure { + Timber.e(it, "Failed to start live location sharing service") + } + } + lastKnownLocation.load()?.let { + dispatch(it) + } + } + + fun unregister(sessionId: SessionId) { + Timber.d("LiveLocationSharingCoordinator unregistering receiver for session $sessionId") + receivers.remove(sessionId) + if (receivers.isEmpty()) { + lastKnownLocation.store(null) + Timber.d("LiveLocationSharingCoordinator stopping service (no more receivers)") + runCatchingExceptions(stopService).onFailure { + Timber.e(it, "Failed to stop live location sharing service") + } + } + } + + suspend fun dispatch(location: Location) { + val currentTimeMillis = nowMillis() + val millisSincePrevious = currentTimeMillis - lastDispatchMillis.load() + if (millisSincePrevious < THROTTLE_WINDOW.inWholeMilliseconds) { + Timber.d("Received location before $THROTTLE_WINDOW, ignore.") + return + } + lastKnownLocation.store(location) + lastDispatchMillis.store(currentTimeMillis) + receivers.forEach { (sessionId, receiver) -> + Timber.d("Dispatch received location for session $sessionId ") + runCatchingExceptions { + receiver.onLocationUpdate(location) + }.onFailure { + Timber.e(it, "Failed to dispatch live location update for session $sessionId") + } + } + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt new file mode 100644 index 0000000000..4451febb19 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.service + +import android.annotation.SuppressLint +import android.app.Service +import android.content.Intent +import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION +import android.os.IBinder +import androidx.core.app.ServiceCompat +import dev.zacsweers.metro.Inject +import io.element.android.features.location.impl.di.LocationBindings +import io.element.android.features.location.impl.live.notification.LiveLocationSharingNotificationCreator +import io.element.android.libraries.architecture.bindings +import io.element.android.libraries.core.coroutine.childScope +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.AppCoroutineScope +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.push.api.notifications.ForegroundServiceType +import io.element.android.libraries.push.api.notifications.NotificationIdProvider +import io.element.android.services.appnavstate.api.AppForegroundStateService +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import org.maplibre.compose.location.AndroidLocationProvider +import org.maplibre.compose.location.DesiredAccuracy +import timber.log.Timber +import kotlin.time.Duration.Companion.seconds +import io.element.android.features.location.api.Location as ApiLocation + +private const val UPDATE_INTERVAL_IN_SECOND = 10 + +class LiveLocationSharingService : Service() { + @Inject lateinit var coordinator: LiveLocationSharingCoordinator + @Inject lateinit var notificationCreator: LiveLocationSharingNotificationCreator + @Inject lateinit var appPreferencesStore: AppPreferencesStore + + @Inject lateinit var appForegroundStateService: AppForegroundStateService + + @AppCoroutineScope + @Inject lateinit var appCoroutineScope: CoroutineScope + private lateinit var coroutineScope: CoroutineScope + + override fun onBind(p0: Intent?): IBinder? = null + + @OptIn(FlowPreview::class) + @SuppressLint("InlinedApi") + override fun onCreate() { + super.onCreate() + Timber.d("LiveLocationSharingService onCreate") + runCatchingExceptions { + bindings().inject(this) + appForegroundStateService.updateIsSharingLiveLocation(true) + coroutineScope = appCoroutineScope.childScope(Dispatchers.Default, "LiveLocationSharingService") + val notificationId = NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.LIVE_LOCATION) + Timber.d("LiveLocationSharingService starting foreground service with notificationId=$notificationId") + ServiceCompat.startForeground( + // service = + this, + // id = + notificationId, + // notification = + notificationCreator.createNotification(), + // foregroundServiceType = + FOREGROUND_SERVICE_TYPE_LOCATION, + ) + startLocationUpdatesListener() + }.onFailure { + Timber.e(it, "Failed to start live location sharing service") + stopSelf() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + private fun startLocationUpdatesListener() { + Timber.d("LiveLocationSharingService listening to location updates") + appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() + .flatMapLatest { minDistanceMeters -> + val locationProvider = AndroidLocationProvider( + context = applicationContext, + updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, + minDistanceMeters = minDistanceMeters.toFloat(), + desiredAccuracy = DesiredAccuracy.Balanced, + coroutineScope = coroutineScope + ) + locationProvider.location + } + .filterNotNull() + .map { location -> + ApiLocation( + lat = location.position.latitude, + lon = location.position.longitude, + accuracy = location.accuracy.toFloat(), + ) + } + .onEach(coordinator::dispatch) + .launchIn(coroutineScope) + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + Timber.d("LiveLocationSharingService onStartCommand startId=$startId") + return START_STICKY + } + + override fun onDestroy() { + Timber.d("LiveLocationSharingService onDestroy") + if (::coroutineScope.isInitialized) { + coroutineScope.cancel() + } + appForegroundStateService.updateIsSharingLiveLocation(false) + super.onDestroy() + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt index d9ebc8b5af..e560ce805f 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt @@ -17,7 +17,8 @@ sealed interface ShareLocationEvent { val isPinned: Boolean, ) : ShareLocationEvent - data object ShowLiveLocationDurationPicker : ShareLocationEvent + data object InitiateLiveLocationShare : ShareLocationEvent + data object AcceptLiveLocationDisclaimer : ShareLocationEvent data class StartLiveLocationShare(val duration: Duration) : ShareLocationEvent data object StartTrackingUserLocation : ShareLocationEvent diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index 10fddf1e50..b56f9c7cb3 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -21,17 +21,22 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.Composer +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.location.impl.common.LocationConstraintsCheck import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.SendLiveLocationPermissions import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.location.impl.common.checkLocationConstraints import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsState +import io.element.android.features.location.impl.common.sendLiveLocationPermissions import io.element.android.features.location.impl.common.toDialogState -import io.element.android.features.location.impl.share.ShareLocationState.Dialog.Constraints +import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.messages.api.MessageComposerContext +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.extensions.flatMap import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.dateformatter.api.DurationFormatter @@ -41,6 +46,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.location.AssetType +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.services.analytics.api.AnalyticsService @@ -63,6 +69,8 @@ class ShareLocationPresenter( private val featureFlagService: FeatureFlagService, private val client: MatrixClient, private val durationFormatter: DurationFormatter, + private val liveLocationShareManager: ActiveLiveLocationShareManager, + private val liveLocationStore: LiveLocationStore, ) : Presenter { @AssistedFactory fun interface Factory { @@ -82,15 +90,39 @@ class ShareLocationPresenter( var dialogState: ShareLocationState.Dialog by remember { mutableStateOf(ShareLocationState.Dialog.None) } + val startLiveLocationAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } val currentUser by client.userProfile.collectAsState() + val sendLiveLocationPermissions by room.permissionsAsState(SendLiveLocationPermissions.DEFAULT) { perms -> + perms.sendLiveLocationPermissions() + } val scope = rememberCoroutineScope() fun checkLocationConstraints() { - val locationConstraints = checkLocationConstraints(permissionsState, locationActions) - dialogState = Constraints(locationConstraints.toDialogState()) + // No need to check SendLiveLocationPermissions here + val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) + dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState()) trackUserPosition = locationConstraints is LocationConstraintsCheck.Success } + suspend fun computeLiveLocationDialogState(): ShareLocationState.Dialog { + val hasAcceptedDisclaimer = liveLocationStore.hasAcceptedLiveLocationDisclaimer() + val constraintsResult = checkLocationConstraints(permissionsState, locationActions, sendLiveLocationPermissions) + return when { + !hasAcceptedDisclaimer -> { + ShareLocationState.Dialog.LiveLocationDisclaimer + } + constraintsResult is LocationConstraintsCheck.Success -> { + val durations = LIVE_LOCATION_DURATIONS.map { + LiveLocationDuration(duration = it, formatted = durationFormatter.format(it)) + } + ShareLocationState.Dialog.LiveLocationDurations(durations.toImmutableList()) + } + else -> { + ShareLocationState.Dialog.Constraints(constraintsResult.toDialogState()) + } + } + } + LaunchedEffect(permissionsState.permissions) { checkLocationConstraints() } fun handleEvent(event: ShareLocationEvent) { @@ -109,20 +141,23 @@ class ShareLocationPresenter( locationActions.openLocationSettings() dialogState = ShareLocationState.Dialog.None } - ShareLocationEvent.ShowLiveLocationDurationPicker -> { - val constraintsResult = checkLocationConstraints(permissionsState, locationActions) - dialogState = if (constraintsResult is LocationConstraintsCheck.Success) { - val durations = LIVE_LOCATION_DURATIONS.map { - LiveLocationDuration(duration = it, formatted = durationFormatter.format(it)) + ShareLocationEvent.InitiateLiveLocationShare -> scope.launch { + dialogState = computeLiveLocationDialogState() + } + ShareLocationEvent.AcceptLiveLocationDisclaimer -> scope.launch { + liveLocationStore.setAcceptedLiveLocationDisclaimer() + .onSuccess { + dialogState = computeLiveLocationDialogState() } - ShareLocationState.Dialog.LiveLocationDurations(durations.toImmutableList()) - } else { - Constraints(constraintsResult.toDialogState()) - } } is ShareLocationEvent.StartLiveLocationShare -> scope.launch { dialogState = ShareLocationState.Dialog.None - // room.startLiveLocationShare(event.duration.inWholeMilliseconds) + startLiveLocationAction.runUpdatingState { + liveLocationShareManager.startShare( + roomId = room.roomId, + duration = event.duration, + ) + } } ShareLocationEvent.RequestPermissions -> { dialogState = ShareLocationState.Dialog.None @@ -138,6 +173,7 @@ class ShareLocationPresenter( hasLocationPermission = permissionsState.isAnyGranted, canShareLiveLocation = isLiveLocationSharingEnabled, appName = appName, + startLiveLocationAction = startLiveLocationAction.value, eventSink = ::handleEvent, ) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt index 8b1f494f1e..68598cba04 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt @@ -9,6 +9,7 @@ package io.element.android.features.location.impl.share import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList @@ -19,11 +20,13 @@ data class ShareLocationState( val hasLocationPermission: Boolean, val appName: String, val canShareLiveLocation: Boolean, + val startLiveLocationAction: AsyncAction, val eventSink: (ShareLocationEvent) -> Unit, ) { sealed interface Dialog { data object None : Dialog data class Constraints(val state: LocationConstraintsDialogState) : Dialog + data object LiveLocationDisclaimer : Dialog data class LiveLocationDurations(val durations: ImmutableList) : Dialog } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt index facef74346..ae1b765b6b 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.location.impl.share import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.persistentListOf @@ -51,6 +52,18 @@ class ShareLocationStateProvider : PreviewParameterProvider trackUserPosition = true, hasLocationPermission = true, ), + aShareLocationState( + dialogState = ShareLocationState.Dialog.None, + trackUserPosition = true, + hasLocationPermission = true, + canShareLiveLocation = true, + ), + aShareLocationState( + dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, + trackUserPosition = true, + hasLocationPermission = true, + canShareLiveLocation = true, + ), aShareLocationState( dialogState = ShareLocationState.Dialog.LiveLocationDurations( persistentListOf( @@ -73,6 +86,7 @@ fun aShareLocationState( hasLocationPermission: Boolean = false, canShareLiveLocation: Boolean = false, appName: String = APP_NAME, + startLiveLocationAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (ShareLocationEvent) -> Unit = {}, ): ShareLocationState { return ShareLocationState( @@ -82,6 +96,7 @@ fun aShareLocationState( hasLocationPermission = hasLocationPermission, canShareLiveLocation = canShareLiveLocation, appName = appName, + startLiveLocationAction = startLiveLocationAction, eventSink = eventSink ) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index 1e163f417d..e20ee3a7a5 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -29,7 +29,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -44,11 +43,16 @@ import io.element.android.features.location.impl.common.ui.LocationFloatingActio import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold import io.element.android.features.location.impl.common.ui.UserLocationPuck import io.element.android.features.location.impl.common.ui.rememberUserLocationState -import io.element.android.libraries.androidutils.system.toast +import io.element.android.features.location.impl.share.ShareLocationEvent.StartLiveLocationShare +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.components.LocationPin import io.element.android.libraries.designsystem.components.PinVariant +import io.element.android.libraries.designsystem.components.async.AsyncIndicator +import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost +import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ListDialog import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.list.RadioButtonListItem @@ -74,7 +78,6 @@ fun ShareLocationView( navigateUp: () -> Unit, modifier: Modifier = Modifier, ) { - val context = LocalContext.current when (val dialogState = state.dialogState) { ShareLocationState.Dialog.None -> Unit is ShareLocationState.Dialog.Constraints -> LocationConstraintsDialog( @@ -85,12 +88,17 @@ fun ShareLocationView( onOpenLocationSettings = { state.eventSink(ShareLocationEvent.OpenLocationSettings) }, onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) }, ) + ShareLocationState.Dialog.LiveLocationDisclaimer -> ConfirmationDialog( + content = stringResource(R.string.screen_share_location_live_location_disclaimer_title), + submitText = stringResource(CommonStrings.action_accept), + cancelText = stringResource(CommonStrings.action_decline), + onSubmitClick = { state.eventSink(ShareLocationEvent.AcceptLiveLocationDisclaimer) }, + onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) }, + ) is ShareLocationState.Dialog.LiveLocationDurations -> LiveLocationDurationDialog( durations = dialogState.durations, onSelectDuration = { duration -> - state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration)) - context.toast("Not implemented yet!") - navigateUp() + state.eventSink(StartLiveLocationShare(duration)) }, onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) }, ) @@ -160,10 +168,46 @@ fun ShareLocationView( .align(Alignment.TopEnd) .padding(all = 16.dp), ) + StartLiveLocationActionView(state.startLiveLocationAction, navigateUp) } ) } +@Composable +private fun StartLiveLocationActionView( + action: AsyncAction, + onActionSuccess: () -> Unit, + modifier: Modifier = Modifier, +) { + Box(modifier = modifier) { + val asyncIndicatorState = rememberAsyncIndicatorState() + AsyncIndicatorHost(state = asyncIndicatorState) + + when (action) { + is AsyncAction.Loading -> { + LaunchedEffect(action) { + asyncIndicatorState.enqueue { + AsyncIndicator.Loading(text = stringResource(CommonStrings.common_waiting_live_location)) + } + } + } + is AsyncAction.Failure -> { + LaunchedEffect(action) { + asyncIndicatorState.enqueue(AsyncIndicator.DURATION_SHORT) { + AsyncIndicator.Failure( + text = stringResource(CommonStrings.common_something_went_wrong), + ) + } + } + } + is AsyncAction.Success -> { + LaunchedEffect(action) { onActionSuccess() } + } + else -> Unit + } + } +} + @Composable private fun BottomSheetContent( cameraState: CameraState, @@ -202,7 +246,7 @@ private fun BottomSheetContent( } if (state.canShareLiveLocation) { ShareLiveLocationItem { - state.eventSink(ShareLocationEvent.ShowLiveLocationDurationPicker) + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) } } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt index 6a3e3521e0..34132dccf3 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt @@ -17,4 +17,5 @@ sealed interface ShowLocationEvent { data object RequestPermissions : ShowLocationEvent data object OpenAppSettings : ShowLocationEvent data object OpenLocationSettings : ShowLocationEvent + data object StopLocationSharing : ShowLocationEvent } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt index 43d3aa6d00..207b4b01dd 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt @@ -15,14 +15,17 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationMode +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.location.impl.common.LocationConstraintsCheck import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.SendLiveLocationPermissions import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.location.impl.common.checkLocationConstraints import io.element.android.features.location.impl.common.permissions.PermissionsEvents @@ -45,6 +48,7 @@ import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.launch @AssistedInject class ShowLocationPresenter( @@ -55,6 +59,7 @@ class ShowLocationPresenter( private val dateFormatter: DateFormatter, private val stringProvider: StringProvider, private val joinedRoom: JoinedRoom, + private val liveLocationShareManager: ActiveLiveLocationShareManager, ) : Presenter { @AssistedFactory fun interface Factory { @@ -65,6 +70,7 @@ class ShowLocationPresenter( @Composable override fun present(): ShowLocationState { + val coroutineScope = rememberCoroutineScope() val permissionsState: PermissionsState = permissionsPresenter.present() var isTrackMyLocation by remember { mutableStateOf(false) } val appName by remember { derivedStateOf { buildMeta.applicationName } } @@ -85,7 +91,7 @@ class ShowLocationPresenter( } is ShowLocationEvent.TrackMyLocation -> { if (event.enabled) { - val locationConstraints = checkLocationConstraints(permissionsState, locationActions) + val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) isTrackMyLocation = locationConstraints is LocationConstraintsCheck.Success dialogState = locationConstraints.toDialogState() } else { @@ -102,6 +108,9 @@ class ShowLocationPresenter( dialogState = LocationConstraintsDialogState.None } ShowLocationEvent.RequestPermissions -> permissionsState.eventSink(PermissionsEvents.RequestPermissions) + ShowLocationEvent.StopLocationSharing -> coroutineScope.launch { + liveLocationShareManager.stopShare(joinedRoom.roomId) + } } } @@ -127,6 +136,7 @@ class ShowLocationPresenter( location = mode.location, isLive = false, assetType = mode.assetType, + isOwnUser = mode.senderId == joinedRoom.sessionId ) ) } @@ -163,6 +173,7 @@ class ShowLocationPresenter( location = location, isLive = true, assetType = lastLocation.assetType, + isOwnUser = share.userId == joinedRoom.sessionId ) } .toImmutableList() diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt index b6a60f35db..720697cbf7 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt @@ -38,7 +38,10 @@ data class LocationShareItem( val location: Location, val isLive: Boolean, val assetType: AssetType?, -) + val isOwnUser: Boolean +) { + val canStopSharing = isLive && isOwnUser +} fun LocationShareItem.toMarkerData(): LocationMarkerData { val pinVariant = if (assetType == AssetType.PIN) { diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt index 2bbf4ae34e..1c7b9a3160 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt @@ -81,6 +81,7 @@ fun aLocationShareItem( assetType: AssetType? = null, formattedTimestamp: String = "Shared 1 min ago", location: Location = Location(1.23, 2.34, 4f), + isOwnUser: Boolean = false, ) = LocationShareItem( userId = userId, displayName = displayName, @@ -89,4 +90,5 @@ fun aLocationShareItem( location = location, isLive = isLive, assetType = assetType, + isOwnUser = isOwnUser, ) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt index 7ac5946723..6766fa6424 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt @@ -147,6 +147,7 @@ fun ShowLocationView( LocationShareRow( item = locationShare, onShareClick = { state.eventSink(ShowLocationEvent.Share(locationShare.location)) }, + onStopClick = { state.eventSink(ShowLocationEvent.StopLocationSharing) }, modifier = Modifier.clickable { state.eventSink(ShowLocationEvent.TrackMyLocation(false)) val position = CameraPosition( diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt index c8e1f21a48..debe95b464 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt @@ -21,7 +21,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.Success) } @@ -33,7 +33,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.Success) } @@ -45,7 +45,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = false) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.LocationServiceDisabled) } @@ -58,7 +58,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.PermissionRationale) } @@ -71,8 +71,20 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.PermissionDenied) } + + @Test + fun `checkLocationConstraints returns NotEnoughPowerLevel when send permissions are not granted`() { + val permissionsState = aPermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = false, + ) + val locationActions = FakeLocationActions(isLocationEnabled = true) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.DEFAULT) + + assertThat(result).isEqualTo(LocationConstraintsCheck.NotEnoughPowerLevel) + } } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt new file mode 100644 index 0000000000..85f0e1c33f --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.emptyPreferences +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.live.service.LiveLocationSharingCoordinator +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID_2 +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory +import io.element.android.libraries.sessionstorage.api.observer.SessionObserver +import io.element.android.libraries.sessionstorage.test.observer.FakeSessionObserver +import io.element.android.services.toolbox.api.systemclock.SystemClock +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.async +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Instant + +@OptIn(ExperimentalCoroutinesApi::class) +class DefaultActiveLiveLocationShareManagerTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `starting the first share starts the coordinator service after the beacon echo and adds an active share`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder + ) + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val room = FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { givenGetRoomResult(A_ROOM_ID, room) }, + coordinator = coordinator, + clock = FakeSystemClock(epochMillisResult = 123L), + ) + advanceUntilIdle() + + val result = async { manager.startShare(A_ROOM_ID, 60.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + + assertThat(result.await().isSuccess).isTrue() + assertThat(manager.sharingRoomIds.value).containsExactly(A_ROOM_ID) + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isNeverCalled() + } + + @Test + fun `stopping the last share stops the coordinator service`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder + ) + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val room = FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { givenGetRoomResult(A_ROOM_ID, room) }, + coordinator = coordinator, + ) + advanceUntilIdle() + + val startResult = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + val result = manager.stopShare(A_ROOM_ID) + + assertThat(result.isSuccess).isTrue() + assertThat(manager.sharingRoomIds.value).isEmpty() + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isCalledOnce() + } + + @Test + fun `two managers with the same room id keep isolated state per session`() = runTest { + val coordinator = createCoordinator() + val beaconInfoUpdatesOne = MutableSharedFlow(replay = 1) + val beaconInfoUpdatesTwo = MutableSharedFlow(replay = 1) + val managerOne = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdatesOne, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + ) + val managerTwo = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID_2, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdatesTwo, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + ) + advanceUntilIdle() + + val startResult = async { managerOne.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdatesOne.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + assertThat(managerOne.sharingRoomIds.value).containsExactly(A_ROOM_ID) + assertThat(managerTwo.sharingRoomIds.value).isEmpty() + } + + @Test + fun `start share persists room expiry after beacon echo`() = runTest { + val liveLocationStore = createLiveLocationStore() + val coordinator = createCoordinator() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 123L), + ) + advanceUntilIdle() + + val result = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + + assertThat(result.await().isSuccess).isTrue() + assertThat(liveLocationStore.getLiveLocationExpiries()).containsKey(A_ROOM_ID) + } + + @Test + fun `stop share removes persisted expiry`() = runTest { + val liveLocationStore = createLiveLocationStore() + val coordinator = createCoordinator() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + liveLocationStore = liveLocationStore, + ) + advanceUntilIdle() + + val startResult = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + manager.stopShare(A_ROOM_ID) + + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + } + + @Test + fun `setup restores unexpired stored share and registers coordinator`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val liveLocationStore = createLiveLocationStore().apply { + setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(10_000L)) + } + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult(A_ROOM_ID, FakeJoinedRoom()) + }, + coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder, + ), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 1_000L), + ) + + assertThat(manager.sharingRoomIds.value).containsExactly(A_ROOM_ID) + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isNeverCalled() + } + + @Test + fun `setup remotely stops expired stored share and removes it from store`() = runTest { + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val liveLocationStore = createLiveLocationStore().apply { + setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)) + } + createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom(stopLiveLocationShareResult = stopLiveLocationShareResult), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 5_000L), + ) + advanceUntilIdle() + assert(stopLiveLocationShareResult).isCalledOnce() + assertThat(liveLocationStore.getLiveLocationExpiries()).isEmpty() + } + + @Test + fun `stop share closes loaded room and removes persisted expiry when room is not tracked`() = runTest { + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val room = FakeJoinedRoom(stopLiveLocationShareResult = stopLiveLocationShareResult) + val liveLocationStore = createInMemoryLiveLocationStore() + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult(A_ROOM_ID, room) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + ) + liveLocationStore.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(10_000L)) + + val result = manager.stopShare(A_ROOM_ID) + + assertThat(result.isSuccess).isTrue() + assert(stopLiveLocationShareResult).isCalledOnce() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + room.baseRoom.assertDestroyed() + } + + @Test + fun `share is automatically stopped when timeout elapses`() = runTest { + val liveLocationStore = createInMemoryLiveLocationStore() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = stopLiveLocationShareResult + ), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 123L), + ) + advanceUntilIdle() + + val startResult = async { manager.startShare(A_ROOM_ID, 1.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + manager.sharingRoomIds.test { + assertThat(awaitItem()).containsExactly(A_ROOM_ID) + assertThat(awaitItem()).isEmpty() + advanceUntilIdle() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(stopLiveLocationShareResult).isCalledExactly(2) + } + } + + @Test + fun `restored share is automatically stopped when remaining timeout elapses`() = runTest { + val liveLocationStore = createInMemoryLiveLocationStore().apply { + setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(6_000L)) + } + val stopLiveLocationShareLambda = lambdaRecorder> { Result.success(Unit) } + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + stopLiveLocationShareResult = stopLiveLocationShareLambda + ), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 1_000L), + ) + + manager.sharingRoomIds.test { + assertThat(awaitItem()).containsExactly(A_ROOM_ID) + assertThat(awaitItem()).isEmpty() + advanceUntilIdle() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(stopLiveLocationShareLambda).isCalledOnce() + } + } + + @Test + fun `session deleted clears local state`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val liveLocationStore = createInMemoryLiveLocationStore() + val sessionObserver = FakeSessionObserver() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder, + ), + liveLocationStore = liveLocationStore, + sessionObserver = sessionObserver, + ) + advanceUntilIdle() + + val firstStart = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(firstStart.await().isSuccess).isTrue() + + sessionObserver.onSessionDeleted(A_SESSION_ID.value) + advanceUntilIdle() + + assertThat(manager.sharingRoomIds.value).isEmpty() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isCalledOnce() + + val secondStart = async { manager.startShare(A_ROOM_ID, 15.minutes) } + advanceUntilIdle() + assertThat(secondStart.isCompleted).isFalse() + + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(secondStart.await().isSuccess).isTrue() + } + + private suspend fun createManager( + client: FakeMatrixClient = FakeMatrixClient(sessionId = A_SESSION_ID), + coordinator: LiveLocationSharingCoordinator = createCoordinator(), + liveLocationStore: LiveLocationStore = createLiveLocationStore(), + clock: SystemClock = FakeSystemClock(), + sessionObserver: SessionObserver = FakeSessionObserver(), + ): DefaultActiveLiveLocationShareManager { + return DefaultActiveLiveLocationShareManager( + matrixClient = client, + coordinator = coordinator, + liveLocationStore = liveLocationStore, + clock = clock, + sessionObserver = sessionObserver, + ).apply { + setup() + } + } + + private fun createCoordinator( + startService: () -> Unit = {}, + stopService: () -> Unit = {}, + nowMillis: () -> Long = { 0L }, + ): LiveLocationSharingCoordinator { + return LiveLocationSharingCoordinator( + startService = startService, + stopService = stopService, + nowMillis = nowMillis, + ) + } + + private fun createLiveLocationStore( + sessionId: io.element.android.libraries.matrix.api.core.SessionId = A_SESSION_ID, + preferenceDataStoreFactory: PreferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + ): LiveLocationStore { + return LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = sessionId, + ) + } + + private fun createInMemoryLiveLocationStore( + sessionId: io.element.android.libraries.matrix.api.core.SessionId = A_SESSION_ID, + ): LiveLocationStore { + val preferenceDataStoreFactory = object : PreferenceDataStoreFactory { + override fun create(name: String): DataStore { + var preferences: Preferences = emptyPreferences() + return object : DataStore { + override val data: Flow + get() = flowOf(preferences) + + override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences { + preferences = transform(preferences) + return preferences + } + } + } + } + return createLiveLocationStore( + sessionId = sessionId, + preferenceDataStoreFactory = preferenceDataStoreFactory, + ) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt new file mode 100644 index 0000000000..f74322b4c5 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.Location +import io.element.android.features.location.impl.live.service.LiveLocationReceiver +import io.element.android.features.location.impl.live.service.LiveLocationSharingCoordinator +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID_2 +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class LiveLocationSharingCoordinatorTest { + @Test + fun `first registration starts the service and last unregister stops it`() = runTest { + var startCount = 0 + var stopCount = 0 + val coordinator = LiveLocationSharingCoordinator( + startService = { startCount++ }, + stopService = { stopCount++ }, + nowMillis = { 0L }, + ) + + coordinator.register(A_SESSION_ID, LiveLocationReceiver { }) + coordinator.unregister(A_SESSION_ID) + + assertThat(startCount).isEqualTo(1) + assertThat(stopCount).isEqualTo(1) + } + + @Test + fun `dispatch isolates receiver failures and still reaches later receivers`() = runTest { + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { 4_000L }, + ) + + coordinator.register(A_SESSION_ID) { error("boom") } + coordinator.register(A_SESSION_ID_2) { location -> delivered += location } + coordinator.dispatch(Location(lat = 1.0, lon = 2.0, accuracy = 3f)) + + assertThat(delivered).containsExactly(Location(lat = 1.0, lon = 2.0, accuracy = 3f)) + } + + @Test + fun `dispatch delivers first location immediately`() = runTest { + var nowMillis = 4_000L + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { nowMillis }, + ) + + coordinator.register(A_SESSION_ID) { location -> delivered += location } + + val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) + + coordinator.dispatch(firstLocation) + + assertThat(delivered).containsExactly(firstLocation) + } + + @Test + fun `dispatch drops updates inside the throttle window`() = runTest { + var nowMillis = 4_000L + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { nowMillis }, + ) + + coordinator.register(A_SESSION_ID) { location -> delivered += location } + + val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) + val secondLocation = Location(lat = 4.0, lon = 5.0, accuracy = 6f) + + coordinator.dispatch(firstLocation) + nowMillis += 500 + coordinator.dispatch(secondLocation) + + assertThat(delivered).containsExactly(firstLocation) + } + + @Test + fun `dispatch delivers next update after the throttle window elapses`() = runTest { + var nowMillis = 4_000L + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { nowMillis }, + ) + + coordinator.register(A_SESSION_ID) { location -> delivered += location } + + val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) + val secondLocation = Location(lat = 4.0, lon = 5.0, accuracy = 6f) + + coordinator.dispatch(firstLocation) + nowMillis += 3_000 + coordinator.dispatch(secondLocation) + + assertThat(delivered).containsExactly(firstLocation, secondLocation).inOrder() + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt index edd000e02c..9b1a14fb51 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt @@ -13,6 +13,8 @@ import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.features.location.impl.live.LiveLocationStore +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter import io.element.android.libraries.featureflag.test.FakeFeatureFlagService @@ -20,8 +22,10 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -30,16 +34,17 @@ class DefaultShareLocationEntryPointTest { val instantTaskExecutorRule = InstantTaskExecutorRule() @Test - fun `test node builder`() { + fun `test node builder`() = runTest { val entryPoint = DefaultShareLocationEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> + val room = FakeJoinedRoom() ShareLocationNode( buildContext = buildContext, plugins = plugins, presenterFactory = { timelineMode: Timeline.Mode -> ShareLocationPresenter( permissionsPresenterFactory = { FakePermissionsPresenter() }, - room = FakeJoinedRoom(), + room = room, timelineMode = timelineMode, analyticsService = FakeAnalyticsService(), messageComposerContext = FakeMessageComposerContext(), @@ -48,6 +53,11 @@ class DefaultShareLocationEntryPointTest { featureFlagService = FakeFeatureFlagService(), client = FakeMatrixClient(), durationFormatter = FakeDurationFormatter(), + liveLocationShareManager = FakeActiveLiveLocationShareManager(), + liveLocationStore = LiveLocationStore( + preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + sessionId = room.sessionId, + ), ) }, analyticsService = FakeAnalyticsService(), diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index 46bc4a55df..855deba694 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -10,6 +10,9 @@ package io.element.android.features.location.impl.share +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.emptyPreferences import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test @@ -22,28 +25,46 @@ import io.element.android.features.location.impl.common.permissions.FakePermissi import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.impl.live.LiveLocationStore +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration +import kotlin.time.Duration.Companion.hours class ShareLocationPresenterTest { @get:Rule @@ -59,9 +80,11 @@ class ShareLocationPresenterTest { private val durationFormatter = FakeDurationFormatter() - private fun createShareLocationPresenter( + private fun TestScope.createShareLocationPresenter( joinedRoom: JoinedRoom = FakeJoinedRoom(), locationActions: FakeLocationActions = fakeLocationActions, + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), + liveLocationStore: LiveLocationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId), ): ShareLocationPresenter = ShareLocationPresenter( permissionsPresenterFactory = { fakePermissionsPresenter }, room = joinedRoom, @@ -73,6 +96,8 @@ class ShareLocationPresenterTest { featureFlagService = fakeFeatureFlagService, client = fakeMatrixClient, durationFormatter = durationFormatter, + liveLocationShareManager = liveLocationShareManager, + liveLocationStore = liveLocationStore, ) @Test @@ -296,7 +321,15 @@ class ShareLocationPresenterTest { @Test fun `ShowLiveLocationDurationPicker shows duration dialog when constraints pass`() = runTest { - val shareLocationPresenter = createShareLocationPresenter() + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId).apply { + setAcceptedLiveLocationDisclaimer().getOrThrow() + } + val shareLocationPresenter = createShareLocationPresenter(joinedRoom = joinedRoom, liveLocationStore = locationStore) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.AllGranted, @@ -307,7 +340,7 @@ class ShareLocationPresenterTest { shareLocationPresenter.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink(ShareLocationEvent.ShowLiveLocationDurationPicker) + initialState.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val durationDialogState = awaitItem() assertThat(durationDialogState.dialogState).isInstanceOf(ShareLocationState.Dialog.LiveLocationDurations::class.java) @@ -315,9 +348,155 @@ class ShareLocationPresenterTest { } } + @Test + fun `ShowLiveLocationDurationPicker shows disclaimer when acceptance is missing`() = runTest { + val presenter = createShareLocationPresenter() + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val dialogState = awaitItem() + + assertThat(dialogState.dialogState).isEqualTo(ShareLocationState.Dialog.LiveLocationDisclaimer) + } + } + + @Test + fun `AcceptLiveLocationDisclaimer persists acceptance and shows durations`() = runTest { + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId) + val presenter = createShareLocationPresenter(joinedRoom = joinedRoom, liveLocationStore = locationStore) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + awaitItem() + + state.eventSink(ShareLocationEvent.AcceptLiveLocationDisclaimer) + val durationState = awaitItem() + + assertThat(locationStore.hasAcceptedLiveLocationDisclaimer()).isTrue() + assertThat(durationState.dialogState).isInstanceOf(ShareLocationState.Dialog.LiveLocationDurations::class.java) + } + } + + @Test + fun `AcceptLiveLocationDisclaimer keeps disclaimer gate active when persistence fails`() = runTest { + val joinedRoom = FakeJoinedRoom() + val presenter = createShareLocationPresenter( + joinedRoom = joinedRoom, + liveLocationStore = createFailingLiveLocationStore(sessionId = joinedRoom.sessionId), + ) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val disclaimerState = awaitItem() + + disclaimerState.eventSink(ShareLocationEvent.AcceptLiveLocationDisclaimer) + advanceUntilIdle() + + expectNoEvents() + } + } + + @Test + fun `ShowLiveLocationDurationPicker bypasses disclaimer when already accepted`() = runTest { + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId).apply { + setAcceptedLiveLocationDisclaimer().getOrThrow() + } + val presenter = createShareLocationPresenter(joinedRoom = joinedRoom, liveLocationStore = locationStore) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val durationState = awaitItem() + + assertThat(durationState.dialogState).isInstanceOf(ShareLocationState.Dialog.LiveLocationDurations::class.java) + } + } + + @Test + fun `ShowLiveLocationDurationPicker uses the active session disclaimer state`() = runTest { + val joinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(sessionId = SessionId("@alice:server"))) + createLiveLocationStore(sessionId = SessionId("@bob:server")) + .setAcceptedLiveLocationDisclaimer() + .getOrThrow() + val presenter = createShareLocationPresenter( + joinedRoom = joinedRoom, + liveLocationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId), + ) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val dialogState = awaitItem() + + assertThat(dialogState.dialogState).isEqualTo(ShareLocationState.Dialog.LiveLocationDisclaimer) + } + } + @Test fun `ShowLiveLocationDurationPicker shows constraint dialog when permissions denied`() = runTest { - val shareLocationPresenter = createShareLocationPresenter() + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId).apply { + setAcceptedLiveLocationDisclaimer().getOrThrow() + } + val shareLocationPresenter = createShareLocationPresenter( + joinedRoom = joinedRoom, + liveLocationStore = locationStore, + ) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -332,7 +511,7 @@ class ShareLocationPresenterTest { initialState.eventSink(ShareLocationEvent.DismissDialog) val dismissedState = awaitItem() - dismissedState.eventSink(ShareLocationEvent.ShowLiveLocationDurationPicker) + dismissedState.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val constraintDialogState = awaitItem() assertThat(constraintDialogState.dialogState).isEqualTo( @@ -447,4 +626,62 @@ class ShareLocationPresenterTest { cancelAndIgnoreRemainingEvents() } } + + @Test + fun `StartLiveLocationShare event calls manager startShare`() = runTest { + val startShareLambda = lambdaRecorder { _: RoomId, _: Duration -> Result.success(Unit) } + val manager = FakeActiveLiveLocationShareManager( + startShareLambda = startShareLambda, + ) + val shareLocationPresenter = createShareLocationPresenter(liveLocationShareManager = manager) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration = 1.hours)) + advanceUntilIdle() + assert(startShareLambda).isCalledOnce().with( + value(A_ROOM_ID), + value(1.hours) + ) + cancelAndIgnoreRemainingEvents() + } + } } + +private fun createLiveLocationStore( + sessionId: SessionId = A_SESSION_ID, + preferenceDataStoreFactory: PreferenceDataStoreFactory = FakePreferenceDataStoreFactory(), +): LiveLocationStore { + return LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = sessionId, + ) +} + +private fun createFailingLiveLocationStore(sessionId: SessionId = A_SESSION_ID): LiveLocationStore { + val failingPreferenceDataStoreFactory = object : PreferenceDataStoreFactory { + override fun create(name: String): DataStore = object : DataStore { + override val data: Flow = flowOf(emptyPreferences()) + + override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences { + error("Failed to update preferences") + } + } + } + return createLiveLocationStore( + sessionId = sessionId, + preferenceDataStoreFactory = failingPreferenceDataStoreFactory, + ) +} + +private fun grantedSendLiveLocationPermissions(): FakeRoomPermissions = FakeRoomPermissions( + canSendState = { it is StateEventType.BeaconInfo }, + canSendMessage = { it is MessageEventType.Beacon } +) diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt index 63c19ba913..370ccac8ab 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt @@ -143,6 +143,38 @@ class ShareLocationViewTest { clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) } + + @Test + fun `when disclaimer is displayed user can accept`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setShareLocationView( + aShareLocationState( + dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, + eventSink = eventsRecorder, + canShareLiveLocation = true, + ), + navigateUp = EnsureNeverCalled(), + ) + + clickOn(CommonStrings.action_accept) + eventsRecorder.assertSingle(ShareLocationEvent.AcceptLiveLocationDisclaimer) + } + + @Test + fun `when disclaimer is displayed user can decline`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setShareLocationView( + aShareLocationState( + dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, + eventSink = eventsRecorder, + canShareLiveLocation = true, + ), + navigateUp = EnsureNeverCalled(), + ) + + clickOn(CommonStrings.action_decline) + eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) + } } private fun AndroidComposeUiTest.setShareLocationView( diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt index 91df447e2a..985dcc1f9c 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt @@ -16,6 +16,7 @@ import io.element.android.features.location.api.ShowLocationEntryPoint import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.test.core.aBuildMeta @@ -34,6 +35,7 @@ class DefaultShowLocationEntryPointTest { fun `test node builder`() { val entryPoint = DefaultShowLocationEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> + val joinedRoom = FakeJoinedRoom() ShowLocationNode( buildContext = buildContext, plugins = plugins, @@ -45,7 +47,8 @@ class DefaultShowLocationEntryPointTest { buildMeta = aBuildMeta(), dateFormatter = FakeDateFormatter(), stringProvider = FakeStringProvider(), - joinedRoom = FakeJoinedRoom(), + joinedRoom = joinedRoom, + liveLocationShareManager = FakeActiveLiveLocationShareManager(), ) }, analyticsService = FakeAnalyticsService(), diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt index 4042cb4c0c..0b8e04abf8 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt @@ -9,7 +9,7 @@ package io.element.android.features.location.impl.show import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare import org.junit.Test class LiveLocationShareComparatorTest { @@ -55,15 +55,3 @@ class LiveLocationShareComparatorTest { assertThat(sortedShares).containsExactly(newerShare, olderShare).inOrder() } } - -private fun aLiveLocationShare( - userId: UserId, - startTimestamp: Long, -): LiveLocationShare { - return LiveLocationShare( - userId = userId, - lastLocation = null, - startTimestamp = startTimestamp, - endTimestamp = startTimestamp + 1_000L, - ) -} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index f38e8dae60..c1f9f6487e 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -20,14 +20,15 @@ import io.element.android.features.location.impl.common.permissions.FakePermissi import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.location.AssetType -import io.element.android.libraries.matrix.api.room.location.LastLocation import io.element.android.libraries.matrix.api.room.location.LiveLocationShare import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test @@ -60,6 +61,7 @@ class ShowLocationPresenterTest { ), locationActions: FakeLocationActions = fakeLocationActions, joinedRoom: JoinedRoom = FakeJoinedRoom(), + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ) = ShowLocationPresenter( mode = mode, permissionsPresenterFactory = { fakePermissionsPresenter }, @@ -68,6 +70,7 @@ class ShowLocationPresenterTest { dateFormatter = fakeDateFormatter, stringProvider = FakeStringProvider(), joinedRoom = joinedRoom, + liveLocationShareManager = liveLocationShareManager, ) @Test @@ -205,7 +208,7 @@ class ShowLocationPresenterTest { ) ) val presenter = createShowLocationPresenter() - presenter.test { + presenter.test { // Skip initial state val initialState = awaitItem() @@ -464,23 +467,3 @@ class ShowLocationPresenterTest { } } } - -private fun aLiveLocationShare( - userId: UserId, - geoUri: String = "geo:48.8584,2.2945", - timestamp: Long = 0L, - startTimestamp: Long = 0L, - endTimestamp: Long = Long.MAX_VALUE, - assetType: AssetType = AssetType.SENDER, -): LiveLocationShare { - return LiveLocationShare( - userId = userId, - lastLocation = LastLocation( - geoUri = geoUri, - timestamp = timestamp, - assetType = assetType, - ), - startTimestamp = startTimestamp, - endTimestamp = endTimestamp, - ) -} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt new file mode 100644 index 0000000000..c42469e705 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.store + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.mutablePreferencesOf +import androidx.datastore.preferences.core.stringPreferencesKey +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.live.LiveLocationStore +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import org.junit.Test +import kotlin.time.Instant + +class LiveLocationStoreTest { + private val preferenceDataStoreFactory = FakePreferenceDataStoreFactory() + + @Test + fun `disclaimer defaults to false`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + assertThat(store.hasAcceptedLiveLocationDisclaimer()).isFalse() + } + + @Test + fun `disclaimer acceptance is isolated per session`() = runTest { + val firstStore = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + val secondStore = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = SessionId("@other:server"), + ) + + firstStore.setAcceptedLiveLocationDisclaimer().getOrThrow() + + assertThat(firstStore.hasAcceptedLiveLocationDisclaimer()).isTrue() + assertThat(secondStore.hasAcceptedLiveLocationDisclaimer()).isFalse() + } + + @Test + fun `can persist and read expiry per room`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)).getOrThrow() + + assertThat(store.getLiveLocationExpiries()) + .containsExactly(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)) + } + + @Test + fun `removing one expiry leaves others untouched`() = runTest { + val otherRoomId = RoomId("!other:server") + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)).getOrThrow() + store.setLiveLocationExpiry(otherRoomId, Instant.fromEpochMilliseconds(2_000L)).getOrThrow() + store.removeLiveLocationExpiry(A_ROOM_ID).getOrThrow() + + assertThat(store.getLiveLocationExpiries()) + .containsExactly(otherRoomId, Instant.fromEpochMilliseconds(2_000L)) + } + + @Test + fun `setting expiry twice replaces the existing room value`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)).getOrThrow() + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(2_000L)).getOrThrow() + + assertThat(store.getLiveLocationExpiries()) + .containsExactly(A_ROOM_ID, Instant.fromEpochMilliseconds(2_000L)) + } + + @Test + fun `malformed expiry payload returns empty map`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = createMalformedExpiryPreferenceDataStoreFactory(), + sessionId = A_SESSION_ID, + ) + + assertThat(store.getLiveLocationExpiries()).isEmpty() + } + + private fun createMalformedExpiryPreferenceDataStoreFactory(): PreferenceDataStoreFactory { + return object : PreferenceDataStoreFactory { + override fun create(name: String): DataStore { + var preferences: Preferences = mutablePreferencesOf( + stringPreferencesKey("live_location_expiries") to "not valid" + ) + return object : DataStore { + override val data: Flow + get() = flowOf(preferences) + + override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences { + preferences = transform(preferences) + return preferences + } + } + } + } + } +} diff --git a/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt new file mode 100644 index 0000000000..255c181ac1 --- /dev/null +++ b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.test + +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.simulateLongTask +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlin.time.Duration + +class FakeActiveLiveLocationShareManager( + val setupLambda: () -> Unit = { lambdaError() }, + val startShareLambda: (roomId: RoomId, duration: Duration) -> Result = { _, _ -> lambdaError() }, + val stopShareLambda: (roomId: RoomId) -> Result = { _ -> lambdaError() }, +) : ActiveLiveLocationShareManager { + private val _sharingRoomIds = MutableStateFlow(emptySet()) + override val sharingRoomIds: StateFlow> = _sharingRoomIds + + override suspend fun setup() { + setupLambda() + } + + override suspend fun startShare(roomId: RoomId, duration: Duration): Result = simulateLongTask { + startShareLambda(roomId, duration).onSuccess { + _sharingRoomIds.update { + it + roomId + } + } + } + + override suspend fun stopShare(roomId: RoomId): Result = simulateLongTask { + stopShareLambda(roomId).onSuccess { + _sharingRoomIds.update { + it - roomId + } + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt index bef8ca84d6..4d621e417f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt @@ -18,6 +18,8 @@ sealed interface MessagesEvent { data class ToggleReaction(val emoji: String, val eventOrTransactionId: EventOrTransactionId) : MessagesEvent data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvent data class OnUserClicked(val user: MatrixUser) : MessagesEvent + data object StopLiveLocationShare : MessagesEvent + data object ShowLiveLocationShare : MessagesEvent data object MarkAsFullyReadAndExit : MessagesEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index ff46ce0041..d20dc4b38e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -278,6 +278,10 @@ class MessagesFlowNode( backstack.push(NavTarget.EditPoll(Timeline.Mode.Live, eventId)) } + override fun navigateToCurrentLiveLocation() { + backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + } + override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { val callData = CallData( sessionId = sessionId, @@ -513,6 +517,10 @@ class MessagesFlowNode( backstack.push(NavTarget.EditPoll(Timeline.Mode.Thread(navTarget.threadRootId), eventId)) } + override fun navigateToCurrentLiveLocation() { + backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + } + override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { val callData = CallData( sessionId = sessionId, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt index e475f579c3..6113b68aab 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt @@ -26,5 +26,6 @@ interface MessagesNavigator { fun navigateToMember(userId: UserId) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToDeveloperSettings() + fun navigateToCurrentLiveLocation() fun close() } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index 308cda506e..a9ce2f5ba1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -127,6 +127,7 @@ class MessagesNode( fun navigateToSendLocation() fun navigateToCreatePoll() fun navigateToEditPoll(eventId: EventId) + fun navigateToCurrentLiveLocation() fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToRoomDetails() @@ -239,6 +240,10 @@ class MessagesNode( callback.navigateToDeveloperSettings() } + override fun navigateToCurrentLiveLocation() { + callback.navigateToCurrentLiveLocation() + } + private fun displaySameRoomToast() { context.toast(CommonStrings.screen_room_permalink_same_room_android) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 5271906fff..1d6f1d3c1b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -27,6 +27,8 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.PinUnpinAction import io.element.android.appconfig.MessageComposerConfig +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.features.location.api.live.isCurrentlySharing import io.element.android.features.messages.api.timeline.HtmlConverterProvider import io.element.android.features.messages.impl.MessagesState.Threads import io.element.android.features.messages.impl.actionlist.ActionListState @@ -79,6 +81,7 @@ import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState +import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.ui.messages.reply.map import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -126,6 +129,7 @@ class MessagesPresenter( private val featureFlagService: FeatureFlagService, private val addRecentEmoji: AddRecentEmoji, private val markAsFullyRead: MarkAsFullyRead, + private val liveLocationShareManager: ActiveLiveLocationShareManager, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, ) : Presenter { @AssistedFactory @@ -172,6 +176,7 @@ class MessagesPresenter( } val canOpenThreadList by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomThreadList).collectAsState(initial = false) + val isCurrentlySharingLiveLocationInRoom by remember { liveLocationShareManager.isCurrentlySharing(room.roomId) }.collectAsState() val userEventPermissions by room.permissionsAsState(UserEventPermissions.DEFAULT) { perms -> perms.userEventPermissions() @@ -260,6 +265,18 @@ class MessagesPresenter( is MessagesEvent.OnUserClicked -> { roomMemberModerationState.eventSink(RoomMemberModerationEvents.ShowActionsForUser(event.user)) } + MessagesEvent.StopLiveLocationShare -> { + localCoroutineScope.launch { + liveLocationShareManager.stopShare(room.roomId) + .onFailure { + Timber.e(it, "Failed to stop live location share for roomId=${room.roomId}") + snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_error)) + } + } + } + MessagesEvent.ShowLiveLocationShare -> { + navigator.navigateToCurrentLiveLocation() + } is MessagesEvent.MarkAsFullyReadAndExit -> if (!markingAsReadAndExiting.getAndSet(true)) { coroutineScope.launch { val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { @@ -311,6 +328,7 @@ class MessagesPresenter( // TODO calculate this properly based on the thread list and the read state of each thread hasUnreadThreads = false, ), + showLiveLocationShareBanner = isCurrentlySharingLiveLocationInRoom && timelineState.timelineMode !is Timeline.Mode.Thread, eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 862f30832b..a16485c6f7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -58,6 +58,7 @@ data class MessagesState( val topBarSharedHistoryIcon: SharedHistoryIcon, val successorRoom: SuccessorRoom?, val threads: Threads, + val showLiveLocationShareBanner: Boolean, val eventSink: (MessagesEvent) -> Unit ) { val isTombstoned = successorRoom != null diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 14c83db833..6389089e07 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -80,6 +80,7 @@ open class MessagesStateProvider : PreviewParameterProvider { currentPinnedMessageIndex = 0, ), ), + aMessagesState(isCurrentlySharingLiveLocationInRoom = true), aMessagesState(successorRoom = SuccessorRoom(RoomId("!id:domain"), null)), aMessagesState( timelineState = aTimelineState( @@ -127,6 +128,7 @@ fun aMessagesState( hasThreads = false, hasUnreadThreads = false, ), + isCurrentlySharingLiveLocationInRoom: Boolean = false, eventSink: (MessagesEvent) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), @@ -156,6 +158,7 @@ fun aMessagesState( topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = successorRoom, threads = threads, + showLiveLocationShareBanner = isCurrentlySharingLiveLocationInRoom, eventSink = eventSink, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 5a0b14b820..3e6f14e805 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -56,6 +56,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.location.api.LiveLocationSharingBanner import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerEvent import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListView @@ -205,15 +206,15 @@ fun MessagesView( val expandableState = rememberExpandableBottomSheetLayoutState() ExpandableBottomSheetLayout( modifier = modifier - .fillMaxSize() - .imePadding() - .systemBarsPadding() - .onSizeChanged { size -> - // Let the composer takes at max half of the available height. - // The value will be different if the soft keyboard is displayed - // or not. - maxComposerHeightPx = (size.height * 0.5f).toInt() - }, + .fillMaxSize() + .imePadding() + .systemBarsPadding() + .onSizeChanged { size -> + // Let the composer takes at max half of the available height. + // The value will be different if the soft keyboard is displayed + // or not. + maxComposerHeightPx = (size.height * 0.5f).toInt() + }, content = { Scaffold( contentWindowInsets = WindowInsets.statusBars, @@ -250,8 +251,8 @@ fun MessagesView( content = { padding -> Box( modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + .padding(padding) + .consumeWindowInsets(padding) ) { MessagesViewContent( state = state, @@ -288,10 +289,10 @@ fun MessagesView( SuggestionsPickerView( modifier = Modifier - .shadow(10.dp) - .background(ElementTheme.colors.bgCanvasDefault) - .align(Alignment.BottomStart) - .heightIn(max = 230.dp), + .shadow(10.dp) + .background(ElementTheme.colors.bgCanvasDefault) + .align(Alignment.BottomStart) + .heightIn(max = 230.dp), roomId = state.roomId, roomName = state.roomName, roomAvatarData = state.roomAvatar, @@ -467,9 +468,9 @@ private fun MessagesViewContent( ) { Box( modifier = modifier - .fillMaxSize() - .navigationBarsPadding() - .imePadding(), + .fillMaxSize() + .navigationBarsPadding() + .imePadding(), ) { AttachmentsBottomSheet( state = state.composerState, @@ -520,25 +521,34 @@ private fun MessagesViewContent( ) if (state.timelineState.timelineMode !is Timeline.Mode.Thread) { - AnimatedVisibility( - visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, - modifier = Modifier.onSizeChanged { pinnedBannerHeightDp = with(density) { it.height.toDp() } }, - enter = expandVertically(), - exit = shrinkVertically(), - ) { - fun focusOnPinnedEvent(eventId: EventId) { - state.timelineState.eventSink( - TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + Column { + AnimatedVisibility( + visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, + modifier = Modifier.onSizeChanged { pinnedBannerHeightDp = with(density) { it.height.toDp() } }, + enter = expandVertically(), + exit = shrinkVertically(), + ) { + fun focusOnPinnedEvent(eventId: EventId) { + state.timelineState.eventSink( + TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + ) + } + PinnedMessagesBannerView( + state = state.pinnedMessagesBannerState, + onClick = ::focusOnPinnedEvent, + onViewAllClick = onViewAllPinnedMessagesClick, + ) + } + if (state.showLiveLocationShareBanner) { + LiveLocationSharingBanner( + onClick = { state.eventSink(MessagesEvent.ShowLiveLocationShare) }, + onStopClick = { state.eventSink(MessagesEvent.StopLiveLocationShare) } ) } - PinnedMessagesBannerView( - state = state.pinnedMessagesBannerState, - onClick = ::focusOnPinnedEvent, - onViewAllClick = onViewAllPinnedMessagesClick, - ) } - knockRequestsBannerView() } + + knockRequestsBannerView() } } } @@ -587,9 +597,9 @@ private fun MessagesViewComposerBottomSheetContents( private fun CantSendMessageBanner() { Row( modifier = Modifier - .fillMaxWidth() - .background(ElementTheme.colors.bgSubtleSecondary) - .padding(16.dp), + .fillMaxWidth() + .background(ElementTheme.colors.bgSubtleSecondary) + .padding(16.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index a69c6d7612..56bac5be33 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -15,6 +15,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser import io.element.android.features.messages.impl.crypto.sendfailure.resolve.anUnsignedDeviceSendFailure import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions +import io.element.android.features.messages.impl.timeline.model.event.aStaticLocationMode import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent @@ -127,7 +128,7 @@ open class ActionListStateProvider : PreviewParameterProvider { anActionListState( target = ActionListState.Target.Success( event = aTimelineItemEvent( - content = aTimelineItemLocationContent(), + content = aTimelineItemLocationContent(mode = aStaticLocationMode()), timelineItemReactions = reactionsState ), sentTimeFull = "January 1, 1970 at 12:00 AM", @@ -140,7 +141,7 @@ open class ActionListStateProvider : PreviewParameterProvider { anActionListState( target = ActionListState.Target.Success( event = aTimelineItemEvent( - content = aTimelineItemLocationContent(), + content = aTimelineItemLocationContent(mode = aStaticLocationMode()), timelineItemReactions = reactionsState ), sentTimeFull = "January 1, 1970 at 12:00 AM", diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 0c58316b5e..63ce48e100 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -136,6 +136,7 @@ class ThreadedMessagesNode( fun navigateToSendLocation() fun navigateToCreatePoll() fun navigateToEditPoll(eventId: EventId) + fun navigateToCurrentLiveLocation() fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToDeveloperSettings() @@ -248,6 +249,11 @@ class ThreadedMessagesNode( callback.navigateToDeveloperSettings() } + override fun navigateToCurrentLiveLocation() { + // Shouldn't happen because LiveLocationSharingBanner is not shown in threads. + callback.navigateToCurrentLiveLocation() + } + override fun close() = navigateUp() @Composable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index edd8d446dc..faa4aabe8e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.messages.impl.MessagesNavigator import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvent @@ -94,6 +95,7 @@ class TimelinePresenter( private val roomCallStatePresenter: Presenter, private val featureFlagService: FeatureFlagService, private val analyticsService: AnalyticsService, + private val liveLocationShareManager: ActiveLiveLocationShareManager, ) : Presenter { private val tag = "TimelinePresenter" @@ -200,7 +202,9 @@ class TimelinePresenter( is TimelineEvent.EditPoll -> { navigator.navigateToEditPoll(event.pollStartId) } - is TimelineEvent.StopLiveLocationShare -> Unit + is TimelineEvent.StopLiveLocationShare -> sessionCoroutineScope.launch { + liveLocationShareManager.stopShare(room.roomId) + } is TimelineEvent.FocusOnEvent -> sessionCoroutineScope.launch { focusRequestState.value = FocusRequestState.Requested(event.eventId, event.debounce) delay(event.debounce) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 5785627564..936028cbd6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -783,7 +783,7 @@ private fun MessageEventBubbleContent( val content = content.ensureActiveLiveLocation() val shouldHide = content.mode is TimelineItemLocationContent.Mode.Live && content.mode.isActive && - content.mode.canStop + content.mode.isOwnUser if (shouldHide) TimestampPosition.Hidden else TimestampPosition.Overlay } is TimelineItemPollContent -> TimestampPosition.Below diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt index f00b6b0b5b..4ab4ee84a6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt @@ -13,14 +13,12 @@ import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -77,13 +75,14 @@ private fun LiveLocationOverlay( Row( modifier = modifier .fillMaxWidth() - .background(ElementTheme.colors.bgCanvasDefault.copy(alpha = 0.9f)) - .padding(horizontal = 8.dp, vertical = 8.dp), + .background(ElementTheme.colors.bgCanvasDefault.copy(alpha = 0.9f)), verticalAlignment = Alignment.CenterVertically, ) { val iconShape = RoundedCornerShape(8.dp) Box( modifier = Modifier + // Ensure this Box uses same spacings than the Stop IconButton. + .minimumInteractiveComponentSize() .size(32.dp) .border( width = 1.dp, @@ -120,7 +119,6 @@ private fun LiveLocationOverlay( ) } } - Spacer(Modifier.width(8.dp)) Column(modifier = Modifier.weight(1f)) { Text( text = if (mode.isActive) { @@ -140,13 +138,16 @@ private fun LiveLocationOverlay( } } - if (mode.isActive && mode.canStop) { + if (mode.canStopSharing) { IconButton( onClick = onStopClick, colors = IconButtonDefaults.iconButtonColors( containerColor = ElementTheme.colors.bgCriticalPrimary, contentColor = ElementTheme.colors.iconOnSolidPrimary, - ) + ), + modifier = Modifier + .minimumInteractiveComponentSize() + .size(30.dp) ) { Icon( imageVector = CompoundIcons.Stop(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt index 7c36521fc0..0d51d9f5b8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt @@ -8,7 +8,9 @@ package io.element.android.features.messages.impl.timeline.di +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent +import io.element.android.features.messages.impl.timeline.model.event.ensureActiveLiveLocation import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.voiceplayer.api.VoiceMessageState import io.element.android.libraries.voiceplayer.api.aVoiceMessageState @@ -18,6 +20,12 @@ import io.element.android.libraries.voiceplayer.api.aVoiceMessageState */ fun aFakeTimelineItemPresenterFactories() = TimelineItemPresenterFactories( mapOf( + Pair( + TimelineItemLocationContent::class, + TimelineItemPresenterFactory { content -> + Presenter { content.ensureActiveLiveLocation() } + }, + ), Pair( TimelineItemVoiceContent::class, TimelineItemPresenterFactory { Presenter { aVoiceMessageState() } }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt index dff195e833..11f6668dfb 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 @@ -127,6 +127,7 @@ class TimelineItemContentFactory( isActive = itemContent.isLive, endsAt = stringProvider.getString(CommonStrings.common_ends_at, endsAt), endTimestamp = itemContent.endTimestamp, + isOwnUser = sessionId == sender ), ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt index 44dd2df38d..52e008e121 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt @@ -27,7 +27,7 @@ class TimelineItemEventContentProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aTimelineItemLocationContent(), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = true, - endsAt = "Ends at 12:34", - endTimestamp = 0L, - canStop = true, - lastKnownLocation = aLocation() - ), + mode = aStaticLocationMode() ), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = true, - endsAt = "Ends at 12:34", - endTimestamp = 0L, - lastKnownLocation = aLocation() - ), + mode = aLiveLocationMode(isActive = true) ), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = true, - endsAt = "Ends at 12:34", - endTimestamp = 0L, - lastKnownLocation = null - ), + mode = aLiveLocationMode(isActive = true, lastKnownLocation = null) ), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = false, - endsAt = "", - endTimestamp = 0L, - lastKnownLocation = aLocation() - ), + mode = aLiveLocationMode(isActive = true, isOwnUser = false) + ), + aTimelineItemLocationContent( + mode = aLiveLocationMode(isActive = false) ), ) } +fun aLiveLocationMode( + isActive: Boolean, + isOwnUser: Boolean = true, + lastKnownLocation: Location? = aLocation(), + endsAt: String = "Ends at 12:34", + endTimestamp: Long = 0L, +): TimelineItemLocationContent.Mode = TimelineItemLocationContent.Mode.Live( + isActive = isActive, + endsAt = endsAt, + endTimestamp = endTimestamp, + isOwnUser = isOwnUser, + lastKnownLocation = lastKnownLocation +) + +fun aStaticLocationMode(location: Location = aLocation()) = TimelineItemLocationContent.Mode.Static(location) fun aTimelineItemLocationContent( senderId: UserId = UserId("@sender:matrix.org"), senderProfile: ProfileDetails = aProfileDetailsReady(), description: String? = null, - mode: TimelineItemLocationContent.Mode = TimelineItemLocationContent.Mode.Static(aLocation()), + mode: TimelineItemLocationContent.Mode, ) = TimelineItemLocationContent( senderId = senderId, senderProfile = senderProfile, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt index 44d82f1a7c..68f9a8d17a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt @@ -28,6 +28,7 @@ class FakeMessagesNavigator( private val navigateToDeveloperSettingsLambda: () -> Unit = { lambdaError() }, private val onOpenThreadLambda: (threadRootId: ThreadId, focusedEventId: EventId?) -> Unit = { _, _ -> lambdaError() }, private val closeLambda: () -> Unit = { lambdaError() }, + private val navigateToCurrentLiveLocationLambda: () -> Unit = { lambdaError() }, ) : MessagesNavigator { override fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) { onShowEventDebugInfoClickLambda(eventId, debugInfo) @@ -65,6 +66,10 @@ class FakeMessagesNavigator( navigateToDeveloperSettingsLambda() } + override fun navigateToCurrentLiveLocation() { + navigateToCurrentLiveLocationLambda() + } + override fun close() { closeLambda() } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 50bacb005f..0c836e6cc0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -13,6 +13,7 @@ package io.element.android.features.messages.impl import androidx.lifecycle.Lifecycle import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.PinUnpinAction +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState @@ -120,6 +121,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds @Suppress("LargeClass") class MessagesPresenterTest { @@ -140,6 +142,39 @@ class MessagesPresenterTest { assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.inviteProgress).isEqualTo(AsyncData.Uninitialized) assertThat(initialState.showReinvitePrompt).isFalse() + assertThat(initialState.showLiveLocationShareBanner).isFalse() + } + } + + @Test + fun `present - exposes live location sharing banner visibility for current room`() = runTest { + val liveLocationShareManager = FakeActiveLiveLocationShareManager( + startShareLambda = { _, _ -> Result.success(Unit) }, + ) + liveLocationShareManager.startShare(A_ROOM_ID, 60.seconds) + val presenter = createMessagesPresenter(liveLocationShareManager = liveLocationShareManager) + + presenter.testWithLifecycleOwner { + val state = consumeItemsUntilTimeout().last() + assertThat(state.showLiveLocationShareBanner).isTrue() + } + } + + @Test + fun `present - stop live location share delegates to manager for current room`() = runTest { + val stopShareLambda = lambdaRecorder> { Result.success(Unit) } + val liveLocationShareManager = FakeActiveLiveLocationShareManager( + stopShareLambda = stopShareLambda + ) + val presenter = createMessagesPresenter(liveLocationShareManager = liveLocationShareManager) + + presenter.testWithLifecycleOwner { + val state = consumeItemsUntilTimeout().last() + state.eventSink(MessagesEvent.StopLiveLocationShare) + advanceUntilIdle() + assert(stopShareLambda) + .isCalledOnce() + .with(value(A_ROOM_ID)) } } @@ -1347,6 +1382,7 @@ class MessagesPresenterTest { actionListEventSink: (ActionListEvent) -> Unit = {}, addRecentEmoji: AddRecentEmoji = AddRecentEmoji { _ -> lambdaError() }, markAsFullyRead: MarkAsFullyRead = FakeMarkAsFullyRead(), + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ): MessagesPresenter { return MessagesPresenter( navigator = navigator, @@ -1376,6 +1412,7 @@ class MessagesPresenterTest { featureFlagService = featureFlagService, addRecentEmoji = addRecentEmoji, markAsFullyRead = markAsFullyRead, + liveLocationShareManager = liveLocationShareManager, sessionCoroutineScope = backgroundScope, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 70ef70325e..be44c64a5a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -643,6 +643,44 @@ class MessagesViewTest { assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_message) assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_action) } + + @Test + fun `live location banner is visible when current room is sharing`() = runAndroidComposeUiTest { + val state = aMessagesState(isCurrentlySharingLiveLocationInRoom = true) + setMessagesView(state = state) + onNodeWithText(activity!!.getString(CommonStrings.screen_room_live_location_banner)).assertExists() + } + + @Test + fun `live location banner is hidden when current room is not sharing`() = runAndroidComposeUiTest { + val state = aMessagesState(isCurrentlySharingLiveLocationInRoom = false) + setMessagesView(state = state) + onNodeWithText(activity!!.getString(CommonStrings.screen_room_live_location_banner)).assertDoesNotExist() + } + + @Test + fun `clicking stop on live location banner emits expected event`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + val state = aMessagesState( + isCurrentlySharingLiveLocationInRoom = true, + eventSink = eventsRecorder, + ) + setMessagesView(state = state) + clickOn(CommonStrings.action_stop) + eventsRecorder.assertSingle(MessagesEvent.StopLiveLocationShare) + } + + @Test + fun `clicking live location banner emit expected event`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + val state = aMessagesState( + isCurrentlySharingLiveLocationInRoom = true, + eventSink = eventsRecorder, + ) + setMessagesView(state = state) + clickOn(CommonStrings.screen_room_live_location_banner) + eventsRecorder.assertSingle(MessagesEvent.ShowLiveLocationShare) + } } private fun AndroidComposeUiTest.setMessagesView( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 194694714b..af37fb61ef 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.timeline import app.cash.turbine.ReceiveTurbine import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.impl.FakeMessagesNavigator import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.fixtures.aMessageEvent @@ -1012,6 +1013,7 @@ class TimelinePresenterTest { sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(), featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ): TimelinePresenter { return TimelinePresenter( timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(), @@ -1030,6 +1032,7 @@ class TimelinePresenterTest { roomCallStatePresenter = { aStandByCallState() }, featureFlagService = featureFlagService, analyticsService = FakeAnalyticsService(), + liveLocationShareManager = liveLocationShareManager, ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt index b3fb68fe05..ef27c499af 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt @@ -20,4 +20,5 @@ sealed interface AdvancedSettingsEvents { data class SetTheme(val theme: ThemeOption) : AdvancedSettingsEvents data class SetTimelineMediaPreviewValue(val value: MediaPreviewValue) : AdvancedSettingsEvents data class SetHideInviteAvatars(val value: Boolean) : AdvancedSettingsEvents + data class SetLiveLocationMinimumDistanceUpdate(val value: Int) : AdvancedSettingsEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt index e58706e9fe..96b1cddc94 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt @@ -10,12 +10,14 @@ package io.element.android.features.preferences.impl.advanced import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode +import io.element.android.libraries.androidutils.system.openAppSettingsPage import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) @@ -28,10 +30,12 @@ class AdvancedSettingsNode( @Composable override fun View(modifier: Modifier) { val state = presenter.present() + val context = LocalContext.current AdvancedSettingsView( state = state, modifier = modifier, - onBackClick = ::navigateUp + onBackClick = ::navigateUp, + onOpenAppSettingsClick = context::openAppSettingsPage ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt index ae32bb01a5..3d1fb3b0c7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt @@ -25,8 +25,11 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch @Inject @@ -53,6 +56,19 @@ class AdvancedSettingsPresenter( appPreferencesStore.getThemeFlow().mapToTheme(isBlackThemeAllowed) }.collectAsState(initial = Theme.System) + @OptIn(ExperimentalCoroutinesApi::class) + val liveLocationMinimumDistanceUpdate by produceState(null) { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.LiveLocationSharing) + .flatMapLatest { isEnabled -> + if (isEnabled) { + appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() + } else { + emptyFlow() + } + } + .collect { value = it } + } + val mediaPreviewConfigState = mediaPreviewConfigStateStore.state() val themeOption by remember { @@ -117,6 +133,9 @@ class AdvancedSettingsPresenter( } is AdvancedSettingsEvents.SetHideInviteAvatars -> mediaPreviewConfigStateStore.setHideInviteAvatars(event.value) is AdvancedSettingsEvents.SetTimelineMediaPreviewValue -> mediaPreviewConfigStateStore.setTimelineMediaPreviewValue(event.value) + is AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate -> sessionCoroutineScope.launch { + appPreferencesStore.setLiveLocationMinimumDistanceInMetersUpdate(event.value) + } is AdvancedSettingsEvents.SetCompressImages -> sessionCoroutineScope.launch { sessionPreferencesStore.setOptimizeImages(event.compress) } @@ -133,6 +152,7 @@ class AdvancedSettingsPresenter( theme = themeOption, availableThemeOptions = availableThemeOptions, mediaPreviewConfigState = mediaPreviewConfigState, + liveLocationMinimumDistanceUpdate = liveLocationMinimumDistanceUpdate, eventSink = ::handleEvent, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt index 0525130048..1deb972abc 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 @@ -23,6 +23,7 @@ data class AdvancedSettingsState( val theme: ThemeOption, val availableThemeOptions: ImmutableList, val mediaPreviewConfigState: MediaPreviewConfigState, + val liveLocationMinimumDistanceUpdate: Int?, 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 87df614074..2df59e3ced 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt @@ -41,6 +41,7 @@ fun aAdvancedSettingsState( availableThemeOptions: ImmutableList = ThemeOption.entries.toImmutableList(), hideInviteAvatars: Boolean = false, timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On, + liveLocationMinimumDistanceUpdate: Int? = 50, setTimelineMediaPreviewAction: AsyncAction = AsyncAction.Uninitialized, setHideInviteAvatarsAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (AdvancedSettingsEvents) -> Unit = {}, @@ -56,5 +57,6 @@ fun aAdvancedSettingsState( setTimelineMediaPreviewAction = setTimelineMediaPreviewAction, setHideInviteAvatarsAction = setHideInviteAvatarsAction ), + liveLocationMinimumDistanceUpdate = liveLocationMinimumDistanceUpdate, eventSink = eventSink ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt index 230f5fa739..af28e3443f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt @@ -8,15 +8,24 @@ package io.element.android.features.preferences.impl.advanced +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.SliderDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp import im.vector.app.features.analytics.plan.Interaction import io.element.android.compound.theme.ElementTheme import io.element.android.features.preferences.impl.R @@ -33,10 +42,12 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.text.stringWithLink import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListSectionHeader import io.element.android.libraries.designsystem.theme.components.ListSupportingText import io.element.android.libraries.designsystem.theme.components.ListSupportingTextDefaults +import io.element.android.libraries.designsystem.theme.components.Slider import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost @@ -47,11 +58,13 @@ import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.compose.LocalAnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction +import kotlin.math.roundToInt @Composable fun AdvancedSettingsView( state: AdvancedSettingsState, onBackClick: () -> Unit, + onOpenAppSettingsClick: () -> Unit, modifier: Modifier = Modifier, ) { val analyticsService = LocalAnalyticsService.current @@ -190,6 +203,15 @@ fun AdvancedSettingsView( } ModerationAndSafety(state) + if (state.liveLocationMinimumDistanceUpdate != null) { + LiveLocationUpdatesSection( + value = state.liveLocationMinimumDistanceUpdate, + onValueSaved = { value -> + state.eventSink(AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate(value)) + }, + onOpenAppPermissionsClick = onOpenAppSettingsClick, + ) + } } } @@ -314,6 +336,78 @@ private fun ModerationAndSafety( } } +@Composable +private fun LiveLocationUpdatesSection( + value: Int, + onValueSaved: (Int) -> Unit, + onOpenAppPermissionsClick: () -> Unit, + modifier: Modifier = Modifier, +) { + PreferenceCategory( + modifier = modifier, + showTopDivider = true, + ) { + ListSectionHeader( + title = stringResource(R.string.screen_advanced_settings_live_location_section_title), + description = { + ListSupportingText( + text = stringResource(R.string.screen_advanced_settings_live_location_section_description), + contentPadding = ListSupportingTextDefaults.Padding.None, + ) + } + ) + var sliderValue by remember(value) { mutableIntStateOf(value) } + Column( + modifier = Modifier.padding(vertical = 12.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + text = pluralStringResource( + R.plurals.screen_advanced_settings_live_location_update_distance, + sliderValue, + sliderValue, + ), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textPrimary, + ) + val valueRange = 1f..100f + val start = valueRange.start.toInt() + val end = valueRange.endInclusive.toInt() + Row(verticalAlignment = Alignment.CenterVertically) { + Text("${start}m", color = ElementTheme.colors.textSecondary, style = ElementTheme.typography.fontBodyMdRegular) + Slider( + modifier = Modifier + .weight(1f) + .padding(horizontal = 12.dp), + value = sliderValue.toFloat(), + onValueChange = { sliderValue = it.roundToInt() }, + onValueChangeFinish = { + onValueSaved(sliderValue) + }, + valueRange = valueRange, + colors = SliderDefaults.colors( + thumbColor = ElementTheme.colors.iconAccentPrimary, + activeTrackColor = ElementTheme.colors.iconAccentPrimary, + inactiveTrackColor = ElementTheme.colors.bgBadgeAccent, + inactiveTickColor = ElementTheme.colors.iconAccentPrimary, + ) + ) + Text("${end}m", color = ElementTheme.colors.textSecondary, style = ElementTheme.typography.fontBodyMdRegular) + } + } + val footerText = stringWithLink( + textRes = R.string.screen_advanced_settings_live_location_section_footer, + url = "", + linkTextRes = R.string.screen_advanced_settings_live_location_section_footer_link, + onLinkClick = { onOpenAppPermissionsClick() }, + ) + ListSupportingText( + annotatedString = footerText, + contentPadding = ListSupportingTextDefaults.Padding.Default, + ) + } +} + @PreviewWithLargeHeight @Composable internal fun AdvancedSettingsViewLightPreview(@PreviewParameter(AdvancedSettingsStateProvider::class) state: AdvancedSettingsState) = @@ -334,7 +428,8 @@ internal fun AdvancedSettingsViewBlackPreview(@PreviewParameter(AdvancedSettings private fun ContentToPreview(state: AdvancedSettingsState) { AdvancedSettingsView( state = state, - onBackClick = { } + onBackClick = { }, + onOpenAppSettingsClick = {} ) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt index fe121e4fe9..27d91bd8de 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.media.MediaPreviewValue +import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore @@ -209,6 +210,72 @@ class AdvancedSettingsPresenterTest { } } + @Test + fun `present - live location minimum distance is null when feature is disabled`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore( + liveLocationMinimumDistanceUpdate = 50, + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.LiveLocationSharing, false) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isNull() + } + } + } + + @Test + fun `present - exposes live location minimum distance from app preferences`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore( + liveLocationMinimumDistanceUpdate = 50, + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isEqualTo(50) + } + } + } + + @Test + fun `present - saving live location minimum distance updates app preferences`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore( + liveLocationMinimumDistanceUpdate = 10, + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isEqualTo(10) + eventSink(AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate(42)) + } + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isEqualTo(42) + } + } + } + @Test fun `present - black theme option shown when feature flag enabled`() = runTest { val presenter = createAdvancedSettingsPresenter( @@ -338,7 +405,7 @@ class AdvancedSettingsPresenterTest { } private fun CoroutineScope.createAdvancedSettingsPresenter( - appPreferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), mediaPreviewConfigStateStore: MediaPreviewConfigStateStore = FakeMediaPreviewConfigStateStore(), featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt index b6fe5c3d0b..4823a7c26e 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 @@ -250,6 +250,7 @@ private fun AndroidComposeUiTest.setAdvancedSettingsView( state: AdvancedSettingsState, analyticsService: AnalyticsService = FakeAnalyticsService(), onBackClick: () -> Unit = EnsureNeverCalled(), + onOpenAppSettings: () -> Unit = EnsureNeverCalled(), ) { setContent { CompositionLocalProvider( @@ -258,6 +259,7 @@ private fun AndroidComposeUiTest.setAdvancedSettingsView( AdvancedSettingsView( state = state, onBackClick = onBackClick, + onOpenAppSettingsClick = onOpenAppSettings ) } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 59fd7a4940..bd7b1399e1 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.room.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.spaces.SpaceService @@ -67,6 +68,7 @@ interface MatrixClient { val sessionCoroutineScope: CoroutineScope val ignoredUsersFlow: StateFlow> val roomMembershipObserver: RoomMembershipObserver + val ownBeaconInfoUpdates: Flow suspend fun getJoinedRoom(roomId: RoomId): JoinedRoom? suspend fun getRoom(roomId: RoomId): BaseRoom? suspend fun findDM(userId: UserId): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt new file mode 100644 index 0000000000..358dcd98d1 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.location + +import io.element.android.libraries.matrix.api.core.EventId + +typealias BeaconId = EventId diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt new file mode 100644 index 0000000000..0b7e9b0f44 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.location + +import io.element.android.libraries.matrix.api.core.RoomId + +data class BeaconInfoUpdate( + val roomId: RoomId, + val beaconId: BeaconId, + val isLive: Boolean, +) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt new file mode 100644 index 0000000000..9b53603042 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.location + +sealed class LiveLocationException(message: String?) : Exception(message) { + class NotLive : LiveLocationException("The beacon event has expired.") + class Network : LiveLocationException("Network error") + class Other(val exception: Exception) : LiveLocationException(exception.message) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt index 3f9c108dc7..4d8bc4638a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt @@ -21,6 +21,8 @@ data class LiveLocationShare( val startTimestamp: Long, /** The timestamp when location sharing ends, in milliseconds. */ val endTimestamp: Long, + /** The event id from the beacon info. */ + val beaconId: BeaconId ) data class LastLocation( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 5a1dc9da4b..05e52605dc 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -70,6 +70,7 @@ import io.element.android.libraries.matrix.impl.room.RustRoomFactory import io.element.android.libraries.matrix.impl.room.TimelineEventFilterFactory import io.element.android.libraries.matrix.impl.room.history.map import io.element.android.libraries.matrix.impl.room.join.map +import io.element.android.libraries.matrix.impl.room.location.map import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper import io.element.android.libraries.matrix.impl.roomdirectory.RustRoomDirectoryService import io.element.android.libraries.matrix.impl.roomdirectory.map @@ -113,6 +114,8 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout import org.matrix.rustcomponents.sdk.AuthData import org.matrix.rustcomponents.sdk.AuthDataPasswordDetails +import org.matrix.rustcomponents.sdk.BeaconInfoListener +import org.matrix.rustcomponents.sdk.BeaconInfoUpdate import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientException import org.matrix.rustcomponents.sdk.IgnoredUsersListener @@ -207,6 +210,15 @@ class RustMatrixClient( analyticsService = analyticsService, ) + override val ownBeaconInfoUpdates = mxCallbackFlow { + val listener = object : BeaconInfoListener { + override fun onUpdate(update: BeaconInfoUpdate) { + trySend(update.map()) + } + } + innerClient.subscribeToOwnBeaconInfoUpdates(listener) + } + override val sessionVerificationService = RustSessionVerificationService( client = innerClient, isSyncServiceReady = syncService.syncState.map { it == SyncState.Running }, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt index 87ef0815ce..caeef02e8e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt @@ -45,6 +45,7 @@ import io.element.android.libraries.matrix.impl.room.history.map import io.element.android.libraries.matrix.impl.room.join.map import io.element.android.libraries.matrix.impl.room.knock.RustKnockRequest import io.element.android.libraries.matrix.impl.room.location.liveLocationSharesFlow +import io.element.android.libraries.matrix.impl.room.location.map import io.element.android.libraries.matrix.impl.room.location.timedByExpiry import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.room.threads.RustThreadsListService @@ -72,6 +73,7 @@ import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.DateDividerMode import org.matrix.rustcomponents.sdk.IdentityStatusChangeListener import org.matrix.rustcomponents.sdk.KnockRequestsListener +import org.matrix.rustcomponents.sdk.LiveLocationException import org.matrix.rustcomponents.sdk.RoomMessageEventMessageType import org.matrix.rustcomponents.sdk.RoomSendQueueUpdate import org.matrix.rustcomponents.sdk.SendQueueListener @@ -525,12 +527,22 @@ class JoinedRustRoom( override suspend fun stopLiveLocationShare(): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.stopLiveLocationShare() + }.mapFailure { throwable -> + when (throwable) { + is LiveLocationException -> throwable.map() + else -> throwable + } } } override suspend fun sendLiveLocation(geoUri: String): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.sendLiveLocation(geoUri) + }.mapFailure { throwable -> + when (throwable) { + is LiveLocationException -> throwable.map() + else -> throwable + } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt new file mode 100644 index 0000000000..44be305c02 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.location + +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate +import org.matrix.rustcomponents.sdk.BeaconInfoUpdate as RustBeaconInfoUpdate + +fun RustBeaconInfoUpdate.map(): BeaconInfoUpdate { + return BeaconInfoUpdate( + roomId = RoomId(roomId), + beaconId = EventId(eventId), + isLive = live + ) +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt new file mode 100644 index 0000000000..b10f5cd41c --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.location + +import io.element.android.libraries.matrix.api.room.location.LiveLocationException +import org.matrix.rustcomponents.sdk.LiveLocationException as RustLiveLocationException + +fun RustLiveLocationException.map(): LiveLocationException { + return when (this) { + is RustLiveLocationException.Network -> LiveLocationException.Network() + is RustLiveLocationException.NotLive -> LiveLocationException.NotLive() + else -> LiveLocationException.Other(this) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt index 1a341d0dc2..8e8181539f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt @@ -7,6 +7,7 @@ package io.element.android.libraries.matrix.impl.room.location +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.location.LastLocation import io.element.android.libraries.matrix.api.room.location.LiveLocationShare @@ -41,9 +42,9 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { } } return callbackFlow { - val liveLocationShares = liveLocationsObserver() + val observer = liveLocationsObserver() val shares: MutableList = ArrayList() - val taskHandle = liveLocationShares.subscribe(object : LiveLocationsListener { + val taskHandle = observer.subscribe(object : LiveLocationsListener { override fun onUpdate(updates: List) { for (update in updates) { shares.applyUpdate(update) @@ -53,13 +54,14 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { }) awaitClose { taskHandle.cancelAndDestroy() - liveLocationShares.destroy() + observer.destroy() } }.buffer(Channel.UNLIMITED) } private fun RustLiveLocationShare.into(): LiveLocationShare { return LiveLocationShare( + beaconId = EventId(beaconId), userId = UserId(userId), lastLocation = lastLocation?.let { LastLocation( @@ -69,6 +71,6 @@ private fun RustLiveLocationShare.into(): LiveLocationShare { ) }, startTimestamp = startTs.toLong(), - endTimestamp = (startTs + timeout).toLong() + endTimestamp = (startTs + timeout).toLong(), ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt index 41627396ad..ba91dae468 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt @@ -11,6 +11,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.emptyFlow @@ -24,9 +25,9 @@ class TimedLiveLocationSharesFlowTest { @Test fun `it keeps emitting shares for subsequent expiries without upstream changes`() = runTest { val shares = listOf( - aLiveLocationShare(userId = "@alice:server", endTimestamp = 1_000), - aLiveLocationShare(userId = "@bob:server", endTimestamp = 2_000), - aLiveLocationShare(userId = "@carol:server", endTimestamp = 3_000), + aLiveLocationShare(userId = UserId("@alice:server"), endTimestamp = 1_000), + aLiveLocationShare(userId = UserId("@bob:server"), endTimestamp = 2_000), + aLiveLocationShare(userId = UserId("@carol:server"), endTimestamp = 3_000), ) flowOf(shares) @@ -56,8 +57,8 @@ class TimedLiveLocationSharesFlowTest { @Test fun `it does not double-emit when a share is already expired on receipt`() = runTest { val shares = listOf( - aLiveLocationShare(userId = "@alice:server", endTimestamp = 500), - aLiveLocationShare(userId = "@bob:server", endTimestamp = 2_000), + aLiveLocationShare(userId = UserId("@alice:server"), endTimestamp = 500), + aLiveLocationShare(userId = UserId("@bob:server"), endTimestamp = 2_000), ) flowOf(shares) @@ -81,8 +82,8 @@ class TimedLiveLocationSharesFlowTest { val upstream = MutableSharedFlow>(extraBufferCapacity = 1) val initialShares = listOf(aLiveLocationShare(endTimestamp = 10_000)) val updatedShares = listOf( - aLiveLocationShare(userId = "@alice:server", endTimestamp = 10_000), - aLiveLocationShare(userId = "@bob:server", endTimestamp = 6_000), + aLiveLocationShare(userId = UserId("@alice:server"), endTimestamp = 10_000), + aLiveLocationShare(userId = UserId("@bob:server"), endTimestamp = 6_000), ) upstream @@ -133,15 +134,3 @@ class TimedLiveLocationSharesFlowTest { } } } - -private fun aLiveLocationShare( - userId: String = "@user:server", - endTimestamp: Long, -): LiveLocationShare { - return LiveLocationShare( - userId = UserId(userId), - lastLocation = null, - startTimestamp = 0L, - endTimestamp = endTimestamp, - ) -} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 26bc0af8c1..af28dc37e4 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.room.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.spaces.SpaceService @@ -107,6 +108,7 @@ class FakeMatrixClient( private val canReportRoomLambda: () -> Boolean = { false }, private val isLivekitRtcSupportedLambda: () -> Boolean = { false }, override val ignoredUsersFlow: StateFlow> = MutableStateFlow(persistentListOf()), + override val ownBeaconInfoUpdates: Flow = emptyFlow(), private val getMaxUploadSizeResult: () -> Result = { lambdaError() }, private val getJoinedRoomIdsResult: () -> Result> = { Result.success(emptySet()) }, private val getRecentEmojisLambda: () -> Result> = { Result.success(emptyList()) }, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index d1cd340641..9f7255ab18 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -89,7 +89,7 @@ class FakeJoinedRoom( private val updateJoinRuleResult: (JoinRule) -> Result = { lambdaError() }, private val setSendQueueEnabledResult: (Boolean) -> Unit = { _: Boolean -> }, private val liveLocationSharesFlow: Flow> = MutableStateFlow(emptyList()), - private val startLiveLocationShareResult: (Long) -> Result = { lambdaError() }, + private val startLiveLocationShareResult: (Long) -> Result = { lambdaError() }, private val stopLiveLocationShareResult: () -> Result = { lambdaError() }, private val sendLiveLocationResult: (String) -> Result = { lambdaError() }, ) : JoinedRoom, BaseRoom by baseRoom { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt new file mode 100644 index 0000000000..23730c8886 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.room.location + +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.location.AssetType +import io.element.android.libraries.matrix.api.room.location.LastLocation +import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_USER_ID + +fun aLiveLocationShare( + beaconId: EventId = AN_EVENT_ID, + userId: UserId = A_USER_ID, + geoUri: String = "geo:48.8584,2.2945", + timestamp: Long = 0L, + startTimestamp: Long = 0L, + endTimestamp: Long = Long.MAX_VALUE, + assetType: AssetType = AssetType.SENDER, +): LiveLocationShare { + return LiveLocationShare( + beaconId = beaconId, + userId = userId, + lastLocation = LastLocation( + geoUri = geoUri, + timestamp = timestamp, + assetType = assetType, + ), + startTimestamp = startTimestamp, + endTimestamp = endTimestamp, + ) +} diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt index 476658946a..df8dc8acc9 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt @@ -23,6 +23,9 @@ interface AppPreferencesStore { suspend fun setTheme(theme: String) fun getThemeFlow(): Flow + suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) + fun getLiveLocationMinimumDistanceInMetersUpdateFlow(): Flow + @Deprecated("Use MediaPreviewService instead. Kept only for migration.") suspend fun setHideInviteAvatars(hide: Boolean?) @Deprecated("Use MediaPreviewService instead. Kept only for migration.") diff --git a/libraries/preferences/impl/build.gradle.kts b/libraries/preferences/impl/build.gradle.kts index 0478d303ea..73327a69a2 100644 --- a/libraries/preferences/impl/build.gradle.kts +++ b/libraries/preferences/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright (c) 2025 Element Creations Ltd. @@ -26,4 +27,6 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.matrix.api) implementation(projects.libraries.sessionStorage.api) + testCommonDependencies(libs) + testImplementation(projects.libraries.preferences.test) } diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt index 6856f8bdb6..44260461da 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.preferences.impl.store import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding @@ -28,6 +29,7 @@ private val customElementCallBaseUrlKey = stringPreferencesKey("elementCallBaseU private val themeKey = stringPreferencesKey("theme") private val hideInviteAvatarsKey = booleanPreferencesKey("hideInviteAvatars") private val timelineMediaPreviewValueKey = stringPreferencesKey("timelineMediaPreviewValue") +private val liveLocationMinimumDistanceUpdateKey = intPreferencesKey("liveLocationMinimumDistanceUpdate") private val logLevelKey = stringPreferencesKey("logLevel") private val traceLogPacksKey = stringPreferencesKey("traceLogPacks") @@ -79,6 +81,18 @@ class DefaultAppPreferencesStore( } } + override suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) { + store.edit { prefs -> + prefs[liveLocationMinimumDistanceUpdateKey] = value + } + } + + override fun getLiveLocationMinimumDistanceInMetersUpdateFlow(): Flow { + return store.data.map { prefs -> + prefs[liveLocationMinimumDistanceUpdateKey] ?: 10 + } + } + @Deprecated("Use MediaPreviewService instead. Kept only for migration.") override fun getHideInviteAvatarsFlow(): Flow { return store.data.map { prefs -> diff --git a/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt b/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt new file mode 100644 index 0000000000..c52d1648ac --- /dev/null +++ b/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.preferences.impl.store + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultAppPreferencesStoreTest { + private val buildMeta = BuildMeta( + buildType = BuildType.DEBUG, + isDebuggable = true, + applicationName = "Element X", + productionApplicationName = "Element", + desktopApplicationName = "Element Desktop", + applicationId = "io.element.android", + isEnterpriseBuild = false, + lowPrivacyLoggingEnabled = false, + versionName = "1.0.0", + versionCode = 1, + gitRevision = "test", + gitBranchName = "test", + flavorDescription = "test", + flavorShortDescription = "test", + ) + + @Test + fun `live location minimum distance defaults to 10`() = runTest { + val store = DefaultAppPreferencesStore( + buildMeta = buildMeta, + preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + ) + + assertThat(store.getLiveLocationMinimumDistanceInMetersUpdateFlow().first()).isEqualTo(10) + } + + @Test + fun `live location minimum distance persists updates`() = runTest { + val store = DefaultAppPreferencesStore( + buildMeta = buildMeta, + preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + ) + + store.setLiveLocationMinimumDistanceInMetersUpdate(25) + + assertThat(store.getLiveLocationMinimumDistanceInMetersUpdateFlow().first()).isEqualTo(25) + } +} diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt index 6e7d22a568..152de12e99 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt @@ -21,12 +21,14 @@ class InMemoryAppPreferencesStore( hideInviteAvatars: Boolean? = null, timelineMediaPreviewValue: MediaPreviewValue? = null, theme: String? = null, + liveLocationMinimumDistanceUpdate: Int = 10, logLevel: LogLevel = LogLevel.INFO, traceLockPacks: Set = emptySet(), ) : AppPreferencesStore { private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled) private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl) private val theme = MutableStateFlow(theme) + private val liveLocationMinimumDistanceUpdate = MutableStateFlow(liveLocationMinimumDistanceUpdate) private val logLevel = MutableStateFlow(logLevel) private val tracingLogPacks = MutableStateFlow(traceLockPacks) private val hideInviteAvatars = MutableStateFlow(hideInviteAvatars) @@ -56,6 +58,14 @@ class InMemoryAppPreferencesStore( return theme } + override suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) { + liveLocationMinimumDistanceUpdate.value = value + } + + override fun getLiveLocationMinimumDistanceInMetersUpdateFlow(): Flow { + return liveLocationMinimumDistanceUpdate + } + @Deprecated("Use MediaPreviewService instead. Kept only for migration.") override fun getHideInviteAvatarsFlow(): Flow { return hideInviteAvatars diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt index ff7119b647..367052eaad 100644 --- a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt @@ -53,4 +53,5 @@ object NotificationIdProvider { enum class ForegroundServiceType { INCOMING_CALL, ONGOING_CALL, + LIVE_LOCATION, } diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt index fdf5cc5f1b..a7c3a6837b 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt @@ -10,12 +10,13 @@ package io.element.android.libraries.sessionstorage.test.observer import io.element.android.libraries.sessionstorage.api.observer.SessionListener import io.element.android.libraries.sessionstorage.api.observer.SessionObserver +import java.util.concurrent.CopyOnWriteArraySet class FakeSessionObserver : SessionObserver { - private val _listeners = mutableListOf() + private val _listeners = CopyOnWriteArraySet() val listeners: List - get() = _listeners + get() = _listeners.toList() override fun addListener(listener: SessionListener) { _listeners.add(listener) diff --git a/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt b/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt index d6effec06f..33c2ee133b 100644 --- a/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt +++ b/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt @@ -34,6 +34,8 @@ interface AppForegroundStateService { */ val isSyncingNotificationEvent: StateFlow + val isSharingLiveLocation: StateFlow + /** * Start observing the foreground state. */ @@ -53,4 +55,6 @@ interface AppForegroundStateService { * Update the active state for the syncing notification event flow. */ fun updateIsSyncingNotificationEvent(isSyncingNotificationEvent: Boolean) + + fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) } diff --git a/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt b/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt index c9fa31caca..9dd37af732 100644 --- a/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt +++ b/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt @@ -20,6 +20,8 @@ class DefaultAppForegroundStateService : AppForegroundStateService { override val isSyncingNotificationEvent = MutableStateFlow(false) override val hasRingingCall = MutableStateFlow(false) + override val isSharingLiveLocation = MutableStateFlow(false) + private val appLifecycle: Lifecycle by lazy { ProcessLifecycleOwner.get().lifecycle } override fun startObservingForeground() { @@ -38,6 +40,10 @@ class DefaultAppForegroundStateService : AppForegroundStateService { this.isSyncingNotificationEvent.value = isSyncingNotificationEvent } + override fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) { + this.isSharingLiveLocation.value = isSharingLiveLocation + } + private val lifecycleObserver = LifecycleEventObserver { _, _ -> isInForeground.value = getCurrentState() } private fun getCurrentState(): Boolean = appLifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) diff --git a/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt index a61733cc22..9174b92684 100644 --- a/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt +++ b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt @@ -16,12 +16,15 @@ class FakeAppForegroundStateService( initialIsInCallValue: Boolean = false, initialIsSyncingNotificationEventValue: Boolean = false, initialHasRingingCall: Boolean = false, + initialIsSharingLiveLocation: Boolean = false, ) : AppForegroundStateService { override val isInForeground = MutableStateFlow(initialForegroundValue) override val isInCall = MutableStateFlow(initialIsInCallValue) override val isSyncingNotificationEvent = MutableStateFlow(initialIsSyncingNotificationEventValue) override val hasRingingCall = MutableStateFlow(initialHasRingingCall) + override val isSharingLiveLocation = MutableStateFlow(initialIsSharingLiveLocation) + override fun startObservingForeground() { // No-op } @@ -41,4 +44,8 @@ class FakeAppForegroundStateService( override fun updateHasRingingCall(hasRingingCall: Boolean) { this.hasRingingCall.value = hasRingingCall } + + override fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) { + this.isSharingLiveLocation.value = isSharingLiveLocation + } } diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png new file mode 100644 index 0000000000..c431ee02e9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aaf113646fa3a8ffd57528d3e97eec05a8d80b99a3bbd7770266353dbe6abd64 +size 10217 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png new file mode 100644 index 0000000000..e3a3776919 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53d9deec2a6295fe0155ce2986463a3b598436c0515ef87e0905c62c25970420 +size 9647 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png index cae8f75b66..afd74655d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aaafea9efc1000495ee469797239b82193844caa3d6f98c0c3a4344a536a1798 -size 17155 +oid sha256:c9ebf3725fa875994cf1a15b30e2d4d533c2a9281f0f7d5d9f83f8685ba384d1 +size 18637 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png index 29f70fc9b1..30fad74bc6 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f113f8979679c0673e4cc1f691140bc570b6826bea23eecc403f2fbfd3f6d09 -size 16460 +oid sha256:65c321199578618012d27afe478c0eaf6a67c44101e7d1d1c51a4c6c1fa9b93a +size 17897 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png index cce7a48382..0c9a67252c 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a97492422d54a6d6666c1ade693dc9b63bc9ca07c17d6c1f787c081984c09f68 -size 42470 +oid sha256:9f3fb75974ce37fc3ce5e303ab5573a0d9a769f3c079de5b0f6462b40e53c1cd +size 26713 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png new file mode 100644 index 0000000000..e8ae396119 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddaf978cdf3e70b01fbee75e7e7290fa390e749b48ae192fe7da0dcaa9a1d4dc +size 38417 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png new file mode 100644 index 0000000000..cce7a48382 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a97492422d54a6d6666c1ade693dc9b63bc9ca07c17d6c1f787c081984c09f68 +size 42470 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png index 541b2a97e1..06ec0c10e9 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:038e12f3caeef6ac8d5389b7cdc68138e089dcac335d0a5904adc55c9bcb7b1c -size 40642 +oid sha256:4031ae26bb8465a61021c15b6166a2186f8f99d7a4dbad7bb28aaf83493cbe69 +size 25907 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png new file mode 100644 index 0000000000..7761c87d2e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9ed7610fbdabb3e88c35e2832d06566431d472ad95890c2fdcbb6d1b43d8feb +size 36751 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png new file mode 100644 index 0000000000..541b2a97e1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:038e12f3caeef6ac8d5389b7cdc68138e089dcac335d0a5904adc55c9bcb7b1c +size 40642 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png index bdb2a689ac..def7635efc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82ed52f907048490ffb63ea9b33274703c1d92d4131cca0320816cc6949bea5e -size 113727 +oid sha256:b9f2f0e8ba6829cb3d83dcc0c6d3ed5a91a0346771f84adb6731ba5fdac01f4d +size 122009 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png index 5d9f6ab2ba..c6a916891b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae3a754c163f83e69ab062c8e638a6e620948081d70105ddb00c32dda7c2ba74 -size 119927 +oid sha256:459141f4442bade537f755d56fe0b4569980a26b92f23409c477802462084b3c +size 122118 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png index 01d01e6806..07613eb447 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:757d555f948a637952aed4b0ad2745212f6a9ab279d172b0a1649fdf547c5a0c -size 120027 +oid sha256:7f85b9e88dca466b567769291fb69afac535135c3a07f412d6b8203968460519 +size 120940 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png index 6962ed5f4d..f06f86068a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb0d86877e5d049d618836846cd8ea97b40d1d66e7bd8d50639280fb3e829372 -size 38499 +oid sha256:00da192b3b46897c9d50986ecd84e07332cd2b490ebc8f3893a9497e72f18af8 +size 41478 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png index 7b0ba78a2c..140a3c3446 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b41879f5159a126b0641c66bed13470756a914cc038dd239d40d359661784b71 -size 40696 +oid sha256:c5a9f9104c9544e32ab0ab67ce03dcbef51e8613c1444aec866ff9bf60f6d241 +size 41683 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png index 8ee52bca11..4cb5fc6e48 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38fa52e6e755d86aa79a029427f04146a3939ac2038cc15717f5aec84ce3be20 -size 40870 +oid sha256:c015bae5b3ce8c4447c62a13fb74d855c23b0e41bf0b128a1834d30781c0d1f8 +size 41110 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png index a63b53d2c1..157e74f7f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7fdd2e68114457368c5d19fe117b2d5a86a02ca475925c9fae0269ff92f5144 -size 66312 +oid sha256:dc02a7c7b38753d9509b3cb0fb2eb0e29b6d6c79b8471ba4dc7dd5b81b13d15b +size 50892 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png new file mode 100644 index 0000000000..a63b53d2c1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7fdd2e68114457368c5d19fe117b2d5a86a02ca475925c9fae0269ff92f5144 +size 66312 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png index b8d8a2cf4c..e4a14ae551 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cb21bd5e7d348d1d07ca4b6a360f26a4735cc9760fdd7e3b4b1bcde32da6f08 -size 62655 +oid sha256:39430896a687266d7a60890fdac5dbca6d36c87fe30d07619c9c50e23c3f77be +size 56972 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png index 157e74f7f0..b8d8a2cf4c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc02a7c7b38753d9509b3cb0fb2eb0e29b6d6c79b8471ba4dc7dd5b81b13d15b -size 50892 +oid sha256:1cb21bd5e7d348d1d07ca4b6a360f26a4735cc9760fdd7e3b4b1bcde32da6f08 +size 62655 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png index d2b5044048..74826e1e9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52441a5e250b027ddd40ee32754a63c6206762084f47ecfa7e057e2ac77e78a8 -size 69120 +oid sha256:805245ffe7f4e99a0f5927b89bcaa6ab8eaf7cc603d352b14b8109e76eecbdf2 +size 51742 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png new file mode 100644 index 0000000000..d2b5044048 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52441a5e250b027ddd40ee32754a63c6206762084f47ecfa7e057e2ac77e78a8 +size 69120 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png index 6e371532de..1ad21c4d64 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86273e812cbc6245527c3d1f138111ece99375aec0d68728882b656b01687bff -size 64392 +oid sha256:289819914863942caad5202131efddd9b880b4af64a36d4b45fb547b5b1ec47f +size 55916 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png index 74826e1e9e..6e371532de 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:805245ffe7f4e99a0f5927b89bcaa6ab8eaf7cc603d352b14b8109e76eecbdf2 -size 51742 +oid sha256:86273e812cbc6245527c3d1f138111ece99375aec0d68728882b656b01687bff +size 64392 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png index da80c7af53..08966f9b39 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:645a7fb89953ff6e72119a105ac966cabaf8ca6a68f3023534301e3471b942f2 -size 49262 +oid sha256:42fd1d9b089b026a9edf1a0ecb71da47a4517062cc19f61e16e70f9b3276ab30 +size 59658 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png index 6aa030a83a..25f2f73063 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea52fd146c53b690c1273b090c6b66701a8f40d80eb1dc693898c3dbf8b24def -size 49115 +oid sha256:314ffd2ccda8d0315a27e0cf08fa6d158ddf38fa0903e1e8d7fe45361254aa0d +size 59525 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png index a31686aaad..c9b289e9d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf3e4ffa06a77fbaa9dc9985274d6b1324fb023f5eeb2b9d229af0854b41e236 -size 49095 +oid sha256:dc25ef0688d2aa9be1fcade1dfa282b243cc3c45bde01d3571b2ad9278dcda74 +size 59509 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png index 421367fee7..3398dc3826 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f68a09667dc19c935decb5b640bed2410dd16ae88c0d0ab6ca410225e48a87da -size 49111 +oid sha256:229b570a3c938e75f5d7b33c7fec89be9582ec06aa85dfa587b995219b145e88 +size 59517 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png index fbcd0538aa..6767c03276 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5defae968cccb0e78ceff23912a364cf72f9ed61ea6ae3cc9770af9c39b05f9d -size 49035 +oid sha256:9c9caa916637c212f2cf1e5d175a9cf096b83606e1161b7c2bb1c8ddcb142e48 +size 59363 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png index 7a3e1e9682..e9434a4041 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c590f67875f9bdc460ab82b59cd3c9e11147bfadc59028552071b64fd440f211 -size 49259 +oid sha256:296c4b7449992b4aaa478038db9b6dd4e687ca05f82cc351db258e3f178adb6f +size 59656 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png index 9c788eb3ab..dcbfd047c6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d48af05c854a8f313f10aaa774e4268756dcf7e0c2bea0e138dc6cd84137673 -size 48995 +oid sha256:f13aab730039d52c1d92e5ed3ad601095cf7c8b3bd76ddf2303f2006ea6f6092 +size 59193 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png index 9d375b0b74..3526e1e6d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1507eeffcfacfcf6c84494f09d89ef3478748ae31f8fee4a9922e4188ccb454 -size 48563 +oid sha256:961959403b1763abd537e05865d86475161e650e61e51e65202522d08faad55b +size 58771 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png index fac0ba3da5..c1707ebef8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4146fd85887aca1a0a65ef559976c1436d1fc2b0de522295f27bfaef1d904ea4 -size 55410 +oid sha256:2e5df1191bf18d6c922ca3d2a22584c98c4b871254512ea86cfb324fddf8a2d0 +size 62520 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png index 9feee4d98d..880c259789 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b832525da2a7744eff8165c842652bfff4742b728b000b1c8ef8be81bca75efe -size 47052 +oid sha256:ad35559b964b2d1197b256348e175a8082bffc9247024a546eea86655c9c0d8e +size 56855 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png index 9a4a40c0e9..c3e7180e3b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ae8264008b6396f31332263472c910b492fffdb9dbf7d0186b44a272476c02c -size 46903 +oid sha256:94b94eca0502a081fbb862c426b5063275ac948c8d998e34f40e362a82591d75 +size 56707 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png index fa74fd4b96..bb6e078571 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4842f6e88df23ae0050f0052ebe9581d6c19ac5e29a0c553716012713fbb00aa -size 46901 +oid sha256:46bd8afffd3a9c4cfb92c7d9ea2c2d0a3c4942115a80809d6bbc16037e2839a1 +size 56705 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png index 5f9af21b6e..c0ea01e3b0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7888dbb0ed5460c54796a6b2c232945bd4449e57feda4aed89ddce097a3c35b -size 46911 +oid sha256:5fc17122d1466b14e85a49165bd3b462756181ec26cbce280437f015734c8e40 +size 56716 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png index fe34c6d5c1..efc3e893a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:215745acc9dc0c86e239acf614c94f1cd46e96cf1b6dd7cdca514d7a4a82f835 -size 46742 +oid sha256:12cb6a8ee6846a0f44d5e14599fd7c6dbf97da97d35c6b6c83545d601a246efe +size 56563 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png index 9df6b272e4..7ee27433d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5d099940f91cb3e520f6eb6cbbc075bc57817f3e46e3f9fb169a36b408388f1 -size 47046 +oid sha256:1546f59a5be6b5f8883729c4b83005ebeb990188a86c100ba384da46b2a1da7e +size 56853 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png index f56d4e2115..aae9546e31 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce9c49a9d136d3bae5fb366fc47d3f48f8fabbe6963d0e53166dc1a5ec4cbc20 -size 46695 +oid sha256:714782c0f439f933f6e0127ccf54b6e09138fa23d44a3596017a23665131c119 +size 56498 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png index f19645feef..efadf6c0dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed86c0b3137dcd650d7ba65d7ec009146234b4e0b983b1ab8b56974000698201 -size 46242 +oid sha256:9a58efd0afbc84c88d8635738d3bb25826c4d25d790d4eaa1aba0e9efafc3b56 +size 56043 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png index 2b725b9e8f..1547c5289c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbdf230e73c3fd93787030d6f5eac65b6a8131bf2eccb07fcd8474f191b87b06 -size 52563 +oid sha256:9d502f4f9ccf2d3eff614d9ed2b751a252acd05c1bf5cf4a8b11775c45725c3d +size 59427 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png index f9a16c247a..1cea623bff 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d57215dd58ace85ad235fb7f95ef592bfddd3c21afbf183bb5d31fbf772b69a -size 48900 +oid sha256:7c80e9985aec6b183e33f12ecb884753d1b8f67927d6d5713ea946ea8f5d6dd6 +size 59300 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png index e662b2dfbe..d32d440b79 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32926b81da50838d883edfd157e7d12cc3d43991556f87e61702b74e693ab6da -size 48798 +oid sha256:5dedcf20e368909de0a6cdeade437bff06b38a1f1b6aba3355968983f1387018 +size 59201 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png index 5ac95223f9..6f672c23b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0594480e59710892e480a83c1352a501504ae1bafb4c5c6b672c7dc62b3e75e1 -size 48801 +oid sha256:a9023d044daba4573bb9a3ed4da598bfb5c27081e4f7a75757a4796bdc44573a +size 59207 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png index ca2e552c10..54bd893d1f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba828796a14ee9e82e01e98a89067649a7f3438a2fcc8e3ce5f69e12e86f86b0 -size 48777 +oid sha256:77eb9f159dbfa30e6f750500c2adf21b18cb5f1dfb7a574be68683db24803225 +size 59174 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png index 6f741da48f..e945e52dfa 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ebb88fa29993c785e6ca82543e7eeafefe365c0018a4f22852b988dc35db4a5 -size 48716 +oid sha256:3dca50c7a0f0d7ce96388a01456871decc76285384d2573161773219c79fb876 +size 59060 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png index 1a12af9468..02c571c605 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2521e5352ee6030f7a0fd8304b19f6a7a95fb6364d43f412eeef03799c8c0f76 -size 48901 +oid sha256:fe4181c3e521f1f788dd06e3cfb1ca078655852415dfd4f26f5480dd47bf084c +size 59303 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png index 962991ff8f..7da66a622f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6dfcf074e7fa4813218f4bf9e472f706c5581e6fc5c1f7ea1eb9ec422172190f -size 48713 +oid sha256:18602ce14232fd438450782a564354c38ebffb0c56d0c3887d88c47cae53dacf +size 58962 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png index 8917220310..015ecaf7fd 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3195a1871862ce32cdcf068608a565c56e794ff66f14473d5f6355918db79b6 -size 48402 +oid sha256:c3ae0af5031f7f850c40fa6560aa6d70127e006931a3e18cbee04acd7c7aed57 +size 58526 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png index 5fc76943b5..19d1ae2ca8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f71219202890afcd4f43b5f57cb4d555b723df48f71848b64c8db415067d1d4b -size 55044 +oid sha256:a980564b6406bbe45b9a170a5744e45c9e019556587d433e5fdffd8ab6f1c6fd +size 62034 From f05ceb9f5dcfa3f396fe737f72922121cceb7967 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 10:47:17 +0200 Subject: [PATCH 0387/1083] review: Use @stringRes annotation for Int --- .../impl/timeline/components/TimelineItemCallNotifyView.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index f4d0d97495..0c3e548f4b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -8,6 +8,7 @@ package io.element.android.features.messages.impl.timeline.components +import androidx.annotation.StringRes import androidx.compose.foundation.border import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement @@ -91,6 +92,7 @@ internal fun TimelineItemCallNotifyView( } } +@StringRes private fun getTextRes( timelineRoomInfo: TimelineRoomInfo, content: TimelineItemRtcNotificationContent From 885d0f2cb926532e4485fd9f7d83cdbeccd5e5cf Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 10:47:32 +0200 Subject: [PATCH 0388/1083] review: better comment --- .../impl/timeline/components/TimelineItemCallNotifyView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index 0c3e548f4b..0c9c4e68c0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -104,7 +104,7 @@ private fun getTextRes( RtcNotificationState.Started -> CommonStrings.common_call_started } } else { - // Only show declined info in DMs + // In Rooms, do not show declined info. CommonStrings.common_call_started } From 4437d4d9df8e63f8914c1a2be94e81f9d766c59f Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 10:47:46 +0200 Subject: [PATCH 0389/1083] review: Invert if for better readability --- .../timeline/factories/event/TimelineItemContentFactory.kt | 6 +++--- 1 file changed, 3 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 2d884d75fd..b3409aa567 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 @@ -106,10 +106,10 @@ class TimelineItemContentFactory( is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent( callIntent = itemContent.callIntent, - state = if (itemContent.declinedBy.isNotEmpty()) { - RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) - } else { + state = if (itemContent.declinedBy.isEmpty()) { RtcNotificationState.Started + } else { + RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) } ) is UnknownContent -> TimelineItemUnknownContent From 9a8046c02d1ada564dc129d5cabf09d238734bf2 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 10:48:50 +0200 Subject: [PATCH 0390/1083] review: Update signature and keep formatters grouped together --- .../eventformatter/impl/DefaultRoomLatestEventFormatter.kt | 2 +- .../impl/DefaultRoomLatestEventFormatterTest.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 eac0e9e88d..d234e7b239 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt @@ -54,8 +54,8 @@ class DefaultRoomLatestEventFormatter( private val roomMembershipContentFormatter: RoomMembershipContentFormatter, private val profileChangeContentFormatter: ProfileChangeContentFormatter, private val stateContentFormatter: StateContentFormatter, - private val permalinkParser: PermalinkParser, private val rtcNotificationContentFormatter: RtcNotificationContentFormatter, + private val permalinkParser: PermalinkParser, ) : RoomLatestEventFormatter { override fun format( latestEvent: LatestEventValue.Local, diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt index 177cc27df2..e0613ed008 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt @@ -74,8 +74,8 @@ class DefaultRoomLatestEventFormatterTest { roomMembershipContentFormatter = RoomMembershipContentFormatter(fakeMatrixClient, stringProvider), profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider), stateContentFormatter = StateContentFormatter(stringProvider), - permalinkParser = FakePermalinkParser(), - rtcNotificationContentFormatter = RtcNotificationContentFormatter(fakeMatrixClient, stringProvider) + rtcNotificationContentFormatter = RtcNotificationContentFormatter(fakeMatrixClient, stringProvider), + permalinkParser = FakePermalinkParser() ) } From 9ce825308677a5f58be978e887f06aceeb5c3b61 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 11:16:45 +0200 Subject: [PATCH 0391/1083] review: Add unit test for notificationFormater --- .../RtcNotificationContentFormatterTest.kt | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt new file mode 100644 index 0000000000..dca34db3cc --- /dev/null +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.eventformatter.impl + +import android.content.Context +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.A_USER_ID_3 +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.services.toolbox.impl.strings.AndroidStringProvider +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config +import kotlin.toString + +@Suppress("LargeClass") +@RunWith(RobolectricTestRunner::class) +class RtcNotificationContentFormatterTest { + private lateinit var context: Context + private lateinit var fakeMatrixClient: FakeMatrixClient + private lateinit var formatter: RtcNotificationContentFormatter + + @Before + fun setup() { + context = RuntimeEnvironment.getApplication() as Context + fakeMatrixClient = FakeMatrixClient() + val stringProvider = AndroidStringProvider(context.resources) + formatter = RtcNotificationContentFormatter( + fakeMatrixClient, + stringProvider + ) + } + + @Test + @Config(qualifiers = "en") + fun `Should not display declined info in rooms`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.VIDEO, + declinedBy = listOf(A_USER_ID_2, A_USER_ID_3) + ), + false + ) + val expected = "Call started" + assertThat(result.toString()).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Declined by me variant`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.VIDEO, + declinedBy = listOf(fakeMatrixClient.sessionId) + ), + true + ) + val expected = "You declined a call" + assertThat(result.toString()).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Declined by other variant`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.VIDEO, + declinedBy = listOf(A_USER_ID_2) + ), + true + ) + val expected = "Call declined" + assertThat(result.toString()).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Call started in DM`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.AUDIO, + declinedBy = listOf() + ), + true + ) + val expected = "Call started" + assertThat(result.toString()).isEqualTo(expected) + } +} From f0f5e8be25e642d44c6f470158a40ae4e3f3f28e Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 11:20:10 +0200 Subject: [PATCH 0392/1083] review: Refactor preview, show all variants --- .../components/TimelineItemCallNotifyView.kt | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index 0c9c4e68c0..61273ff07a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -125,21 +125,23 @@ private fun getIcon( @PreviewsDayNight @Composable internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { - Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { - listOf( - aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Started), - aTimelineRoomInfo() to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Started), - aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.AUDIO, RtcNotificationState.Declined(false)), - aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined(false)), - aTimelineRoomInfo(isDm = true) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Declined(true)), - aTimelineRoomInfo(isDm = false) to TimelineItemRtcNotificationContent(CallIntent.VIDEO, RtcNotificationState.Started), - ).forEach { (info, content) -> - TimelineItemCallNotifyView( - timelineRoomInfo = info, - event = aTimelineItemEvent(content = content), - content = content, - onLongClick = {}, - ) + Column(modifier = Modifier.padding(2.dp), verticalArrangement = Arrangement.spacedBy(2.dp)) { + listOf(false, true).forEach { isDm -> + listOf(CallIntent.AUDIO, CallIntent.VIDEO).forEach { callIntent -> + listOf( + RtcNotificationState.Started, + RtcNotificationState.Declined(byMe = false), + RtcNotificationState.Declined(byMe = true), + ).forEach { state -> + val content = TimelineItemRtcNotificationContent(callIntent, state) + TimelineItemCallNotifyView( + timelineRoomInfo = aTimelineRoomInfo(isDm = isDm), + event = aTimelineItemEvent(content = content), + content = content, + onLongClick = {}, + ) + } + } } } } From c5a054b9e3d48b1df20b0f25735b7e19f0eb3de7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 11 May 2026 09:36:54 +0000 Subject: [PATCH 0393/1083] Update screenshots --- ...imeline.components_TimelineItemCallNotifyView_Day_0_en.png | 4 ++-- ...eline.components_TimelineItemCallNotifyView_Night_0_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png index 13b76dc106..e89697a8cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a618360cff745818c0ad066b4c6599ff804d9c022e6b54dfec97aa152a84f29 -size 27716 +oid sha256:5529e89e00208e38522f5206f5b8d304bd472b27071cab4e0d3c2daf3cb64db0 +size 49741 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png index 4d1d5d8f00..37037907c8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54e56f77c535db49bb9352ca09033fc81ba21b71e7c28079aec8f9bc09dcc1ad -size 26644 +oid sha256:fa29aaa82f21912dd5147ffb6fdc457fd5880e8be4abde4f0177d0ab1a412fe2 +size 48245 From 90ce30d6e7f70e47a8d6690500ebe2c1f35f1f6d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 14:13:23 +0200 Subject: [PATCH 0394/1083] Update actions/add-to-project action to v2 (#6758) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/triage-incoming.yml | 2 +- .github/workflows/triage-labelled.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/triage-incoming.yml b/.github/workflows/triage-incoming.yml index 8e8d03c9c4..b93ea81403 100644 --- a/.github/workflows/triage-incoming.yml +++ b/.github/workflows/triage-incoming.yml @@ -10,7 +10,7 @@ jobs: triage-new-issues: runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/91 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml index 3ec20f332b..0b587369ed 100644 --- a/.github/workflows/triage-labelled.yml +++ b/.github/workflows/triage-labelled.yml @@ -14,7 +14,7 @@ jobs: if: > github.repository == 'element-hq/element-x-android' steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/43 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -23,7 +23,7 @@ jobs: name: Move triaged needs info issues on board runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 id: addItem with: project-url: https://github.com/orgs/element-hq/projects/91 @@ -47,7 +47,7 @@ jobs: if: > contains(github.event.issue.labels.*.name, 'Team: Element X Feature') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/73 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -58,7 +58,7 @@ jobs: if: > contains(github.event.issue.labels.*.name, 'Team: Verticals Feature') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/57 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -70,7 +70,7 @@ jobs: contains(github.event.issue.labels.*.name, 'Team: QA') || contains(github.event.issue.labels.*.name, 'X-Needs-Signoff') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/69 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -81,7 +81,7 @@ jobs: if: > contains(github.event.issue.labels.*.name, 'X-Needs-Signoff') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/89 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} From 7f545079ad4ebb187bfdaa2b042ffe4614017883 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 May 2026 14:49:53 +0200 Subject: [PATCH 0395/1083] Prevent user from starting LLS in thread --- .../impl/share/ShareLocationPresenter.kt | 7 ++- .../impl/share/ShareLocationPresenterTest.kt | 44 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index b56f9c7cb3..6c0d2120bc 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -171,7 +171,7 @@ class ShareLocationPresenter( dialogState = dialogState, trackUserLocation = trackUserPosition, hasLocationPermission = permissionsState.isAnyGranted, - canShareLiveLocation = isLiveLocationSharingEnabled, + canShareLiveLocation = isLiveLocationSharingEnabled && timelineMode.canShareLiveLocation(), appName = appName, startLiveLocationAction = startLiveLocationAction.value, eventSink = ::handleEvent, @@ -210,4 +210,9 @@ class ShareLocationPresenter( } } +private fun Timeline.Mode.canShareLiveLocation() = when (this) { + is Timeline.Mode.Thread -> false + else -> true +} + private fun generateBody(uri: String): String = "Location was shared at $uri" diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index 855deba694..dff5f05ee9 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -29,6 +29,7 @@ import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -40,6 +41,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.A_THREAD_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta @@ -82,13 +84,14 @@ class ShareLocationPresenterTest { private fun TestScope.createShareLocationPresenter( joinedRoom: JoinedRoom = FakeJoinedRoom(), + timelineMode: Timeline.Mode = Timeline.Mode.Live, locationActions: FakeLocationActions = fakeLocationActions, liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), liveLocationStore: LiveLocationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId), ): ShareLocationPresenter = ShareLocationPresenter( permissionsPresenterFactory = { fakePermissionsPresenter }, room = joinedRoom, - timelineMode = Timeline.Mode.Live, + timelineMode = timelineMode, analyticsService = fakeAnalyticsService, messageComposerContext = fakeMessageComposerContext, locationActions = locationActions, @@ -653,6 +656,45 @@ class ShareLocationPresenterTest { cancelAndIgnoreRemainingEvents() } } + + @Test + fun `canShareLiveLocation is false when the feature is disabled`() = runTest { + fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, false) + val shareLocationPresenter = createShareLocationPresenter( + timelineMode = Timeline.Mode.Live, + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.canShareLiveLocation).isFalse() + } + } + + @Test + fun `canShareLiveLocation is true when the feature is enabled`() = runTest { + fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + val shareLocationPresenter = createShareLocationPresenter( + timelineMode = Timeline.Mode.Live, + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.canShareLiveLocation).isTrue() + } + } + + @Test + fun `canShareLiveLocation is false in thread timeline`() = runTest { + fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + val shareLocationPresenter = createShareLocationPresenter( + timelineMode = Timeline.Mode.Thread(A_THREAD_ID), + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.canShareLiveLocation).isFalse() + } + } } private fun createLiveLocationStore( From 6bc8cd84e4ce625a5e2a484393cb84970dab04e0 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 16:54:30 +0200 Subject: [PATCH 0396/1083] fixup test compilation --- .../mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt index 6602f475eb..ab3ffa98c7 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt @@ -62,7 +62,7 @@ class DefaultEventItemFactoryTest { fun `create check all null cases`() { val factory = createEventItemFactory() val contents = listOf( - CallNotifyContent(callIntent = CallIntent.VIDEO), + CallNotifyContent(callIntent = CallIntent.VIDEO, emptyList()), FailedToParseMessageLikeContent("", ""), FailedToParseStateContent("", "", ""), LegacyCallInviteContent, From 1ffc09e046ecb24023ef9aac5a06d82446c0cbfa Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 11 May 2026 16:55:40 +0200 Subject: [PATCH 0397/1083] Stop removing the `logs` dir when clearing cache (#6765) --- .../features/preferences/impl/tasks/ClearCacheUseCase.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt index 141adafe2b..de6ccf5da7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt @@ -55,7 +55,12 @@ class DefaultClearCacheUseCase( // Clear OkHttp cache okHttpClient().cache?.delete() // Clear app cache - context.cacheDir.deleteRecursively() + context.cacheDir?.listFiles { + // But keep the logs + it.name != "logs" + }?.onEach { + it.deleteRecursively() + } // Clear some settings seenInvitesStore.clear() // Ensure any error will be displayed again From 5e5e0bbc6e555437b62ec70e80ac7cde433ba088 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 17:00:49 +0200 Subject: [PATCH 0398/1083] Update dependency io.github.sergio-sastre.ComposablePreviewScanner:android to v0.9.0 (#6759) 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 4a1e0c2f80..7a79320530 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -168,7 +168,7 @@ test_truth = "com.google.truth:truth:1.4.5" test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.22" test_robolectric = "org.robolectric:robolectric:4.16.1" test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" } -test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.8.2" +test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.9.0" test_detekt_api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" } test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" } From 11476c73cfe71b3e9d137bb4dd3bfdc533010c88 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 11 May 2026 17:22:16 +0200 Subject: [PATCH 0399/1083] Adapt to new DM definition changes in the SDK (#6748) * Set `DmRoomDefinition.TwoPeople` in `ClientBuilder`. This applies the 'direct and with at most 2 non-service members' rule to what the SDK should consider a DM. * Map `RoomInfo.isDm` from the SDK * Map `NotificationData.isDm` from `NotificationInfo.roomInfo.isDm` * Remove `RoomIsDmCheck` file as its extension functions are now redundant. Move `Room.isDm` helper function to `BaseRoom`. * Map `isDm` in `SpaceRoom` from the SDK too * Replace `isDirect` with `isDm` where possible * Map `RoomMember.isServiceMember` from the SDK and use it to tell apart normal members of a room from service members (i.e. `RoomMembersState.getDirectRoomMember`) --- .../impl/utils/DefaultCallWidgetProvider.kt | 1 - .../datasource/RoomListRoomSummaryFactory.kt | 1 - .../android/features/invite/api/InviteData.kt | 1 - .../impl/DefaultInvitePeoplePresenterTest.kt | 6 +-- .../joinroom/impl/JoinRoomPresenter.kt | 1 - .../leaveroom/impl/LeaveRoomPresenter.kt | 1 - .../impl/LeaveBaseRoomPresenterTest.kt | 2 +- .../messages/impl/MessagesPresenter.kt | 1 - .../MessageComposerPresenter.kt | 1 - .../suggestions/SuggestionsPickerView.kt | 1 + .../list/PinnedMessagesListPresenter.kt | 1 - .../impl/timeline/TimelinePresenter.kt | 1 - .../messages/impl/MessagesPresenterTest.kt | 4 +- .../MessageComposerPresenterTest.kt | 2 +- .../NotificationSettingsPresenter.kt | 4 +- .../EditDefaultNotificationSettingNode.kt | 4 +- ...EditDefaultNotificationSettingPresenter.kt | 14 ++--- ...efaultNotificationSettingsPresenterTest.kt | 2 +- .../NotificationSettingsPresenterTest.kt | 8 +-- .../roomcall/impl/RoomCallStatePresenter.kt | 1 - .../impl/RoomCallStatePresenterTest.kt | 4 +- .../roomdetails/impl/RoomDetailsPresenter.kt | 6 +-- .../impl/RoomDetailsStateProvider.kt | 4 +- .../members/RoomMemberListStateProvider.kt | 2 + .../RoomNotificationSettingsPresenter.kt | 4 +- .../impl/RoomDetailsPresenterTest.kt | 7 ++- .../addroom/AddRoomToSpaceSearchDataSource.kt | 1 - .../space/impl/leave/LeaveSpacePresenter.kt | 2 +- .../space/impl/root/SpaceStateProvider.kt | 1 + .../impl/leave/LeaveSpacePresenterTest.kt | 6 +-- .../matrix/api/analytics/ViewRoomExt.kt | 2 +- .../NotificationSettingsService.kt | 2 +- .../libraries/matrix/api/room/BaseRoom.kt | 9 ++-- .../libraries/matrix/api/room/RoomInfo.kt | 1 + .../matrix/api/room/RoomIsDmCheck.kt | 32 ----------- .../libraries/matrix/api/room/RoomMember.kt | 1 + .../matrix/api/room/RoomMembersState.kt | 2 +- .../api/room/recent/RecentDirectRoom.kt | 1 - .../matrix/api/roomlist/RoomSummary.kt | 2 +- .../libraries/matrix/api/spaces/SpaceRoom.kt | 1 + .../matrix/api/room/RoomIsDmCheckTest.kt | 54 ------------------- .../matrix/impl/RustMatrixClientFactory.kt | 2 + .../matrix/impl/analytics/JoinedRoomExt.kt | 1 - .../impl/notification/NotificationMapper.kt | 9 +--- .../RustNotificationSettingsService.kt | 4 +- .../matrix/impl/room/JoinedRustRoom.kt | 2 +- .../libraries/matrix/impl/room/RoomInfoExt.kt | 2 +- .../matrix/impl/room/RoomInfoMapper.kt | 1 + .../matrix/impl/room/RustBaseRoom.kt | 3 +- .../impl/room/member/RoomMemberMapper.kt | 3 +- .../matrix/impl/spaces/SpaceRoomMapper.kt | 1 + .../matrix/impl/timeline/RustTimeline.kt | 1 - .../matrix/impl/analytics/JoinedExtKtTest.kt | 16 +++++- .../impl/fixtures/factories/SpaceRoom.kt | 2 +- .../fixtures/fakes/FakeFfiClientBuilder.kt | 2 + .../matrix/impl/room/RoomInfoExtTest.kt | 19 ++----- .../matrix/impl/room/RoomInfoMapperTest.kt | 4 ++ .../FakeNotificationSettingsService.kt | 4 +- .../matrix/test/room/FakeJoinedRoom.kt | 6 ++- .../matrix/test/room/RoomInfoFixture.kt | 2 + .../matrix/test/room/RoomMemberFixture.kt | 2 + .../matrix/test/room/RoomSummaryFixture.kt | 1 + .../matrix/ui/room/RoomMembersTest.kt | 52 +++--------------- .../previewutils/room/RoomMemberFixture.kt | 2 + .../previewutils/room/SpaceRoomFixture.kt | 4 +- .../NotificationBroadcastReceiverHandler.kt | 1 - 66 files changed, 115 insertions(+), 232 deletions(-) delete mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt delete mode 100644 libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt index b31b6152d0..8de7b81d6d 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt @@ -14,7 +14,6 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.services.appnavstate.api.ActiveRoomsHolder diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt index 26054d7e56..e34f2845da 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt @@ -19,7 +19,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter import io.element.android.libraries.matrix.api.room.CallIntentConsensus import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.ui.model.getAvatarData diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt index 696e02a0d7..8bfea2c12c 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt @@ -11,7 +11,6 @@ package io.element.android.features.invite.api import android.os.Parcelable import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.parcelize.Parcelize diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index 4ecd74a42f..5d5a533bb6 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -540,7 +540,7 @@ internal class DefaultInvitePeoplePresenterTest { } @Test - fun `present - suggestions are loaded from recent direct rooms`() = runTest { + fun `present - suggestions are loaded from recent DM rooms`() = runTest { val dmRoomId = RoomId("!dm_room:server.org") val otherUserId = UserId("@frank:server.org") val matrixClient = FakeMatrixClient(sessionId = A_USER_ID).apply { @@ -554,7 +554,7 @@ internal class DefaultInvitePeoplePresenterTest { roomId = dmRoomId, initialRoomInfo = aRoomInfo( id = dmRoomId, - isDirect = true, + isDm = true, activeMembersCount = 2, currentUserMembership = CurrentUserMembership.JOINED, ), @@ -591,7 +591,7 @@ internal class DefaultInvitePeoplePresenterTest { roomId = dmRoomId, initialRoomInfo = aRoomInfo( id = dmRoomId, - isDirect = true, + isDm = true, activeMembersCount = 2, currentUserMembership = CurrentUserMembership.JOINED, ), diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 1e685d3f5a..d257952209 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -44,7 +44,6 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipDetails import io.element.android.libraries.matrix.api.room.RoomType -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo diff --git a/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt b/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt index 6455b45659..d11dc7e7e8 100644 --- a/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt +++ b/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt @@ -24,7 +24,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.usersWithRole import io.element.android.libraries.push.api.notifications.conversations.NotificationConversationService import kotlinx.coroutines.CoroutineScope diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt index 59d2c1ce23..90b7f2369f 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt @@ -115,7 +115,7 @@ class LeaveBaseRoomPresenterTest { givenGetRoomResult( roomId = A_ROOM_ID, result = FakeBaseRoom().apply { - givenRoomInfo(aRoomInfo(isDirect = true, activeMembersCount = 2)) + givenRoomInfo(aRoomInfo(isDm = true, activeMembersCount = 2)) }, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 1d6f1d3c1b..6754d703a3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -79,7 +79,6 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 90b91691a9..d93fe0ee86 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -57,7 +57,6 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType import io.element.android.libraries.matrix.api.room.getDirectRoomMember -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.use import io.element.android.libraries.matrix.api.timeline.TimelineException import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt index 3d18db12d9..ef2362c794 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt @@ -190,6 +190,7 @@ internal fun SuggestionsPickerViewPreview() { isIgnored = false, role = RoomMember.Role.User, membershipChangeReason = null, + isServiceMember = false, ) val anAlias = remember { RoomAlias("#room:domain.org") } SuggestionsPickerView( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index 6cd037484d..9e5f5ba304 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -44,7 +44,6 @@ import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.ui.strings.CommonStrings diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index faa4aabe8e..0b99c45e06 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -49,7 +49,6 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.timeline.ReceiptType diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 0c836e6cc0..65aa1d857e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -598,7 +598,7 @@ class MessagesPresenterTest { baseRoom = FakeBaseRoom( roomPermissions = roomPermissions(), ).apply { - givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1)) + givenRoomInfo(aRoomInfo(isDm = true, joinedMembersCount = 1, activeMembersCount = 1)) }, typingNoticeResult = { Result.success(Unit) }, ) @@ -1112,7 +1112,7 @@ class MessagesPresenterTest { canRedactOwn = true, canPinUnpin = true, ), - initialRoomInfo = aRoomInfo(isDirect = true, isEncrypted = true) + initialRoomInfo = aRoomInfo(isDm = true, isEncrypted = true) ).apply { givenRoomMembersState(RoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2)))) }, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index 7a2cc1110a..e8d106a80f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -1066,7 +1066,7 @@ class MessageComposerPresenterTest { ) givenRoomInfo( aRoomInfo( - isDirect = true, + isDm = true, activeMembersCount = 2, ) ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index 9d9e80b3f3..12f13e734b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -223,7 +223,7 @@ class NotificationSettingsPresenter( notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = encryptedGroupDefaultMode != RoomNotificationMode.ALL_MESSAGES, mode = RoomNotificationMode.ALL_MESSAGES, - isOneToOne = false, + isDM = false, ) } @@ -234,7 +234,7 @@ class NotificationSettingsPresenter( notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = encryptedOneToOneDefaultMode != RoomNotificationMode.ALL_MESSAGES, mode = RoomNotificationMode.ALL_MESSAGES, - isOneToOne = true, + isDM = true, ) } }.fold( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt index 96097983c9..1357caeef3 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt @@ -34,12 +34,12 @@ class EditDefaultNotificationSettingNode( } data class Inputs( - val isOneToOne: Boolean + val isDm: Boolean ) : NodeInputs private val callback: Callback = callback() private val inputs = inputs() - private val presenter = presenterFactory.create(inputs.isOneToOne) + private val presenter = presenterFactory.create(inputs.isDm) @Composable override fun View(modifier: Modifier) { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt index 178f7033f3..f2cb8b02cc 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt @@ -42,12 +42,12 @@ import kotlin.time.Duration.Companion.seconds @AssistedInject class EditDefaultNotificationSettingPresenter( private val notificationSettingsService: NotificationSettingsService, - @Assisted private val isOneToOne: Boolean, + @Assisted private val isDm: Boolean, private val roomListService: RoomListService, ) : Presenter { @AssistedFactory interface Factory { - fun create(isOneToOne: Boolean): EditDefaultNotificationSettingPresenter + fun create(isDm: Boolean): EditDefaultNotificationSettingPresenter } private val collator = Collator.getInstance().apply { @@ -86,7 +86,7 @@ class EditDefaultNotificationSettingPresenter( } return EditDefaultNotificationSettingState( - isOneToOne = isOneToOne, + isOneToOne = isDm, mode = mode.value, roomsWithUserDefinedMode = roomsWithUserDefinedMode.value.toImmutableList(), changeNotificationSettingAction = changeNotificationSettingAction.value, @@ -96,7 +96,7 @@ class EditDefaultNotificationSettingPresenter( } private fun CoroutineScope.fetchSettings(mode: MutableState) = launch { - mode.value = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = isOneToOne).getOrThrow() + mode.value = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = isDm).getOrThrow() } @OptIn(FlowPreview::class) @@ -129,7 +129,7 @@ class EditDefaultNotificationSettingPresenter( val roomWithUserDefinedRules: Set = notificationSettingsService.getRoomsWithUserDefinedRules().getOrDefault(emptyList()).toSet() roomsWithUserDefinedMode.value = summaries .filter { roomSummary -> - roomWithUserDefinedRules.contains(roomSummary.roomId) && roomSummary.isOneToOne == isOneToOne + roomWithUserDefinedRules.contains(roomSummary.roomId) && roomSummary.isDm == isDm } .map { roomSummary -> EditNotificationSettingRoomInfo( @@ -154,9 +154,9 @@ class EditDefaultNotificationSettingPresenter( private fun CoroutineScope.setDefaultNotificationMode(mode: RoomNotificationMode, action: MutableState>) = launch { action.runUpdatingStateNoSuccess { // On modern clients, we don't have different settings for encrypted and non-encrypted rooms (Legacy clients did). - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, mode = mode, isOneToOne = isOneToOne) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, mode = mode, isDM = isDm) .map { - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, mode = mode, isOneToOne = isOneToOne) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, mode = mode, isDM = isDm) } } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt index e03b65f0a9..509d00db25 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt @@ -198,7 +198,7 @@ class EditDefaultNotificationSettingsPresenterTest { ): EditDefaultNotificationSettingPresenter { return EditDefaultNotificationSettingPresenter( notificationSettingsService = notificationSettingsService, - isOneToOne = false, + isDm = false, roomListService = roomListService, ) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt index 9b36c477a4..26bb0ba1ee 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt @@ -61,8 +61,8 @@ class NotificationSettingsPresenterTest { val notificationSettingsService = FakeNotificationSettingsService() val presenter = createNotificationSettingsPresenter(notificationSettingsService) presenter.test { - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES) - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isDM = false, mode = RoomNotificationMode.ALL_MESSAGES) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isDM = false, mode = RoomNotificationMode.ALL_MESSAGES) val updatedState = consumeItemsUntilPredicate { (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid) ?.defaultGroupNotificationMode == RoomNotificationMode.ALL_MESSAGES @@ -79,12 +79,12 @@ class NotificationSettingsPresenterTest { presenter.test { notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = true, - isOneToOne = false, + isDM = false, mode = RoomNotificationMode.ALL_MESSAGES ) notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = false, - isOneToOne = false, + isDM = false, mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ) val updatedState = consumeItemsUntilPredicate { diff --git a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt index 3d863321e3..15e320c8f8 100644 --- a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt +++ b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt @@ -23,7 +23,6 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.room.CallIntentConsensus import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.canCall import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState diff --git a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt index 4c6fcf8e59..0612adbea1 100644 --- a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt +++ b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt @@ -89,10 +89,10 @@ class RoomCallStatePresenterTest { } @Test - fun `present - initial state - when is direct room`() = runTest { + fun `present - initial state - when is DM room`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - initialRoomInfo = aRoomInfo(isDirect = true), + initialRoomInfo = aRoomInfo(isDm = true), roomPermissions = roomPermissions(true), ) ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 2ba7b4fa4a..56e5e1735e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -42,7 +42,6 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState @@ -53,7 +52,6 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction -import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -145,7 +143,7 @@ class RoomDetailsPresenter( } RoomDetailsEvent.UnmuteNotification -> { scope.launch(dispatchers.io) { - notificationSettingsService.unmuteRoom(room.roomId, isEncrypted, room.isOneToOne) + notificationSettingsService.unmuteRoom(room.roomId, isEncrypted, room.isDm()) } } is RoomDetailsEvent.SetFavorite -> scope.setFavorite(event.isFavorite) @@ -184,7 +182,7 @@ class RoomDetailsPresenter( isFavorite = isFavorite, displayRolesAndPermissionsSettings = !isDm && permissions.canEditRolesAndPermissions, isPublic = joinRule == JoinRule.Public, - heroes = roomInfo.heroes.toImmutableList(), + heroes = roomInfo.heroes, pinnedMessagesCount = pinnedMessagesCount, snackbarMessage = snackbarMessage, canShowKnockRequests = canShowKnockRequests, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index a8cd84be72..ad627d8677 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -74,6 +74,7 @@ fun aDmRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -83,7 +84,8 @@ fun aDmRoomMember( powerLevel = powerLevel, isIgnored = isIgnored, role = role, - membershipChangeReason = membershipChangeReason + membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomDetailsState( diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt index fb213ef0cc..23c6292294 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt @@ -128,6 +128,7 @@ fun aRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -138,6 +139,7 @@ fun aRoomMember( isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomMemberList() = persistentListOf( diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index c7930b5895..08dbf2019d 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -160,7 +160,7 @@ class RoomNotificationSettingsPresenter( suspend { val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() pendingModeState.value = null - notificationSettingsService.getRoomNotificationSettings(room.roomId, isEncrypted, room.isOneToOne).getOrThrow() + notificationSettingsService.getRoomNotificationSettings(room.roomId, isEncrypted, room.isDm()).getOrThrow() }.runCatchingUpdatingState(roomNotificationSettings) } @@ -170,7 +170,7 @@ class RoomNotificationSettingsPresenter( val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode( isEncrypted, - room.isOneToOne + room.isDm() ).getOrThrow() } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index 1b93a92884..3da2f5cf25 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -199,7 +199,7 @@ class RoomDetailsPresenterTest { givenRoomInfo( aRoomInfo( isEncrypted = true, - isDirect = true, + isDm = true, ) ) } @@ -284,7 +284,7 @@ class RoomDetailsPresenterTest { givenRoomInfo( aRoomInfo( isEncrypted = true, - isDirect = true, + isDm = true, ) ) } @@ -307,7 +307,6 @@ class RoomDetailsPresenterTest { val myRoomMember = aRoomMember(A_SESSION_ID) val otherRoomMember = aRoomMember(A_USER_ID_2) val room = aJoinedRoom( - isDirect = true, topic = null, roomPermissions = roomPermissions(), userDisplayNameResult = { Result.success(A_USER_NAME) }, @@ -325,7 +324,7 @@ class RoomDetailsPresenterTest { givenRoomInfo( aRoomInfo( - isDirect = true, + isDm = true, activeMembersCount = 2, topic = null, ) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt index 10c70d6f7d..882db26f00 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt @@ -15,7 +15,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.recent.getRecentlyVisitedRoomInfoFlow import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.roomlist.RoomListFilter diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt index 4e1fd34673..e0876c255c 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt @@ -67,7 +67,7 @@ class LeaveSpacePresenter( .orEmpty() .partition { it.spaceRoom.roomId == leaveSpaceHandle.id } // By default select all rooms that can be left - val otherRoomsExcludingDm = otherRooms.filter { it.spaceRoom.isDirect != true } + val otherRoomsExcludingDm = otherRooms.filter { it.spaceRoom.isDm != true } selectedRoomIds = otherRoomsExcludingDm .filter { it.isLastOwner.not() } .map { it.spaceRoom.roomId } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt index c43257b383..20f4918a98 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt @@ -109,6 +109,7 @@ private fun aSpaceInfo( avatarUrl = null, isPublic = true, isDirect = false, + isDm = false, isEncrypted = false, joinRule = joinRule, isSpace = true, diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt index b3b6fc7976..021f52defd 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt @@ -98,13 +98,13 @@ class LeaveSpacePresenterTest { listOf( aLeaveSpaceRoom(spaceRoom = aSpace), aLeaveSpaceRoom( - spaceRoom = aSpaceRoom(roomId = A_ROOM_ID, isDirect = false) + spaceRoom = aSpaceRoom(roomId = A_ROOM_ID, isDm = false) ), aLeaveSpaceRoom( - spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_2, isDirect = true) + spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_2, isDm = true) ), aLeaveSpaceRoom( - spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_3, isDirect = null) + spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_3, isDm = null) ), ) ) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt index ac3b0c8e3a..f515ce8c32 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt @@ -19,7 +19,7 @@ fun BaseRoom.toAnalyticsViewRoom( val activeSpace = selectedSpace?.toActiveSpace() ?: ViewRoom.ActiveSpace.Home return ViewRoom( - isDM = info().isDirect, + isDM = info().isDm, isSpace = info().isSpace, trigger = trigger, activeSpace = activeSpace, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt index 4d8ce8afb4..7ae1ca4886 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -21,7 +21,7 @@ interface NotificationSettingsService { val notificationSettingsChangeFlow: SharedFlow suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result - suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result + suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isDM: Boolean): Result suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result suspend fun muteRoom(roomId: RoomId): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt index 589f88e9fd..f7f4924d5a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt @@ -61,13 +61,12 @@ interface BaseRoom : Closeable { */ fun info(): RoomInfo = roomInfoFlow.value - fun predecessorRoom(): PredecessorRoom? - /** - * A one-to-one is a room with exactly 2 members. - * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). + * Returns whether the [BaseRoom] is a DM, with an updated state from the latest [RoomInfo]. */ - val isOneToOne: Boolean get() = info().activeMembersCount == 2L + fun isDm() = roomInfoFlow.value.isDm + + fun predecessorRoom(): PredecessorRoom? /** * Try to load the room members and update the membersFlow. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt index 5247e402a6..b9ed8d61b1 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt @@ -29,6 +29,7 @@ data class RoomInfo( val avatarUrl: String?, val isPublic: Boolean?, val isDirect: Boolean, + val isDm: Boolean, val isEncrypted: Boolean?, val joinRule: JoinRule?, val isSpace: Boolean, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt deleted file mode 100644 index f33319e2ee..0000000000 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.api.room - -import kotlinx.coroutines.flow.first - -/** - * Returns whether the room with the provided info is a DM. - * A DM is a room with at most 2 active members (one of them may have left). - * - * @param isDirect true if the room is direct - * @param activeMembersCount the number of active members in the room (joined or invited) - */ -fun isDm(isDirect: Boolean, activeMembersCount: Int): Boolean { - return isDirect && activeMembersCount <= 2 -} - -/** - * Returns whether the [BaseRoom] is a DM, with an updated state from the latest [RoomInfo]. - */ -suspend fun BaseRoom.isDm() = roomInfoFlow.first().isDm - -/** - * Returns whether the [RoomInfo] is from a DM. - */ -val RoomInfo.isDm get() = isDm(isDirect, activeMembersCount.toInt()) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt index 0b3d7071c8..abf685a38b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt @@ -22,6 +22,7 @@ data class RoomMember( val isIgnored: Boolean, val role: Role, val membershipChangeReason: String?, + val isServiceMember: Boolean, ) { /** * Role of the RoomMember, based on its [powerLevel]. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt index 1c35fab7d0..2c93fa94f0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt @@ -40,5 +40,5 @@ fun RoomMembersState.activeRoomMembers(): List { fun RoomMembersState.getDirectRoomMember(roomInfo: RoomInfo, sessionId: SessionId): RoomMember? { return roomMembers() ?.takeIf { roomInfo.isDm } - ?.find { it.userId != sessionId && it.membership.isActive() } + ?.find { !it.isServiceMember && it.userId != sessionId && it.membership.isActive() } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt index 6db326c854..3441a4be3a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt @@ -12,7 +12,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.toMatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.coroutines.flow.Flow diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt index aca093eab6..10ca376105 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt @@ -21,5 +21,5 @@ data class RoomSummary( is LatestEventValue.Remote -> latestEvent.timestamp is LatestEventValue.RoomInvite -> latestEvent.timestamp } - val isOneToOne get() = info.activeMembersCount == 2L + val isDm = info.isDm } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt index 6a72577760..e22b0a5c9c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt @@ -38,6 +38,7 @@ data class SpaceRoom( */ val via: ImmutableList, val isDirect: Boolean?, + val isDm: Boolean?, ) { val isSpace = roomType == RoomType.Space diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt deleted file mode 100644 index 1461d28fd9..0000000000 --- a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.api.room - -import com.google.common.truth.Truth.assertThat -import org.junit.Test - -class RoomIsDmCheckTest { - @Test - fun `a room is a DM only if it has at most 2 members and is direct`() { - val isDirect = true - val activeMembersCount = 2 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isTrue() - } - - @Test - fun `a room can be a DM if it has also a single active user`() { - val isDirect = true - val activeMembersCount = 1 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isTrue() - } - - @Test - fun `a room is not a DM if it's not direct`() { - val isDirect = false - val activeMembersCount = 2 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isFalse() - } - - @Test - fun `a room is not a DM if it has more than 2 active users`() { - val isDirect = true - val activeMembersCount = 3 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isFalse() - } -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 0bf26091c2..9a573a59c1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -41,6 +41,7 @@ import org.matrix.rustcomponents.sdk.SlidingSyncVersion import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder import org.matrix.rustcomponents.sdk.use import timber.log.Timber +import uniffi.matrix_sdk_base.DmRoomDefinition import uniffi.matrix_sdk_base.MediaRetentionPolicy import uniffi.matrix_sdk_crypto.CollectStrategy import uniffi.matrix_sdk_crypto.DecryptionSettings @@ -169,6 +170,7 @@ class RustMatrixClientFactory( ) .enableShareHistoryOnInvite(true) .threadsEnabled(featureFlagService.isFeatureEnabled(FeatureFlags.Threads), threadSubscriptions = false) + .dmRoomDefinition(DmRoomDefinition.TWO_MEMBERS) .requestConfig( RequestConfig( timeout = 30_000uL, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt index 263ce15bd3..8a0a246c22 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt @@ -11,7 +11,6 @@ package io.element.android.libraries.matrix.impl.analytics import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.isDm import kotlinx.coroutines.flow.first private fun Long.toAnalyticsRoomSize(): JoinedRoom.RoomSize { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt index f1996dd942..bfb49d6ceb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt @@ -17,7 +17,6 @@ import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.impl.room.join.map import io.element.android.services.toolbox.api.systemclock.SystemClock import org.matrix.rustcomponents.sdk.NotificationEvent @@ -37,10 +36,6 @@ class NotificationMapper( ): Result { return runCatchingExceptions { notificationItem.use { item -> - val isDm = isDm( - isDirect = item.roomInfo.isDirect, - activeMembersCount = item.roomInfo.joinedMembersCount.toInt(), - ) val timestamp = item.timestamp() ?: clock.epochMillis() NotificationData( sessionId = sessionId, @@ -50,10 +45,10 @@ class NotificationMapper( senderAvatarUrl = item.senderInfo.avatarUrl, senderDisplayName = item.senderInfo.displayName, senderIsNameAmbiguous = item.senderInfo.isNameAmbiguous, - roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { isDm }, + roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { item.roomInfo.isDm }, roomDisplayName = item.roomInfo.displayName, isDirect = item.roomInfo.isDirect, - isDm = isDm, + isDm = item.roomInfo.isDm, isSpace = item.roomInfo.isSpace, isEncrypted = item.roomInfo.isEncrypted.orFalse(), isNoisy = item.isNoisy.orFalse(), diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index 7da0f14d14..6a88e5051b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -62,11 +62,11 @@ class RustNotificationSettingsService( override suspend fun setDefaultRoomNotificationMode( isEncrypted: Boolean, mode: RoomNotificationMode, - isOneToOne: Boolean + isDM: Boolean ): Result = withContext(dispatchers.io) { runCatchingExceptions { try { - notificationSettings.await().setDefaultRoomNotificationMode(isEncrypted, isOneToOne, mode.let(RoomNotificationSettingsMapper::mapMode)) + notificationSettings.await().setDefaultRoomNotificationMode(isEncrypted, isDM, mode.let(RoomNotificationSettingsMapper::mapMode)) } catch (exception: NotificationSettingsException.RuleNotFound) { // `setDefaultRoomNotificationMode` updates multiple rules including unstable rules (e.g. the polls push rules defined in the MSC3930) // since production home servers may not have these rules yet, we drop the RuleNotFound error diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt index caeef02e8e..e75091eadc 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt @@ -348,7 +348,7 @@ class JoinedRustRoom( roomNotificationSettingsStateFlow.value = RoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) runCatchingExceptions { val isEncrypted = roomInfoFlow.value.isEncrypted ?: getUpdatedIsEncrypted().getOrThrow() - notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow() + notificationSettingsService.getRoomNotificationSettings(roomId = roomId, isEncrypted = isEncrypted, isOneToOne = isDm()).getOrThrow() }.map { roomNotificationSettingsStateFlow.value = RoomNotificationSettingsState.Ready(it) }.onFailure { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt index 668cfc46df..4c8da1aca7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt @@ -18,7 +18,7 @@ import org.matrix.rustcomponents.sdk.RoomInfo */ fun RoomInfo.elementHeroes(): List { return heroes - .takeIf { isDirect && activeMembersCount.toLong() == 2L } + .takeIf { isDm } ?.takeIf { it.size == 1 } ?.map { it.map() } .orEmpty() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt index deca0f8ee6..0e9aadc65b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt @@ -43,6 +43,7 @@ class RoomInfoMapper { avatarUrl = it.avatarUrl, isPublic = it.isPublic, isDirect = it.isDirect, + isDm = it.isDm, isEncrypted = when (it.encryptionState) { EncryptionState.ENCRYPTED -> true EncryptionState.NOT_ENCRYPTED -> false diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index e73bed084e..0551891a6d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -23,7 +23,6 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.draft.ComposerDraft -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom @@ -119,7 +118,7 @@ class RustBaseRoom( innerRoom.membersNoSync().use { members -> members.nextChunk(members.len()) ?.map(RoomMemberMapper::map) - ?.firstOrNull { roomMember -> roomMember.userId != sessionId && roomMember.membership.isActive() } + ?.firstOrNull { roomMember -> !roomMember.isServiceMember && roomMember.userId != sessionId && roomMember.membership.isActive() } } } else { null diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt index 447fa427a6..33ecb74ff3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt @@ -28,7 +28,8 @@ object RoomMemberMapper { powerLevel = powerLevel, isIgnored = roomMember.isIgnored, role = mapRole(roomMember.suggestedRoleForPowerLevel, powerLevel), - membershipChangeReason = roomMember.membershipChangeReason + membershipChangeReason = roomMember.membershipChangeReason, + isServiceMember = roomMember.isServiceMember, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt index f83cd648a6..cd729d0df1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt @@ -36,6 +36,7 @@ class SpaceRoomMapper { worldReadable = spaceRoom.worldReadable.orFalse(), via = spaceRoom.via.toImmutableList(), isDirect = spaceRoom.isDirect, + isDm = spaceRoom.isDm, ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 7b398529a0..5da4be408d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -20,7 +20,6 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MsgType diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt index 68adfe00a2..3c094f3581 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt @@ -43,6 +43,19 @@ class JoinedExtKtTest { @Test fun `test isDirect parameter mapping`() = runTest { assertThat(aRoom(isDirect = true).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = false, + roomSize = JoinedRoom.RoomSize.One, + trigger = null + ) + ) + } + + @Test + fun `test isDm parameter mapping`() = runTest { + assertThat(aRoom(isDm = true).toAnalyticsJoinedRoom(null)) .isEqualTo( JoinedRoom( isDM = true, @@ -80,12 +93,13 @@ class JoinedExtKtTest { } private fun aRoom( + isDm: Boolean = false, isDirect: Boolean = false, isSpace: Boolean = false, joinedMemberCount: Long = 0 ): FakeBaseRoom { return FakeBaseRoom().apply { - givenRoomInfo(aRoomInfo(isDirect = isDirect, isSpace = isSpace, joinedMembersCount = joinedMemberCount)) + givenRoomInfo(aRoomInfo(isDm = isDm, isDirect = isDirect, isSpace = isSpace, joinedMembersCount = joinedMemberCount)) } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt index 50e2f6168e..2eb46eddaf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt @@ -50,5 +50,5 @@ internal fun aRustSpaceRoom( childrenCount = childrenCount, state = state, heroes = heroes, - via = emptyList() + via = emptyList(), ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt index 59d82487b9..623fe9a8cf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt @@ -17,6 +17,7 @@ import org.matrix.rustcomponents.sdk.RequestConfig import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder import org.matrix.rustcomponents.sdk.SqliteStoreBuilder import uniffi.matrix_sdk.BackupDownloadStrategy +import uniffi.matrix_sdk_base.DmRoomDefinition import uniffi.matrix_sdk_crypto.CollectStrategy import uniffi.matrix_sdk_crypto.DecryptionSettings @@ -47,5 +48,6 @@ class FakeFfiClientBuilder( override fun sqliteStore(config: SqliteStoreBuilder): ClientBuilder = this override fun inMemoryStore(): ClientBuilder = this override fun crossProcessLockConfig(crossProcessLockConfig: CrossProcessLockConfig): ClientBuilder = this + override fun dmRoomDefinition(dmRoomDefinition: DmRoomDefinition): ClientBuilder = this override suspend fun build() = buildResult() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index 86a50c3926..dd91595359 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -20,8 +20,7 @@ class RoomInfoExtTest { @Test fun `get non empty element Heroes`() { val result = aRustRoomInfo( - isDirect = true, - activeMembersCount = 2uL, + isDm = true, heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEqualTo( @@ -38,8 +37,7 @@ class RoomInfoExtTest { @Test fun `too many heroes and element Heroes is empty`() { val result = aRustRoomInfo( - isDirect = true, - activeMembersCount = 2uL, + isDm = true, heroes = listOf(aRustRoomHero(), aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() @@ -48,18 +46,7 @@ class RoomInfoExtTest { @Test fun `not direct and element Heroes is empty`() { val result = aRustRoomInfo( - isDirect = false, - activeMembersCount = 2uL, - heroes = listOf(aRustRoomHero()) - ).elementHeroes() - assertThat(result).isEmpty() - } - - @Test - fun `too many members and element Heroes is empty`() { - val result = aRustRoomInfo( - isDirect = true, - activeMembersCount = 3uL, + isDm = false, heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt index ab353bc0f5..56b480d97f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt @@ -86,6 +86,7 @@ class RoomInfoMapperTest { privilegedCreatorsRole = true, isLowPriority = true, activeRoomCallConsensusIntent = RtcCallIntentConsensus.Full(RtcCallIntent.AUDIO), + isDm = true, ) ) ).isEqualTo( @@ -136,6 +137,7 @@ class RoomInfoMapperTest { privilegedCreatorRole = true, isLowPriority = true, activeCallIntentConsensus = CallIntentConsensus.Full(CallIntent.AUDIO), + isDm = true, ) ) } @@ -181,6 +183,7 @@ class RoomInfoMapperTest { privilegedCreatorsRole = true, isLowPriority = true, activeRoomCallConsensusIntent = RtcCallIntentConsensus.None, + isDm = false, ) ) ).isEqualTo( @@ -225,6 +228,7 @@ class RoomInfoMapperTest { privilegedCreatorRole = true, isLowPriority = true, activeCallIntentConsensus = CallIntentConsensus.None, + isDm = false, ) ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index 564cd231b2..f7970e7971 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -70,12 +70,12 @@ class FakeNotificationSettingsService( } } - override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result { + override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isDM: Boolean): Result { val error = setDefaultNotificationModeError if (error != null) { return Result.failure(error) } - if (isOneToOne) { + if (isDM) { if (isEncrypted) { defaultEncryptedOneToOneRoomNotificationMode = mode } else { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index 9f7255ab18..b4425ddd4b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -134,7 +134,11 @@ class FakeJoinedRoom( } override suspend fun updateRoomNotificationSettings(): Result = simulateLongTask { - val notificationSettings = roomNotificationSettingsService.getRoomNotificationSettings(roomId, info().isEncrypted.orFalse(), isOneToOne).getOrThrow() + val notificationSettings = roomNotificationSettingsService.getRoomNotificationSettings( + roomId = roomId, + isEncrypted = info().isEncrypted.orFalse(), + isOneToOne = isDm(), + ).getOrThrow() (roomNotificationSettingsStateFlow as MutableStateFlow).value = RoomNotificationSettingsState.Ready(notificationSettings) return Result.success(Unit) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt index c7faaba627..c15330e9dc 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt @@ -71,6 +71,7 @@ fun aRoomInfo( privilegedCreatorRole: Boolean = false, isLowPriority: Boolean = false, activeCallIntentConsensus: CallIntentConsensus = CallIntentConsensus.None, + isDm: Boolean = false, ) = RoomInfo( id = id, name = name, @@ -109,4 +110,5 @@ fun aRoomInfo( privilegedCreatorRole = privilegedCreatorRole, isLowPriority = isLowPriority, activeCallIntentConsensus = activeCallIntentConsensus, + isDm = isDm, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt index f6bc0c5ec2..33a1b68ba3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt @@ -23,6 +23,7 @@ fun aRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -33,6 +34,7 @@ fun aRoomMember( isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomMemberList() = persistentListOf( diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index afe4c88f5a..32635a7eea 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -120,6 +120,7 @@ fun aRoomSummary( privilegedCreatorRole = privilegedCreatorRole, isLowPriority = isLowPriority, activeCallIntentConsensus = activeCallIntentConsensus, + isDm = false, ), latestEvent = latestEvent, ) diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt index 816ac0967e..737fff34ee 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt @@ -30,13 +30,10 @@ class RoomMembersTest { private val roomMember3 = aRoomMember(A_USER_ID_3) @Test - fun `getDirectRoomMember emits other member for encrypted DM with 2 joined members`() = runTest { + fun `getDirectRoomMember emits other member for encrypted DM`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo( - isDirect = true, - joinedMembersCount = 2, - ) + initialRoomInfo = aRoomInfo(isDm = true, isEncrypted = true) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -51,7 +48,7 @@ class RoomMembersTest { fun `getDirectRoomMember emit null if the room is not a dm`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(isDirect = false) + initialRoomInfo = aRoomInfo(isDm = false) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -66,10 +63,7 @@ class RoomMembersTest { fun `getDirectRoomMember emits other member even if the room is not encrypted`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo( - isDirect = true, - activeMembersCount = 2, - ) + initialRoomInfo = aRoomInfo(isDm = true) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -80,42 +74,11 @@ class RoomMembersTest { } } - @Test - fun `getDirectRoomMember emit null if the room has only 1 member`() = runTest { - val joinedRoom = FakeBaseRoom( - sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(isDirect = true) - ) - moleculeFlow(RecompositionMode.Immediate) { - joinedRoom.getDirectRoomMember( - RoomMembersState.Ready(persistentListOf(roomMember1)) - ) - }.test { - assertThat(awaitItem().value).isNull() - } - } - - @Test - fun `getDirectRoomMember emit null if the room has only 3 members`() = runTest { - val joinedRoom = FakeBaseRoom( - sessionId = A_USER_ID, - ).apply { - givenRoomInfo(aRoomInfo(isDirect = true, activeMembersCount = 3L)) - } - moleculeFlow(RecompositionMode.Immediate) { - joinedRoom.getDirectRoomMember( - RoomMembersState.Ready(persistentListOf(roomMember1, roomMember2, roomMember3)) - ) - }.test { - assertThat(awaitItem().value).isNull() - } - } - @Test fun `getDirectRoomMember emit null if the other member is not active`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(isDirect = true), + initialRoomInfo = aRoomInfo(isDm = true), ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -135,10 +98,7 @@ class RoomMembersTest { fun `getDirectRoomMember emit the other member if there are 2 active members`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo( - isDirect = true, - activeMembersCount = 2, - ) + initialRoomInfo = aRoomInfo(isDm = true) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt index 42fc527bb2..49f77ddefb 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt @@ -33,6 +33,7 @@ fun aRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -43,6 +44,7 @@ fun aRoomMember( isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomMemberList() = persistentListOf( diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt index 68825540a4..6f86789693 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt @@ -34,6 +34,7 @@ fun aSpaceRoom( topic: String? = null, worldReadable: Boolean = false, isDirect: Boolean? = null, + isDm: Boolean? = null, via: List = emptyList(), ) = SpaceRoom( rawName = rawName, @@ -51,5 +52,6 @@ fun aSpaceRoom( topic = topic, worldReadable = worldReadable, via = via.toImmutableList(), - isDirect = isDirect + isDirect = isDirect, + isDm = isDm, ) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt index eb08a25c6a..cb9ef8c82d 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt @@ -19,7 +19,6 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.preferences.api.store.SessionPreferencesStoreFactory From a227b830beb62b517c651a6be76cb7cad412aa19 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 11 May 2026 18:08:28 +0200 Subject: [PATCH 0400/1083] add test to MessageSummaryFormatter --- .../DefaultMessageSummaryFormatterTest.kt | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt new file mode 100644 index 0000000000..7d0a097b3c --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.utils + +import android.content.Context +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.Location +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent.Mode +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent +import io.element.android.features.messages.impl.utils.messagesummary.DefaultMessageSummaryFormatter +import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.timeline.aProfileDetails +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +class DefaultMessageSummaryFormatterTest { + private val formatter = DefaultMessageSummaryFormatter( + RuntimeEnvironment.getApplication() as Context + ) + + @Test + @Config(qualifiers = "en") + fun `format call notification started`() { + val expected = formatter.format(TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Started + )) + + assertThat(expected).isEqualTo("Call started") + } + + @Test + @Config(qualifiers = "en") + fun `format call notification declined by me`() { + val expected = formatter.format(TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Declined(byMe = true) + )) + + assertThat(expected).isEqualTo("You declined a call") + } + + @Test + @Config(qualifiers = "en") + fun `format call notification declined`() { + val expected = formatter.format(TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Declined(byMe = false) + )) + + assertThat(expected).isEqualTo("Call declined") + } + + @Test + @Config(qualifiers = "en") + fun `format live location`() { + val expected = formatter.format( + aLocationContent(isLive = true) + ) + + assertThat(expected).isEqualTo("Shared live location") + } + + @Test + @Config(qualifiers = "en") + fun `format static location`() { + val expected = formatter.format( + aLocationContent(isLive = false) + ) + + assertThat(expected).isEqualTo("Shared location") + } +} + +private fun aLocationContent(isLive: Boolean): TimelineItemLocationContent = TimelineItemLocationContent( + senderId = A_USER_ID, + senderProfile = aProfileDetails(), + description = null, + assetType = null, + mode = if (isLive) { + Mode.Live( + lastKnownLocation = Location.fromGeoUri("geo:1,5"), + isActive = true, + endsAt = "", + endTimestamp = 0, + isOwnUser = true + ) + } else { + Mode.Static( + location = Location.fromGeoUri("geo:1,5")!! + ) + } +) From e0046e9862bc4d0475e5a60b7cd98363e465230f Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Mon, 11 May 2026 11:27:31 -0700 Subject: [PATCH 0401/1083] Return null instead of return@launch Co-authored-by: Benoit Marty --- .../features/messages/impl/timeline/TimelinePresenter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5fb63a4f4b..2507b046f2 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 @@ -228,7 +228,7 @@ class TimelinePresenter( TimelineEvent.MarkAllAsRead -> sessionCoroutineScope.launch { val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { Timber.tag(tag).w(it, "Failed to get latest event id to mark as fully read") - return@launch + null } ?: return@launch markAsFullyRead(room.roomId, latestEventId) } From 65ed527384a6d77ad5c804b421ed473f03a10197 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Mon, 11 May 2026 11:34:28 -0700 Subject: [PATCH 0402/1083] Add comment to explain jump to bottom button containing box --- .../android/features/messages/impl/timeline/TimelineView.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index a2a40071c3..443fc1681a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -430,6 +430,8 @@ private fun BoxScope.TimelineScrollHelper( onMarkAsRead = onMarkAllAsRead, testTag = TestTags.jumpToUnreadButton, ) + // Reserves space for the jump to bottom button so the jump to unread button above + // stays in the same position regardless of whether the jump to bottom button is visible. Box(modifier = Modifier.size(36.dp)) { JumpToPositionButton( icon = CompoundIcons.ChevronDown(), From 8d8ac9373efc1cae4d868868025669dc11f226fe Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Mon, 11 May 2026 11:59:10 -0700 Subject: [PATCH 0403/1083] Rename preview to reflect actual state --- .../android/features/messages/impl/timeline/TimelineView.kt | 5 ++++- .../io/element/android/tests/konsist/KonsistPreviewTest.kt | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 443fc1681a..cec1d57e58 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -604,6 +604,9 @@ internal fun TimelineViewPreview( } } +// The jump-to-unread FAB's indicator is always rendered when the FAB is visible — in +// production the FAB only appears when unread content exists above. So `hasUnreadAbove` +// here only varies the scroll-target state, not the upper indicator's visibility. @Composable private fun TimelineViewWithReadMarker( hasUnreadAbove: Boolean, @@ -648,7 +651,7 @@ private fun TimelineViewWithReadMarker( @PreviewsDayNight @Composable -internal fun TimelineViewWithReadMarkerNoIndicatorsPreview() = ElementPreview { +internal fun TimelineViewWithReadMarkerJumpToUnreadIndicatorOnlyPreview() = ElementPreview { TimelineViewWithReadMarker(hasUnreadAbove = false, hasUnreadBelow = false) } 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 6dc0e7fc56..0a8d5d6b89 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 @@ -161,7 +161,7 @@ class KonsistPreviewTest { "TimelineVideoWithCaptionRowPreview", "TimelineViewMessageShieldPreview", "TimelineViewWithReadMarkerBothIndicatorsPreview", - "TimelineViewWithReadMarkerNoIndicatorsPreview", + "TimelineViewWithReadMarkerJumpToUnreadIndicatorOnlyPreview", "UserAvatarColorsPreview", "UserProfileHeaderSectionWithVerificationViolationPreview", "VoiceItemViewPlayPreview", From 77b444581d9ead7cd9ef45f64c09832f9cd9d7a8 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 12 May 2026 11:40:46 +0200 Subject: [PATCH 0404/1083] Improve `FetchPushForegroundService`'s reliability (#6757) * Improve `FetchPushForegroundService`'s reliability - Don't use DI, we can just create the notification channel. This should speed up the creation of the service and reduce the number of `ForegroundServiceDidNotStartInTimeException` received. Also use `MainScope` instead of the app's coroutine scope. - Move the wakelock releasing mechanism to `onDestroy` so it's always used. Previously, this would only happen when `stopService` was called, which would only happen when `stopSelf()` is called, but not when the OS or the service manager stops the service. * Add fallback value for the notification channel title * Replace the wrong string for the notification/channel title --------- Co-authored-by: Benoit Marty --- .../libraries/push/impl/di/PushBindings.kt | 17 ----- .../impl/push/FetchPushForegroundService.kt | 65 ++++++++++++------- .../src/main/res/values-cs/translations.xml | 2 +- .../src/main/res/values-da/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-el/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 2 +- .../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-it/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 2 +- .../main/res/values-zh-rTW/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values/localazy.xml | 2 +- 22 files changed, 60 insertions(+), 62 deletions(-) delete mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt deleted file mode 100644 index 49b2c43bc7..0000000000 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt +++ /dev/null @@ -1,17 +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.di - -import dev.zacsweers.metro.AppScope -import dev.zacsweers.metro.ContributesTo -import io.element.android.libraries.push.impl.push.FetchPushForegroundService - -@ContributesTo(AppScope::class) -interface PushBindings { - fun inject(fetchPushForegroundService: FetchPushForegroundService) -} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt index 2b3587837e..b1c90a374a 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt @@ -13,17 +13,14 @@ import android.content.pm.ServiceInfo import android.os.Build import android.os.IBinder import android.os.PowerManager +import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat import androidx.core.app.ServiceCompat -import dev.zacsweers.metro.Inject -import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.push.impl.di.PushBindings -import io.element.android.libraries.push.impl.notifications.channels.NotificationChannels import io.element.android.libraries.ui.strings.CommonStrings -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import timber.log.Timber @@ -34,6 +31,12 @@ private const val NOTIFICATION_ID = 1001 // This kind of foreground service can only last up to 3 minutes before onTimeout is called private val wakelockTimeout = 3.minutes.inWholeMilliseconds +// The channel ID to use for the notification of the foreground service. +private const val CHANNEL_ID = "fetch_push_notification_channel" + +// The tag to use for the wakelock, this is used for debugging purposes and should be unique to this service. +private const val WAKELOCK_TAG = "FetchPushService:WakeLock" + /** * Foreground service used to ensure the device stays awake while we handle the pushes and schedule and run the work to fetch the notification content. */ @@ -42,28 +45,35 @@ class FetchPushForegroundService : Service() { return null } - @Inject lateinit var notificationChannels: NotificationChannels - @Inject @AppCoroutineScope lateinit var coroutineScope: CoroutineScope - private val wakelock: PowerManager.WakeLock by lazy { val powerManager = getSystemService(POWER_SERVICE) as PowerManager - powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FetchPushService:WakeLock").apply { + powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG).apply { setReferenceCounted(false) } } private var isOnForeground = false + private fun ensureNotificationChannelExists() { + NotificationManagerCompat.from(this).createNotificationChannelsCompat( + listOf( + NotificationChannelCompat.Builder(CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_LOW) + .setName(getString(CommonStrings.common_fetching_notifications_title_android).ifEmpty { "Syncing notifications…" }) + .setVibrationEnabled(false) + .setSound(null, null) + .build() + ) + ) + } + override fun onCreate() { - Timber.d("Creating FetchPushForegroundService") + Timber.i("Creating FetchPushForegroundService to handle incoming push, acquiring wakelock for up to $wakelockTimeout ms") + ensureNotificationChannelExists() - bindings().inject(this) - - Timber.d("Starting FetchPushForegroundService with wakelock timeout of $wakelockTimeout ms") // Start the foreground service as soon as possible - val notificationCompat = NotificationCompat.Builder(this, notificationChannels.getSilentChannelId()) + val notificationCompat = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(CommonDrawables.ic_notification) - .setContentTitle(getString(CommonStrings.common_android_fetching_notifications_title)) + .setContentTitle(getString(CommonStrings.common_fetching_notifications_title_android).ifEmpty { "Syncing notifications…" }) .setProgress(0, 0, true) .setVibrate(longArrayOf(0)) .setSound(null) @@ -103,7 +113,7 @@ class FetchPushForegroundService : Service() { // The timeout is not automatic before Android 15, so we need to schedule it ourselves if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { - coroutineScope.launch { + MainScope().launch { delay(wakelockTimeout) onTimeoutAction(calledByTheSystem = false) } @@ -112,13 +122,18 @@ class FetchPushForegroundService : Service() { return START_NOT_STICKY } - override fun stopService(intent: Intent?): Boolean { - if (isOnForeground) { - wakelock.release() - ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) - } + override fun onDestroy() { + super.onDestroy() - return super.stopService(intent) + if (isOnForeground) { + Timber.i("Destroying FetchPushForegroundService, releasing wakelock and stopping foreground") + if (wakelock.isHeld) { + wakelock.release() + } + ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) + } else { + Timber.w("Destroying FetchPushForegroundService that was not running in foreground, this is unexpected") + } } override fun onTimeout(startId: Int) { @@ -127,9 +142,9 @@ class FetchPushForegroundService : Service() { } private fun onTimeoutAction(calledByTheSystem: Boolean) { - Timber.d("onTimeoutAction, calledByTheSystem: $calledByTheSystem, isOnForeground: $isOnForeground") + Timber.w("onTimeoutAction, calledByTheSystem: $calledByTheSystem, isOnForeground: $isOnForeground") if (isOnForeground) { - Timber.d("Wakelock timeout reached, stopping FetchPushForegroundService") + Timber.w("Wakelock timeout reached, stopping FetchPushForegroundService") stopSelf() } } diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index e177c23957..4a8623f5dc 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -198,7 +198,6 @@ "Pokročilá nastavení" "obrázek" "Analytika" - "Synchronizace oznámení…" "Opustili jste místnost" "Byli jste odhlášeni z relace" "Vzhled" @@ -242,6 +241,7 @@ Důvod: %1$s." "Selhalo" "Oblíbené" "Oblíbené" + "Synchronizace oznámení…" "Soubor" "Soubor smazán" "Soubor uložen" 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 1769a5d223..0837d0bb33 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -198,7 +198,6 @@ "Avancerede indstillinger" "et billede" "Analyse-værktøj" - "Synkroniserer notifikationer…" "Du forlod rummet" "Du blev logget ud af sessionen" "Udseende" @@ -244,6 +243,7 @@ "Mislykkedes" "Favorit" "Favoritmarkeret" + "Synkroniserer notifikationer…" "Fil" "Fil slettet" "Fil gemt" 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 e6332b9df2..1a9190568c 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -192,7 +192,6 @@ "Erweiterte Einstellungen" "ein Bild" "Analysedaten" - "Benachrichtigungen werden synchronisiert…" "Du hast den Chat verlassen" "Du wurdest aus der Sitzung abgemeldet." "Erscheinungsbild" @@ -236,6 +235,7 @@ Grund: %1$s." "Fehlgeschlagen" "Favorit" "Favorisiert" + "Benachrichtigungen werden synchronisiert…" "Datei" "Datei wurde gelöscht" "Datei gespeichert" 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 a12122b00b..e5d6d0d1f5 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -192,7 +192,6 @@ "Ρυθμίσεις για προχωρημένους" "μια εικόνα" "Στατιστικά στοιχεία" - "Συγχρονισμός ειδοποιήσεων…" "Αποχωρήσατε από την αίθουσα" "Αποσυνδεθήκατε από την περίοδο λειτουργίας" "Εμφάνιση" @@ -236,6 +235,7 @@ "Απέτυχε" "Αγαπημένο" "Είναι αγαπημένο" + "Συγχρονισμός ειδοποιήσεων…" "Αρχείο" "Το αρχείο διαγράφηκε" "Το αρχείο αποθηκεύτηκε" 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 e76e3153e1..6004792f51 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -197,7 +197,6 @@ "Täiendavad seadistused" "pilt" "Analüütika" - "Sünkroonin teavitusi…" "Sina lahkusid jututoast" "Sa olid sessioonist väljaloginud" "Välimus" @@ -242,6 +241,7 @@ Põhjus: %1$s." "Ei õnnestunud" "Lemmik" "Märgitud lemmikuks" + "Sünkroonin teavitusi…" "Fail" "Fail on kustutatud" "Fail on salvestatud" 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 e35ef5c2e1..1a7f6c50c9 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -193,7 +193,6 @@ "Edistyneet asetukset" "kuva" "Analytiikka" - "Synkronoidaan ilmoituksia…" "Poistuit huoneesta" "Sinut kirjattiin ulos istunnosta" "Ulkoasu" @@ -237,6 +236,7 @@ Syy: %1$s." "Epäonnistui" "Lisää suosikkeihin" "Lisätty suosikkeihin" + "Synkronoidaan ilmoituksia…" "Tiedosto" "Tiedosto poistettu" "Tiedosto tallennettu" 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 7617571f17..5cb21b772f 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -198,7 +198,6 @@ "Paramètres avancés" "une image" "Statistiques d’utilisation" - "Synchronisation des notifications…" "Vous avez quitté le salon" "Vous avez été déconnecté de la session" "Apparence" @@ -244,6 +243,7 @@ Raison : %1$s." "Échec" "Favori" "Ajouté aux favoris" + "Synchronisation des notifications…" "Fichier" "Fichier supprimé" "Fichier enregistré" 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 7c3cfbd83b..bb6cf79187 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -200,7 +200,6 @@ "Napredne postavke" "slika" "Analitika" - "Sinkronizacija obavijesti…" "Napustili ste sobu" "Odjavljeni ste iz sesije" "Izgled" @@ -246,6 +245,7 @@ Razlog: %1$s ." "Nije uspjelo" "Favorit" "Označeno kao favorit" + "Sinkronizacija obavijesti…" "Datoteka" "Datoteka je izbrisana" "Datoteka je spremljena" 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 8973ebc4f6..c477a6b6ba 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -199,7 +199,6 @@ "Speciális beállítások" "egy kép" "Elemzések" - "Értesítések szinkronizálása…" "Elhagyta a szobát" "Ki lett jelentkeztetve a munkamenetből" "Megjelenítés" @@ -245,6 +244,7 @@ Ok: %1$s." "Sikertelen" "Kedvenc" "Kedvencnek jelölve" + "Értesítések szinkronizálása…" "Fájl" "Fájl törölve" "A fájl mentve" 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 ba0d6f022c..cdc523a5ab 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -199,7 +199,6 @@ "Impostazioni avanzate" "un\'immagine" "Statistiche di utilizzo" - "Sincronizzazione delle notifiche…" "Hai lasciato la stanza" "Sei stato disconnesso dalla sessione" "Aspetto" @@ -245,6 +244,7 @@ Motivo:. %1$s" "Fallito" "Preferiti" "Preferita" + "Sincronizzazione delle notifiche…" "File" "File eliminato" "File salvato" 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 b7a33d4dfd..e25ca0cf4e 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -197,7 +197,6 @@ "高度な設定" "画像" "分析" - "通知を同期中…" "あなたがルームを退出" "セッションからログアウトされました" "テーマ" @@ -243,6 +242,7 @@ "失敗" "お気に入り" "お気に入り" + "通知を同期中…" "ファイル" "ファイルを削除しました" "ファイルを保存しました" 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 4f594f002b..3a029e20fc 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -190,7 +190,6 @@ "고급 설정" "이미지" "통계" - "알림 동기화 중…" "방을 떠남" "세션에서 로그아웃되었습니다." "외관" @@ -234,6 +233,7 @@ "실패" "즐겨찾기" "즐겨찾기 됨" + "알림 동기화 중…" "파일" "파일 삭제됨" "파일 저장됨" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index 30f2c383b6..1a9a45cd94 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -201,7 +201,6 @@ "Ustawienia zaawansowane" "obraz" "Dane analityczne" - "Synchronizuję powiadomienia…" "Opuściłeś pokój" "Zostałeś wylogowany z sesji" "Wygląd" @@ -247,6 +246,7 @@ Powód: %1$s." "Niepowodzenie" "Ulubione" "Ulubione" + "Synchronizuję powiadomienia…" "Plik" "Plik usunięty" "Plik zapisany" 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 a691d1d69b..fe852dcfd0 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -195,7 +195,6 @@ "Расширенные настройки" "изображение" "Аналитика" - "Синхронизация уведомлений…" "Вы покинули комнату" "Вы вышли из сессии" "Внешний вид" @@ -239,6 +238,7 @@ "Ошибка" "Избранное" "Избранное" + "Синхронизация уведомлений…" "Файл" "Файл удалён" "Файл сохранен" diff --git a/libraries/ui-strings/src/main/res/values-uk/translations.xml b/libraries/ui-strings/src/main/res/values-uk/translations.xml index db0fa31804..a9e1d14b40 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -201,7 +201,6 @@ "Додаткові налаштування" "зображення" "Аналітика" - "Синхронізація сповіщень…" "Ви вийшли з кімнати" "Ви вийшли з сеансу" "Тема" @@ -247,6 +246,7 @@ "Помилка" "Обране" "Обране" + "Синхронізація сповіщень…" "Файл" "Файл видалено" "Файл збережено" 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 304a044e0b..50d14ef4d4 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -193,7 +193,6 @@ "Kengaytirilgan sozlamalar" "rasm" "Analitika" - "Bildirishnomalar sinxronlanmoqda…" "Siz xonani tark etdingiz" "Siz sessiyadan chiqdingiz" "Ko\'rinish" @@ -237,6 +236,7 @@ Sababi:%1$s." "Xatolikka uchradi" "Sevimli" "Sevimli" + "Bildirishnomalar sinxronlanmoqda…" "Fayl" "Fayl o\'chirildi" "Fayl saqlandi" 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 2db0ce1dae..825ff12bea 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -191,7 +191,6 @@ "Cài đặt nâng cao" "một hình ảnh" "Phân tích" - "Đang đồng bộ thông báo…" "Bạn rời phòng" "Bạn đã bị đăng xuất" "Giao diện" @@ -235,6 +234,7 @@ Lý do: %1$s ." "Thất bại" "Yêu thích" "Được yêu thích" + "Đang đồng bộ thông báo…" "Tập tin" "Tệp đã bị xóa" "Tệp đã được lưu" 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 819c993bb1..b4c993e852 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -191,7 +191,6 @@ "進階設定" "影像" "分析" - "正在同步通知……" "您離開聊天室" "您已登出工作階段" "外觀" @@ -235,6 +234,7 @@ "失敗" "我的最愛" "我的最愛" + "正在同步通知……" "檔案" "檔案已刪除" "檔案已儲存" 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 00bb686f78..7366a4fd95 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -196,7 +196,6 @@ "高级设置" "一张图片" "分析" - "正在同步通知…" "你离开了房间" "你已注销会话" "外观" @@ -242,6 +241,7 @@ "失败" "收藏" "已收藏" + "正在同步通知…" "文件" "文件已删除" "文件已保存" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 656ec50569..173a525919 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -199,7 +199,6 @@ "Advanced settings" "an image" "Analytics" - "Syncing notifications…" "You left the room" "You were logged out of the session" "Appearance" @@ -245,6 +244,7 @@ Reason: %1$s." "Failed" "Favourite" "Favourited" + "Syncing notifications…" "File" "File deleted" "File saved" From 72be7ff1f9a2bf1b0bff2136ab92421560185865 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 May 2026 12:23:16 +0200 Subject: [PATCH 0405/1083] Reduce FeatureFlags `Knock` effect on room creation and room edition form. Closes #6701 --- features/knockrequests/impl/build.gradle.kts | 2 -- .../impl/data/KnockRequestsModule.kt | 7 ++----- .../impl/data/KnockRequestsService.kt | 19 ++++++------------- .../KnockRequestsBannerPresenterTest.kt | 14 -------------- .../list/KnockRequestsListPresenterTest.kt | 1 - .../roomdetails/impl/RoomDetailsPresenter.kt | 8 +------- .../impl/RoomDetailsPresenterTest.kt | 18 +----------------- 7 files changed, 10 insertions(+), 59 deletions(-) diff --git a/features/knockrequests/impl/build.gradle.kts b/features/knockrequests/impl/build.gradle.kts index 6f030479f5..e6a1a30167 100644 --- a/features/knockrequests/impl/build.gradle.kts +++ b/features/knockrequests/impl/build.gradle.kts @@ -33,9 +33,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.uiStrings) implementation(projects.libraries.designsystem) - implementation(projects.libraries.featureflag.api) testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.libraries.featureflag.test) } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt index b51b78f105..73e4a2ddeb 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt @@ -15,8 +15,6 @@ import dev.zacsweers.metro.SingleIn import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.api.knockRequestPermissions import io.element.android.libraries.di.RoomScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.powerlevels.permissionsFlow @@ -25,14 +23,13 @@ import io.element.android.libraries.matrix.api.room.powerlevels.permissionsFlow object KnockRequestsModule { @Provides @SingleIn(RoomScope::class) - fun knockRequestsService(room: JoinedRoom, featureFlagService: FeatureFlagService): KnockRequestsService { + fun knockRequestsService(room: JoinedRoom): KnockRequestsService { return KnockRequestsService( knockRequestsFlow = room.knockRequestsFlow, permissionsFlow = room.permissionsFlow(KnockRequestPermissions.DEFAULT) { perms -> perms.knockRequestPermissions() }, - isKnockFeatureEnabledFlow = featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock), - coroutineScope = room.roomCoroutineScope + coroutineScope = room.roomCoroutineScope, ) } } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt index 98570e6b28..00e0a30563 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt @@ -12,7 +12,6 @@ import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.knock.KnockRequest -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async @@ -28,26 +27,20 @@ import kotlinx.coroutines.supervisorScope class KnockRequestsService( knockRequestsFlow: Flow>, permissionsFlow: Flow, - isKnockFeatureEnabledFlow: Flow, coroutineScope: CoroutineScope, ) { // Keep track of the knock requests that have been handled, so we don't have to wait for sync to remove them. private val handledKnockRequestIds = MutableStateFlow>(emptySet()) val knockRequestsFlow = combine( - isKnockFeatureEnabledFlow, knockRequestsFlow, handledKnockRequestIds, - ) { isKnockEnabled, knockRequests, handledKnockIds -> - if (!isKnockEnabled) { - AsyncData.Success(persistentListOf()) - } else { - val presentableKnockRequests = knockRequests - .filter { it.eventId !in handledKnockIds } - .map { inner -> KnockRequestWrapper(inner) } - .toImmutableList() - AsyncData.Success(presentableKnockRequests) - } + ) { knockRequests, handledKnockIds -> + val presentableKnockRequests = knockRequests + .filter { it.eventId !in handledKnockIds } + .map { inner -> KnockRequestWrapper(inner) } + .toImmutableList() + AsyncData.Success(presentableKnockRequests) }.stateIn(coroutineScope, SharingStarted.Lazily, AsyncData.Loading()) val permissionsFlow = permissionsFlow.stateIn( diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt index 3161d3e81f..1595fcdbd9 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt @@ -28,18 +28,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class KnockRequestsBannerPresenterTest { - @Test - fun `present - when feature is disabled then the banner should be hidden`() = runTest { - val knockRequests = flowOf(listOf(FakeKnockRequest())) - val presenter = createKnockRequestsBannerPresenter(isFeatureEnabled = false, knockRequestsFlow = knockRequests) - presenter.test { - skipItems(1) - awaitItem().also { state -> - assertThat(state.isVisible).isFalse() - } - } - } - @Test fun `present - when empty knock request list then the banner should be hidden`() = runTest { val knockRequests = flowOf(emptyList()) @@ -229,12 +217,10 @@ import org.junit.Test private fun TestScope.createKnockRequestsBannerPresenter( knockRequestsFlow: Flow> = flowOf(emptyList()), canAcceptKnockRequests: Boolean = true, - isFeatureEnabled: Boolean = true, ): KnockRequestsBannerPresenter { val knockRequestsService = KnockRequestsService( knockRequestsFlow = knockRequestsFlow, coroutineScope = backgroundScope, - isKnockFeatureEnabledFlow = flowOf(isFeatureEnabled), permissionsFlow = flowOf(KnockRequestPermissions(canAcceptKnockRequests, canAcceptKnockRequests, canAcceptKnockRequests)), ) return KnockRequestsBannerPresenter( diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt index 7102b01773..209e67cadf 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt @@ -298,7 +298,6 @@ internal fun TestScope.createKnockRequestsListPresenter( val knockRequestsService = KnockRequestsService( knockRequestsFlow = knockRequestsFlow, coroutineScope = backgroundScope, - isKnockFeatureEnabledFlow = flowOf(true), permissionsFlow = flowOf(KnockRequestPermissions(canAccept, canDecline, canBan)), ) return KnockRequestsListPresenter(knockRequestsService = knockRequestsService) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 56e5e1735e..167cc2ced5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -35,8 +35,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService @@ -61,7 +59,6 @@ import kotlinx.coroutines.launch class RoomDetailsPresenter( private val client: MatrixClient, private val room: JoinedRoom, - private val featureFlagService: FeatureFlagService, private val notificationSettingsService: NotificationSettingsService, private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory, private val leaveRoomPresenter: Presenter, @@ -110,14 +107,11 @@ class RoomDetailsPresenter( } } - val isKnockRequestsEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock) - }.collectAsState(false) val knockRequestsCount by produceState(null) { room.knockRequestsFlow.collect { value = it.size } } val canShowKnockRequests by remember { - derivedStateOf { isKnockRequestsEnabled && permissions.knockRequestsPermissions.hasAny && joinRule == JoinRule.Knock } + derivedStateOf { permissions.knockRequestsPermissions.hasAny && joinRule == JoinRule.Knock } } val canShowSecurityAndPrivacy by remember { derivedStateOf { !isDm && permissions.securityAndPrivacyPermissions.hasAny(isSpace = false, joinRule = joinRule) } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index 3da2f5cf25..9c116f5a9d 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -21,9 +21,6 @@ import io.element.android.libraries.androidutils.clipboard.ClipboardHelper import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMembersState @@ -80,11 +77,6 @@ class RoomDetailsPresenterTest { dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), analyticsService: AnalyticsService = FakeAnalyticsService(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService( - mapOf( - FeatureFlags.Knock.key to false, - ) - ), encryptionService: FakeEncryptionService = FakeEncryptionService(), clipboardHelper: ClipboardHelper = FakeClipboardHelper(), appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore() @@ -106,7 +98,6 @@ class RoomDetailsPresenterTest { return RoomDetailsPresenter( client = matrixClient, room = room, - featureFlagService = featureFlagService, notificationSettingsService = matrixClient.notificationSettingsService, roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory, leaveRoomPresenter = { leaveRoomState }, @@ -564,17 +555,11 @@ class RoomDetailsPresenterTest { roomPermissions = roomPermissions(), joinRule = JoinRule.Knock, ) - val featureFlagService = FakeFeatureFlagService( - mapOf(FeatureFlags.Knock.key to false) - ) val presenter = createRoomDetailsPresenter( room = room, - featureFlagService = featureFlagService, ) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { skipItems(1) - assertThat(awaitItem().canShowKnockRequests).isFalse() - featureFlagService.setFeatureEnabled(FeatureFlags.Knock, true) assertThat(awaitItem().canShowKnockRequests).isTrue() room.givenRoomInfo(aRoomInfo(joinRule = JoinRule.Invite)) assertThat(awaitItem().canShowKnockRequests).isFalse() @@ -587,8 +572,7 @@ class RoomDetailsPresenterTest { val room = aJoinedRoom( roomPermissions = roomPermissions(), ) - val featureFlagService = FakeFeatureFlagService() - val presenter = createRoomDetailsPresenter(room = room, featureFlagService = featureFlagService) + val presenter = createRoomDetailsPresenter(room = room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { skipItems(1) with(awaitItem()) { From 3234931d3c972d7751f83f5b91f70d2f78edd6f2 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 12 May 2026 15:04:13 +0200 Subject: [PATCH 0406/1083] Use the right analytics span as a parent in `checkNetworkConnection` (#6751) `AnalyticsLongRunningTransaction.PushToWorkManager` was incorrectly used instead of `AnalyticsLongRunningTransaction.PushToNotification`, resulting in wrongly formatter analytic traces --- .../push/impl/workmanager/FetchPendingNotificationsWorker.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt index c18a0015aa..cefbd31515 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt @@ -153,7 +153,7 @@ class FetchPendingNotificationsWorker( private suspend fun checkNetworkConnection(requests: List): Result? { val networkTimeoutSpans = requests.mapNotNull { request -> - val parent = analyticsService.getLongRunningTransaction(AnalyticsLongRunningTransaction.PushToWorkManager(request.eventId)) + val parent = analyticsService.getLongRunningTransaction(AnalyticsLongRunningTransaction.PushToNotification(request.eventId)) parent?.startChild("Waiting for network connectivity", "await_network") } From c30fee7f148ffd940fe4c1d4d7125742a8f6183c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 May 2026 15:21:20 +0200 Subject: [PATCH 0407/1083] Do not close the MediaPlayer when navigating back from a thread. --- .../features/messages/impl/threads/ThreadedMessagesNode.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 63ce48e100..be573fa92f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -67,7 +67,6 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo -import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsService @@ -88,7 +87,6 @@ class ThreadedMessagesNode( private val presenterFactory: MessagesPresenter.Factory, private val actionListPresenterFactory: ActionListPresenter.Factory, private val timelineItemPresenterFactories: TimelineItemPresenterFactories, - private val mediaPlayer: MediaPlayer, private val permalinkParser: PermalinkParser, private val appNavigationStateService: AppNavigationStateService, private val roomMemberModerationRenderer: RoomMemberModerationRenderer, @@ -157,9 +155,6 @@ class ThreadedMessagesNode( onStop = { appNavigationStateService.onLeavingThread(id) }, - onDestroy = { - mediaPlayer.close() - } ) } From f04c83637186198e8aa08c457bc3c9b2efaff7fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 15:42:06 +0200 Subject: [PATCH 0408/1083] Update dependency io.element.android:element-call-embedded to v0.19.3 (#6766) 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 7a79320530..8cdeecb285 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -234,7 +234,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.19.2" +element_call_embedded = "io.element.android:element-call-embedded:0.19.3" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From d299b722e3e0514708e075e4d666d2424da493a9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 May 2026 15:50:47 +0200 Subject: [PATCH 0409/1083] Format code. --- .../DefaultMessageSummaryFormatterTest.kt | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt index 7d0a097b3c..664d21ed64 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt @@ -33,33 +33,36 @@ class DefaultMessageSummaryFormatterTest { @Test @Config(qualifiers = "en") fun `format call notification started`() { - val expected = formatter.format(TimelineItemRtcNotificationContent( - callIntent = CallIntent.VIDEO, - state = RtcNotificationState.Started - )) - + val expected = formatter.format( + TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Started + ) + ) assertThat(expected).isEqualTo("Call started") } @Test @Config(qualifiers = "en") fun `format call notification declined by me`() { - val expected = formatter.format(TimelineItemRtcNotificationContent( - callIntent = CallIntent.VIDEO, - state = RtcNotificationState.Declined(byMe = true) - )) - + val expected = formatter.format( + TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Declined(byMe = true) + ) + ) assertThat(expected).isEqualTo("You declined a call") } @Test @Config(qualifiers = "en") fun `format call notification declined`() { - val expected = formatter.format(TimelineItemRtcNotificationContent( - callIntent = CallIntent.VIDEO, - state = RtcNotificationState.Declined(byMe = false) - )) - + val expected = formatter.format( + TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Declined(byMe = false) + ) + ) assertThat(expected).isEqualTo("Call declined") } @@ -69,7 +72,6 @@ class DefaultMessageSummaryFormatterTest { val expected = formatter.format( aLocationContent(isLive = true) ) - assertThat(expected).isEqualTo("Shared live location") } @@ -79,27 +81,26 @@ class DefaultMessageSummaryFormatterTest { val expected = formatter.format( aLocationContent(isLive = false) ) - assertThat(expected).isEqualTo("Shared location") } } -private fun aLocationContent(isLive: Boolean): TimelineItemLocationContent = TimelineItemLocationContent( +private fun aLocationContent(isLive: Boolean) = TimelineItemLocationContent( senderId = A_USER_ID, senderProfile = aProfileDetails(), description = null, assetType = null, mode = if (isLive) { Mode.Live( - lastKnownLocation = Location.fromGeoUri("geo:1,5"), - isActive = true, - endsAt = "", - endTimestamp = 0, - isOwnUser = true - ) + lastKnownLocation = Location.fromGeoUri("geo:1,5"), + isActive = true, + endsAt = "", + endTimestamp = 0, + isOwnUser = true, + ) } else { Mode.Static( - location = Location.fromGeoUri("geo:1,5")!! - ) + location = Location.fromGeoUri("geo:1,5")!!, + ) } ) From c68e1b8845071b6718a8ebfbc45ed5930e989b1d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 15:57:18 +0200 Subject: [PATCH 0410/1083] Update tspascoal/get-user-teams-membership action to v4.0.1 (#6750) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9b4a5e3689..f0c8fd1e6f 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Check membership if: github.event.pull_request.user.login != 'renovate[bot]' - uses: tspascoal/get-user-teams-membership@b1480b119326dde04ceffbeccd98e41892539c74 # v4.0.0 + uses: tspascoal/get-user-teams-membership@818140d631d5f29f26b151afbe4179f87d9ceb5e # v4.0.1 id: teams with: username: ${{ github.event.pull_request.user.login }} From ae50f6b8973f11bf51da00d0b06daf5a8a0c50bf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 16:03:34 +0200 Subject: [PATCH 0411/1083] Update plugin sonarqube to v7.3.0.8198 (#6743) 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 384b69b49f..64a7ec7031 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -268,7 +268,7 @@ paparazzi = "app.cash.paparazzi:2.0.0-alpha04" roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" } -sonarqube = "org.sonarqube:7.2.3.7755" +sonarqube = "org.sonarqube:7.3.0.8198" licensee = "app.cash.licensee:1.14.1" compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } gms_google_services = { id = "com.google.gms.google-services", version = "4.4.4" } From 3f02f527f03aad526a7bf561b85fea0f7012ba9b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 May 2026 16:17:10 +0200 Subject: [PATCH 0412/1083] Rename FF title --- .../element/android/libraries/featureflag/api/FeatureFlags.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index cdda66579b..ab7dcb9960 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -102,7 +102,7 @@ enum class FeatureFlags( ), AllowBlackTheme( key = "feature.allow_black_theme", - title = "Allow black theme", + title = "Black theme", description = "Allow selecting the black appearance theme for battery saving on OLED.", defaultValue = { false }, isFinished = false, From b4305b17492fdc4153eec3c31533dc1eae90f06e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 16:56:34 +0200 Subject: [PATCH 0413/1083] Update plugin dependencycheck to v12.2.2 (#6760) 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 64a7ec7031..97933dfb61 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -262,7 +262,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.1" +dependencycheck = "org.owasp.dependencycheck:12.2.2" dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" } paparazzi = "app.cash.paparazzi:2.0.0-alpha04" roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } From 9eac27515e844d3f1eb7fc15902534b1d739edd2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 15:35:51 +0000 Subject: [PATCH 0414/1083] Update dependency com.google.guava:guava to v33.6.0-jre (#6646) * Update dependency com.google.guava:guava to v33.6.0-jre * Use android version --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Benoit Marty --- 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 97933dfb61..b5393bcc22 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -214,7 +214,7 @@ maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" opusencoder = "io.element.android:opusencoder:1.2.0" zxing_cpp = "io.github.zxing-cpp:android:3.0.2" google_zxing = "com.google.zxing:core:3.5.4" -google_guava = "com.google.guava:guava:33.5.0-android" +google_guava = "com.google.guava:guava:33.6.0-android" haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" } haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" } From 3ca06d71ef75e4363fe8109492a231e5d6ef325d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 May 2026 16:27:16 +0200 Subject: [PATCH 0415/1083] Rename keys on Localazy and add Black theme. --- .../preferences/impl/advanced/AdvancedSettingsState.kt | 10 +++++----- .../impl/src/main/res/values-be/translations.xml | 3 +++ .../impl/src/main/res/values-bg/translations.xml | 3 +++ .../impl/src/main/res/values-cs/translations.xml | 3 +++ .../impl/src/main/res/values-cy/translations.xml | 3 +++ .../impl/src/main/res/values-da/translations.xml | 3 +++ .../impl/src/main/res/values-de/translations.xml | 3 +++ .../impl/src/main/res/values-el/translations.xml | 3 +++ .../impl/src/main/res/values-es/translations.xml | 3 +++ .../impl/src/main/res/values-et/translations.xml | 3 +++ .../impl/src/main/res/values-eu/translations.xml | 3 +++ .../impl/src/main/res/values-fa/translations.xml | 3 +++ .../impl/src/main/res/values-fi/translations.xml | 3 +++ .../impl/src/main/res/values-fr/translations.xml | 3 +++ .../impl/src/main/res/values-hr/translations.xml | 3 +++ .../impl/src/main/res/values-hu/translations.xml | 3 +++ .../impl/src/main/res/values-in/translations.xml | 3 +++ .../impl/src/main/res/values-it/translations.xml | 3 +++ .../impl/src/main/res/values-ja/translations.xml | 3 +++ .../impl/src/main/res/values-ka/translations.xml | 3 +++ .../impl/src/main/res/values-ko/translations.xml | 3 +++ .../impl/src/main/res/values-nb/translations.xml | 3 +++ .../impl/src/main/res/values-nl/translations.xml | 3 +++ .../impl/src/main/res/values-pl/translations.xml | 3 +++ .../impl/src/main/res/values-pt-rBR/translations.xml | 3 +++ .../impl/src/main/res/values-pt/translations.xml | 3 +++ .../impl/src/main/res/values-ro/translations.xml | 3 +++ .../impl/src/main/res/values-ru/translations.xml | 3 +++ .../impl/src/main/res/values-sk/translations.xml | 3 +++ .../impl/src/main/res/values-sv/translations.xml | 3 +++ .../impl/src/main/res/values-tr/translations.xml | 3 +++ .../impl/src/main/res/values-uk/translations.xml | 3 +++ .../impl/src/main/res/values-ur/translations.xml | 3 +++ .../impl/src/main/res/values-uz/translations.xml | 3 +++ .../impl/src/main/res/values-vi/translations.xml | 3 +++ .../impl/src/main/res/values-zh-rTW/translations.xml | 3 +++ .../impl/src/main/res/values-zh/translations.xml | 3 +++ .../preferences/impl/src/main/res/values/localazy.xml | 4 ++++ .../impl/advanced/AdvancedSettingsViewTest.kt | 6 +++--- .../ui-strings/src/main/res/values-be/translations.xml | 3 --- .../ui-strings/src/main/res/values-bg/translations.xml | 3 --- .../ui-strings/src/main/res/values-cs/translations.xml | 3 --- .../ui-strings/src/main/res/values-cy/translations.xml | 3 --- .../ui-strings/src/main/res/values-da/translations.xml | 3 --- .../ui-strings/src/main/res/values-de/translations.xml | 3 --- .../ui-strings/src/main/res/values-el/translations.xml | 3 --- .../ui-strings/src/main/res/values-es/translations.xml | 3 --- .../ui-strings/src/main/res/values-et/translations.xml | 3 --- .../ui-strings/src/main/res/values-eu/translations.xml | 3 --- .../ui-strings/src/main/res/values-fa/translations.xml | 3 --- .../ui-strings/src/main/res/values-fi/translations.xml | 3 --- .../ui-strings/src/main/res/values-fr/translations.xml | 3 --- .../ui-strings/src/main/res/values-hr/translations.xml | 3 --- .../ui-strings/src/main/res/values-hu/translations.xml | 3 --- .../ui-strings/src/main/res/values-in/translations.xml | 3 --- .../ui-strings/src/main/res/values-it/translations.xml | 3 --- .../ui-strings/src/main/res/values-ja/translations.xml | 3 --- .../ui-strings/src/main/res/values-ka/translations.xml | 3 --- .../ui-strings/src/main/res/values-ko/translations.xml | 3 --- .../ui-strings/src/main/res/values-nb/translations.xml | 3 --- .../ui-strings/src/main/res/values-nl/translations.xml | 3 --- .../ui-strings/src/main/res/values-pl/translations.xml | 3 --- .../src/main/res/values-pt-rBR/translations.xml | 3 --- .../ui-strings/src/main/res/values-pt/translations.xml | 3 --- .../ui-strings/src/main/res/values-ro/translations.xml | 3 --- .../ui-strings/src/main/res/values-ru/translations.xml | 3 --- .../ui-strings/src/main/res/values-sk/translations.xml | 3 --- .../ui-strings/src/main/res/values-sv/translations.xml | 3 --- .../ui-strings/src/main/res/values-tr/translations.xml | 3 --- .../ui-strings/src/main/res/values-uk/translations.xml | 3 --- .../ui-strings/src/main/res/values-ur/translations.xml | 3 --- .../ui-strings/src/main/res/values-uz/translations.xml | 3 --- .../ui-strings/src/main/res/values-vi/translations.xml | 3 --- .../src/main/res/values-zh-rTW/translations.xml | 3 --- .../ui-strings/src/main/res/values-zh/translations.xml | 3 --- libraries/ui-strings/src/main/res/values/localazy.xml | 3 --- libraries/ui-strings/src/main/res/values/temporary.xml | 10 ---------- tools/localazy/config.json | 1 + 78 files changed, 121 insertions(+), 129 deletions(-) delete mode 100644 libraries/ui-strings/src/main/res/values/temporary.xml 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 1deb972abc..94019c1f01 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt @@ -11,9 +11,9 @@ package io.element.android.features.preferences.impl.advanced import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.res.stringResource +import io.element.android.features.preferences.impl.R import io.element.android.libraries.designsystem.components.preferences.DropdownOption import io.element.android.libraries.preferences.api.store.VideoCompressionPreset -import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList data class AdvancedSettingsState( @@ -44,24 +44,24 @@ enum class ThemeOption : DropdownOption { System { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_system) + override fun getText(): String = stringResource(R.string.theme_system) }, Light { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_light) + override fun getText(): String = stringResource(R.string.theme_light) }, Dark { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_dark) + override fun getText(): String = stringResource(R.string.theme_dark) }, Black { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_black) + override fun getText(): String = stringResource(R.string.theme_black) } } diff --git a/features/preferences/impl/src/main/res/values-be/translations.xml b/features/preferences/impl/src/main/res/values-be/translations.xml index b27a22bb8d..7f487afa24 100644 --- a/features/preferences/impl/src/main/res/values-be/translations.xml +++ b/features/preferences/impl/src/main/res/values-be/translations.xml @@ -53,6 +53,9 @@ "налады сістэмы" "Сістэмныя апавяшчэнні выключаны" "Апавяшчэнні" + "Цёмная" + "Светлая" + "Сістэмная" "Выпраўленне непаладак" "Выпраўленне непаладак з апавяшчэннямі" diff --git a/features/preferences/impl/src/main/res/values-bg/translations.xml b/features/preferences/impl/src/main/res/values-bg/translations.xml index 692f0ac8f3..d5ad7facb2 100644 --- a/features/preferences/impl/src/main/res/values-bg/translations.xml +++ b/features/preferences/impl/src/main/res/values-bg/translations.xml @@ -58,6 +58,9 @@ "системни настройки" "Системните известия са изключени" "Известия" + "Тъмен" + "Светъл" + "Система" "Отстраняване на неизправности" "Отстраняване на неизправности с известията" diff --git a/features/preferences/impl/src/main/res/values-cs/translations.xml b/features/preferences/impl/src/main/res/values-cs/translations.xml index 12014e7104..e51d05c455 100644 --- a/features/preferences/impl/src/main/res/values-cs/translations.xml +++ b/features/preferences/impl/src/main/res/values-cs/translations.xml @@ -87,6 +87,9 @@ Pokud budete pokračovat, některá nastavení se mohou změnit." "systémová nastavení" "Systémová oznámení byla vypnuta" "Oznámení" + "Tmavé" + "Světlý" + "Systém" "Historie push oznámení" "Odstraňování problémů" "Odstraňování problémů s upozorněními" diff --git a/features/preferences/impl/src/main/res/values-cy/translations.xml b/features/preferences/impl/src/main/res/values-cy/translations.xml index 9711eda179..e857f6aebe 100644 --- a/features/preferences/impl/src/main/res/values-cy/translations.xml +++ b/features/preferences/impl/src/main/res/values-cy/translations.xml @@ -70,6 +70,9 @@ Os ewch ymlaen, efallai y bydd rhai o\'ch gosodiadau\'n newid." "gosodiadau system" "Hysbysiadau system wedi\'u diffodd" "Hysbysiadau" + "Tywyll" + "Golau" + "System" "Hanes gwthio" "Datrys Problemau" "Hysbysiadau datrys problemau" diff --git a/features/preferences/impl/src/main/res/values-da/translations.xml b/features/preferences/impl/src/main/res/values-da/translations.xml index 2f828a4063..459ea33632 100644 --- a/features/preferences/impl/src/main/res/values-da/translations.xml +++ b/features/preferences/impl/src/main/res/values-da/translations.xml @@ -84,6 +84,9 @@ Hvis du fortsætter, kan nogle af dine indstillinger blive ændret." "systemindstillinger" "Systemmeddelelser slået fra" "Notifikationer" + "Mørkt tema" + "Lyst tema" + "System" "Push-historik" "Fejlfind" "Fejlfinding af meddelelser" diff --git a/features/preferences/impl/src/main/res/values-de/translations.xml b/features/preferences/impl/src/main/res/values-de/translations.xml index c3722ec88c..e35cf871a1 100644 --- a/features/preferences/impl/src/main/res/values-de/translations.xml +++ b/features/preferences/impl/src/main/res/values-de/translations.xml @@ -76,6 +76,9 @@ Wenn du fortfährst, können sich einige deiner Einstellungen ändern." "Systemeinstellungen" "Systembenachrichtigungen deaktiviert" "Benachrichtigungen" + "Dunkel" + "Hell" + "System" "Verlauf pushen" "Fehlerbehebung" "Fehlerbehebung für Benachrichtigungen" diff --git a/features/preferences/impl/src/main/res/values-el/translations.xml b/features/preferences/impl/src/main/res/values-el/translations.xml index 64b651114d..6db52343d3 100644 --- a/features/preferences/impl/src/main/res/values-el/translations.xml +++ b/features/preferences/impl/src/main/res/values-el/translations.xml @@ -76,6 +76,9 @@ "ρυθμίσεις συστήματος" "Ειδοποιήσεις συστήματος ανενεργές" "Ειδοποιήσεις" + "Σκοτεινό" + "Φωτεινό" + "Σύστημα" "Ιστορικό push" "Αντιμετώπιση προβλημάτων" "Αντιμετώπιση προβλημάτων ειδοποιήσεων" diff --git a/features/preferences/impl/src/main/res/values-es/translations.xml b/features/preferences/impl/src/main/res/values-es/translations.xml index afdc23d90b..dd496a1273 100644 --- a/features/preferences/impl/src/main/res/values-es/translations.xml +++ b/features/preferences/impl/src/main/res/values-es/translations.xml @@ -63,6 +63,9 @@ Si continúas, es posible que algunos de tus ajustes cambien." "ajustes del sistema" "Notificaciones del sistema desactivadas" "Notificaciones" + "Oscuro" + "Claro" + "Sistema" "Historial de notificaciones push" "Solucionar problemas" "Solucionar problemas con las notificaciones" diff --git a/features/preferences/impl/src/main/res/values-et/translations.xml b/features/preferences/impl/src/main/res/values-et/translations.xml index c9094f1d31..ba1ee2ac7c 100644 --- a/features/preferences/impl/src/main/res/values-et/translations.xml +++ b/features/preferences/impl/src/main/res/values-et/translations.xml @@ -81,6 +81,9 @@ Kui sa jätkad muutmist, siis võivad muutuda ka need peidetud eelistused.""süsteemi seadistusi" "Süsteemi teavitused on välja lülitatud" "Teavitused" + "Tume" + "Hele" + "Süsteem" "Tõuketeadete ajalugu" "Veaotsing" "Teavituste veaotsing" diff --git a/features/preferences/impl/src/main/res/values-eu/translations.xml b/features/preferences/impl/src/main/res/values-eu/translations.xml index 42a90e0328..42416c682b 100644 --- a/features/preferences/impl/src/main/res/values-eu/translations.xml +++ b/features/preferences/impl/src/main/res/values-eu/translations.xml @@ -55,4 +55,7 @@ "sistemaren ezarpenak" "Sistemaren jakinarazpenak desaktibatuta daude" "Jakinarazpenak" + "Iluna" + "Argia" + "Sistema" diff --git a/features/preferences/impl/src/main/res/values-fa/translations.xml b/features/preferences/impl/src/main/res/values-fa/translations.xml index 1a832ca54c..df42ca953c 100644 --- a/features/preferences/impl/src/main/res/values-fa/translations.xml +++ b/features/preferences/impl/src/main/res/values-fa/translations.xml @@ -67,6 +67,9 @@ "تنظیمات سامانه" "آگاهی‌های سامانه‌ای خاموش شدند" "آگاهی‌ها" + "تیره" + "روشن" + "سامانه" "تاریخچهٔ آگاهی‌های ارسالی" "رفع‌اشکال" "رفع‌اشکال آگاهی‌ها" diff --git a/features/preferences/impl/src/main/res/values-fi/translations.xml b/features/preferences/impl/src/main/res/values-fi/translations.xml index f1462f3bb7..97da4e138a 100644 --- a/features/preferences/impl/src/main/res/values-fi/translations.xml +++ b/features/preferences/impl/src/main/res/values-fi/translations.xml @@ -76,6 +76,9 @@ Jos jatkat, jotkin asetukset saattavat muuttua." "järjestelmäsi asetuksia" "Järjestelmän ilmoitukset on poissa päältä" "Ilmoitukset" + "Tumma" + "Vaalea" + "Järjestelmän oletus" "Push-historia" "Vianmääritys" "Ilmoitusten vianmääritys" diff --git a/features/preferences/impl/src/main/res/values-fr/translations.xml b/features/preferences/impl/src/main/res/values-fr/translations.xml index 292b5bf9a5..3f97b67eb8 100644 --- a/features/preferences/impl/src/main/res/values-fr/translations.xml +++ b/features/preferences/impl/src/main/res/values-fr/translations.xml @@ -84,6 +84,9 @@ Si vous continuez, il est possible que certains de vos paramètres soient modifi "paramètres du système" "Les notifications du système sont désactivées" "Notifications" + "Sombre" + "Clair" + "Système" "Historique des Push" "Dépannage" "Dépanner les notifications" diff --git a/features/preferences/impl/src/main/res/values-hr/translations.xml b/features/preferences/impl/src/main/res/values-hr/translations.xml index a40a6feccd..d101146f8c 100644 --- a/features/preferences/impl/src/main/res/values-hr/translations.xml +++ b/features/preferences/impl/src/main/res/values-hr/translations.xml @@ -85,6 +85,9 @@ Ako nastavite, neke od vaših postavki mogu se promijeniti." "postavke sustava" "Obavijesti sustava su isključene" "Obavijesti" + "Tamno" + "Svijetlo" + "Sustav" "Povijest push obavijesti" "Rješavanje problema" "Rješavanje problema s obavijestima" diff --git a/features/preferences/impl/src/main/res/values-hu/translations.xml b/features/preferences/impl/src/main/res/values-hu/translations.xml index d75166df5e..4c3ff5c04d 100644 --- a/features/preferences/impl/src/main/res/values-hu/translations.xml +++ b/features/preferences/impl/src/main/res/values-hu/translations.xml @@ -84,6 +84,9 @@ Ha folytatja, egyes beállítások megváltozhatnak." "rendszerbeállításokat" "A rendszerértesítések ki vannak kapcsolva" "Értesítések" + "Sötét" + "Világos" + "Rendszer" "Leküldéses értesítések előzmények" "Hibaelhárítás" "Értesítések hibaelhárítása" diff --git a/features/preferences/impl/src/main/res/values-in/translations.xml b/features/preferences/impl/src/main/res/values-in/translations.xml index 5ce794c8ac..9c853aed45 100644 --- a/features/preferences/impl/src/main/res/values-in/translations.xml +++ b/features/preferences/impl/src/main/res/values-in/translations.xml @@ -72,6 +72,9 @@ Jika Anda melanjutkan, beberapa pengaturan Anda dapat berubah." "pengaturan sistem" "Pemberitahuan sistem dimatikan" "Notifikasi" + "Gelap" + "Terang" + "Sistem" "Riwayat dorongan" "Pemecahan masalah" "Pecahkan masalah notifikasi" diff --git a/features/preferences/impl/src/main/res/values-it/translations.xml b/features/preferences/impl/src/main/res/values-it/translations.xml index 7872a2d47d..73555754fc 100644 --- a/features/preferences/impl/src/main/res/values-it/translations.xml +++ b/features/preferences/impl/src/main/res/values-it/translations.xml @@ -84,6 +84,9 @@ Se procedi, alcune delle tue impostazioni potrebbero cambiare." "impostazioni di sistema" "Notifiche di sistema disattivate" "Notifiche" + "Scuro" + "Chiaro" + "Sistema" "Cronologia push" "Risoluzione dei problemi" "Risoluzione di problemi delle notifiche" diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml index 22334c4120..95380cf148 100644 --- a/features/preferences/impl/src/main/res/values-ja/translations.xml +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -83,6 +83,9 @@ "システム設定" "システムで通知がオフです" "通知" + "ダーク" + "ライト" + "システム" "プッシュ履歴" "トラブルシューティング" "通知のトラブルシューティング" diff --git a/features/preferences/impl/src/main/res/values-ka/translations.xml b/features/preferences/impl/src/main/res/values-ka/translations.xml index 1efe197267..5a20e718a0 100644 --- a/features/preferences/impl/src/main/res/values-ka/translations.xml +++ b/features/preferences/impl/src/main/res/values-ka/translations.xml @@ -50,6 +50,9 @@ "სისტემის პარამეტრები" "სისტემის შეტყობინებები გამორთულია" "შეტყობინებები" + "მუქი" + "ღია" + "სისტემა" "პრობლემების გადაჭრა" "პრობლემების გადაჭრის შეტყობინებები" diff --git a/features/preferences/impl/src/main/res/values-ko/translations.xml b/features/preferences/impl/src/main/res/values-ko/translations.xml index 5e17d57a87..e2c5e8e83b 100644 --- a/features/preferences/impl/src/main/res/values-ko/translations.xml +++ b/features/preferences/impl/src/main/res/values-ko/translations.xml @@ -77,6 +77,9 @@ "시스템 설정" "시스템 알림이 꺼져 있습니다." "알림" + "다크" + "라이트" + "시스템" "푸시 기록" "문제 해결" "문제 해결 알림" diff --git a/features/preferences/impl/src/main/res/values-nb/translations.xml b/features/preferences/impl/src/main/res/values-nb/translations.xml index 90ec12a1a1..ac67e04259 100644 --- a/features/preferences/impl/src/main/res/values-nb/translations.xml +++ b/features/preferences/impl/src/main/res/values-nb/translations.xml @@ -76,6 +76,9 @@ Hvis du fortsetter, kan noen av innstillingene dine endres." "systeminnstillinger" "Systemvarsler er slått av" "Varslinger" + "Mørk" + "Lys" + "System" "Push-historikk" "Feilsøk" "Feilsøk varsler" diff --git a/features/preferences/impl/src/main/res/values-nl/translations.xml b/features/preferences/impl/src/main/res/values-nl/translations.xml index 28614965c5..c5c439a0c3 100644 --- a/features/preferences/impl/src/main/res/values-nl/translations.xml +++ b/features/preferences/impl/src/main/res/values-nl/translations.xml @@ -54,6 +54,9 @@ Als je doorgaat, kunnen sommige van je instellingen veranderen." "systeeminstellingen" "Systeemmeldingen uitgeschakeld" "Meldingen" + "Donker" + "Licht" + "Systeem" "Problemen oplossen" "Problemen met meldingen oplossen" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index 606a79df0d..3fc2a3eac8 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -85,6 +85,9 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "ustawienia systemowe" "Powiadomienia systemowe wyłączone" "Powiadomienia" + "Ciemny" + "Jasny" + "System" "Historia powiadomień Push" "Rozwiązywanie problemów" "Rozwiązywanie problemów powiadomień" diff --git a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml index f6e1bc90ba..be354681f5 100644 --- a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml @@ -76,6 +76,9 @@ Se você continuar, algumas de suas configurações poderão mudar." "configurações do seu sistema" "Notificações do sistema desativadas" "Notificações" + "Escuro" + "Claro" + "Sistema" "Histórico de push" "Solução de problemas" "Solucionar problemas de notificações" diff --git a/features/preferences/impl/src/main/res/values-pt/translations.xml b/features/preferences/impl/src/main/res/values-pt/translations.xml index ffd38b961f..0e27d58de5 100644 --- a/features/preferences/impl/src/main/res/values-pt/translations.xml +++ b/features/preferences/impl/src/main/res/values-pt/translations.xml @@ -76,6 +76,9 @@ Se prosseguires, algumas delas podem ser alteradas." "configurações do sistema" "Notificações do sistema desativadas" "Notificações" + "Escuro" + "Claro" + "Sistema" "Histórico de push" "Resolução de problemas" "Corrigir notificações" diff --git a/features/preferences/impl/src/main/res/values-ro/translations.xml b/features/preferences/impl/src/main/res/values-ro/translations.xml index 6f8e41c5b9..18f8326bf3 100644 --- a/features/preferences/impl/src/main/res/values-ro/translations.xml +++ b/features/preferences/impl/src/main/res/values-ro/translations.xml @@ -78,6 +78,9 @@ Dacă continuați, unele dintre setările dumneavoastră pot fi modificate.""Setări de sistem" "Notificările de sistem sunt dezactivate" "Notificări" + "Întunecat" + "Deschis" + "Sistem" "Istoricul notificărilor" "Depanare" "Depanați notificările" diff --git a/features/preferences/impl/src/main/res/values-ru/translations.xml b/features/preferences/impl/src/main/res/values-ru/translations.xml index 77be6fd8db..edb98feee8 100644 --- a/features/preferences/impl/src/main/res/values-ru/translations.xml +++ b/features/preferences/impl/src/main/res/values-ru/translations.xml @@ -76,6 +76,9 @@ "системные настройки" "Системные уведомления выключены" "Уведомления" + "Темная" + "Светлое" + "Системное" "История уведомлений" "Устранение неполадок" "Уведомления об устранении неполадок" diff --git a/features/preferences/impl/src/main/res/values-sk/translations.xml b/features/preferences/impl/src/main/res/values-sk/translations.xml index 9968c6d4cb..530fccd90b 100644 --- a/features/preferences/impl/src/main/res/values-sk/translations.xml +++ b/features/preferences/impl/src/main/res/values-sk/translations.xml @@ -78,6 +78,9 @@ Ak budete pokračovať, niektoré z vašich nastavení sa môžu zmeniť.""nastavenia systému" "Systémové oznámenia sú vypnuté" "Oznámenia" + "Tmavý" + "Svetlý" + "Systém" "História push oznámení" "Riešenie problémov" "Oznámenia riešení problémov" diff --git a/features/preferences/impl/src/main/res/values-sv/translations.xml b/features/preferences/impl/src/main/res/values-sv/translations.xml index e25e36a44f..109000440f 100644 --- a/features/preferences/impl/src/main/res/values-sv/translations.xml +++ b/features/preferences/impl/src/main/res/values-sv/translations.xml @@ -70,6 +70,9 @@ Om du fortsätter kan vissa av dina inställningar ändras." "systeminställningar" "Systemaviseringar avstängda" "Aviseringar" + "Mörkt" + "Ljust" + "System" "Push-historik" "Felsök" "Felsök aviseringar" diff --git a/features/preferences/impl/src/main/res/values-tr/translations.xml b/features/preferences/impl/src/main/res/values-tr/translations.xml index 0df8500fda..78e9018554 100644 --- a/features/preferences/impl/src/main/res/values-tr/translations.xml +++ b/features/preferences/impl/src/main/res/values-tr/translations.xml @@ -74,6 +74,9 @@ Devam ederseniz, bazı ayarlarınız değişebilir." "si̇stem ayarları" "Sistem bildirimleri kapalı" "Bildirimler" + "Koyu" + "Aydınlık" + "Sistem" "Sorun gider" "Sorun Giderme Bildirimleri" diff --git a/features/preferences/impl/src/main/res/values-uk/translations.xml b/features/preferences/impl/src/main/res/values-uk/translations.xml index eeffc97328..4d8d738122 100644 --- a/features/preferences/impl/src/main/res/values-uk/translations.xml +++ b/features/preferences/impl/src/main/res/values-uk/translations.xml @@ -85,6 +85,9 @@ "системні налаштування" "Системні сповіщення вимкнені" "Сповіщення" + "Темна" + "Світла" + "Системна" "Історія push-сповіщень" "Усунення несправностей" "Усунення неполадок сповіщень" diff --git a/features/preferences/impl/src/main/res/values-ur/translations.xml b/features/preferences/impl/src/main/res/values-ur/translations.xml index 470763e877..35b8f4aa4e 100644 --- a/features/preferences/impl/src/main/res/values-ur/translations.xml +++ b/features/preferences/impl/src/main/res/values-ur/translations.xml @@ -53,6 +53,9 @@ "نظام کی ترتیبات" "نظام کی اطلاعات بند کر دی گئیں" "اطلاعات" + "اندھیرا" + "روشنی" + "نظام" "ازالہ کریں" "اطلاعات کا ازالہ کریں" diff --git a/features/preferences/impl/src/main/res/values-uz/translations.xml b/features/preferences/impl/src/main/res/values-uz/translations.xml index 9c81fc3daa..884027f9b8 100644 --- a/features/preferences/impl/src/main/res/values-uz/translations.xml +++ b/features/preferences/impl/src/main/res/values-uz/translations.xml @@ -76,6 +76,9 @@ Davom ettirsangiz, baʼzi sozlamalaringiz oʻzgarishi mumkin." "tizim sozlamalari" "Tizim bildirishnomalari o\'chirilgan" "Bildirishnomalar" + "Tungi" + "Nur" + "Tizim" "Bildirishnoma tarixi" "Muammolarni bartaraf etish" "Bildirishnomalar bilan bog‘liq muammolarni bartaraf etish" diff --git a/features/preferences/impl/src/main/res/values-vi/translations.xml b/features/preferences/impl/src/main/res/values-vi/translations.xml index 9f24244b7e..9889b1697a 100644 --- a/features/preferences/impl/src/main/res/values-vi/translations.xml +++ b/features/preferences/impl/src/main/res/values-vi/translations.xml @@ -61,6 +61,9 @@ Nếu bạn tiếp tục, một số cài đặt của bạn có thể thay đ "cài đặt hệ thống" "Thông báo hệ thống đã tắt" "Thông báo" + "Tối" + "Sáng" + "Hệ thống" "Khắc phục sự cố" "Khắc phục sự cố thông báo" diff --git a/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml b/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml index 634911100a..03892ce980 100644 --- a/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml @@ -76,6 +76,9 @@ "系統設定" "已關閉系統通知" "通知" + "深色" + "淺色" + "系統" "推播通知歷史紀錄" "疑難排解" "疑難排解通知" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 41eb147141..e91bc58752 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -83,6 +83,9 @@ "系统设置" "系统通知已关闭" "通知" + "深色" + "浅色" + "系统" "推送历史" "排查问题" "排查通知问题" diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index d5abe1df6a..a431139fd6 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -84,6 +84,10 @@ If you proceed, some of your settings may change." "system settings" "System notifications turned off" "Notifications" + "Black" + "Dark" + "Light" + "System" "Push history" "Troubleshoot" "Troubleshoot notifications" diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt index 4823a7c26e..302a209578 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt @@ -62,7 +62,7 @@ class AdvancedSettingsViewTest { ), ) clickOn(CommonStrings.common_appearance) - clickOn(CommonStrings.common_dark) + clickOn(R.string.theme_dark) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTheme(ThemeOption.Dark)) } @@ -75,7 +75,7 @@ class AdvancedSettingsViewTest { ) clickOn(CommonStrings.common_appearance) run { - val text = activity!!.getString(CommonStrings.common_black) + val text = activity!!.getString(R.string.theme_black) onNodeWithText(text).assertExists() } } @@ -88,7 +88,7 @@ class AdvancedSettingsViewTest { ), ) clickOn(CommonStrings.common_appearance) - assertNoNodeWithText(CommonStrings.common_black) + assertNoNodeWithText(R.string.theme_black) } @Test diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index f106b46e6c..f550ce1075 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -170,7 +170,6 @@ "Аўтарскае права" "Стварэнне пакоя…" "Выйшаў з пакоя" - "Цёмная" "Памылка расшыфроўкі" "Параметры распрацоўшчыка" "Прамы чат" @@ -197,7 +196,6 @@ "Усталяваць APK" "Гэты Matrix ID не знойдзены, таму запрашэнне можа быць не атрымана." "Пакінуць пакой" - "Светлая" "Спасылка скапіравана ў буфер абмену" "Загрузка…" @@ -272,7 +270,6 @@ "Поспех" "Прапановы" "Сінхранізацыя" - "Сістэмная" "Тэкст" "Паведамленні трэціх асоб" "Гутарка" diff --git a/libraries/ui-strings/src/main/res/values-bg/translations.xml b/libraries/ui-strings/src/main/res/values-bg/translations.xml index 596b7b3e34..3f38b1991f 100644 --- a/libraries/ui-strings/src/main/res/values-bg/translations.xml +++ b/libraries/ui-strings/src/main/res/values-bg/translations.xml @@ -145,7 +145,6 @@ "Създаване на стая…" "Стаята е напусната" "Пространството е напуснато" - "Тъмен" "Грешка при разшифроване" "Описание" "Опции за разработчици" @@ -176,7 +175,6 @@ "Този Matrix ID не може да бъде намерен, така че поканата може да не бъде получена." "Стаята се напуска" "Пространството се напуска" - "Светъл" "Връзката е копирана в клипборда" "Зарежда се…" "Зарежда се още…" @@ -269,7 +267,6 @@ "Успешно" "Предложения" "Синхронизиране" - "Система" "Текст" "Уведомления от трети страни" "Нишка" diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 4a8623f5dc..36bd188c2a 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -215,7 +215,6 @@ "Místnost opuštěna" "Opustit prostor" "Pozvánka odmítnuta" - "Tmavé" "Chyba dešifrování" "Popis" "Možnosti pro vývojáře" @@ -255,7 +254,6 @@ Důvod: %1$s." "Tento Matrix identifikátor nelze najít, takže pozvánka nemusí být přijata." "Opuštění místnosti" "Opuštění prostoru" - "Světlý" "Řádek zkopírován do schránky" "Odkaz zkopírován do schránky" "Připojit nové zařízení" @@ -380,7 +378,6 @@ Důvod: %1$s." "Doporučeno" "Návrhy" "Synchronizace" - "Systém" "Text" "Oznámení třetích stran" "Vlákno" diff --git a/libraries/ui-strings/src/main/res/values-cy/translations.xml b/libraries/ui-strings/src/main/res/values-cy/translations.xml index 98538f517d..00e2a39297 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -198,7 +198,6 @@ "Wedi gadael yr ystafell" "Gofod chwith" "Wedi gwrthod y gwahoddiad" - "Tywyll" "Gwall dadgryptio" "Disgrifiad" "Dewisiadau datblygwr" @@ -235,7 +234,6 @@ Rheswm: %1$s." "Gosod APK" "Nid oes modd dod o hyd i\'r ID Matrics hwn, felly mae\'n bosibl na fydd y gwahoddiad yn cael ei dderbyn." "Gadael ystafell" - "Golau" "Llinell wedi\'i chopïo i\'r clipfwrdd" "Dolen wedi\'i chopïo i\'r clipfwrdd" "Yn Llwytho…" @@ -359,7 +357,6 @@ Rheswm: %1$s." "Llwyddiant" "Awgrymiadau" "Cydweddu" - "System" "Testun" "Hysbysiadau trydydd parti" "Edefyn" diff --git a/libraries/ui-strings/src/main/res/values-da/translations.xml b/libraries/ui-strings/src/main/res/values-da/translations.xml index 0837d0bb33..ce79b8972b 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -217,7 +217,6 @@ "Forlod rummet" "Forlod klynge" "Invitationen blev afvist" - "Mørkt tema" "Fejl under dekryptering" "Beskrivelse" "Indstillinger for udviklere" @@ -257,7 +256,6 @@ "Dette Matrix-ID kan ikke findes, så invitationen modtages muligvis ikke." "Forlader rummet" "Forlader klynge" - "Lyst tema" "Linje kopieret til udklipsholder" "Linket er kopieret til udklipsholderen" "Forbind ny enhed" @@ -376,7 +374,6 @@ "Forslag" "Forslag" "Synkroniserer" - "System" "Tekst" "Tredjepartsmeddelelser" "Tråd" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 1a9190568c..5b7f52cf4e 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -209,7 +209,6 @@ "Hat den Chat verlassen" "Space verlassen" "Einladung abgelehnt" - "Dunkel" "Dekodierungsfehler" "Beschreibung" "Entwickleroptionen" @@ -249,7 +248,6 @@ Grund: %1$s." "Diese Matrix Kennung wurde nicht gefunden, daher wird die Einladung möglicherweise nicht empfangen." "Chat verlassen" "Space wird verlassen" - "Hell" "Zeile in die Zwischenablage kopiert" "Link in die Zwischenablage kopiert" "Neues Gerät verknüpfen" @@ -369,7 +367,6 @@ Grund: %1$s." "Empfohlen" "Vorschläge" "Synchronisieren" - "System" "Text" "Hinweise von Drittanbietern" "Thread" diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml index e5d6d0d1f5..ec14b73e04 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -209,7 +209,6 @@ "Αποχώρησε από την αίθουσα" "Αποχωρήσατε από τον χώρο" "Η πρόσκληση απορρίφθηκε" - "Σκοτεινό" "Σφάλμα αποκρυπτογράφησης" "Περιγραφή" "Επιλογές προγραμματιστή" @@ -249,7 +248,6 @@ "Αυτό το Matrix ID δεν μπορεί να βρεθεί, επομένως η πρόσκληση ενδέχεται να μην ληφθεί." "Αποχώρηση από την αίθουσα" "Αποχωρείτε από τον χώρο" - "Φωτεινό" "Η γραμμή αντιγράφηκε στο πρόχειρο" "Ο σύνδεσμος αντιγράφηκε στο πρόχειρο" "Σύνδεση νέας συσκευής" @@ -369,7 +367,6 @@ "Προτεινόμενο" "Προτάσεις" "Συγχρονισμός" - "Σύστημα" "Κείμενο" "Ειδοποιήσεις τρίτων" "Νήμα" diff --git a/libraries/ui-strings/src/main/res/values-es/translations.xml b/libraries/ui-strings/src/main/res/values-es/translations.xml index 1dc69b127c..b03223a70e 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -165,7 +165,6 @@ "Solicitud cancelada" "Saliste de la sala" "Invitación rechazada" - "Oscuro" "Error de descifrado" "Opciones de desarrollador" "ID de dispositivo" @@ -201,7 +200,6 @@ Motivo: %1$s." "Instalar APK" "No se encontró este ID de Matrix, por lo que es posible que no se reciba la invitación." "Saliendo de la sala" - "Claro" "Línea copiada al portapapeles" "Enlace copiado al portapapeles" "Cargando…" @@ -280,7 +278,6 @@ Motivo: %1$s." "Terminado" "Sugerencias" "Sincronizando" - "Sistema" "Texto" "Avisos de terceros" "Hilo" diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index 6004792f51..1669abc4e0 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -216,7 +216,6 @@ "Lahkus jututoast" "Lahkus kogukonnast" "Keeldusid kutsest" - "Tume" "Dekrüptimisviga" "Kirjeldus" "Arendaja valikud" @@ -255,7 +254,6 @@ Põhjus: %1$s." "Sellist Matrix\'i kasutajatunnust ei õnnestu leida, seega sõnumit ilmselt keegi kätte ei saa." "Oled lahkumas jututoast" "Oled lahkumas kogukonnast" - "Hele" "Rida on kopeeritud lõikelauale" "Link on kopeeritud lõikelauale" "Seo uus seade" @@ -374,7 +372,6 @@ Põhjus: %1$s." "Soovitatud" "Soovitused" "Sünkroniseerime" - "Süsteem" "Tekst" "Kolmandate osapoolte teatised" "Jutulõng" diff --git a/libraries/ui-strings/src/main/res/values-eu/translations.xml b/libraries/ui-strings/src/main/res/values-eu/translations.xml index 7e9d3a05fe..0c046b8bb4 100644 --- a/libraries/ui-strings/src/main/res/values-eu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-eu/translations.xml @@ -169,7 +169,6 @@ "Eskaera bertan behera utzi da" "Gelatik atera da" "Gonbidapenari uko egin zaio" - "Iluna" "Deszifratze-errorea" "Garapen aukerak" "Gailuaren IDa" @@ -204,7 +203,6 @@ Arrazoia: %1$s." "Instalatu APK" "Matrix IDa ezin da topatu eta, beraz, litekeena da gonbidapena ez jasotzea." "Gelatik ateratzen" - "Argia" "Lerroa arbelean kopiatu da" "Esteka arbelean kopiatu da" "Kargatzen…" @@ -287,7 +285,6 @@ Arrazoia: %1$s." "Arrakasta" "Iradokizunak" "Sinkronizatzen" - "Sistema" "Testua" "Hirugarrenei buruzko oharrak" "Haria" diff --git a/libraries/ui-strings/src/main/res/values-fa/translations.xml b/libraries/ui-strings/src/main/res/values-fa/translations.xml index 418ca96419..c14f281f0d 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -185,7 +185,6 @@ "اتاق را ترک کرد" "فضا را ترک کرد" "دعوت لغو شد" - "تیره" "خطای رمزگشایی" "توضیح" "گزینه‌های توسعه دهنده" @@ -220,7 +219,6 @@ "شناسهٔ ماتریکس نتوانست پیدا شود. ممکن است دعوت نرسیده باشد." "ترک کردن اتاق" "ترک کردن فضا" - "روشن" "خط در تخته‌گیره رونوشت شد" "پیوند در تخته‌گیره رونوشت شد" "بار کردن…" @@ -308,7 +306,6 @@ "موفّقیت" "پیشنهادها" "هم‌گام ساختن" - "سامانه" "متن" "تذکّرهای سوم‌شخص" "رشته" diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index 1a7f6c50c9..d5093590ca 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -210,7 +210,6 @@ "Poistuit huoneesta" "Poistuit tilasta" "Kutsu hylätty" - "Tumma" "Salauksen purkuvirhe" "Kuvaus" "Kehittäjän asetukset" @@ -250,7 +249,6 @@ Syy: %1$s." "Tätä Matrix-tunnusta ei löytynyt, joten kutsu ei välttämättä mene perille." "Poistutaan huoneesta" "Poistutaan tilasta" - "Vaalea" "Rivi kopioitu leikepöydälle" "Linkki kopioitu leikepöydälle" "Yhdistä uusi laite" @@ -370,7 +368,6 @@ Syy: %1$s." "Ehdotettu" "Ehdotukset" "Synkronoidaan" - "Järjestelmän oletus" "Teksti" "Kolmannen osapuolen ilmoitukset" "Viestiketju" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 5cb21b772f..545cf66c73 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -217,7 +217,6 @@ "Vous avez quitté le salon" "Vous avez quitté l’espace" "Invitation refusée" - "Sombre" "Erreur de déchiffrement" "Description" "Options pour les développeurs" @@ -257,7 +256,6 @@ Raison : %1$s." "Cet identifiant Matrix est introuvable, il est donc possible que l’invitation ne soit pas reçue." "Quitter le salon…" "En train de quitter l’espace" - "Clair" "Ligne copiée dans le presse-papiers" "Lien copié dans le presse-papiers" "Associer un nouvel appareil" @@ -377,7 +375,6 @@ Raison : %1$s." "Recommandé" "Suggestions" "Synchronisation" - "Système" "Texte" "Avis de tiers" "Fil de discussion" diff --git a/libraries/ui-strings/src/main/res/values-hr/translations.xml b/libraries/ui-strings/src/main/res/values-hr/translations.xml index bb6cf79187..369d8ccce4 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -219,7 +219,6 @@ "Napustio/la je sobu" "Napušteni prostor" "Poziv je odbijen" - "Tamno" "Pogreška kod dešifriranja" "Opis" "Mogućnosti za razvojne inženjere" @@ -259,7 +258,6 @@ Razlog: %1$s ." "Ovaj Matrix ID nije moguće pronaći, pa se pozivnica možda neće primiti." "Izlazak iz sobe" "Napuštanje prostora" - "Svijetlo" "Redak je kopiran u međuspremnik" "Poveznica je kopirana u međuspremnik." "Poveži novi uređaj" @@ -385,7 +383,6 @@ Razlog: %1$s ." "Preporučeno" "Prijedlozi" "Sinkronizacija" - "Sustav" "Tekst" "Obavijesti trećih strana" "Nit" diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index c477a6b6ba..7acfb90ef7 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -218,7 +218,6 @@ "Elhagyta a szobát" "Tér elhagyva" "Meghívás elutasítva" - "Sötét" "Visszafejtési hiba" "Leírás" "Fejlesztői beállítások" @@ -258,7 +257,6 @@ Ok: %1$s." "Ez a Matrix-azonosító nem található, ezért előfordulhat, hogy a meghívó nem érkezik meg." "Szoba elhagyása" "Tér elhagyása" - "Világos" "A sor a vágólapra másolva" "Hivatkozás a vágólapra másolva" "Új eszköz összekapcsolása" @@ -377,7 +375,6 @@ Ok: %1$s." "Javaslat" "Javaslatok" "Szinkronizálás" - "Rendszer" "Szöveg" "Harmadik felek nyilatkozatai" "Üzenetszál" diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index ec5a582838..51d78530a8 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -185,7 +185,6 @@ "Permintaan dibatalkan" "Keluar dari ruangan" "Undangan ditolak" - "Gelap" "Kesalahan dekripsi" "Deskripsi" "Opsi pengembang" @@ -222,7 +221,6 @@ Alasan: %1$s." "Pasang APK" "ID Matrix ini tidak dapat ditemukan, sehingga undangan mungkin tidak diterima." "Meninggalkan ruangan" - "Terang" "Baris disalin ke papan klip" "Tautan disalin ke papan klip" "Memuat…" @@ -308,7 +306,6 @@ Alasan: %1$s." "Berhasil" "Saran" "Menyinkronkan" - "Sistem" "Teks" "Pemberitahuan pihak ketiga" "Utas" diff --git a/libraries/ui-strings/src/main/res/values-it/translations.xml b/libraries/ui-strings/src/main/res/values-it/translations.xml index cdc523a5ab..d1ec78d920 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -218,7 +218,6 @@ "Hai lasciato la stanza" "Hai lasciato lo spazio" "Invito rifiutato" - "Scuro" "Errore di decrittazione" "Descrizione" "Opzioni sviluppatore" @@ -258,7 +257,6 @@ Motivo:. %1$s" "Questo ID Matrix non può essere trovato, quindi l\'invito potrebbe non essere ricevuto." "Lascio la stanza" "Uscendo dallo spazio" - "Chiaro" "Riga copiata negli appunti" "Collegamento copiato negli appunti" "Collega un nuovo dispositivo" @@ -378,7 +376,6 @@ Motivo:. %1$s" "Suggeriti" "Suggerimenti" "Sincronizzazione" - "Sistema" "Testo" "Comunicazioni di terze parti" "Discussione" 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 e25ca0cf4e..c62c579f32 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -216,7 +216,6 @@ "ルームを退出しました" "スペースから退出しました" "招待は却下されました" - "ダーク" "復号化エラー" "詳細" "開発者向けオプション" @@ -256,7 +255,6 @@ "このMatrix IDは見つからないため、招待が届かない可能性があります。" "ルームを退出しています" "スペースを退出しています" - "ライト" "行をクリップボードにコピーしました" "リンクをクリップボードにコピーしました" "新しい端末から接続" @@ -369,7 +367,6 @@ "推奨される" "提案" "同期中" - "システム" "テキスト" "第三者に関する通知" "スレッド" diff --git a/libraries/ui-strings/src/main/res/values-ka/translations.xml b/libraries/ui-strings/src/main/res/values-ka/translations.xml index aa7659dde2..2be4e43d61 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -122,7 +122,6 @@ "საავტორო უფლება" "ოთახის შექმნა…" "დატოვა ოთახი" - "მუქი" "გაშიფვრის შეცდომა" "დეველოპერის პარამეტრები" "პირდაპირი ჩატი" @@ -145,7 +144,6 @@ "დააინსტალირეთ APK" "ეს Matrix ID ვერ მოიძებნა, ამიტომ მოწვევა შეიძლება არ იყოს მიღებული." "ოთახის დატოვება" - "ღია" "ბმული კოპირებულია გაცვლის ბუფერში" "იტვირთება…" @@ -212,7 +210,6 @@ "წარმატება" "შეთავაზებები" "სინქრონიზაცია" - "სისტემა" "ტექსტი" "მესამე პირის შენიშვნები" "თემა" diff --git a/libraries/ui-strings/src/main/res/values-ko/translations.xml b/libraries/ui-strings/src/main/res/values-ko/translations.xml index 3a029e20fc..303e8ba929 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -207,7 +207,6 @@ "방 떠남" "스페이스 떠남" "초대 거부됨" - "다크" "복호화 오류" "설명" "개발자 설정" @@ -247,7 +246,6 @@ "Matrix ID를 찾을 수 없기 때문에 초대가 수신되지 않을 수도 있습니다." "방을 떠나는 중" "스페이스 떠나는 중" - "라이트" "줄이 클립보드에 복사되었습니다." "링크가 클립보드에 복사됨" "새 기기 연결" @@ -360,7 +358,6 @@ "공유된 스페이스" "제안" "동기화 중" - "시스템" "글자" "제3자 고지" "스레드" 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 a0bb1b1a16..aa594f8027 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -207,7 +207,6 @@ "Forlot rommet" "Forlot område" "Invitasjon avslått" - "Mørk" "Dekrypteringsfeil" "Beskrivelse" "Alternativer for utviklere" @@ -245,7 +244,6 @@ "Finner ikke denne Matrix-IDen, så invitasjonen blir kanskje ikke mottatt." "Forlater rommet" "Forlater området" - "Lys" "Linje kopiert til utklippstavlen" "Lenke kopiert til utklippstavlen" "Koble til ny enhet" @@ -360,7 +358,6 @@ "Foreslått" "Forslag" "Synkroniserer" - "System" "Tekst" "Varsler fra tredjeparter" "Tråd" diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml index ab39365f8e..3edeeb00a0 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -172,7 +172,6 @@ "Kamer maken…" "Heeft de kamer verlaten" "Uitnodiging geweigerd" - "Donker" "Decryptie fout" "Ontwikkelaarsopties" "Apparaat-ID" @@ -200,7 +199,6 @@ Reden: %1$s." "APK installeren" "Deze Matrix-ID kan niet worden gevonden, dus de uitnodiging is mogelijk niet ontvangen." "De kamer verlaten" - "Licht" "Link gekopieerd naar klembord" "Laden…" @@ -278,7 +276,6 @@ Reden: %1$s." "Geslaagd" "Suggesties" "Synchroniseren" - "Systeem" "Tekst" "Kennisgevingen van derden" "Gesprek" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index 1a9a45cd94..fb6b06daf7 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -220,7 +220,6 @@ "Opuszczono pokój" "Opuścił przestrzeń" "Odrzucono zaproszenie" - "Ciemny" "Błąd deszyfrowania" "Opis" "Opcje programisty" @@ -260,7 +259,6 @@ Powód: %1$s." "Nie można znaleźć identyfikatora Matrix ID, zaproszenie mogło nie dotrzeć." "Opuszczanie pokoju" "Opuszczam przestrzeń" - "Jasny" "Wiersz skopiowany do schowka" "Link został skopiowany do schowka" "Powiąż nowe urządzenie" @@ -387,7 +385,6 @@ Powód: %1$s." "Polecane" "Sugestie" "Synchronizuję" - "System" "Tekst" "Informacje stron trzecich" "Wątek" diff --git a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml index 68035e0cc2..f35aca5a58 100644 --- a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml @@ -200,7 +200,6 @@ "Saiu da sala" "Saiu do espaço" "Convite recusado" - "Escuro" "Erro de descriptografia" "Descrição" "Opções de desenvolvedor" @@ -238,7 +237,6 @@ Motivo:​ %1$s." "Este ID Matrix não foi encontrado, então o convite pode não ser recebido" "Saindo da sala" "Saindo do espaço" - "Claro" "Linha copiada para a área de transferência" "Link copiado para área de transferência" "Vincular novo dispositivo" @@ -350,7 +348,6 @@ Motivo:​ %1$s." "Sugerido" "Sugestões" "Sincronizando" - "Sistema" "Texto" "Comunicados de terceiros" "Tópico" diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index d82855223d..0acc939565 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -195,7 +195,6 @@ "Saíste da sala" "Saíste do espaço" "Convite rejeitado" - "Escuro" "Erro de decifragem" "Descrição" "Opções de programador" @@ -233,7 +232,6 @@ Razão: %1$s." "Não foi possível encontrar este ID Matrix, portanto o convite pode não ser recebido." "A sair da sala" "A sair do espaço" - "Claro" "Linha copiada para a área de transferência" "Ligação copiada para a área de transferência" "A carregar…" @@ -334,7 +332,6 @@ Razão: %1$s." "Sucesso" "Sugestões" "A sincronizar…" - "Sistema" "Texto" "Avisos de terceiros" "Tópico" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index 33a39278a4..35930b694e 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -198,7 +198,6 @@ "Ați parăsit camera" "S-a părăsit spațiul" "Invitația a fost refuzată" - "Întunecat" "Eroare de decriptare" "Descriere" "Opțiuni programator" @@ -236,7 +235,6 @@ Motiv:%1$s." "Nu am putut valida ID-ul Matrix al acestui utilizator. Este posibil ca invitația să nu fi fost trimisă." "Se părăsește conversația" "Se părăsește spațiul" - "Deschis" "Linie copiată în clipboard" "Linkul a fost copiat în clipboard" "Conectați un dispozitiv nou" @@ -347,7 +345,6 @@ Motiv:%1$s." "Succes" "Sugestii" "Se sincronizează…" - "Sistem" "Text" "Notificări despre software de la terți" "Fir" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index fe852dcfd0..26e1dcfe8d 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -212,7 +212,6 @@ "Покинул комнату" "Покинуть пространство" "Приглашение отклонено" - "Темная" "Ошибка расшифровки" "Описание" "Для разработчиков" @@ -252,7 +251,6 @@ "Идентификатор Matrix ID не найден, приглашение может быть не получено." "Покидаем комнату" "Покидаем пространство" - "Светлое" "Строка скопирована в буфер обмена" "Ссылка скопирована в буфер обмена" "Привязать новое устройство" @@ -379,7 +377,6 @@ "Рекомендуемые" "Предложения" "Синхронизация" - "Системное" "Текст" "Уведомления о третьих лицах" "Обсуждение" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 208016e363..11f4b22005 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -206,7 +206,6 @@ "Opustil/a miestnosť" "Opustil priestor" "Pozvánka bola odmietnutá" - "Tmavý" "Chyba dešifrovania" "Popis" "Možnosti pre vývojárov" @@ -244,7 +243,6 @@ Dôvod: %1$s." "Toto Matrix ID sa nedá nájsť, takže pozvánka nemusí byť prijatá." "Opustenie miestnosti" "Opúšťanie priestoru" - "Svetlý" "Riadok skopírovaný do schránky" "Odkaz bol skopírovaný do schránky" "Prepojiť nové zariadenie" @@ -363,7 +361,6 @@ Dôvod: %1$s." "Navrhované" "Návrhy" "Synchronizuje sa" - "Systém" "Text" "Oznámenia tretích strán" "Vlákno" diff --git a/libraries/ui-strings/src/main/res/values-sv/translations.xml b/libraries/ui-strings/src/main/res/values-sv/translations.xml index afc58de8a5..28dd63d425 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -187,7 +187,6 @@ "Begäran avbruten" "Lämnade rummet" "Inbjudan avvisad" - "Mörkt" "Avkrypteringsfel" "Beskrivning" "Utvecklaralternativ" @@ -224,7 +223,6 @@ Anledning:%1$s." "Installera APK" "Det här Matrix-ID:t kan inte hittas, så inbjudan kanske inte tas emot." "Lämnar rummet" - "Ljust" "Rad kopierad till klippbordet" "Länk kopierad till klippbordet" "Laddar …" @@ -322,7 +320,6 @@ Anledning:%1$s." "Lyckades" "Förslag" "Synkar" - "System" "Text" "Meddelanden från tredje part" "Tråd" diff --git a/libraries/ui-strings/src/main/res/values-tr/translations.xml b/libraries/ui-strings/src/main/res/values-tr/translations.xml index a6d0b3e198..d500b57507 100644 --- a/libraries/ui-strings/src/main/res/values-tr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-tr/translations.xml @@ -175,7 +175,6 @@ "İstek iptal edildi" "Sol oda" "Davet reddedildi" - "Koyu" "Şifre çözme hatası" "Geliştirici seçenekleri" "Cihaz Kimliği" @@ -211,7 +210,6 @@ Neden: %1$s." "APK\'yı yükleyin" "Bu Matrix Kimliği bulunamıyor, bu nedenle davet alınmayabilir." "Odadan ayrılma" - "Aydınlık" "Metin panoya kopyalandı" "Bağlantı panoya kopyalandı" "Yükleniyor…" @@ -295,7 +293,6 @@ Neden: %1$s." "Başarılı" "Öneriler" "Senkronizasyon" - "Sistem" "Metin" "Üçüncü taraf bildirimleri" "Konu" diff --git a/libraries/ui-strings/src/main/res/values-uk/translations.xml b/libraries/ui-strings/src/main/res/values-uk/translations.xml index a9e1d14b40..d7b18bf1ae 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -220,7 +220,6 @@ "Виходить з кімнати" "Вийшов із простору" "Запрошення відхилено" - "Темна" "Помилка розшифрування" "Опис" "Налаштування розробника" @@ -260,7 +259,6 @@ "Цей Matrix-ID не знайдено, тому запрошення може не бути отримано." "Вихід з кімнати" "Вихід з простору" - "Світла" "Рядок скопійовано до буфера обміну" "Посилання скопійовано в буфер обміну" "Під\'єднати новий пристрій" @@ -387,7 +385,6 @@ "Запропоновано" "Пропозиції" "Синхронізація" - "Системна" "Текст" "Повідомлення третіх сторін" "Гілка" diff --git a/libraries/ui-strings/src/main/res/values-ur/translations.xml b/libraries/ui-strings/src/main/res/values-ur/translations.xml index 7bf138deb5..accba4556c 100644 --- a/libraries/ui-strings/src/main/res/values-ur/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ur/translations.xml @@ -141,7 +141,6 @@ "حقوقِ طبع و نشر" "کمرہ تخلیق کررہاہے…" "کمرہ چھوڑ لیا" - "اندھیرا" "رمزکشائی کی خرابی" "مطور اختیارات" "براہ راست گفتگو" @@ -168,7 +167,6 @@ "APK تنصیب کریں" "یہ میٹرکس شناخت نہیں مل سکتی، تو ہو سکتا ہے کہ دعوت نامہ موصول نہ ہو۔" "کمرہ چھوڑنا" - "روشنی" "ربط تختہ تراشہ پر نقل کردا گیا" "لاد رہا ہے…" @@ -240,7 +238,6 @@ "کامیابی" "تجاویز" "ہمسات سازی" - "نظام" "متن" "فریق ثالث کے اشعارات" "دھاگہ" diff --git a/libraries/ui-strings/src/main/res/values-uz/translations.xml b/libraries/ui-strings/src/main/res/values-uz/translations.xml index 50d14ef4d4..63e1756a23 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -210,7 +210,6 @@ "Xonani tark etdi" "Tar etilgan maydon" "Taklif rad etildi" - "Tungi" "Shifrni ochish xatosi" "Tavsif" "Dasturchi variantlari" @@ -250,7 +249,6 @@ Sababi:%1$s." "Ushbu Matrix identifikatori topilmadi, shuning uchun taklif qabul qilinmasligi mumkin." "Xonadan chiqish" "Maydonni tark etish" - "Nur" "Satr vaqtinchalik xotiraga nusxalandi" "Havola vaqtinchalik xotiraga nusxalandi" "Yangi qurilmani ulang" @@ -370,7 +368,6 @@ Sababi:%1$s." "Tavsiya etilgan" "Tavsiyalar" "Sinxronlash" - "Tizim" "Matn" "Uchinchi tomon bildirishnomalari" "Ip" 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 825ff12bea..5cfbe26fba 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -208,7 +208,6 @@ "Đã rời khỏi phòng" "Rời khỏi không gian" "Lời mời bị từ chối" - "Tối" "Lỗi khi giải mã" "Mô tả" "Tùy chọn nhà phát triển" @@ -248,7 +247,6 @@ Lý do: %1$s ." "Không tìm thấy Matrix ID này, nên lời mời có thể chưa được nhận." "Rời khỏi phòng" "Rời khỏi không gian" - "Sáng" "Đã sao chép dòng" "Đã chép liên kết vào bộ nhớ tạm" "Liên kết thiết bị mới" @@ -359,7 +357,6 @@ Lý do: %1$s ." "Gợi ý" "Gợi ý" "Đang đồng bộ" - "Hệ thống" "Văn bản" "Thông báo từ bên thứ ba" "Chủ đề" diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index b4c993e852..71159b78e4 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -208,7 +208,6 @@ "已離開聊天室" "離開空間" "邀請被拒絕" - "深色" "解密錯誤" "描述" "開發者選項" @@ -248,7 +247,6 @@ "找不到此 Matrix ID,因此可能沒有人會收到邀請。" "正在離開聊天室" "離開空間" - "淺色" "行已複製到剪貼簿" "連結已複製到剪貼簿" "連結新裝置" @@ -361,7 +359,6 @@ "已建議" "建議" "同步中" - "系統" "文字" "第三方通知" "討論串" diff --git a/libraries/ui-strings/src/main/res/values-zh/translations.xml b/libraries/ui-strings/src/main/res/values-zh/translations.xml index 7366a4fd95..9cea16d2f0 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -215,7 +215,6 @@ "离开房间" "离开空间" "邀请已拒绝" - "深色" "解密错误" "描述" "开发者选项" @@ -255,7 +254,6 @@ "找不到此 Matrix ID,因此可能无法收到邀请。" "正在离开房间" "正在离开空间" - "浅色" "链接已复制到剪贴板" "链接已复制到剪贴板" "关联新设备" @@ -368,7 +366,6 @@ "建议" "建议" "正在同步" - "系统" "文本" "第三方通知" "消息列" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 173a525919..ee0f51000a 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -218,7 +218,6 @@ "Left room" "Left space" "Invite declined" - "Dark" "Decryption error" "Description" "Developer options" @@ -258,7 +257,6 @@ Reason: %1$s." "This Matrix ID can\'t be found, so the invite might not be received." "Leaving room" "Leaving space" - "Light" "Line copied to clipboard" "Link copied to clipboard" "Link new device" @@ -378,7 +376,6 @@ Reason: %1$s." "Suggested" "Suggestions" "Syncing" - "System" "Text" "Third-party notices" "Thread" diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml deleted file mode 100644 index ba6c431d8b..0000000000 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - "Black" - diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 03ada90c4b..6ea495439e 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -331,6 +331,7 @@ "screen_blocked_users_.*", "full_screen_intent_banner_.*", "troubleshoot_notifications_entry_point_.*", + "theme\\..*", "screen\\.labs\\..*" ] }, From e8f1bf0085d4f7c7f5f2d75376ed836f6603337b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 12 May 2026 19:33:02 +0200 Subject: [PATCH 0416/1083] Make Element Call screen work edge-to-edge (#6634) * Update dependency io.element.android:element-call-embedded to v0.19.3 * Remove `Scaffold` component from CallScreenView * Add immersive mode to calls in landscape orientation * Add `consumeWindowInsets`, which fixes the webview not displaying any insets for the bottom nav bar * Update screenshots * Ignore compact height in PiP mode --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: ElementBot --- .../features/call/impl/ui/CallScreenView.kt | 149 +++++++++--------- .../call/impl/ui/ElementCallActivity.kt | 25 +++ ...s.call.impl.ui_CallScreenView_Day_3_en.png | 4 +- ...call.impl.ui_CallScreenView_Night_3_en.png | 4 +- 4 files changed, 100 insertions(+), 82 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index 1c68a62f55..095d511e0e 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -17,9 +17,10 @@ import android.webkit.WebChromeClient import android.webkit.WebView import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -45,7 +46,6 @@ import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.ui.strings.CommonStrings import timber.log.Timber @@ -72,86 +72,79 @@ internal fun CallScreenView( } } - Scaffold( - modifier = modifier, - ) { padding -> - BackHandler { - handleBack() + BackHandler { + handleBack() + } + if (state.webViewError != null) { + ErrorDialog( + content = buildString { + append(stringResource(CommonStrings.error_unknown)) + state.webViewError.takeIf { it.isNotEmpty() }?.let { append("\n\n").append(it) } + }, + onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, + ) + } else { + var webViewAudioManager by remember { mutableStateOf(null) } + val coroutineScope = rememberCoroutineScope() + + var invalidAudioDeviceReason by remember { mutableStateOf(null) } + invalidAudioDeviceReason?.let { + InvalidAudioDeviceDialog(invalidAudioDeviceReason = it) { + invalidAudioDeviceReason = null + } } - if (state.webViewError != null) { - ErrorDialog( - content = buildString { - append(stringResource(CommonStrings.error_unknown)) - state.webViewError.takeIf { it.isNotEmpty() }?.let { append("\n\n").append(it) } - }, - onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, - ) - } else { - var webViewAudioManager by remember { mutableStateOf(null) } - val coroutineScope = rememberCoroutineScope() - var invalidAudioDeviceReason by remember { mutableStateOf(null) } - invalidAudioDeviceReason?.let { - InvalidAudioDeviceDialog(invalidAudioDeviceReason = it) { - invalidAudioDeviceReason = null - } + CallWebView( + modifier = modifier.consumeWindowInsets(WindowInsets.systemBars).fillMaxSize(), + url = state.urlState, + userAgent = state.userAgent, + onPermissionsRequest = { request -> + val androidPermissions = mapWebkitPermissions(request.resources) + val callback: RequestPermissionCallback = { request.grant(it) } + requestPermissions(androidPermissions.toTypedArray(), callback) + }, + onConsoleMessage = onConsoleMessage, + onCreateWebView = { webView -> + webView.addBackHandler(onBackPressed = ::handleBack) + val interceptor = WebViewWidgetMessageInterceptor( + webView = webView, + onUrlLoaded = { url -> + webView.evaluateJavascript("controls.onBackButtonPressed = () => { backHandler.onBackPressed() }", null) + if (webViewAudioManager?.isInCallMode?.get() == false) { + Timber.d("URL $url is loaded, starting in-call audio mode") + webViewAudioManager?.onCallStarted() + } else { + Timber.d("Can't start in-call audio mode since the app is already in it.") + } + }, + onError = { state.eventSink(CallScreenEvent.OnWebViewError(it)) }, + ) + webViewAudioManager = WebViewAudioManager( + webView = webView, + coroutineScope = coroutineScope, + onInvalidAudioDeviceAdded = { invalidAudioDeviceReason = it }, + ) + state.eventSink(CallScreenEvent.SetupMessageChannels(interceptor)) + val pipController = WebViewPipController(webView) + pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) + }, + onDestroyWebView = { + // Reset audio mode + webViewAudioManager?.onCallStopped() } - - CallWebView( - modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) - .fillMaxSize(), - url = state.urlState, - userAgent = state.userAgent, - onPermissionsRequest = { request -> - val androidPermissions = mapWebkitPermissions(request.resources) - val callback: RequestPermissionCallback = { request.grant(it) } - requestPermissions(androidPermissions.toTypedArray(), callback) - }, - onConsoleMessage = onConsoleMessage, - onCreateWebView = { webView -> - webView.addBackHandler(onBackPressed = ::handleBack) - val interceptor = WebViewWidgetMessageInterceptor( - webView = webView, - onUrlLoaded = { url -> - webView.evaluateJavascript("controls.onBackButtonPressed = () => { backHandler.onBackPressed() }", null) - if (webViewAudioManager?.isInCallMode?.get() == false) { - Timber.d("URL $url is loaded, starting in-call audio mode") - webViewAudioManager?.onCallStarted() - } else { - Timber.d("Can't start in-call audio mode since the app is already in it.") - } - }, - onError = { state.eventSink(CallScreenEvent.OnWebViewError(it)) }, - ) - webViewAudioManager = WebViewAudioManager( - webView = webView, - coroutineScope = coroutineScope, - onInvalidAudioDeviceAdded = { invalidAudioDeviceReason = it }, - ) - state.eventSink(CallScreenEvent.SetupMessageChannels(interceptor)) - val pipController = WebViewPipController(webView) - pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) - }, - onDestroyWebView = { - // Reset audio mode - webViewAudioManager?.onCallStopped() - } - ) - when (state.urlState) { - AsyncData.Uninitialized, - is AsyncData.Loading -> - ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait)) - is AsyncData.Failure -> { - Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") - ErrorDialog( - content = state.urlState.error.message.orEmpty(), - onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, - ) - } - is AsyncData.Success -> Unit + ) + when (state.urlState) { + AsyncData.Uninitialized, + is AsyncData.Loading -> + ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait)) + is AsyncData.Failure -> { + Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") + ErrorDialog( + content = state.urlState.error.message.orEmpty(), + onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, + ) } + is AsyncData.Success -> Unit } } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index 367328ed10..26df7c160c 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -32,6 +32,9 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.core.app.PictureInPictureModeChangedInfo import androidx.core.content.IntentCompat import androidx.core.util.Consumer +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.lifecycle.Lifecycle import dev.zacsweers.metro.Inject import io.element.android.compound.colors.SemanticColorsLightDark @@ -52,6 +55,7 @@ import io.element.android.libraries.audio.api.AudioFocusRequester import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.designsystem.theme.ElementThemeApp +import io.element.android.libraries.designsystem.utils.hasCompactHeightWindowSize import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.preferences.api.store.AppPreferencesStore import timber.log.Timber @@ -111,6 +115,27 @@ class ElementCallActivity : val colors by remember(webViewTarget.value?.sessionId) { enterpriseService.semanticColorsFlow(sessionId = webViewTarget.value?.sessionId) }.collectAsState(SemanticColorsLightDark.default) + + // When the height is compact, hide the system bars by default to maximize the space for the call, using immersive mode + val hasCompactHeight = hasCompactHeightWindowSize() + DisposableEffect(hasCompactHeight, pipState.isInPictureInPicture) { + if (hasCompactHeight && !pipState.isInPictureInPicture) { + val window = this@ElementCallActivity.window ?: return@DisposableEffect onDispose {} + val insetsController = WindowCompat.getInsetsController(window, window.decorView) + val systemBarInsets = WindowInsetsCompat.Type.systemBars() + insetsController.hide(systemBarInsets) + + insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + + onDispose { + insetsController.show(systemBarInsets) + insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_DEFAULT + } + } else { + onDispose {} + } + } + ElementThemeApp( appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService, diff --git a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png index b5e7419267..b45afb67bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48fa7b1415694f0a7ebb3de458edee8792f5643f681cc25627560f2e3d8ba491 -size 16331 +oid sha256:49731638f35e9c7583ece7122e3690728f3d4183a65e2e49cd270d02fb93ac70 +size 15950 diff --git a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png index 1c8ce2991d..14fd900451 100644 --- a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebf559265b2cd4ebba7c5439b759365ed8d31532988bda5d8c76bb7c8d76dd68 -size 14892 +oid sha256:11a77776662896532ef2999e3b90aa93b3459bf9b7a5f461c06ccb3743612aab +size 14738 From 960ff0fb75000e9872b62672232c606071de0e0f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 May 2026 21:39:48 +0200 Subject: [PATCH 0417/1083] Renovate: Keep Guava on the Android variant and ignore jre-only upgrades. --- .github/renovate.json5 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 17e1fa0f1c..c16310cf43 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -34,6 +34,13 @@ "/^org.jetbrains.kotlinx:kotlinx-datetime/", ], }, + { + // Keep Guava on the Android variant and ignore jre-only upgrades. + "matchPackageNames": [ + "com.google.guava:guava", + ], + "allowedVersions": "/-android$/", + }, { // Limit PostHog Android upgrade to one PR per month, the first day of the month "matchPackageNames": [ From c959f50d53f17c0c432c1c15e65e6ea55ea7cdc2 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Wed, 13 May 2026 16:17:23 +0800 Subject: [PATCH 0418/1083] Back button web view to esc (revive fixed version of: https://github.com/element-hq/element-x-android/pull/6724) (#6725) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change native back button behavior in EC view: - inject escape into webview instead of going back. - the webview will call back when no other modal is open. * call down and up in the webview + make sure that we fall back to close pip in case the webview did not handle the esc action. * Tests and refactor to CallScreenBackPressPolicy --------- Co-authored-by: Jorge Martín --- .../call/impl/ui/CallScreenBackPressPolicy.kt | 26 +++ .../features/call/impl/ui/CallScreenView.kt | 38 +++-- .../call/ui/CallScreenBackPressPolicyTest.kt | 96 +++++++++++ .../features/call/ui/CallScreenViewTest.kt | 151 ++++++++++++++++++ ...nticsNodeInteractionsProviderExtensions.kt | 17 ++ 5 files changed, 317 insertions(+), 11 deletions(-) create mode 100644 features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt create mode 100644 features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt new file mode 100644 index 0000000000..cd47cd8bb1 --- /dev/null +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.impl.ui +internal sealed interface CallScreenBackPressAction { + data object DispatchEscapeToWebView : CallScreenBackPressAction + data object EnterPictureInPicture : CallScreenBackPressAction +} + +internal object CallScreenBackPressPolicy { + fun resolve( + supportPip: Boolean, + hasWebView: Boolean, + fromNative: Boolean, + ): CallScreenBackPressAction? { + return when { + hasWebView && fromNative -> CallScreenBackPressAction.DispatchEscapeToWebView + hasWebView && supportPip -> CallScreenBackPressAction.EnterPictureInPicture + else -> null + } + } +} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index 095d511e0e..2537eb739c 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -64,16 +64,20 @@ internal fun CallScreenView( requestPermissions: (Array, RequestPermissionCallback) -> Unit, modifier: Modifier = Modifier, ) { - fun handleBack() { - if (pipState.supportPip) { - pipState.eventSink.invoke(PictureInPictureEvent.EnterPictureInPicture) - } else { - state.eventSink(CallScreenEvent.Hangup) + var callWebView by remember { mutableStateOf(null) } + + fun handleBack(fromNative: Boolean = false) { + when (CallScreenBackPressPolicy.resolve(supportPip = pipState.supportPip, hasWebView = callWebView != null, fromNative)) { + CallScreenBackPressAction.EnterPictureInPicture -> + pipState.eventSink(PictureInPictureEvent.EnterPictureInPicture) + CallScreenBackPressAction.DispatchEscapeToWebView -> + callWebView?.dispatchEscKeyEvent() + null -> Timber.d("Back press with unsupported pip is a no-op") } } BackHandler { - handleBack() + handleBack(fromNative = true) } if (state.webViewError != null) { ErrorDialog( @@ -105,6 +109,7 @@ internal fun CallScreenView( }, onConsoleMessage = onConsoleMessage, onCreateWebView = { webView -> + callWebView = webView webView.addBackHandler(onBackPressed = ::handleBack) val interceptor = WebViewWidgetMessageInterceptor( webView = webView, @@ -129,6 +134,7 @@ internal fun CallScreenView( pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) }, onDestroyWebView = { + callWebView = null // Reset audio mode webViewAudioManager?.onCallStopped() } @@ -241,15 +247,16 @@ private fun WebView.setup( private fun WebView.addBackHandler(onBackPressed: () -> Unit) { addJavascriptInterface( - object { - @Suppress("unused") - @JavascriptInterface - fun onBackPressed() = onBackPressed() - }, + JavascriptBackHandlerBridge(callback = onBackPressed), "backHandler" ) } +private fun WebView.dispatchEscKeyEvent() { + dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_ESCAPE)) + dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_ESCAPE)) +} + @PreviewsDayNight @Composable internal fun CallScreenViewPreview( @@ -268,3 +275,12 @@ internal fun CallScreenViewPreview( internal fun InvalidAudioDeviceDialogPreview() = ElementPreview { InvalidAudioDeviceDialog(invalidAudioDeviceReason = InvalidAudioDeviceReason.BT_AUDIO_DEVICE_DISABLED) {} } + +internal class JavascriptBackHandlerBridge( + private val callback: () -> Unit, +) { + @JavascriptInterface + fun onBackPressed() { + callback() + } +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt new file mode 100644 index 0000000000..f07f7039d3 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.ui + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.impl.ui.CallScreenBackPressAction +import io.element.android.features.call.impl.ui.CallScreenBackPressPolicy +import org.junit.Test + +class CallScreenBackPressPolicyTest { + @Test + fun `resolve returns dispatch escape when a web view is available and native button is pressed`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = true, + fromNative = true, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) + } + + @Test + fun `resolve dispatch escape when there is a web view and pip is supported on native button press`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = true, + fromNative = true, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) + } + + @Test + fun `resolve returns hangup when there is no web view and pip is not supported from native button`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = false, + fromNative = true, + ) + + assertThat(result).isNull() + } + + @Test + fun `resolve returns hangup when there is no web view even though pip is supported from native button`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = false, + fromNative = true, + ) + + assertThat(result).isNull() + } + + @Test + fun `resolve goes to pip if its not from native but from the webview`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = true, + fromNative = false, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.EnterPictureInPicture) + } + @Test + fun `resolve hangs up if its not from native but from the webview and pip is not supported`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = true, + fromNative = false, + ) + + assertThat(result).isNull() + } + + @Test + fun `invalid cases (event comes from webview but there is now webview) all result in hangup`() { + val withPipSupport = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = false, + fromNative = false, + ) + assertThat(withPipSupport).isNull() + val withOutPipSupport = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = false, + fromNative = false, + ) + assertThat(withOutPipSupport).isNull() + } +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt new file mode 100644 index 0000000000..99aaee6f39 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.ui + +import android.view.KeyEvent +import android.webkit.WebView +import androidx.activity.ComponentActivity +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.call.impl.pip.PictureInPictureEvent +import io.element.android.features.call.impl.pip.PictureInPictureState +import io.element.android.features.call.impl.pip.aPictureInPictureState +import io.element.android.features.call.impl.ui.CallScreenEvent +import io.element.android.features.call.impl.ui.CallScreenState +import io.element.android.features.call.impl.ui.CallScreenView +import io.element.android.features.call.impl.ui.JavascriptBackHandlerBridge +import io.element.android.features.call.impl.ui.aCallScreenState +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.pressBackKey +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements +import org.robolectric.annotation.Resetter +import org.robolectric.shadows.ShadowWebView + +@OptIn(ExperimentalTestApi::class) +@RunWith(AndroidJUnit4::class) +class CallScreenViewTest { + @Test + fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() = runAndroidComposeUiTest { + val callEvents = EventsRecorder() + + setCallScreenView( + state = aCallScreenState(eventSink = callEvents), + useInspectionMode = true, + ) + + pressBackKey() + + callEvents.assertEmpty() + } + + @Config(shadows = [RecordingShadowWebView::class]) + @Test + fun `pressing back key dispatches escape key events to web view when pip is unsupported`() = runAndroidComposeUiTest { + setCallScreenView( + state = aCallScreenState(), + useInspectionMode = false, + pipState = aPictureInPictureState(supportPip = false), + ) + + pressBackKey() + + val dispatchedEvents = RecordingShadowWebView.dispatchedEvents + assertEquals(2, dispatchedEvents.size) + assertEquals(KeyEvent.ACTION_DOWN, dispatchedEvents[0].action) + assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[0].keyCode) + assertEquals(KeyEvent.ACTION_UP, dispatchedEvents[1].action) + assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[1].keyCode) + } + + @Config(shadows = [RecordingShadowWebView::class]) + @Test + fun `web view javascript back handler emits pip event when pip is supported`() = runAndroidComposeUiTest { + val pipEvents = EventsRecorder() + + setCallScreenView( + state = aCallScreenState(), + useInspectionMode = false, + pipState = aPictureInPictureState( + supportPip = true, + eventSink = pipEvents, + ), + ) + + runOnIdle { + RecordingShadowWebView.invokeJavascriptBackHandler() + } + + pipEvents.assertSize(2) + pipEvents.assertTrue(0) { it is PictureInPictureEvent.SetPipController } + pipEvents.assertTrue(1) { it is PictureInPictureEvent.EnterPictureInPicture } + } +} + +@OptIn(ExperimentalTestApi::class) +private fun AndroidComposeUiTest.setCallScreenView( + state: CallScreenState, + useInspectionMode: Boolean, + pipState: PictureInPictureState = aPictureInPictureState(supportPip = false), +) { + setContent { + // Inspection mode disables AndroidView creation; keep it configurable per test. + CompositionLocalProvider(LocalInspectionMode provides useInspectionMode) { + CallScreenView( + state = state, + pipState = pipState, + onConsoleMessage = {}, + requestPermissions = { _, _ -> }, + ) + } + } +} + +@Implements(WebView::class) +internal class RecordingShadowWebView : ShadowWebView() { + companion object { + val dispatchedEvents = mutableListOf() + private var backHandlerJavascriptInterface: JavascriptBackHandlerBridge? = null + + @Resetter + @JvmStatic + @Suppress("unused") + fun resetRecordedEvents() { + dispatchedEvents.clear() + backHandlerJavascriptInterface = null + } + + fun invokeJavascriptBackHandler() { + val backHandler = checkNotNull(backHandlerJavascriptInterface) { "Expected backHandler JavaScript interface to be registered" } + backHandler.onBackPressed() + } + } + + @Implementation + protected override fun addJavascriptInterface(`object`: Any, name: String) { + super.addJavascriptInterface(`object`, name) + if (name == "backHandler") { + backHandlerJavascriptInterface = `object` as? JavascriptBackHandlerBridge + } + } + + @Implementation + @Suppress("unused") + fun dispatchKeyEvent(event: KeyEvent): Boolean { + dispatchedEvents += KeyEvent(event) + return false + } +} diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt index a473e6bd22..232116b385 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt @@ -23,9 +23,11 @@ import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasText import androidx.compose.ui.test.isDialog +import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import io.element.android.libraries.ui.strings.CommonStrings +import org.junit.rules.TestRule val trueMatcher = SemanticsMatcher("true matcher") { true } @@ -48,6 +50,14 @@ fun AndroidComposeUiTest.pressBack() { onNode(hasContentDescription(text)).performClick() } +/** + * Press the back button in the app bar. + */ +fun AndroidComposeTestRule.pressBack() { + val text = activity.getString(CommonStrings.action_back) + onNode(hasContentDescription(text)).performClick() +} + /** * Press the back key. */ @@ -55,6 +65,13 @@ fun AndroidComposeUiTest.pressBackKey() { activity!!.onBackPressedDispatcher.onBackPressed() } +/** + * Press the back key. + */ +fun AndroidComposeTestRule.pressBackKey() { + activity.onBackPressedDispatcher.onBackPressed() +} + fun SemanticsNodeInteractionsProvider.pressTag(tag: String) { onNode(hasTestTag(tag)).performClick() } From 737882d35efa1975b7f0ffa1ed280be3b556204b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 10:18:59 +0200 Subject: [PATCH 0419/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.13 (#6779) 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 b5393bcc22..6a69c25787 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.7" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.13" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 31d06391ed89e415dabc30c53f015a36114771d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 May 2026 11:39:46 +0200 Subject: [PATCH 0420/1083] Pin code: remove the key if there is no pin code --- .../lockscreen/impl/pin/DefaultPinCodeManager.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt index 2bda5759a8..d699357933 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt @@ -16,6 +16,10 @@ import io.element.android.libraries.cryptography.api.EncryptionDecryptionService import io.element.android.libraries.cryptography.api.EncryptionResult import io.element.android.libraries.cryptography.api.SecretKeyRepository import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import java.util.concurrent.CopyOnWriteArrayList internal const val SECRET_KEY_ALIAS = "elementx.SECRET_KEY_ALIAS_PIN_CODE" @@ -29,6 +33,8 @@ class DefaultPinCodeManager( ) : PinCodeManager { private val callbacks = CopyOnWriteArrayList() + private val migrationMutex = Mutex() + override fun addCallback(callback: PinCodeManager.Callback) { callbacks.add(callback) } @@ -39,6 +45,15 @@ class DefaultPinCodeManager( override fun hasPinCode(): Flow { return secretKeyRepository.hasKey(SECRET_KEY_ALIAS) + .onStart { + migrationMutex.withLock { + val hasKey = secretKeyRepository.hasKey(SECRET_KEY_ALIAS).first() + if (hasKey && lockScreenStore.getEncryptedCode() == null) { + // Remove the key if there is no pin code + secretKeyRepository.deleteKey(SECRET_KEY_ALIAS) + } + } + } } override suspend fun getPinCodeSize(): Int? { From 7e6d3c60d2df7f1f9dd87638295392f5aaed66f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 13 May 2026 12:15:26 +0200 Subject: [PATCH 0421/1083] Setting version for the release 26.05.1 --- enterprise | 2 +- plugins/src/main/kotlin/Versions.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/enterprise b/enterprise index fb7e9287d9..6781da90aa 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit fb7e9287d9d446012925139842d9aaa8e99a74dc +Subproject commit 6781da90aae61cf77dcdbc543e18d76411d578b4 diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index fa197e4a08..a3de4327b4 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 5 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** From 4823267013eda7feb9406de18938cc236d1aa371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 13 May 2026 13:12:42 +0200 Subject: [PATCH 0422/1083] Adding fastlane file for version 26.05.1 --- fastlane/metadata/android/en-US/changelogs/202605010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202605010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202605010.txt b/fastlane/metadata/android/en-US/changelogs/202605010.txt new file mode 100644 index 0000000000..0ad08f5b4d --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202605010.txt @@ -0,0 +1,2 @@ +Main changes in this version: improvements in Element Call, room knocking and room directory are now available, improvements on DMs. +Full changelog: https://github.com/element-hq/element-x-android/releases From 5e577e2360f154e56fe4c0520c6a33fbd6ac705e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 13 May 2026 13:59:48 +0200 Subject: [PATCH 0423/1083] Changelog for version 26.05.1 --- CHANGES.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a57395b833..19665d542c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,47 @@ +Changes in Element X v26.05.1 +============================= + + + +## What's Changed +### ✨ Features +* Make Element Call screen work edge-to-edge by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6634 +### 🙌 Improvements +* Stop removing the `logs` dir when clearing cache by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6765 +* Adapt to new DM definition changes in the SDK by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6748 +* feat: Update call started timeline item + declined support by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6649 +### 🐛 Bugfixes +* Improve pin code UX by @bmarty in https://github.com/element-hq/element-x-android/pull/6744 +* Use just the other user's avatar for DM details by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6738 +* Improve `FetchPushForegroundService`'s reliability by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6757 +* Prevent user from starting Live Location Sharing in thread by @bmarty in https://github.com/element-hq/element-x-android/pull/6767 +* Fix media playback from the timeline broken when exiting a thread by @bmarty in https://github.com/element-hq/element-x-android/pull/6771 +* Pin code: remove the key if there is no pin code by @bmarty in https://github.com/element-hq/element-x-android/pull/6780 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6761 +### 🚧 In development 🚧 +* Feature : share live location by @ganfra in https://github.com/element-hq/element-x-android/pull/6741 +### Dependency upgrades +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.7 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6746 +* Update actions/add-to-project action to v2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6758 +* Update dependency io.github.sergio-sastre.ComposablePreviewScanner:android to v0.9.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6759 +* Update dependency io.element.android:element-call-embedded to v0.19.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6766 +* Update metro to v1 (major) by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6720 +* Update tspascoal/get-user-teams-membership action to v4.0.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6750 +* Update plugin sonarqube to v7.3.0.8198 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6743 +* Update plugin dependencycheck to v12.2.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6760 +* Update dependency com.google.guava:guava to v33.6.0-android by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6646 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.13 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6779 +### Others +* Render media captions formatting in the media viewer by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6729 +* Reduce FeatureFlag `Knock` effect on room creation and room edition forms by @bmarty in https://github.com/element-hq/element-x-android/pull/6768 +* Use the right analytics span as a parent in `checkNetworkConnection` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6751 +* Add missing strings `theme.black` by @bmarty in https://github.com/element-hq/element-x-android/pull/6772 +* Map back button in web view to esc (revive fixed version of: https://github.com/element-hq/element-x-android/pull/6724) by @toger5 in https://github.com/element-hq/element-x-android/pull/6725 + + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.05.0...v26.05.1 + Changes in Element X v26.05.0 ============================= From e563fc79199ea93481c183c85de5d4e833131824 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 08:08:21 +0200 Subject: [PATCH 0424/1083] Update dependency androidx.compose:compose-bom to v2026.05.00 (#6784) 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 6a69c25787..a786c342e4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ camera = "1.6.0" work = "2.11.2" # Compose -compose_bom = "2026.04.01" +compose_bom = "2026.05.00" # Coroutines coroutines = "1.10.2" From 486754602dfd164ea2a00fe40061fedea5587588 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 08:09:00 +0200 Subject: [PATCH 0425/1083] Update dependency io.sentry:sentry-android to v8.41.0 (#6787) 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 a786c342e4..5eac4e71a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -222,7 +222,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.43.0" -sentry = "io.sentry:sentry-android:8.40.0" +sentry = "io.sentry:sentry-android:8.41.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 432a7712c43aca40ffa1d64d90448e6e48f5fef3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 09:03:50 +0200 Subject: [PATCH 0426/1083] Update kotlin (#6790) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5eac4e71a4..a8158a638f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ work = "2.11.2" compose_bom = "2026.05.00" # Coroutines -coroutines = "1.10.2" +coroutines = "1.11.0" # Accompanist accompanist = "0.37.3" @@ -35,7 +35,7 @@ test_core = "1.7.0" roborazzi = "1.60.0" # Jetbrain -datetime = "0.7.1" +datetime = "0.8.0" serialization_json = "1.11.0" #other From cbc677b80dd11f7d634e86f5463f288fed3ba343 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Fri, 15 May 2026 01:43:21 -0700 Subject: [PATCH 0427/1083] Fix room list duplicate-detection telemetry crashing before it can report (#6791) * Add room dupe regression tests * Fix telemetry path for dedupe discovery --- .../impl/datasource/RoomListDataSourceTest.kt | 100 +++++++++++++++++- .../impl/roomlist/RoomListEntriesUpdateExt.kt | 12 +-- .../impl/roomlist/RoomSummaryListProcessor.kt | 7 +- .../roomlist/RoomSummaryListProcessorTest.kt | 56 +++++++++- 4 files changed, 165 insertions(+), 10 deletions(-) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt index 1ce5061356..ace1ef2eaa 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt @@ -14,6 +14,8 @@ import io.element.android.features.home.impl.FakeDateTimeObserver import io.element.android.libraries.androidutils.system.DateTimeObserver import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.roomlist.FakeDynamicRoomList @@ -100,11 +102,107 @@ class RoomListDataSourceTest { } } + /** + * Tracking issue #4182: rooms duplicated in the room list around midnight. + * + * If the SDK ever leaks a list containing the same roomId twice (the suspected cause of #4182), + * the UI mapper's `distinctBy` safety net in [RoomListDataSource.buildAndEmitAllRooms] must + * remove the duplicate AND `analyticsService.trackError` must fire so the team can root-cause + * it via Sentry. + */ + @Test + fun `when SDK summaries source contains duplicate roomIds, UI layer dedupes and reports trackError`() = runTest { + val analyticsService = FakeAnalyticsService() + val duplicatedSummaries = listOf( + aRoomSummary(roomId = A_ROOM_ID), + aRoomSummary(roomId = A_ROOM_ID), + aRoomSummary(roomId = A_ROOM_ID_2), + ) + val roomList = FakeDynamicRoomList(summaries = MutableStateFlow(duplicatedSummaries)) + val roomListService = FakeRoomListService( + createRoomListLambda = { roomList } + ).apply { + postState(RoomListService.State.Running) + } + val roomListDataSource = createRoomListDataSource( + roomListService = roomListService, + analyticsService = analyticsService, + ) + + roomListDataSource.roomSummariesFlow.test { + roomListDataSource.launchIn(backgroundScope) + val list = awaitItem() + assertThat(list.map { it.roomId }).containsExactly(A_ROOM_ID, A_ROOM_ID_2).inOrder() + assertThat(analyticsService.trackedErrors).hasSize(1) + } + } + + /** + * Tracking issue #4182. + * + * Targeted scenario: a `DateChanged` tick fires after an initial SDK emit, then a follow-up + * SDK emit lands (mimicking "midnight, then a new message arrives"). Even though the diffCache + * is bypassed during the rebuild (`useCache = false`), the final state must contain each + * roomId exactly once and trackError must not fire on a happy path. + */ + @Test + fun `interleaved date change and SDK update with overlapping content does not produce duplicates`() = runTest { + val analyticsService = FakeAnalyticsService() + val summariesFlow = MutableStateFlow( + listOf( + aRoomSummary(roomId = A_ROOM_ID), + aRoomSummary(roomId = A_ROOM_ID_2), + ) + ) + val roomList = FakeDynamicRoomList(summaries = summariesFlow) + val roomListService = FakeRoomListService( + createRoomListLambda = { roomList } + ).apply { + postState(RoomListService.State.Running) + } + val dateTimeObserver = FakeDateTimeObserver() + val roomListDataSource = createRoomListDataSource( + roomListService = roomListService, + dateTimeObserver = dateTimeObserver, + analyticsService = analyticsService, + ) + + roomListDataSource.roomSummariesFlow.test { + roomListDataSource.launchIn(backgroundScope) + val initial = awaitItem() + assertThat(initial.map { it.roomId }).containsExactly(A_ROOM_ID, A_ROOM_ID_2).inOrder() + + // Midnight ticks while the cache holds [A_ROOM_ID, A_ROOM_ID_2] + dateTimeObserver.given(DateTimeObserver.Event.DateChanged(Instant.MIN, Instant.now())) + val afterMidnight = awaitItem() + assertThat(afterMidnight.map { it.roomId }).containsExactly(A_ROOM_ID, A_ROOM_ID_2).inOrder() + + // A new message bumps A_ROOM_ID — different unread count makes the StateFlow see this + // as a new value + summariesFlow.value = listOf( + aRoomSummary(roomId = A_ROOM_ID, numUnreadMessages = 1), + aRoomSummary(roomId = A_ROOM_ID_2), + ) + val afterMessage = awaitItem() + assertThat(afterMessage.map { it.roomId }).containsExactly(A_ROOM_ID, A_ROOM_ID_2).inOrder() + assertThat(afterMessage.map { it.roomId }.toSet()).hasSize(afterMessage.size) + + // Second midnight rebuild after the new message + dateTimeObserver.given(DateTimeObserver.Event.DateChanged(Instant.MIN, Instant.now())) + val afterSecondMidnight = awaitItem() + assertThat(afterSecondMidnight.map { it.roomId }).containsExactly(A_ROOM_ID, A_ROOM_ID_2).inOrder() + assertThat(afterSecondMidnight.map { it.roomId }.toSet()).hasSize(afterSecondMidnight.size) + + assertThat(analyticsService.trackedErrors).isEmpty() + } + } + private fun TestScope.createRoomListDataSource( roomListService: FakeRoomListService = FakeRoomListService(), roomListRoomSummaryFactory: RoomListRoomSummaryFactory = aRoomListRoomSummaryFactory(), notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), dateTimeObserver: FakeDateTimeObserver = FakeDateTimeObserver(), + analyticsService: FakeAnalyticsService = FakeAnalyticsService(), ) = RoomListDataSource( roomListService = roomListService, roomListRoomSummaryFactory = roomListRoomSummaryFactory, @@ -112,6 +210,6 @@ class RoomListDataSourceTest { notificationSettingsService = notificationSettingsService, sessionCoroutineScope = backgroundScope, dateTimeObserver = dateTimeObserver, - analyticsService = FakeAnalyticsService(), + analyticsService = analyticsService, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt index 27b19ebf19..5d8367bb99 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt @@ -16,25 +16,25 @@ import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate internal fun RoomListEntriesUpdate.describe(): String { return when (this) { is RoomListEntriesUpdate.Set -> { - "Set #$index to '${value.displayName()}'" + "Set #$index to '${value.id()}'" } is RoomListEntriesUpdate.Append -> { - "Append ${values.map { "'" + it.displayName() + "'" }}" + "Append ${values.map { "'" + it.id() + "'" }}" } is RoomListEntriesUpdate.PushBack -> { - "PushBack '${value.displayName()}'" + "PushBack '${value.id()}'" } is RoomListEntriesUpdate.PushFront -> { - "PushFront '${value.displayName()}'" + "PushFront '${value.id()}'" } is RoomListEntriesUpdate.Insert -> { - "Insert at #$index: '${value.displayName()}'" + "Insert at #$index: '${value.id()}'" } is RoomListEntriesUpdate.Remove -> { "Remove #$index" } is RoomListEntriesUpdate.Reset -> { - "Reset all to ${values.map { "'" + it.displayName() + "'" }}" + "Reset all to ${values.map { "'" + it.id() + "'" }}" } RoomListEntriesUpdate.PopBack -> { "PopBack" diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 968a768fa2..afdac3db12 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -112,6 +112,11 @@ class RoomSummaryListProcessor( private suspend fun updateRoomSummaries(updates: List, block: suspend MutableList.() -> Unit) = withContext( coroutineContext ) { + // Capture the description before applying updates: applyUpdate consumes each Room via + // `entry.use { ... }` which destroys it, and the duplicate-detection branch below reads + // id() through `describe()`. Without this capture the trackError call crashes before it + // can be reported. + val updatesDescription = updates.description() mutex.withLock { val current = roomSummaries.replayCache.lastOrNull() val mutableRoomSummaries = current.orEmpty().toMutableList() @@ -126,7 +131,7 @@ class RoomSummaryListProcessor( analyticsService.trackError( IllegalStateException( "Found duplicates in room summaries after a list update from the SDK: $duplicates. " + - "Updates: ${updates.description()}" + "Updates: $updatesDescription" ) ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index 6fac54b904..d951b3d339 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -173,16 +173,68 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_3) } + /** + * Tracking issue #4182 / #5031: rooms duplicated in the room list. + * + * If duplicates are present in the upstream summaries flow, the dedupe safety net in + * [RoomSummaryListProcessor.updateRoomSummaries] must remove them and report the incident via + * [analyticsService.trackError]. Uses an empty update to drive the dedupe path without + * passing a Rust Room through the destroy-on-use path. + */ + @Test + fun `pre-existing duplicates in summaries are deduped on next update and trackError fires`() = runTest { + summaries.value = listOf( + aRoomSummary(roomId = A_ROOM_ID), + aRoomSummary(roomId = A_ROOM_ID), // simulated SDK-side leak + aRoomSummary(roomId = A_ROOM_ID_2), + ) + val analyticsService = FakeAnalyticsService() + val processor = createProcessor(analyticsService = analyticsService) + + processor.postUpdate(emptyList()) + + assertThat(summaries.value.map { it.roomId }).containsExactly(A_ROOM_ID, A_ROOM_ID_2).inOrder() + assertThat(analyticsService.trackedErrors).hasSize(1) + } + + /** + * Tracking issue #4182 / #5031. + * + * Insert is the most likely Rust-SDK trigger for a duplicate-room report: it blindly inserts + * a new entry at an index without checking whether the roomId already exists. Before the + * describe-capture fix, the dedupe branch in [updateRoomSummaries] would call `Room.id()` + * on an already-destroyed Room (because [applyUpdate] consumes each value via + * `entry.use { ... }`) and crash before [trackError] could be invoked. This test guards the + * fix: the Insert is processed, the list is emitted deduplicated, and the tracked error + * message carries the human-readable description of the offending update. + */ + @Test + fun `Insert that triggers dedupe is reported via trackError without crashing`() = runTest { + summaries.value = listOf(aRoomSummary(roomId = A_ROOM_ID)) + val analyticsService = FakeAnalyticsService() + val processor = createProcessor(analyticsService = analyticsService) + + processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(0u, aRustRoom(A_ROOM_ID)))) + + assertThat(summaries.value.map { it.roomId }).containsExactly(A_ROOM_ID) + assertThat(analyticsService.trackedErrors).hasSize(1) + val message = analyticsService.trackedErrors.single().message.orEmpty() + assertThat(message).contains("Found duplicates") + assertThat(message).contains("Insert at #0") + } + private fun aRustRoom(roomId: RoomId = A_ROOM_ID) = FakeFfiRoom( roomId = roomId, latestEventLambda = { LatestEventValue.None } ) - private fun TestScope.createProcessor() = RoomSummaryListProcessor( + private fun TestScope.createProcessor( + analyticsService: FakeAnalyticsService = FakeAnalyticsService(), + ) = RoomSummaryListProcessor( summaries, FakeFfiRoomListService(), coroutineContext = StandardTestDispatcher(testScheduler), roomSummaryFactory = RoomSummaryFactory(), - analyticsService = FakeAnalyticsService(), + analyticsService = analyticsService, ) } From dcc67f9fc6b1bb4a3d3ea14d716a2386cb21b08b Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 18 May 2026 00:57:56 +0000 Subject: [PATCH 0428/1083] Sync Strings from Localazy --- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-ro/translations.xml | 20 + .../src/main/res/values-cs/translations.xml | 6 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-ro/translations.xml | 6 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 4 +- .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 4 + .../src/main/res/values-ro/translations.xml | 4 + .../src/main/res/values-ro/translations.xml | 3 + .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 2 + .../src/main/res/values-ro/translations.xml | 6 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 8 +- .../src/main/res/values-ro/translations.xml | 13 +- .../src/main/res/values-et/translations.xml | 16 +- .../src/main/res/values-cs/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 4 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 10 + .../src/main/res/values-zh/translations.xml | 3 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 4 +- .../src/main/res/values-ro/translations.xml | 14 +- .../src/main/res/values-et/translations.xml | 27 +- .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 11 +- .../src/main/res/values-ro/translations.xml | 11 + .../src/main/res/values-et/translations.xml | 8 +- .../src/main/res/values-ro/translations.xml | 4 +- .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 2 + .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-ro/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 3 +- .../src/main/res/values-ro/translations.xml | 8 +- .../src/main/res/values-cs/translations.xml | 8 + .../src/main/res/values-et/translations.xml | 35 +- .../src/main/res/values-fi/translations.xml | 2 +- .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-ro/translations.xml | 109 +- ...s.call.impl.ui_CallScreenView_Day_3_de.png | 4 +- ...api_LiveLocationSharingBanner_Day_0_de.png | 3 + ....impl.share_ShareLocationView_Day_6_de.png | 4 +- ....impl.share_ShareLocationView_Day_7_de.png | 3 + ....impl.share_ShareLocationView_Day_8_de.png | 3 + ...vent_TimelineItemLocationView_Day_1_de.png | 4 +- ...vent_TimelineItemLocationView_Day_2_de.png | 4 +- ...vent_TimelineItemLocationView_Day_3_de.png | 4 +- ...ts_TimelineItemCallNotifyView_Day_0_de.png | 4 +- ...s.messages.impl_MessagesView_Day_10_de.png | 4 +- ...s.messages.impl_MessagesView_Day_11_de.png | 3 + ...es.messages.impl_MessagesView_Day_8_de.png | 4 +- ...es.messages.impl_MessagesView_Day_9_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_0_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_1_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_2_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_3_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_4_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_5_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_6_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_7_de.png | 4 +- ...dvanced_AdvancedSettingsViewBlack_8_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_0_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_1_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_2_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_3_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_4_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_5_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_6_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_7_de.png | 4 +- ...advanced_AdvancedSettingsViewDark_8_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_0_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_1_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_2_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_3_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_4_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_5_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_6_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_7_de.png | 4 +- ...dvanced_AdvancedSettingsViewLight_8_de.png | 4 +- screenshots/html/data.js | 2128 +++++++++-------- 96 files changed, 1447 insertions(+), 1231 deletions(-) create mode 100644 features/location/impl/src/main/res/values-ro/translations.xml create mode 100644 screenshots/de/features.location.api_LiveLocationSharingBanner_Day_0_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_7_de.png create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_8_de.png create mode 100644 screenshots/de/features.messages.impl_MessagesView_Day_11_de.png diff --git a/features/call/impl/src/main/res/values-et/translations.xml b/features/call/impl/src/main/res/values-et/translations.xml index 16b72b8b97..fa0415a5f5 100644 --- a/features/call/impl/src/main/res/values-et/translations.xml +++ b/features/call/impl/src/main/res/values-et/translations.xml @@ -4,5 +4,5 @@ "Kõne juurde naasmiseks klõpsa" "☎️ Kõne on pooleli" "Element Call ei võimalda selles Androidi versioonis Bluetoothi heliseadmete kasutamist. Palun vali mõni muu heliseade." - "Sissetulev Element Calli kõne" + "Saabuv Element Calli kõne" diff --git a/features/createroom/impl/src/main/res/values-ro/translations.xml b/features/createroom/impl/src/main/res/values-ro/translations.xml index fd1854db40..33a5351877 100644 --- a/features/createroom/impl/src/main/res/values-ro/translations.xml +++ b/features/createroom/impl/src/main/res/values-ro/translations.xml @@ -3,14 +3,34 @@ "Cameră nouă" "Invitați prieteni" "A apărut o eroare la crearea camerei" + "Spațiul nu a putut fi creat din cauza unei erori necunoscute. Încercați din nou mai târziu." + "Adăugați un nume…" + "Cameră nouă" + "Spațiu nou" "Doar persoanele invitate se pot alătura." + "Privat" "Oricine poate găsi această cameră. Puteți modifica acest lucru oricând în setări." + "Oricine se poate alătura." + "Public" "Oricine poate cere să se alăture camerei, dar un administrator sau un moderator va trebui să accepte cererea" "Permite solicitarea de alăturare" + "Oricine din %1$s se poate alătura, dar oricine altcineva trebuie să solicite acces." + "Solicitați să vă alăturați" + "Doar persoanele invitate se pot alătura." + "Privat" "Oricine se poate alătura acestei camere" + "Public" + "Oricine din %1$s se poate alătura." + "Standard" + "Cine are acces" "Pentru ca această cameră să fie vizibilă în directorul de camere publice, veți avea nevoie de o adresă de cameră." "Adresă" "Vizibilitatea camerei" + "(nicun spațiu)" + "Nu adăugați la un spațiu" + "Niciun spațiu selectat" + "Adăugați la spațiu" "Subiect (opțional)" + "Adăugați o descriere…" diff --git a/features/deactivation/impl/src/main/res/values-cs/translations.xml b/features/deactivation/impl/src/main/res/values-cs/translations.xml index e0f4fd14c7..13659e1a75 100644 --- a/features/deactivation/impl/src/main/res/values-cs/translations.xml +++ b/features/deactivation/impl/src/main/res/values-cs/translations.xml @@ -1,14 +1,14 @@ - "Potvrďte prosím, že chcete svůj účet deaktivovat. Tuto akci nelze vrátit zpět." + "Potvrďte prosím, že chcete smazat svůj účet. Tuto akci nelze vrátit zpět." "Smazat všechny mé zprávy" "Upozornění: Budoucí uživatelé mohou vidět neúplné konverzace." - "Deaktivace vašeho účtu je %1$s, což způsobí:" + "Smazání účtu je %1$s, dojde k:" "nezvratná" "%1$s váš účet (nemůžete se znovu přihlásit a vaše ID nelze znovu použít)." "Trvale zakázat" "Odebere vás ze všech chatovacích místností." "Odstraní informace o vašem účtu z našeho serveru identit." "Vaše zprávy budou stále viditelné registrovaným uživatelům, ale nebudou dostupné novým ani neregistrovaným uživatelům, pokud se rozhodnete je smazat." - "Deaktivovat účet" + "Smazat účet" diff --git a/features/deactivation/impl/src/main/res/values-et/translations.xml b/features/deactivation/impl/src/main/res/values-et/translations.xml index 1776e2de17..bfb41d7665 100644 --- a/features/deactivation/impl/src/main/res/values-et/translations.xml +++ b/features/deactivation/impl/src/main/res/values-et/translations.xml @@ -3,7 +3,7 @@ "Palun kinnita uuesti, et soovid kustutada oma kasutajakonto. Seda tegevust ei saa tagasi pöörata." "Kustuta kõik minu sõnumid" "Hoiatus: tulevased kasutajad võivad näha poolikuid vestlusi." - "Sinu konto kasutusest eemaldamine on %1$s ja sellega:" + "Sinu konto kustutamine on %1$s ja sellega:" "pöördumatu" "Sinu kasutajakonto %1$s (sa ei saa enam sellega võrku logida ning kasutajatunnust ei saa enam pruukida)." "jäädavalt eemaldatakse kasutusest" diff --git a/features/deactivation/impl/src/main/res/values-ro/translations.xml b/features/deactivation/impl/src/main/res/values-ro/translations.xml index acd4c0747d..6176b4584e 100644 --- a/features/deactivation/impl/src/main/res/values-ro/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ro/translations.xml @@ -1,14 +1,14 @@ - "Vă rugăm să confirmați că doriți să vă dezactivați contul. Această acțiune nu poate fi anulată." + "Vă rugăm să confirmați că doriți să vă ștergeți contul. Această acțiune nu poate fi anulată." "Ștergeți toate mesajele mele" "Avertisment: este posibil ca viitorii utilizatori să vadă conversații incomplete." - "Dezactivarea contului dumneavoastră este %1$s, acesta va:" + "Ștergerea contului dumneavoastră este %1$s, acesta va:" "ireversibilă" "%1$s contul dumneavoastră (nu vă puteți conecta din nou, iar ID-ul dvs. nu poate fi reutilizat)." "Dezactivați permanent" "Îndepărta din toate camerele de chat." "Șterge informațiile contului dumneavoastră de pe serverul nostru de identitate." "Mesajele dumneavoastră vor fi în continuare vizibile pentru utilizatorii înregistrați, dar nu vor fi disponibile pentru utilizatorii noi sau neînregistrați dacă alegeți să le ștergeți." - "Dezactivați contul" + "Ștergeți contul" 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 3e961d6249..c013556568 100644 --- a/features/ftue/impl/src/main/res/values-et/translations.xml +++ b/features/ftue/impl/src/main/res/values-et/translations.xml @@ -2,7 +2,7 @@ "Kas kinnitamine pole võimalik?" "Loo uus taastevõti" - "Krüptitud sõnumivahetuse tagamiseks verifitseeri see seade." + "Turvalise sõnumside seadistamiseks vali verifitseerimise viis." "Kinnita oma digitaalne identiteet" "Kasuta teist seadet" "Kasuta taastevõtit" diff --git a/features/home/impl/src/main/res/values-et/translations.xml b/features/home/impl/src/main/res/values-et/translations.xml index 9d938ed941..4ba1695d7e 100644 --- a/features/home/impl/src/main/res/values-et/translations.xml +++ b/features/home/impl/src/main/res/values-et/translations.xml @@ -5,8 +5,8 @@ "Sa ei näe kõiki teavitusi?" "Sinu nutiseadme teavituste heli on uuenenud - see on nüüd selgem, kiirem ja vähem häiriv." "Oleme sinu helisid värskendanud" - "Loo uus taastevõti, mida saad kasutada oma krüptitud sõnumite ajaloo taastamisel olukorras, kus kaotad ligipääsu oma seadmetele." - "Seadista andmete taastamine" + "Sinu vestlused on automaatselt varundatud kasutades läbivat krüptimist. Kui peaksid kaotama ligipääsu kõikidele oma seadmetele, siis selle varukoopia taastamiseks ja oma digitaalse identiteedi säilitamiseks, on vaja taastevõtit." + "Seadista taastevõti" "Varunda oma vestlused" "Säilitamaks ligipääsu vestluste ja krüptovõtmete varukoopiale, palun sisesta kinnituseks oma taastevõti." "Sisesta oma taastevõti" diff --git a/features/home/impl/src/main/res/values-ro/translations.xml b/features/home/impl/src/main/res/values-ro/translations.xml index be1933e160..14cf100c22 100644 --- a/features/home/impl/src/main/res/values-ro/translations.xml +++ b/features/home/impl/src/main/res/values-ro/translations.xml @@ -50,6 +50,7 @@ Nu aveți mesaje necitite!" "Marcați ca citită" "Marcați ca necitită" "Această cameră a fost modernizată." + "Spațiile dumneavoastră" "Se pare că folosiți un dispozitiv nou. Verificați-vă identitatea cu un alt dispozitiv pentru a accesa mesajele dumneavoastră criptate." "Verificați că sunteți dumneavoastră" diff --git a/features/invitepeople/impl/src/main/res/values-et/translations.xml b/features/invitepeople/impl/src/main/res/values-et/translations.xml index 44484d23c3..1bdf5f780c 100644 --- a/features/invitepeople/impl/src/main/res/values-et/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-et/translations.xml @@ -2,4 +2,8 @@ "Sa juba oled jututoa liige" "Sa juba oled kutse saanud" + "Sul pole hetkel nende kontaktidega ühtegi vestlust. Enne jätkamist kinnita neile siia jututuppa kutse saatmine." + "Sul pole hetkel selle kontaktiga ühtegi vestlust. Enne jätkamist kinnita talle siia jututuppa kutse saatmine." + "Kas kutsud uued kontaktid siia jututuppa?" + "Kas kutsud uue kontakti siia jututuppa?" diff --git a/features/invitepeople/impl/src/main/res/values-ro/translations.xml b/features/invitepeople/impl/src/main/res/values-ro/translations.xml index f03be4b263..40189e3186 100644 --- a/features/invitepeople/impl/src/main/res/values-ro/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-ro/translations.xml @@ -2,4 +2,8 @@ "Deja membru" "Deja invitat" + "În prezent, nu aveți nicio conversație cu aceste contacte. Confirmați invitarea lor în această cameră înainte de a continua." + "În prezent, nu aveți nicio conversație cu acest contact. Confirmați invitarea acestuia în cameră înainte de a continua." + "Invitați contactele noi în această cameră?" + "Invitați contactul nou în această cameră?" diff --git a/features/linknewdevice/impl/src/main/res/values-ro/translations.xml b/features/linknewdevice/impl/src/main/res/values-ro/translations.xml index c99b537084..57d439240d 100644 --- a/features/linknewdevice/impl/src/main/res/values-ro/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-ro/translations.xml @@ -26,6 +26,7 @@ "Se încarcă codul QR…" "Dispozitiv mobil" "Ce tip de dispozitiv doriți să conectați?" + "Încercați din nou și asigurați-vă că ați introdus corect codul de 2 cifre. Dacă numerele tot nu se potrivesc, contactați furnizorul contului." "Numerele nu se potrivesc" "Nu a putut fi făcută o conexiune sigură la noul dispozitiv. Dispozitivele existente sunt încă în siguranță și nu trebuie să vă faceți griji cu privire la ele." "Și acum?" @@ -39,6 +40,8 @@ "Cererea de autentificare a fost anulată" "Autentificarea a fost refuzată pe celălalt dispozitiv." "Autentificarea a fost refuzată" + "Nu trebuie să faceți nimic altceva." + "Celălalt dispozitiv este deja conectat" "Autentificarea a expirat. Vă rugăm să încercați din nou." "Autentificarea nu a fost finalizată la timp" "Celălalt dispozitiv nu acceptă autentificarea la %s cu un cod QR. diff --git a/features/location/impl/src/main/res/values-cs/translations.xml b/features/location/impl/src/main/res/values-cs/translations.xml index 6bb5b1db8c..98af57abba 100644 --- a/features/location/impl/src/main/res/values-cs/translations.xml +++ b/features/location/impl/src/main/res/values-cs/translations.xml @@ -2,4 +2,5 @@ "Vaše historie aktuální polohy bude uložena v místnosti a bude viditelná pro členy i po skončení relace." "Zvolte, jak dlouho chcete sdílet svou aktuální polohu." + "Nemáte oprávnění sdílet svou aktuální polohu v této místnosti." diff --git a/features/location/impl/src/main/res/values-et/translations.xml b/features/location/impl/src/main/res/values-et/translations.xml index 53aede1bb2..73847bcb43 100644 --- a/features/location/impl/src/main/res/values-et/translations.xml +++ b/features/location/impl/src/main/res/values-et/translations.xml @@ -1,4 +1,6 @@ + "Sinu reaalajas jagatud asukoha ajalugu salvestub siin jututoas ja see on liikmetele nähtav ka pärast jagamissessiooni lõppu." "Vali, kui kaua tahad oma reaalajas jagada." + "Sul pole õigust jagada selles jututoas oma asukohta reaalajas" diff --git a/features/location/impl/src/main/res/values-ro/translations.xml b/features/location/impl/src/main/res/values-ro/translations.xml new file mode 100644 index 0000000000..85e665647a --- /dev/null +++ b/features/location/impl/src/main/res/values-ro/translations.xml @@ -0,0 +1,6 @@ + + + "Istoricul locațiilor dumneavoastră va fi stocat în cameră și va fi vizibil pentru membri după încheierea sesiunii." + "Alegeți cât timp doriți să vă partajați locația în timp real." + "Nu aveți permisiunea de a vă partaja locația în această cameră." + diff --git a/features/location/impl/src/main/res/values-zh/translations.xml b/features/location/impl/src/main/res/values-zh/translations.xml index 563bba593f..86f2f2a9da 100644 --- a/features/location/impl/src/main/res/values-zh/translations.xml +++ b/features/location/impl/src/main/res/values-zh/translations.xml @@ -1,6 +1,6 @@ - "你实时位置历史将存储在房间中,并于会话结束后对其他成员可见。" + "你的实时位置历史将存储在房间中,并于会话结束后对其他成员可见。" "选择共享实时位置的时长。" "你无权在此房内共享实时位置。" 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 ac25914f8c..7137c09b60 100644 --- a/features/lockscreen/impl/src/main/res/values-et/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-et/translations.xml @@ -34,5 +34,5 @@ Vali midagi, mis hästi meelde jääb. Kui unustad selle PIN-koodi, siis turvaka "Kasuta biomeetriat" "Kasuta PIN-koodi" - "Logime välja…" + "Eemaldan seadet…" 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 c5887de6c6..3181e823bb 100644 --- a/features/login/impl/src/main/res/values-cs/translations.xml +++ b/features/login/impl/src/main/res/values-cs/translations.xml @@ -28,7 +28,7 @@ "Jaká je adresa vašeho serveru?" "Vyberte váš server" "Vytvořit účet" - "Tento účet byl deaktivován." + "Tento účet byl smazán." "Nesprávné uživatelské jméno nebo heslo" "Toto není platný identifikátor uživatele. Očekávaný formát: \'@user:homeserver.org\'" "Tento server je nakonfigurován tak, aby používal obnovovací tokeny. Ty nejsou podporovány při použití přihlašovacích údajů založených na hesle." 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 b0b60009d4..dc37ed3e38 100644 --- a/features/login/impl/src/main/res/values-et/translations.xml +++ b/features/login/impl/src/main/res/values-et/translations.xml @@ -28,7 +28,7 @@ "Mis on sinu koduserveri aadress?" "Vali oma server" "Loo kasutajakonto" - "Konto on kasutusest eemaldatud." + "See kasutajakonto on kustutatud." "Vigane kasutajanimi ja/või salasõna" "See ei ole korrektne kasutajanimi. Õige vorming on: „@kasutaja:koduserver.ee“" "See server on seadistatud kasutama tunnusloa põhist sisselogimist. Salasõnaga sisselogimisel see võimalus aga ei ole toetatud." @@ -39,7 +39,13 @@ "Logi sisse serverisse %1$s" "Ava Element Classic" "Ava Element Classic oma seadmes" + "Ava „Seadistused“ → „Turvalisus ja privaatsus“" + "Krüptovõtmete halduses vali „Krüptitud sõnumite taastamine“" + "Võtmehoidla kasutuselevõtmiseks palun järgi juhendit" + "Tule tagasi rakendusse %1$s" + "Enne jätkamist rakenduses %1$s võta oma võtmehoidla kasutusele" "Versioon %1$s" + "Kontrollin kasutajakontot" "Logi sisse käsitsi" "Logi sisse serverisse %1$s" "Logi sisse QR-koodi alusel" diff --git a/features/login/impl/src/main/res/values-ro/translations.xml b/features/login/impl/src/main/res/values-ro/translations.xml index ec9b260208..b44242abf8 100644 --- a/features/login/impl/src/main/res/values-ro/translations.xml +++ b/features/login/impl/src/main/res/values-ro/translations.xml @@ -28,7 +28,7 @@ "Care este adresa serverului dumneavoastră?" "Selectați serverul dumneavoastra" "Creați un cont" - "Acest cont a fost dezactivat." + "Acest cont a fost șters." "Utilizator și/sau parolă incorecte" "Acesta nu este un identificator de utilizator valid. Format așteptat: „@user:homeserver.org”" "Acest server este configurat pentru a utiliza token-uri de reîmprospătare. Acestea nu sunt acceptate atunci când utilizați autentificare bazată pe parolă." @@ -37,11 +37,20 @@ "Matrix este o rețea deschisă pentru o comunicare sigură și descentralizată." "Bine ați revenit!" "Conectați-vă la %1$s" + "Deschideți Element Clasic" + "Deschideți Element Classic pe dispozitivul dumneavoastră" + "Accesați Setări > Securitate și confidențialitate" + "În Gestionarea cheilor criptografice, selectați Recuperarea mesajelor criptate" + "Urmați instrucțiunile pentru a activa stocarea cheilor" + "Reveniți la %1$s" + "Activați stocarea cheilor înainte de a continua către %1$s" "Versiunea %1$s" + "Se verifică contul…" "Conectați-vă manual" "Conectați-vă la %1$s" "Conectați-vă cu un cod QR" "Creați un cont" + "Bine ați revenit" "Bine ați venit la cel mai rapid %1$s din toate timpurile. Supraalimentat pentru viteză și simplitate." "Bun venit în %1$s. Supraalimentat, pentru viteză și simplitate." "Fii în Elementul tău" @@ -60,6 +69,8 @@ "Cererea de autentificare a fost anulată" "Autentificarea a fost refuzată pe celălalt dispozitiv." "Autentificarea a fost refuzată" + "Nu trebuie să faceți nimic altceva." + "Celălalt dispozitiv este deja conectat" "Autentificarea a expirat. Vă rugăm să încercați din nou." "Autentificarea nu a fost finalizată la timp" "Celălalt dispozitiv nu acceptă autentificarea la %s cu un cod QR. 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 ee5a2ce9d0..cd29e13354 100644 --- a/features/logout/impl/src/main/res/values-et/translations.xml +++ b/features/logout/impl/src/main/res/values-et/translations.xml @@ -1,18 +1,18 @@ - "Kas sa oled kindel, et soovid välja logida?" + "Kas sa oled kindel, et soovid selle seadme eemaldada?" "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" - "Kui su võrguühendus katkes, siis sinu krüptovõtmed oli parasjagu varundamisel. Loo võrguühendus uuesti, oota kuni krüptovõtmete varundamine lõppeb ja alles siis logi rakendusest välja." + "Eemaldan seadet…" + "See on sinu ainus seade. Kui sa selle eemaldad, vajad taastamisvõtit, et kinnitada oma digitaalset identiteeti ja taastada järgmisel sisselogimisel oma krüptitud vestlused." + "Sa kaotad peagi juurdepääsu oma krüptitud vestlustele" + "Kui su võrguühendus katkes, siis sinu krüptovõtmed oli parasjagu varundamisel. Loo võrguühendus uuesti, oota kuni krüptovõtmete varundamine lõppeb ja alles siis eemalda see seade." "Sinu krüptovõtmed on veel varundamisel" - "Enne väljalogimist palun oota, et pooleliolev toiming lõppeb." + "Enne selle seadme eemaldamist palun oota, et pooleliolev toiming lõppeb." "Sinu krüptovõtmed on veel varundamisel" "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." + "See on sinu ainus seade. Kui sa selle eemaldad, vajad taastamisvõtit, et kinnitada oma digitaalset identiteeti ja taastada järgmisel sisselogimisel oma krüptitud vestlused." "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." - "Kas sa oled oma taastevõtme salvestanud?" + "Enne selle seadme eemaldamist veendu, et sul on juurdepääs taastevõtmele" diff --git a/features/messages/impl/src/main/res/values-cs/translations.xml b/features/messages/impl/src/main/res/values-cs/translations.xml index 93ea0d8178..9bf1c5c079 100644 --- a/features/messages/impl/src/main/res/values-cs/translations.xml +++ b/features/messages/impl/src/main/res/values-cs/translations.xml @@ -1,7 +1,7 @@ "Odesílatel události se neshoduje s vlastníkem zařízení, které ji odeslalo." - "Autenticitu této zašifrované zprávy nelze na tomto zařízení zaručit." + "Pravost této šifrované zprávy nelze na tomto zařízení zaručit." "Zašifrováno dříve ověřeným uživatelem." "Není zašifrováno." "Šifrováno neznámým nebo smazaným zařízením." diff --git a/features/messages/impl/src/main/res/values-et/translations.xml b/features/messages/impl/src/main/res/values-et/translations.xml index 8da4d23f79..506b5ce195 100644 --- a/features/messages/impl/src/main/res/values-et/translations.xml +++ b/features/messages/impl/src/main/res/values-et/translations.xml @@ -35,7 +35,7 @@ "Salvesta video" "Manus" "Fotode ja videote galerii" - "Asukoht" + "Jaga asukohta" "Küsitlus" "Tekstivorming" "Sõnumite ajalugu pole hetkel saadaval" diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index 0085e1d4ee..efb84cd153 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -32,7 +32,7 @@ "Powód zgłoszenia treści" "Kamera" "Zrób zdjęcie" - "Nagraj film" + "Nagraj wideo" "Załącznik" "Zdjęcia i filmy" "Udostępnij lokalizację" diff --git a/features/preferences/impl/src/main/res/values-cs/translations.xml b/features/preferences/impl/src/main/res/values-cs/translations.xml index e51d05c455..5c690dd824 100644 --- a/features/preferences/impl/src/main/res/values-cs/translations.xml +++ b/features/preferences/impl/src/main/res/values-cs/translations.xml @@ -87,6 +87,7 @@ Pokud budete pokračovat, některá nastavení se mohou změnit." "systémová nastavení" "Systémová oznámení byla vypnuta" "Oznámení" + "Černý" "Tmavé" "Světlý" "Systém" diff --git a/features/preferences/impl/src/main/res/values-et/translations.xml b/features/preferences/impl/src/main/res/values-et/translations.xml index ba1ee2ac7c..d1e2b91d58 100644 --- a/features/preferences/impl/src/main/res/values-et/translations.xml +++ b/features/preferences/impl/src/main/res/values-et/translations.xml @@ -11,7 +11,10 @@ "Peida jututubade kutsetest tunnuspildid" "Peida meedia eelvaated ajajoonel" "Katsed" + "Vahemaa, mille pead andmete uuenduse käivitamiseks läbima." + "Veendu, et sellel rakendusel on õigus kasutada funktsionaalsust „Täpne asukoht“. Õiguste muutmiseks ava %1$s." "Rakenduse seadistused" + "Andmete uuendused reaalajas asukoha jagamisel" "Iga %1$d meeter" "Iga %1$d meetrit" @@ -81,6 +84,7 @@ Kui sa jätkad muutmist, siis võivad muutuda ka need peidetud eelistused.""süsteemi seadistusi" "Süsteemi teavitused on välja lülitatud" "Teavitused" + "Süsimust kujundus" "Tume" "Hele" "Süsteem" diff --git a/features/preferences/impl/src/main/res/values-hu/translations.xml b/features/preferences/impl/src/main/res/values-hu/translations.xml index 4c3ff5c04d..4c1b988696 100644 --- a/features/preferences/impl/src/main/res/values-hu/translations.xml +++ b/features/preferences/impl/src/main/res/values-hu/translations.xml @@ -84,6 +84,7 @@ Ha folytatja, egyes beállítások megváltozhatnak." "rendszerbeállításokat" "A rendszerértesítések ki vannak kapcsolva" "Értesítések" + "Fekete" "Sötét" "Világos" "Rendszer" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index 3fc2a3eac8..83b02c6fe2 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -85,6 +85,7 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "ustawienia systemowe" "Powiadomienia systemowe wyłączone" "Powiadomienia" + "Czarny" "Ciemny" "Jasny" "System" diff --git a/features/preferences/impl/src/main/res/values-ro/translations.xml b/features/preferences/impl/src/main/res/values-ro/translations.xml index 18f8326bf3..69eddf05f5 100644 --- a/features/preferences/impl/src/main/res/values-ro/translations.xml +++ b/features/preferences/impl/src/main/res/values-ro/translations.xml @@ -11,6 +11,15 @@ "Ascundeți avatarele din invitațiile pentru camere" "Ascundeți previzualizările media în lista de mesaje" "Laboratoare" + "Distanța pe care trebuie să o parcurgeți pentru a declanșa o actualizare." + "Asigurați-vă că este activată opțiunea „Locație precisă” pentru această aplicație. Pentru a schimba permisiunea, accesați %1$s." + "Setările aplicației" + "Actualizări in timp real ale locației" + + "La fiecare %1$d metru" + "La fiecare %1$d metri" + "La fiecare %1$d metri" + "Încărcați fotografii și videoclipuri mai rapid și reduceți consumul de date" "Optimizați calitatea media" "Moderare și siguranță" @@ -78,6 +87,7 @@ Dacă continuați, unele dintre setările dumneavoastră pot fi modificate.""Setări de sistem" "Notificările de sistem sunt dezactivate" "Notificări" + "Negru" "Întunecat" "Deschis" "Sistem" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index e91bc58752..8f6de8209e 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -78,11 +78,12 @@ "全部" "提及" "通知我以下类型" - "我在房间中被提及时通知我" + "提及所有成员(@room)时通知我" "要接收通知,请更改 %1$s。" "系统设置" "系统通知已关闭" "通知" + "纯黑" "深色" "浅色" "系统" diff --git a/features/reportroom/impl/src/main/res/values-zh/translations.xml b/features/reportroom/impl/src/main/res/values-zh/translations.xml index e79148a45d..4366e33455 100644 --- a/features/reportroom/impl/src/main/res/values-zh/translations.xml +++ b/features/reportroom/impl/src/main/res/values-zh/translations.xml @@ -2,7 +2,7 @@ "你的举报已成功提交,但在尝试退出房间时遇到问题。请重试。" "无法离开房间" - "向管理员举报此房间。如果信息已加密,管理员将无法读取。" + "向管理员举报此房间。如果消息已加密,管理员将无法读取。" "描述举报的理由…" "举报房间" diff --git a/features/rolesandpermissions/impl/src/main/res/values-cs/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-cs/translations.xml index 87936de3a7..662096dd20 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-cs/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-cs/translations.xml @@ -6,6 +6,7 @@ "Odstranit zprávy" "Člen" "Pozvat přátele" + "Sdílet aktuální polohu" "Správa prostoru" "Spravovat místnosti" "Spravovat členy" diff --git a/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml index 1c1f490580..02ec4ad07d 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-et/translations.xml @@ -6,6 +6,7 @@ "Eemalda sõnumid" "Liikmed" "Osalejate kutsumine" + "Jaga asukohta reaalajas" "Halda kogukonda" "Halda jututuba" "Liikmete haldus" diff --git a/features/rolesandpermissions/impl/src/main/res/values-ro/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-ro/translations.xml index ac9ec710a2..962f8b2d4d 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-ro/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-ro/translations.xml @@ -6,6 +6,7 @@ "Ștergeți mesajele" "Membru" "Invitați persoane" + "Partajați locația în timp real" "Gestionați spațiul" "Gestionați camerele" "Gestionați membrii" diff --git a/features/roomdetails/impl/src/main/res/values-pl/translations.xml b/features/roomdetails/impl/src/main/res/values-pl/translations.xml index 7af5d8e557..ccc359ed25 100644 --- a/features/roomdetails/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pl/translations.xml @@ -108,8 +108,8 @@ "Zezwalaj na ustawienia niestandardowe" "Włączenie tej opcji nadpisze ustawienie domyślne" "Powiadamiaj mnie o tym czacie przez" - "Możesz to zmienić w swoim %1$s." - "ustawienia globalne" + "Możesz to zmienić w %1$s." + "ustawieniach globalnych" "Ustawienie domyślne" "Usuń ustawienia własne" "Wystąpił błąd podczas ładowania ustawień powiadomień." diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml index 0374c64314..425e35a23c 100644 --- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml @@ -1,5 +1,8 @@ + "Membrii noi nu pot vedea istoricul" + "Membrii noi pot vedea istoricul" + "Oricine poate vedea istoricul" "Veți avea nevoie de o adresă pentru a o face vizibilă în directorul public." "Editați adresa" "A apărut o eroare în timpul actualizării setărilor pentru notificari." @@ -135,6 +138,7 @@ "Adăugați o adresă" "Oricine se află în spațiile autorizate se poate alătura, dar toți ceilalți trebuie să solicite accesul." "Toată lumea trebuie să solicite acces." + "Solicitați să vă alăturați" "Oricine în %1$s se poate alătura, dar toți ceilalți trebuie să solicite acces." "Da, activați criptarea" "Odată activată, criptarea pentru o cameră nu poate fi dezactivată. Mesajele anterioare vor fi vizibile numai pentru membrii camerei de la momentul la care au fost invitați sau de la momentul la care s-au alăturat camerei. @@ -145,22 +149,26 @@ Nu recomandăm activarea criptării pentru camerele pe care oricine le poate gă "Criptare" "Activați criptarea end-to-end" "Oricine se poate alătura." - "Alegeți membrii căror spații se pot alătura acestei camere fără invitație. %1$s" + "Oricine" + "Alegeți membrii căror spații se pot alătura acestei cameră fără invitație. %1$s" "Gestionați spațiile" "Doar persoanele invitate se pot alătura." "Doar pe bază de invitație" "Acces" "Oricine se află într-un spațiu autorizat poate participa." "Oricine din %1$s se poate alătura." + "Membrii spațiului" "Spațiile nu sunt momentan suportate." "Veți avea nevoie de o adresă pentru a o face vizibilă în directorul public." "Adresă" "Permiteți găsirea acestei camere prin căutarea în directorul de camere publice al %1$s" "Permiteți găsirea prin căutarea în directorul public." "Vizibilă în directorul de camere publice" + "Oricine (istoricul este public)" + "Modificările nu vor afecta mesajele anterioare, ci doar pe cele noi. %1$s" "Cine poate citi mesajele anterioare" - "Doar pentru membri, de la momentul în care au fost invitați" - "Doar pentru membri, după selectarea acestei opțiuni" + "Membri de la momentul invitației" + "Membri (istoric complet)" "Adresele camerelor sunt modalități de a găsi și accesa camere. Acest lucru vă asigură, de asemenea, că puteți partaja cu ușurință camera dumneavoastră cu alte persoane. Puteți alege să publicați camera în directorul public al camerelor serverului dumneavoastră." "Publicare cameră" diff --git a/features/securebackup/impl/src/main/res/values-et/translations.xml b/features/securebackup/impl/src/main/res/values-et/translations.xml index c3d849f37b..860d017781 100644 --- a/features/securebackup/impl/src/main/res/values-et/translations.xml +++ b/features/securebackup/impl/src/main/res/values-et/translations.xml @@ -2,16 +2,17 @@ "Lülita võtmete varundamine välja" "Lülita võtmete varundamine sisse" - "Salvesta oma krüptoidentiteet ja sõnumite krüptovõtmed turvaliselt serveris. See tagab, et sinu sõnumite ajalugu on alati loetav, ka kõikides uutes seadmetes. %1$s." + "Salvesta oma digitaalne identiteet ja sõnumite krüptovõtmed turvaliselt serveris. See tagab, et sinu sõnumite ajalugu on alati loetav, ka kõikides uutes seadmetes. %1$s." "Krüptovõtmete varundus" - "Taastamise seadistamiseks peab võtmehoidla olema sisselülitatud." + "Sinu vestluste varundamiseks peab võtmehoidla olema sisselülitatud." "Laadi siin seadmes leiduvad võtmed üles" "Luba krüptovõtmete salvestamine" "Muuda taastevõtit" - "Kui sa oled kaotanud ligipääsu kõikidele oma olemasolevatele seadmetele, siis sa saad taastevõtme abil taastada ligipääsu oma krüptoidentiteedile ja sõnumite ajaloole." + "Kui sa oled kaotanud ligipääsu kõikidele oma olemasolevatele seadmetele, siis sa saad taastevõtme abil taastada ligipääsu oma digitaalsele identiteedile ja sõnumite ajaloole." "Sisesta taastevõti" "Sinu krüptovõtmete varundus pole hetkel enam sünkroonis." - "Seadista andmete taastamine" + "Seadista taastevõti" + "Sinu vestlused on automaatselt varundatud kasutades läbivat krüptimist. Kui peaksid kaotama ligipääsu kõikidele oma seadmetele, siis selle varukoopia taastamiseks ja oma digitaalse identiteedi säilitamiseks, on vaja taastevõtit." "Ava %1$s töölauaga seadmes" "Logi uuesti sisse oma kasutajakontole" "Kui sul palutakse seadet verifitseerida, vali %1$s" @@ -23,12 +24,12 @@ "Sinu kasutajakonto andmed, kontaktid, eelistused ja vestluste loend säiluvad" "Sa kaotad seniste sõnumite ajaloo" "Sa pead kõik oma olemasolevad seadmed ja kontaktid uuesti verifitseerima" - "Lähtesta oma identiteet vaid siis, kui sul pole ligipääsu mitte ühelegi oma seadmele ja sa oled kaotanud oma taastevõtme." - "Kui sa ühtegi muud võimalust ei leia, siis lähtesta oma identiteet." - "Lülita välja" - "Kui sa logid välja kõikidest oma seadmetest, siis sa kaotad ligipääsu oma krüptitud sõnumitele." - "Kas sa oled kindel, et soovid varukoopiate tegemise välja lülitada?" - "Varunduse väljalülitamisel kustutatakse hetkel olemasolev sinu krüptovõtmete varukoopia ning lülituvad välja veel mõned turvafunktsionaalsused. Sellisel juhul sul:" + "Lähtesta oma digitaalne identiteet vaid siis, kui sul pole ligipääsu mitte ühelegi oma seadmele ja sa oled kaotanud oma taastevõtme." + "Kui sa ühtegi muud võimalust ei leia, siis lähtesta oma digitaalne identiteet." + "Kustuta" + "Kui sa eemaldad kõik oma seadmed, siis sa kaotad ligipääsu oma krüptitud sõnumitele ja pead oma digitaalse identiteedi lähtestama." + "Kas oled kindel, et soovid võtmehoidla kustutada?" + "Võtmehoidla kustutamine eemaldab sinu digitaalse identiteedi ja sõnumivõtmed serverist ning lülitab välja järgmised turvafunktsionaalsused:" "sul ei ole krüptitud sõnumite ajalugu uutes seadmetes" "sa kaotad ligipääsu oma krüptitud sõnumitele, kui sa logid kõikjal välja rakendusest %1$s" "Kas sa oled kindel, et soovid varunduse välja lülitada?" @@ -58,12 +59,12 @@ "Loo oma taastevõti" "Ära jaga seda kellegagi" "Andmete taastamise seadistamine õnnestus" - "Seadista andmete taastamine" + "Seadista taastevõti" "Jah, lähtesta nüüd" "See tegevus on tagasipöördumatu." - "Kas sa oled kindel, et soovid oma võrguidentiteeti lähtestada?" + "Kas sa oled kindel, et soovid oma digitaalse identiteedi lähtestada?" "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti." "Sisesta…" - "Palun kinnita, et soovid oma võrguidentiteedi lähtestada." + "Palun kinnita, et soovid oma digitaalse identiteedi lähtestada." "Jätkamaks sisesta oma kasutajakonto salasõna" diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index f2f44e10f3..99bbcc8159 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -30,7 +30,7 @@ "Jeśli usuniesz wszystkie swoje urządzenia, stracisz zaszyfrowaną historię wiadomości i będziesz musiał zresetować swoją tożsamość cyfrową." "Czy na pewno chcesz usunąć magazyn kluczy?" "Usunięcie magazynu kluczy usunie Twoją tożsamość cyfrową i klucze wiadomości z serwera, wyłączając następujące funkcje bezpieczeństwa:" - "Posiadał historii wiadomości szyfrowanych na nowych urządzeniach" + "Stracisz dostęp do zaszyfrowanej historii wiadomości na nowych urządzeniach" "Utracisz dostęp do wiadomości szyfrowanych, jeśli zostaniesz wszędzie wylogowany z %1$s" "Czy na pewno chcesz wyłączyć backup?" "Uzyskaj nowy klucz przywracania, jeśli straciłeś dostęp do obecnego. Po zmianie klucza przywracania stary nie będzie już działał." diff --git a/features/securebackup/impl/src/main/res/values-ro/translations.xml b/features/securebackup/impl/src/main/res/values-ro/translations.xml index 452a0543c8..2351a54923 100644 --- a/features/securebackup/impl/src/main/res/values-ro/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ro/translations.xml @@ -12,6 +12,7 @@ "Introduceți cheia de recuperare" "Backup-ul pentru chat nu este sincronizat în prezent." "Obțineți cheia de recuperare" + "Chaturile dumneavoastră sunt salvate automat cu criptare end-to-end. Pentru a restaura această copie de rezervă și a vă păstra identitatea digitală atunci când pierdeți accesul la toate dispozitivele dumneavoastră, veți avea nevoie de cheia de recuperare." "Deschideți %1$s pe un dispozitiv desktop" "Conectați-vă din nou la contul dumneavoastră" "Când vi se cere să vă verificați dispozitivul, selectați%1$s" diff --git a/features/securityandprivacy/impl/src/main/res/values-ro/translations.xml b/features/securityandprivacy/impl/src/main/res/values-ro/translations.xml index 83292637ce..2f3eaab319 100644 --- a/features/securityandprivacy/impl/src/main/res/values-ro/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-ro/translations.xml @@ -10,6 +10,7 @@ "Adăugați o adresă" "Oricine se află în spațiile autorizate se poate alătura, dar toți ceilalți trebuie să solicite accesul." "Toată lumea trebuie să solicite acces." + "Solicitați să vă alăturați" "Oricine în %1$s se poate alătura, dar toți ceilalți trebuie să solicite acces." "Da, activați criptarea" "Odată activată, criptarea pentru o cameră nu poate fi dezactivată. Mesajele anterioare vor fi vizibile numai pentru membrii camerei de la momentul la care au fost invitați sau de la momentul la care s-au alăturat camerei. @@ -20,22 +21,26 @@ Nu recomandăm activarea criptării pentru camerele pe care oricine le poate gă "Criptare" "Activați criptarea end-to-end" "Oricine se poate alătura." - "Alegeți membrii căror spații se pot alătura acestei camere fără invitație. %1$s" + "Oricine" + "Alegeți membrii căror spații se pot alătura acestei cameră fără invitație. %1$s" "Gestionați spațiile" "Doar persoanele invitate se pot alătura." "Doar pe bază de invitație" "Acces" "Oricine se află într-un spațiu autorizat poate participa." "Oricine din %1$s se poate alătura." + "Membrii spațiului" "Spațiile nu sunt momentan suportate." "Veți avea nevoie de o adresă pentru a o face vizibilă în directorul public." "Adresă" "Permiteți găsirea acestei camere prin căutarea în directorul de camere publice al %1$s" "Permiteți găsirea prin căutarea în directorul public." "Vizibilă în directorul de camere publice" + "Oricine (istoricul este public)" + "Modificările nu vor afecta mesajele anterioare, ci doar pe cele noi. %1$s" "Cine poate citi mesajele anterioare" - "Doar pentru membri, de la momentul în care au fost invitați" - "Doar pentru membri, după selectarea acestei opțiuni" + "Membri de la momentul invitației" + "Membri (istoric complet)" "Adresele camerelor sunt modalități de a găsi și accesa camere. Acest lucru vă asigură, de asemenea, că puteți partaja cu ușurință camera dumneavoastră cu alte persoane. Puteți alege să publicați camera în directorul public al camerelor serverului dumneavoastră." "Publicare cameră" diff --git a/features/space/impl/src/main/res/values-ro/translations.xml b/features/space/impl/src/main/res/values-ro/translations.xml index 2bf5d0e251..7748f44ee2 100644 --- a/features/space/impl/src/main/res/values-ro/translations.xml +++ b/features/space/impl/src/main/res/values-ro/translations.xml @@ -9,10 +9,21 @@ "Selectați camerele pe care doriți să le părăsiți și în care nu sunteți singurul administrator:" "Trebuie să desemnați un alt administrator pentru acest spațiu înainte de a-l părăsi." + "Sunteți singurul proprietar al %1$s. Trebuie să transferați dreptul de proprietate către altcineva înainte de a parăsi camera." "Nu veți părăsi următoarele camere deoarece sunteți singurul administrator:" "Părăsiți %1$s?" "Sunteți singurul administrator pentru %1$s" + "Transferați proprietatea" + "Cameră" + "Adăugarea unei camere nu va afecta accesul la cameră. Pentru a modifica accesul, accesați Setări cameră > Securitate și confidențialitate." + "Adăugați prima dumneavoastră cameră" "Vizualizați membrii" + "Eliminarea unei camere nu va afecta accesul la aceasta. Pentru a modifica accesul, accesați Informații despre cameră > Confidențialitate și securitate." + + "Eliminați camera %1$d din %2$s" + "Eliminați camerele %1$d din %2$s" + "Eliminați camerele %1$d din %2$s" + "Părăsiți spațiul" "Roluri și permisiuni" "Securitate & confidențialitate" 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 f09202c9c2..25cf6272fe 100644 --- a/features/verifysession/impl/src/main/res/values-et/translations.xml +++ b/features/verifysession/impl/src/main/res/values-et/translations.xml @@ -2,7 +2,7 @@ "Kas kinnitamine pole võimalik?" "Loo uus taastevõti" - "Krüptitud sõnumivahetuse tagamiseks verifitseeri see seade." + "Turvalise sõnumside seadistamiseks vali verifitseerimise viis." "Kinnita oma digitaalne identiteet" "Kasuta teist seadet" "Kasuta taastevõtit" @@ -17,7 +17,7 @@ "Kinnita, et kõik järgnevalt kuvatud numbrid on täpselt samad, mida sa näed oma teises sessioonis." "Võrdle numbreid" "Võid nüüd sõnumeid oma teises seadmes turvaliselt saata ja vastu võtta." - "Nüüd sa võid sõnumite vastuvõtmisel ja saatmisel selle kasutaja identiteeti usaldada." + "Nüüd sa võid sõnumite vastuvõtmisel ja saatmisel selle kasutaja digitaalset identiteeti usaldada." "Seade on verifitseeritud" "Sisesta taastevõti" "Kas verifitseerimine aegus, teine osapool keeldus vastamast või tekkis vastuste mittevastavus." @@ -42,7 +42,7 @@ "Ava rakendus teises verifitseeritud seadmes" "Lisaturvalisuse nimel verifitseeri seee kasutaja, võrreldes oma seadmetes olevaid emojisid. Tee seda, kasutades usaldusväärset suhtlusviisi." "Kas verifitseerime selle kasutaja?" - "Lisaturvalisuse nimel soovib teine kasutaja sinu identiteeti verifitseerida. Järgmiseks näed sa emojisid, mida peate omavahel võrdlema." + "Lisaturvalisuse nimel soovib teine kasutaja sinu digitaalse identiteeti verifitseerida. Järgmiseks näed sa emojisid, mida peate omavahel võrdlema." "Sa peaksid teises seadmes nägema hüpikakent. Palun alusta sealt verifitseerimist." "Alusta verifitseerimist teises seadmes" "Alusta verifitseerimist teises seadmes" @@ -50,5 +50,5 @@ "Kui oled nõustunud, siis saad sa verifitseerimist jätkata." "Jätkamaks nõustu verifitseerimisprotsessi alustamisega oma teises sessioonis." "Ootame nõustumist verifitseerimispäringuga" - "Logime välja…" + "Eemaldan seadet…" diff --git a/features/verifysession/impl/src/main/res/values-ro/translations.xml b/features/verifysession/impl/src/main/res/values-ro/translations.xml index cb22fd02d9..25f897d954 100644 --- a/features/verifysession/impl/src/main/res/values-ro/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ro/translations.xml @@ -17,7 +17,7 @@ "Confirmați că numerele de mai jos se potrivesc cu cele afișate în cealaltă sesiune." "Comparați numerele" "Noua dumneavoastră sesiune este acum verificată. Are acces la mesajele dumneavoastră criptate, iar ceilalti utilizatori vă vor vedea ca fiind de încredere." - "Acum puteți avea încredere în identitatea acestui utilizator atunci când trimiteți sau primiți mesaje." + "Acum puteți avea încredere în identitatea digitală a acestui utilizator atunci când trimiteți sau primiți mesaje." "Dispozitiv verificat" "Introduceți cheia de recuperare" "Fie cererea a expirat, cererea a fost respinsă, fie a existat o nepotrivire de verificare." @@ -42,7 +42,7 @@ "Deschideți aplicația pe un alt dispozitiv verificat" "Pentru securitate suplimentară, verificați acest utilizator comparând un set de emoji-uri pe dispozitivele dvs. Faceți acest lucru utilizând o metodă de comunicare de încredere." "Verificați acest utilizator?" - "Pentru o securitate suplimentară, un alt utilizator dorește să vă verifice identitatea. Vi se va afișa un set de emoji-uri pentru comparație." + "Pentru o securitate sporită, un alt utilizator dorește să vă verifice identitatea digitală. Vi se va afișa un set de emoji-uri pentru comparație." "Ar trebui să vedeți o fereastră pop-up pe celălalt dispozitiv. Începeți verificarea de acolo acum." "Începeți verificarea pe celălalt dispozitiv" "Începeți verificarea pe celălalt dispozitiv" diff --git a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml index e45227ad62..94e1015375 100644 --- a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml @@ -29,7 +29,7 @@ "Zaprosiłeś %1$s" "%1$s zaprosił Cię" "%1$s dołączył do pokoju" - "Dołączyłeś(aś) do pokoju" + "Dołączyłeś do pokoju" "%1$s prosi o możliwość dołączenia" "%1$s zezwolił %2$s na dołączenie" "Zezwoliłeś %1$s na dołączenie" diff --git a/libraries/matrixui/src/main/res/values-et/translations.xml b/libraries/matrixui/src/main/res/values-et/translations.xml index abd3830768..a84990af10 100644 --- a/libraries/matrixui/src/main/res/values-et/translations.xml +++ b/libraries/matrixui/src/main/res/values-et/translations.xml @@ -3,6 +3,7 @@ "Saada kutse" "Kas sa soovid alustada vestlust kasutajaga %1$s?" "Kas saadame kutse?" + "Sul pole hetkel selle inimesega ühtegi vestlust. Enne jätkamist kinnita talle kutse saatmine." "Kas alustad vestlust selle uue kontaktiga?" "%1$s (%2$s) saatis sulle kutse" diff --git a/libraries/matrixui/src/main/res/values-ro/translations.xml b/libraries/matrixui/src/main/res/values-ro/translations.xml index 5156d6bd16..4d3eaa2364 100644 --- a/libraries/matrixui/src/main/res/values-ro/translations.xml +++ b/libraries/matrixui/src/main/res/values-ro/translations.xml @@ -3,5 +3,7 @@ "Trimiteți invitația" "Doriți să începeți o discuție cu %1$s?" "Trimiteți invitația?" + "În prezent, nu aveți nicio chat cu această persoană. Confirmați invitația înainte de a continua." + "Începeți o conversație cu acest nou contact?" "%1$s (%2$s) v-a invitat." diff --git a/libraries/mediaviewer/impl/src/main/res/values-cs/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-cs/translations.xml index bcb7b64237..654aa869a6 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-cs/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-cs/translations.xml @@ -16,6 +16,7 @@ "Název souboru" "Žádné další soubory k zobrazení" "Žádná další média k zobrazení" + "Informace o souboru" "Nahrál(a)" "Nahráno" diff --git a/libraries/mediaviewer/impl/src/main/res/values-et/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-et/translations.xml index 63329a797d..f982b32433 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-et/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-et/translations.xml @@ -16,6 +16,7 @@ "Failinimi" "Pole enam kuvatavaid faile" "Pole enam kuvatavat meediat" + "Faili teave" "Üleslaadija" "Üleslaaditud" diff --git a/libraries/mediaviewer/impl/src/main/res/values-ro/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-ro/translations.xml index bfd1d49c2b..aa713361d0 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-ro/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-ro/translations.xml @@ -16,6 +16,7 @@ "Nume fișier" "Nu mai există fișiere de afișat" "Nu mai există conținut media de afișat" + "Informații despre fișier" "Încărcat de" "Încărcat la" diff --git a/libraries/push/impl/src/main/res/values-et/translations.xml b/libraries/push/impl/src/main/res/values-et/translations.xml index 4b00b7b5e7..49010359cd 100644 --- a/libraries/push/impl/src/main/res/values-et/translations.xml +++ b/libraries/push/impl/src/main/res/values-et/translations.xml @@ -19,7 +19,8 @@ "Sul on %d uus sõnum." "Sul on %d uut sõnumit." - "📹 Sissetulev kõne" + "📞 Saabuv kõne" + "📹 Saabuv kõne" "** Saatmine ei õnnestunud - palun ava jututoa täisvaade" "Liitu" "Keeldu" diff --git a/libraries/push/impl/src/main/res/values-ro/translations.xml b/libraries/push/impl/src/main/res/values-ro/translations.xml index 0a83e6afad..2f677568ea 100644 --- a/libraries/push/impl/src/main/res/values-ro/translations.xml +++ b/libraries/push/impl/src/main/res/values-ro/translations.xml @@ -15,10 +15,16 @@ "Distribuitorul de notificări UnifiedPush nu a putut fi înregistrat, așadar nu veți mai primi notificări. Verificați setările de notificări ale aplicației și starea distribuitorului push." "Aveți mesaje noi" + + "Aveți %d mesaj nou." + "Aveți %d mesaje noi." + "Aveți %d mesaje noi." + + "📞 Apel primit" "Apel primit" "** Trimiterea eșuată - vă rugăm să deschideți camera" "Alăturați-vă" - "Respinge" + "Respingeți" "%d invitație" "%d invitații" 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 36bd188c2a..1bf3802b12 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -15,6 +15,7 @@ "Podrobnosti o šifrování" "Rozbalit textové pole zprávy" "Skrýt heslo" + "Informace" "Připojit se k hovoru" "Přejít dolů" "Přesunout mapu na mou polohu" @@ -50,6 +51,7 @@ "Odeslat soubory" "Poloha odesílatele" "Vyžaduje se časově omezená akce, na ověření máte jednu minutu" + "Nastavení, vyžaduje akci" "Zobrazit heslo" "Zahájit hovor" "Zahájit videohovor" @@ -71,6 +73,7 @@ "Hovor" "Zrušit" "Prozatím zrušit" + "Vyberte soubor" "Vybrat fotku" "Vymazat" "Zavřít" @@ -205,7 +208,9 @@ "Beta" "Blokovaní uživatelé" "Bubliny" + "Hovor odmítnut" "Hovor zahájen" + "Odmítli jste hovor" "Záloha chatu" "Zkopírováno do schránky" "Autorská práva" @@ -466,6 +471,9 @@ Opravdu chcete pokračovat?" "Omlouváme se, došlo k chybě" "🔐️ Připojte se ke mně na %1$s" "Ahoj, ozvi se mi na %1$s: %2$s" + "Sdílení polohy v reálném čase" + "Probíhá sdílení polohy" + "%1$s Aktuální poloha" "%1$s Android" "Zatřeste zařízením pro nahlášení chyby" "Snímek obrazovky" 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 1669abc4e0..eef46172bd 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -14,6 +14,7 @@ "Krüptimise üksikasjad" "Laienda tekstivälja" "Peida salasõna" + "Teave" "Liitu kõnega" "Mine lõppu" "Nihuta kaart minu asukohta" @@ -48,6 +49,7 @@ "Saada faile" "Saatja asukoht" "Palun tee see ajapiiranguga toiming, sul on aega üks minut" + "Seaded, vajalik on tegevus" "Näita salasõna" "Helista" "Alusta videokõnet" @@ -231,6 +233,7 @@ "Tühi fail" "Krüptimine" "Krüptimine on kasutusel" + "Lõpeb kell %1$s" "Sisesta oma PIN-kood" "Viga" "Tekkis viga ja sa ei pruugi enam saada uute sõnumite kohta teavitusi. Palun kontrolli teavituste seadistusi ja proovi viga tuvastada. @@ -354,9 +357,10 @@ Põhjus: %1$s." "Seadistused" "Jaga kogukonda" "Uued liikmed näevad ajalugu" + "Reaalajas jagatud asukoht" "Jagatud asukoht" "Jagatud kogukond" - "Logime välja" + "Seade on eemaldamisel" "Midagi läks valesti" "Tekkis viga. Palun proovi uuesti." "Kogukond" @@ -381,7 +385,7 @@ Põhjus: %1$s." "Dekrüptimine ei olnud võimalik" "Saadetud ebaturvalisest seadmest" "Sul pole ligipääsu antud sõnumile" - "Saatja verifitseeritud identiteet on lähtestatud" + "Saatja digitaalse identiteet on lähtestatud" "Kutset polnud võimalik saata ühele või enamale kasutajale." "Kutse(te) saatmine ei õnnestunud" "Eemalda lukustus" @@ -412,12 +416,13 @@ Põhjus: %1$s." "Kuna sind polnud saatmise ajal jututoas, siis %1$s (%2$s) jagas seda sõnumit sinuga." "%1$s jagas seda sõnumit, kuna sind ei olnud selle algse saatmise ajal jututoas." "See jututuba on seadistatud sedaviisi, et ka uued liikmed saavad lugeda varasemat ajalugu. %1$s" - "Kasutaja %1$s võrguidentiteet on lähtestatud. %2$s" - "Kasutaja %1$s %2$s võrguidentiteet on lähtestatud. %3$s" + "Kasutaja %1$s digitaalse identiteet on lähtestatud. %2$s" + "Kasutaja %1$s %2$s digitaalse identiteet on lähtestatud. %3$s" "(%1$s)" - "%1$s kasutaja verifitseeritud identiteet on lähtestatud." - "%1$s kasutaja (%2$s kasutajanimi) verifitseeritud identiteet on lähtestatud. %3$s" + "%1$s kasutaja digitaalse identiteet on lähtestatud." + "%1$s kasutaja (ksutajanimega %2$s) digitaalse identiteet on lähtestatud. %3$s" "Võta verifitseerimine tagasi" + "Luba juurdepääs" "%1$s link viib sind teise veebisaiti %2$s Kas sa oled kindel, et soovid jätkata?" @@ -447,6 +452,7 @@ Kas sa oled kindel, et soovid jätkata?" "Rakendus %1$s ei suutnud tuvastada sinu asukohta. Palun proovi hiljem uuesti." "Sinu häälsõnumi üleslaadimine ei õnnestunud." "Seda jututuba pole enam olemas või pole see kutse enam kehtiv." + "Asukohapõhise funktsionaalsuse kasutamiseks palun lülita nutiseadmes GPS sisse." "Sõnumit ei leidu" "Rakendusel %1$s puudub õigus sinu asukohta tuvastada. Sa saad seda lubada süsteemi seadistustest." "Rakendusel %1$s puudub õigus sinu asukohta tuvastada. Järgnevalt anna vastavad õigused." @@ -458,6 +464,9 @@ Kas sa oled kindel, et soovid jätkata?" "Vabandust, ilmnes viga" "🔐️ Liitu minuga rakenduses %1$s" "Hei, suhtle minuga %1$s võrgus: %2$s" + "Asukoha jagamine reaalajas" + "Asukoha jagamine käimas" + "Asukoht reaalajas: %1$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" "Ekraanitõmmis" @@ -480,11 +489,11 @@ Kas sa oled kindel, et soovid jätkata?" "%1$d esiletõstetud sõnumit" "Esiletõstetud sõnumid" - "Oma võrguidentiteedi lähtestamiseks suuname sind %1$s kasutajakonto halduse lehele. Hiljem suunatakse sind tagasi sama rakenduse juurde." - "Sa ei saa seda kinnitada? Ava oma kasutajakonto haldus ja lähtesta oma võrguidentiteet." + "Oma digitaalse identiteedi lähtestamiseks suuname sind %1$s kasutajakonto halduse lehele. Hiljem suunatakse sind tagasi sama rakenduse juurde." + "Sa ei saa seda kinnitada? Ava oma kasutajakonto haldus ja lähtesta oma digitaalne identiteet." "Unusta verifitseerimine ja saada ikkagi" "Sa võid jätta verifitseerimisvea tähelepanuta ja sõnumi ikkagi saata või katkestad saatmise ja peale kasutaja %1$s verifitseerimist proovid seda uuesti." - "Sinu sõnum on saatmata, kuna kasutaja %1$s verifitseeritud identiteet on lähtestatud." + "Sinu sõnum on saatmata, kuna kasutaja %1$s digitaalse identiteet on lähtestatud." "Saada sõnum ikkagi" "%1$s kasutab ühte või enamat verifitseerimata seadet. Sa võid sõnumi ikkagi saata või katkestad selle ning ootad kuni %2$s on kõik oma seadmed verifitseerinud ning proovid seejärel uuesti." "Sinu sõnum on saatmata, kuna %1$s pole verifitseerinud kõiki oma seadmeid" @@ -508,14 +517,16 @@ Kas sa oled kindel, et soovid jätkata?" "Ava Apple Mapsis" "Ava Google Mapsis" "Ava OpenStreetMapis" - "Jaga seda asukohta" + "Jaga valitud asukohta" "Jagamise valikud" "Sinu loodud kogukonnad ning need, millega oled liitunud." "%1$s • %2$s" "Jututubade haldamiseks võid luua kogukondi" "Kogukond: %1$s" "Kogukonnad" - "Sõnum on saatmata, kuna kasutaja %1$s verifitseeritud identiteet on lähtestatud." + "Jagatud %1$s" + "Kaardil" + "Sõnum on saatmata, kuna kasutaja %1$s digitaalse identiteet on lähtestatud." "Sõnum on saatmata, kuna %1$s pole verifitseerinud kõiki oma seadmeid." "Kuna sa pole üks või enamgi oma seadet verifitseerinud, siis sinu sõnum on saatmata." "Asukoht" @@ -525,5 +536,5 @@ Kas sa oled kindel, et soovid jätkata?" "Ligipääsuks vanadele sõnumitele pead selle seadme verifitseerima" "Sul pole ligipääsu antud sõnumile" "Sõnumi dekrüptimine ei õnnestu" - "Kuna seade on verifitseerimata või saatja pole sind verifitseerinud, siis sõnumi näitamine on blokeeritud." + "Kuna seade on verifitseerimata või saatja pole sinu digitaalset identiteeti verifitseerinud, siis sõnumi näitamine on blokeeritud." 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 d5093590ca..b3f0f32639 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -235,7 +235,7 @@ Syy: %1$s." "Epäonnistui" "Lisää suosikkeihin" "Lisätty suosikkeihin" - "Synkronoidaan ilmoituksia…" + "Synkronoidaan ilmoituksia…" "Tiedosto" "Tiedosto poistettu" "Tiedosto tallennettu" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index fb6b06daf7..c654a66541 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -409,7 +409,7 @@ Powód: %1$s." "Zweryfikuj urządzenie" "Zweryfikuj tożsamość" "Zweryfikuj użytkownika" - "Film" + "Wideo" "Wysoka jakość" "Najlepsza jakość, większy rozmiar pliku" "Niska jakość" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index 35930b694e..dfd68686ce 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -15,6 +15,7 @@ "Detalii privind criptarea" "Extindeți câmpul mesajului" "Ascundeți parola" + "Informații" "Alăturați-vă apelului" "Mergeți în jos" "Mutați harta la locația mea" @@ -28,9 +29,12 @@ "Pauză" "Mesaj vocal, durată:%1$s, poziție curentă: %2$s" "Câmp PIN" + "Locație fixată" "Redați" + "Viteză de redare" "Sondaj" "Sondaj încheiat" + "Cod QR" "Reacționați cu %1$s" "Reacționați cu alte emoji-uri" "Citit de %1$s și %2$s" @@ -45,9 +49,13 @@ "Îndepărtați reacția %1$s" "Avatarul camerei" "Trimiteți fișiere" + "Locația expeditorului" "Acțiune limitată în timp necesară, aveți un minut pentru a verifica" + "Setări, acțiune necesară" "Afișați parola" "Începeți un apel" + "Inițiați un apel video" + "Inițiați un apel vocal" "Cameră terminată" "Avatar utilizator" "Meniu utilizator" @@ -59,15 +67,17 @@ "Avatarul dumneavoastră" "Acceptați" "Adăugați o descriere" + "Adăugați camere existente" "Adăugați listei de mesaje" "Înapoi" - "Apel" + "Apelați" "Anulați" "Anulați pentru moment" + "Alegeți fișierul" "Alegeți o fotografie" "Ștergeți" "Închideți" - "Verificare completă" + "Finalizați verificarea" "Confirmați" "Confirmați parola" "Continuați" @@ -78,22 +88,27 @@ "Copiați textul" "Creați" "Creați o cameră" + "Creeați spațiu" "Dezactivați" "Dezactivați contul" "Refuzați" "Refuzați și blocați" + "Ștergere" + "Ștergeți contul" "Ștergeți sondajul" "Deselectați tot" "Dezactivați" "Renunţare" "Renunțați" - "Efectuat" + "Terminat" + "Descărcare" "Editați" "Editați descrierea" "Editați sondajul" "Activați" "Închideți sondajul" "Introduceți PIN-ul" + "Explorați spațiile publice" "Finalizați" "Ați uitat parola?" "Redirecționați" @@ -113,10 +128,11 @@ "Părăsiți camera" "Părăsiți spațiul" "Încărcați mai mult" - "Administrare cont" - "Gestionare dispozitive" + "Gestionați contul" + "Gestionați contul și dispozitivele" + "Gestionați dispozitivele" "Gestionați camerele" - "Mesaj" + "Contactați" "Minimizați" "Următorul" "Nu" @@ -125,11 +141,11 @@ "Deschideți meniul contextual" "Setări" "Deschideți cu" - "Fixează" + "Fixați" "Raspuns rapid" - "Citat" + "Citați" "Reacționați" - "Respinge" + "Respingeți" "Indepărtați" "Ștergeți descrierea" "Ștergeți mesajul" @@ -140,7 +156,7 @@ "Raportați conținutul" "Raportați conversația" "Raportați camera" - "Resetare" + "Resetați" "Resetați identitatea" "Reîncercați" "Reîncercați decriptarea" @@ -153,7 +169,8 @@ "Trimiteți un mesaj vocal" "Partajați" "Partajați linkul" - "Afișare" + "Partajați locația în timp real" + "Afișați" "Autentificați-vă din nou" "Deconectați-vă" "Deconectați-vă oricum" @@ -163,10 +180,12 @@ "Începeți din nou" "Începeți verificarea" "Atingeți pentru a încărca harta" + "Opriți" "Faceți o fotografie" "Atingeți pentru opțiuni" + "Traduceți" "Încercați din nou" - "Defixeaza" + "Defixați" "Vizualizați" "Vedeți în lista de mesaje" "Vedeți sursă" @@ -176,8 +195,8 @@ "Upgrade disponibil" "Despre" "Politică de utilizare rezonabilă" - "Adăugați un cont" - "Adăugați un alt cont" + "Adăugare cont" + "Adăugare cont" "Adăugare descriere" "Setări avansate" "o imagine" @@ -189,14 +208,17 @@ "Beta" "Utilizatori blocați" "Baloane" - "A început un apel" + "Apel respins" + "Apel inițiat" + "Ați respins un apel" "Backup conversații" "Copiat în clipboard" "Drepturi de autor" "Se creează camera…" + "Se crează spațiul" "Cerere anulată" - "Ați parăsit camera" - "S-a părăsit spațiul" + "Cameră părăsită" + "Spațiu părăsit" "Invitația a fost refuzată" "Eroare de decriptare" "Descriere" @@ -213,6 +235,7 @@ "Fișier gol" "Criptare" "Criptare activată" + "Se termină la %1$s" "Introduceți codul PIN" "Eroare" "A apărut o eroare, este posibil să nu primiți notificări pentru mesaje noi. Vă rugăm să depanați notificările din setări. @@ -222,6 +245,7 @@ Motiv:%1$s." "Eșuat" "Favorite" "Favorită" + "Se sincronizează notificările…" "Fişier" "Fișier șters" "Fișier salvat" @@ -238,6 +262,8 @@ Motiv:%1$s." "Linie copiată în clipboard" "Linkul a fost copiat în clipboard" "Conectați un dispozitiv nou" + "Locație în timp real" + "Locația în timp real s-a încheiat" "Se încarcă…" "Se încarcă…" @@ -256,7 +282,7 @@ Motiv:%1$s." "Aspectul mesajelor" "Mesaj șters" "Modern" - "Dezactivați sunetul" + "Dezactivare sunet" "Nume" "%1$s (%2$s)" "Niciun rezultat" @@ -266,6 +292,7 @@ Motiv:%1$s." "Deconectat" "Licențe open source" "sau" + "Alte opțiuni" "Parola" "Persoane" "Permalink" @@ -284,8 +311,10 @@ Motiv:%1$s." "Se pregăteşte…" "Politica de confidențialitate" + "Privat" "Cameră privată" "Spațiu privat" + "Public" "Cameră publică" "Spațiu public" "Reacţie" @@ -293,6 +322,7 @@ Motiv:%1$s." "Motiv" "Cheie de recuperare" "Se actualizează" + "Se elimină…" "%1$d răspuns" "%1$d răspunsuri" @@ -302,6 +332,7 @@ Motiv:%1$s." "Raportați o problemă" "Raport trimis" "Editor text avansat" + "Rol" "Cameră" "Numele camerei" "de exemplu, numele proiectului dumneavoastră" @@ -318,6 +349,11 @@ Motiv:%1$s." "Securitate" "Văzut de" "Selectați un cont" + + "%1$d selectat" + "%1$d selectate" + "%1$d selectate" + "Trimiteți către" "Se trimite…" "Trimiterea a eșuat" @@ -327,13 +363,16 @@ Motiv:%1$s." "Serverul nu poate fi accesat" "Adresa URL a serverului" "Setări" - "Partajați spațiul" + "Partajare spațiu" + "Membrii noi pot vedea istoricul" + "Locație în timp real partajată" "Locație partajată" "Spațiu comun" "Eliminare în curs" "Ceva nu a mers bine" "Am întâmpinat o problemă. Vă rugăm să încercați din nou." "Spațiu" + "Membrii spațiului" "Despre ce este vorba în acest spațiu?" "%1$d Spațiu" @@ -343,11 +382,13 @@ Motiv:%1$s." "Se începe conversația…" "Autocolant" "Succes" + "Sugerat" "Sugestii" "Se sincronizează…" "Text" "Notificări despre software de la terți" "Fir" + "Fire" "Subiect" "Despre ce este vorba în această cameră?" "Nu s-a putut decripta" @@ -357,8 +398,8 @@ Motiv:%1$s." "Nu am putut trimite invitații unuia sau mai multor utilizatori." "Nu s-a putut trimite invitația (invitațiile)" "Deblocare" - "Activați sunetul" - "Apel nesuportat" + "Activare sunet" + "Apel incompatibil" "Eveniment neacceptat" "Utilizator" "Verificare anulată" @@ -378,14 +419,19 @@ Motiv:%1$s." "Mesaj vocal" "Se aşteaptă…" "Mesaj în așteptare" + "Se așteptă localizarea în timp real…" + "Oricine poate vedea istoricul" "Dumneavoastră" + "%1$s (%2$s) a distribuit acest mesaj deoarece nu erați în cameră când a fost trimis." + "%1$s a distribuit acest mesaj deoarece nu erați în cameră când a fost trimis." "Această cameră a fost configurată astfel încât noii membri să poată citi istoricul. %1$s" "Identitatea digitala lui %1$s a fost resetată. %2$s" "Identitatea digitala %2$s a lui %1$s a fost resetată. %3$s" "(%1$s)" "Identitatea lui %1$s a fost resetată." - "Identitatea %2$s a lui %1$s a fost resetată. %3$s" + "Identitatea digitală %2$s a lui %1$s a fost resetată. %3$s" "Retrageți verificarea" + "Permiteți accesul" "Linkul %1$s vă redirecționează către un alt site %2$s Sunteți sigur că doriți să continuați?" @@ -415,6 +461,7 @@ Sunteți sigur că doriți să continuați?" "%1$s nu a putut accesa locația dumneavoastră. Vă rugăm să încercați din nou mai târziu." "Trimiterea mesajului vocal nu a reușit." "Camera nu mai există sau invitația nu mai este valabilă." + "Vă rugăm să activați GPS-ul pentru a accesa funcțiile bazate pe locație." "Mesajul nu a fost găsit" "%1$s nu are permisiuni pentru a accesa locația dumneavoastră. Puteți permite accesul în Setări." "%1$s nu are permisiuni pentru a accesa locația dumneavoastră. Permiteți accesul mai jos." @@ -426,6 +473,9 @@ Sunteți sigur că doriți să continuați?" "Ne pare rău, a apărut o eroare" "🔐️ Alăturați-vă mie în %1$s" "Hei, vorbește cu mine pe %1$s: %2$s" + "Partajarea locației în timp real" + "Partajarea locației este în curs de desfășurare" + "%1$s Locație în timp real" "%1$s Android" "Rageshake pentru a raporta erori" "Captură de ecran" @@ -433,6 +483,14 @@ Sunteți sigur că doriți să continuați?" "Opțiuni" "Ștergeți %1$s" "Setări" + "Nimeni nu își partajează locația" + "Se partajează locația în timp real" + + "%1$d persoană" + "%1$d persoane" + "%1$d persoane" + + "Pe hartă" "Selectarea fișierelor media a eșuat, încercați din nou." "Apăsați pe un mesaj și alegeți \"%1$s\" pentru a-l include aici." "Fixați mesajele importante, astfel încât să poată fi descoperite cu ușurință" @@ -458,6 +516,7 @@ Sunteți sigur că doriți să continuați?" "Mesaj în %1$s" "Extindeți" "Reduceți" + "Se partajează locația în timp real" "Deja vizualizați această cameră!" "%1$s din %2$s" "%1$s Mesaje fixate" @@ -470,10 +529,14 @@ Sunteți sigur că doriți să continuați?" "Deschideți în Google Maps" "Deschideți în OpenStreetMap" "Partajați locația selectată" + "Opțiuni de partajare" "Spații pe care le-ați creat sau la care v-ați alăturat." "%1$s • %2$s" + "Creați spații pentru a organiza camerele" "Spațiu %1$s" "Spații" + "Partajat %1$s" + "Pe hartă" "Mesajul nu a fost trimis deoarece identitatea digitala verificată a lui %1$s s-a schimbat." "Mesajul nu a fost trimis deoarece %1$s nu a verificat toate dispozitivele." "Mesajul nu a fost trimis deoarece nu ați verificat unul sau mai multe dispozitive." @@ -484,5 +547,5 @@ Sunteți sigur că doriți să continuați?" "Trebuie să verificați acest dispozitiv pentru a avea acces la mesajele anterioare." "Nu aveți acces la acest mesaj" "Nu s-a putut decripta mesajul" - "Acest mesaj a fost blocat fie pentru că nu ați verificat dispozitivul, fie pentru că expeditorul trebuie să vă verifice identitatea." + "Acest mesaj a fost blocat fie pentru că nu ați verificat dispozitivul, fie pentru că expeditorul trebuie să vă verifice identitatea digitală." diff --git a/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png b/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png index bfa7251296..0996d18bf0 100644 --- a/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png +++ b/screenshots/de/features.call.impl.ui_CallScreenView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5988ca59d9fcfaccbf4bc2929d7c135f67be0852e739caeb566b0518fac7f75 -size 19021 +oid sha256:bc9627a6288987e446206dc54abb8e1319ba6996674f0b588decd5418eeafc1b +size 18688 diff --git a/screenshots/de/features.location.api_LiveLocationSharingBanner_Day_0_de.png b/screenshots/de/features.location.api_LiveLocationSharingBanner_Day_0_de.png new file mode 100644 index 0000000000..f889a65156 --- /dev/null +++ b/screenshots/de/features.location.api_LiveLocationSharingBanner_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efd6cb8498b29f79769b3287a062ee1ddad3c34195aa5d653b8e28e4e6f973bc +size 10767 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png index bf8a621fe1..bb93cfc575 100644 --- a/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a5606179cc7dacc1d0bc86ff0f38a7654cebeb7c428575e2da51d4af0ba12b9 -size 43384 +oid sha256:1342bc5c63e6fa38797d1867b5006ebc91cfa926d189e4ff9060f84efd8146ca +size 26114 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_7_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_7_de.png new file mode 100644 index 0000000000..0663eceb1d --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b08870ebcd6da6372363b0af0334524a4288db7242cdb5a377512ef9aa728a66 +size 38883 diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_8_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_8_de.png new file mode 100644 index 0000000000..bf8a621fe1 --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a5606179cc7dacc1d0bc86ff0f38a7654cebeb7c428575e2da51d4af0ba12b9 +size 43384 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png index 642cb48d0f..a854d161d7 100644 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebee62aecbbc7e65168799cdeb940d112095d7e38059bf91e4192dea242eb884 -size 113883 +oid sha256:ad01125850f8dc08f39832fe3ffcaae1950edd736a80f39811b4c1d9a6eafd93 +size 122264 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png index 0b33acb4dc..a8d7c0385c 100644 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7bc6e29e43c98d47257304e38b5d6f3c0aeb55fc671adc02ea0234ba6ff31be -size 120123 +oid sha256:5dd0fa202f0d1ec868537a2726df10013072fe9cec7bce4c947ab13f39e683dc +size 122366 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png index 400c371f56..2ed9893cb4 100644 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aec9126323f766fa0caf0bf1aba5ebd2110bfe6076c91197f4613088eb3b8a62 -size 120233 +oid sha256:dbe9d2831b54807db3c329ac4ca9e853198195df21f8db348050b40fe98cab5f +size 121228 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png index 610bc5d0a0..d005896ab7 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2b86e1326023be378c0c03b12305810f36e4fed11886ffd3bfa46ef9e5802ab -size 18767 +oid sha256:08984e24e297742f065201c4cea3d07eda34e4c80fbcb4689e539ac64f32f1db +size 53795 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png index 98dd645229..63497b4081 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b13eb680dca1d551d843b92dff0062a58781c6c9c1fe713e35c26412b6addf6 -size 68596 +oid sha256:a7cf06d5921dae7bbdd3b774e38ac6fcbad724261c1adef9ad93ff992fcc7669 +size 51515 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png new file mode 100644 index 0000000000..98dd645229 --- /dev/null +++ b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b13eb680dca1d551d843b92dff0062a58781c6c9c1fe713e35c26412b6addf6 +size 68596 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png index b713fac540..194a69f62b 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e08f56a74a85de1d5e792dbc17a409f95c0a72df49b3c2538814442fdd63d4a9 -size 65018 +oid sha256:cd28a4f1e30c5ef7db0cd167a3d0328af7b969ccd7c35f616472dc2ab02b5c4a +size 57867 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png index 63497b4081..b713fac540 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7cf06d5921dae7bbdd3b774e38ac6fcbad724261c1adef9ad93ff992fcc7669 -size 51515 +oid sha256:e08f56a74a85de1d5e792dbc17a409f95c0a72df49b3c2538814442fdd63d4a9 +size 65018 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png index 20df66736f..0793b01c92 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2c1dc2c23f6b8dafab3eec3bd703c9ffeacf8e3de6f0da8b182ded7dea27244 -size 53656 +oid sha256:cea139c9bc1d71d342a99ce43b6bff414e1f9cb53ac69b8994b1b7ea2c750f41 +size 60894 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png index e9d7ece4cc..c50a3e35cf 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2215fecf0a0cd2e708d7b2aba1879528d3a1ea07cc2dfa255d74986fec933ca -size 53531 +oid sha256:e19998bcd7bb878ee3fa1429ce7edd03293e8f9dfc2dc9cd439ad3a71ccd6276 +size 60764 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png index 5ed68bb027..eb4c703d89 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca1bff9d9c6f5b68823a43eebc8196ae9705f743e7b59897a69cc4016ee155ea -size 53523 +oid sha256:139462dbd69c23df0aff5b8a2b310c2a9a40a9f691ebff57a03d0bf7cf638269 +size 60757 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png index 7e71476836..4e5adc17e1 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c208bdd8a985ab7108020659f0c6dec3413fdd54a529f86d7f2bcb44448fe0d9 -size 53520 +oid sha256:3013b0a0e261f87364a5e72cce9d25cf59c2d1360dc778fec533268e1340a0ca +size 60755 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png index 46d1ca20e2..33a8e007e4 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abe747567a372eb4b674a1e7976b24d498ad2a4d7e20d425c9291ddb05922a14 -size 53339 +oid sha256:a8f056723e3999c53a1e582237290b74e178e652fd49d5b636d1256bcb846de3 +size 60597 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png index 567949e6e5..61e1649e93 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90068ee2e83b713cd11d9879bbcc3c389dd0f79778d8999df6bfc9f2b1b1bb55 -size 53662 +oid sha256:db5aa655ec48b8b8c3019e886a742a2e7922f329c7d7e7c88ca5d70cbf2f6f3e +size 60901 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png index 04837d0ca6..f48a864d6d 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3387219f505ee6168eb44879b4f943b75459f4c5b6c311cce874eba5e49ba628 -size 53108 +oid sha256:0fdcef2b4374ba9a1dded6c7fe3315ccc3c585e489d59572879a1e5efe2dff1c +size 60422 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png index 304befe3c3..3c66dd1128 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7333bd76d2de37bd13fe507d89c000984d73141a3dec81f71eaa13d6658871e -size 52600 +oid sha256:ee1b3b15e7f08f2f63c556a584db2fa3ebcf004b980f7fe837c32ea2d166159c +size 60000 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png index 025b3d596f..1eca9c9326 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97f271f0ba965c1b40edaad388e111bf624c01e5caceb73dfae1e09c28b3856a -size 61504 +oid sha256:1dca13f4ac7e2d0f80d302d2d819a32f536d5765b2d7533be4f019b6bc28dd92 +size 63485 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_de.png index 0bf95ba4b1..246e46b33d 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:030671a61e231a9c87a221e20e63bac8add5f0a3fe4aa967313af45196151c64 -size 51196 +oid sha256:a060a4ef3ae0e7117863606fac9196536fce38d5483e3d882e86931d5f6098e1 +size 57951 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_de.png index 8ece7cdeaa..248175a402 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c813fcb2b9cf76749d9233d5cb66e643e185ac3248eab4c4fdd71f4c7fab7ba4 -size 51057 +oid sha256:9e4faac64c7b38a8b9613eddc62805a5816ed340984e62dc5d6625a79782d3e6 +size 57811 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_de.png index 89c8b5a536..c8bc853a8e 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66feb2ac420379ece0b85ffe53d5a25a8d11cbe27133313dd9e679d582c384fc -size 51052 +oid sha256:7e4713a87444130061d605edcf65d67d5aa1d6730e8afee1ba41c751c2dac77f +size 57804 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_de.png index cff6d2b2f4..19d124ead1 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fd601997ff6e5af28e70c25c7c8c2a61c37e47e736b955b1510ac67e3a05034 -size 51064 +oid sha256:d8907dbe4553c7aac67cd5007dffc12a06e3c3f218fa95a75c390ee8982cf117 +size 57815 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_de.png index fba8ff45f9..26bdb4b258 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b089d766841cc1ce24ea03d3d91b59d0f2ea1789aee3a9d06ece551c862d1ce -size 50901 +oid sha256:961a4dd2ef4c74770f9c140f4b337146225d7a626ca2082f35cc107c91263e12 +size 57670 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_de.png index fb27f001cd..dca7c97656 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b38f2502dd31806ffab41547b66b9987de66c4e899b0df59c068d08ed4350b6 -size 51198 +oid sha256:0ea1eb184dcfcf13c8673f3df717a540c74eb500b759cd752e8fd270da9b8f4e +size 57951 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_de.png index 0429803048..53eb657d5f 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ce5af26d03b80ad7bb0190b6b1dcdbdba4f7a666c442109da58f05c07505aad -size 50867 +oid sha256:ad17f959304774a8956cc38cb008024e79ae70dd1d2f147b2de20a95ca29ca96 +size 57638 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_de.png index 27f6862b8c..1d51b69a1a 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:536cbfdce1cfdecdbf076f0747c50f2db7e3a88dda54c0708d4b7388c9efbf30 -size 50402 +oid sha256:85693d212e3726d4e7bc5cd3c4c2e9d73276cac7a6cba7b9549d5b45bf55b686 +size 57160 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_de.png index 0d41a18697..5736128377 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20285a2d5b10f74f927f8459a2d92180b7f86bc266c95889b5d017679b622462 -size 58368 +oid sha256:aca6e0c7f9d7c48ca80c5a8e56a86e8d0a1cced6020d5b4ef0aae443575071ae +size 60239 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_de.png index ab828c858a..36df3fb547 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ff37f653ce34795f7d054e1d552c161c83fe85b6c80c6925953440a75fd4ea4 -size 53181 +oid sha256:7713d5bb6252597bfc465fc85b3283e08d95684f9d0a17fc89e08f5cf8e870e4 +size 60327 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_de.png index 6583fc352d..833794c51e 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d69ff7dc1c3efb334b8a03dbd796cde640aecac07a10adb910519810bddefed -size 53065 +oid sha256:59b93100a819cc8a0b8b8156da39f47034745bfc6d06957907009ff3eef3c2b0 +size 60210 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_de.png index 1080a3e297..25914b7cbe 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:827f3291c252fa8a5b938ca7a38a76d0d58e1969607f2c5514d06264e10a1ddd -size 53078 +oid sha256:eaaf5ae88296f64e80ebbe60a126a1fd40944e31311329cade209631f36424cd +size 60223 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_de.png index 1b77b7d963..2af3d0fc1b 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb8636f0a7dbad6b32346cad952b5447a79b96d3db0e5da876fca7a78ced91c2 -size 53072 +oid sha256:77c71a0c84d3fa9e39ba3c9b9b81e8a3b6e406af87e4158bfb8bb4736a8b27c7 +size 60217 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_de.png index 3048b141f6..9f0b5c037c 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24dfd7e781f8b035045ca075b607676a2a4cbc0ef882c1f527252d85339a738e -size 52922 +oid sha256:c9228e4ace7d30444a45deb04f211782ca53c5a366e0e812145b5b772fa51d3b +size 60085 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_de.png index 8ebc7b90cd..a880ff90f4 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:640ecec1abd4992b962a9ab8ce68d4c5a3accfde9116b93af4d55d8365c35307 -size 53187 +oid sha256:c00205667f22842c1c5d63c20c0990b6e0fb7f7cd134f625957df733627378df +size 60330 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_de.png index c1dda2d9d5..4265684997 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc3da8b4380809f5f9724d98ba4eceb86ea9d6a7df54c4a2117d187550b46597 -size 52800 +oid sha256:cbed351c3ce6dfcb334d28316501baa5f97ade4614bd9b7dbbd91b0ce7689994 +size 59987 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_de.png index 419eec6b72..dd801a4745 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c03b9b002d3d5a42c6a5662301e8feda20f734a299dbd753b4fa797023ad697f -size 52372 +oid sha256:09bcae54d99e6b9279794ebebf32a67f67a8347c94f3286243fe8d2c0a92f352 +size 59623 diff --git a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_de.png b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_de.png index 75634a5633..2e74f12057 100644 --- a/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_de.png +++ b/screenshots/de/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7abc46138c98086dab38fc368d56e06ea6a434bfe61b0023a665b40e66f0aa53 -size 60801 +oid sha256:5d0ccc252fedce22f568f8d26f25a8600c21236e1d489a4dd59ccd63c1085227 +size 62771 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index eea6b4b636..08d02138ef 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -2,99 +2,99 @@ export const screenshots = [ ["en","en-dark","de",], ["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",0,], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20581,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20588,], ["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",20581,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20581,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20581,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20581,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20581,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20581,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20581,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20581,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20581,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20581,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20588,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20588,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20588,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20588,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20588,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20588,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20588,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20588,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20588,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20588,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20588,], ["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",20581,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20581,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20588,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20588,], ["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",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20588,], ["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",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20581,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20581,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20581,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20581,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20581,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20581,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20581,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20581,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20581,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20588,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20588,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20588,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20588,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20588,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20588,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20588,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20588,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20588,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20581,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20581,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20581,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20581,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20581,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20588,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20588,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20588,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20588,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20588,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20581,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20581,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20581,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20581,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20588,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20588,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20588,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20588,], ["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",20581,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20588,], ["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",20581,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20588,], ["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",20581,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20588,], ["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",20581,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20588,], ["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,], @@ -104,19 +104,19 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20581,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20588,], ["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",20581,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20588,], ["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,], @@ -146,22 +146,22 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20581,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20588,], ["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",20581,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20581,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20581,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20581,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20581,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20581,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20588,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20581,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20581,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20581,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20581,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20588,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20588,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20588,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20588,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20588,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -172,141 +172,141 @@ export const screenshots = [ ["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20581,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20581,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20588,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20588,], ["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",20581,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20588,], ["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",20581,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20581,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20581,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20581,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20581,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20581,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20588,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20588,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20588,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20588,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20588,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20588,], ["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",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20581,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20581,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20588,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20588,], ["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",20581,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20581,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20581,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20581,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20588,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20588,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20588,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20588,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20588,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20581,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20588,], ["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",20581,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20581,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20581,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20581,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20581,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20581,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20581,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20581,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20588,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20588,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20588,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20588,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20588,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20588,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20588,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20588,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], -["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20588,], ["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",20581,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20581,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20581,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20581,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20581,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20581,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20588,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20588,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20588,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20588,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20588,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20588,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20588,], ["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","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20581,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20581,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20581,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20581,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20581,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20588,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20588,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20588,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20588,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20588,], ["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",20581,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20581,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20581,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20581,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20581,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20581,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20581,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20581,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20581,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20581,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20581,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20581,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20581,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20581,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20581,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20581,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20581,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20581,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20581,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20581,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20588,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20588,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20588,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20588,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20588,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20588,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20588,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20588,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20588,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20588,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20588,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20588,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20588,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20588,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20588,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20588,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20588,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20588,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20588,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20588,], ["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","",20581,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20581,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20581,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20581,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20581,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20581,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20581,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20588,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20588,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20588,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20588,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20588,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20588,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20588,], ["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",20581,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20581,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20581,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20588,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20588,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20588,], ["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",20581,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20588,], ["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",20581,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20581,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20581,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20581,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20581,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20581,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20581,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20581,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20588,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20588,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20588,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20588,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20588,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20588,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20588,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20588,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20588,], ["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,], @@ -319,20 +319,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",20581,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20581,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20581,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20581,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20581,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20581,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20581,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20581,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20581,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20581,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20581,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20581,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20581,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20588,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20588,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20588,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20588,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20588,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20588,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20588,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20588,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20588,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20588,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20588,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20588,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20588,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20588,], ["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,], @@ -340,29 +340,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20581,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20581,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20588,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20588,], ["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",20581,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20581,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20581,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20581,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20581,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20581,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20581,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20581,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20581,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20588,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20588,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20588,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20588,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20588,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20588,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20588,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20588,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20588,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20588,], ["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,], @@ -382,49 +382,49 @@ export const screenshots = [ ["features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en","features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20581,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20581,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20581,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20588,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20588,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20588,], ["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",20581,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20581,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20588,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20588,], ["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",20581,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20588,], ["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",20581,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20581,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20581,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20581,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20581,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20588,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20588,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20588,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20588,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20588,], ["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",20581,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20581,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20588,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20588,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20581,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20581,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20588,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20588,], ["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",20581,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20581,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20581,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20581,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20581,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20581,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20581,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20581,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20581,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20581,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20581,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20581,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20581,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20588,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20588,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20588,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20588,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20588,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20588,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20588,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20588,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20588,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20588,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20588,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20588,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20588,], ["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,], @@ -435,12 +435,12 @@ export const screenshots = [ ["libraries.designsystem.atomic.molecules_IconTitlePlaceholdersRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_IconTitlePlaceholdersRowMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_IconTitleSubtitleMolecule_Day_0_en","libraries.designsystem.atomic.molecules_IconTitleSubtitleMolecule_Night_0_en",0,], ["libraries.designsystem.theme.components_IconToggleButton_Toggles_en","",0,], -["appicon.enterprise_Icon_en","",0,], ["appicon.element_Icon_en","",0,], +["appicon.enterprise_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",20581,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20581,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20588,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20588,], ["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,], @@ -448,119 +448,119 @@ export const screenshots = [ ["libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20581,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20588,], ["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",20581,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20588,], ["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",20581,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20581,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20588,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20588,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20581,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20588,], ["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",20581,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20581,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20581,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20588,], ["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",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20588,], ["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",20581,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20581,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20581,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20588,], ["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",20581,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20581,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20581,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20581,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20581,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20581,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20581,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20588,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20588,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20588,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20588,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20588,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20588,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20588,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20588,], ["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",20581,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20581,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20581,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20581,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20588,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20588,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20588,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20581,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20581,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20588,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20588,], ["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",20581,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20581,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20581,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20581,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20581,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20581,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20581,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20588,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20588,], ["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",20581,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20581,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20581,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20581,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20581,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20588,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20588,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20588,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20588,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20588,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20588,], ["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",20581,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20588,], ["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,], @@ -613,47 +613,48 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextNoPadding_List_supporting_text_-_no_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], +["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20591,], ["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",20581,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20588,], ["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",20581,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20581,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20581,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20588,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20588,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20588,], ["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",20581,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20581,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20581,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20581,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20581,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20581,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20581,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20581,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20581,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20581,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20581,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20581,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20581,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20581,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20581,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20581,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20581,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20581,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20581,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20581,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20581,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20581,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20581,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20581,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20581,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20581,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20581,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20588,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20588,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20588,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20588,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20588,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20588,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20588,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20588,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20588,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20588,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20588,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20588,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20588,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20588,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20588,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20588,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20588,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20588,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20588,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20588,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20588,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20588,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20588,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20588,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20588,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20588,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20588,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20581,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20581,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20581,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20581,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20588,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20588,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20588,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20588,], ["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,], @@ -666,26 +667,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20581,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20581,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20581,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20581,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20581,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20581,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20588,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20588,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20588,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20588,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20588,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20588,], ["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",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20581,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20588,], ["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,], @@ -693,10 +694,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20581,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20588,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20588,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], @@ -706,7 +707,7 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20588,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -716,10 +717,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20581,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20588,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20588,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], @@ -729,7 +730,7 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerView_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20588,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -743,7 +744,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",20581,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20588,], ["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,], @@ -752,7 +753,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",20581,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20588,], ["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,], @@ -761,23 +762,24 @@ 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",20581,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20581,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20581,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20581,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20581,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20581,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20581,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20581,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20581,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20581,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20581,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20581,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20581,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20581,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20581,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20588,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20588,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20588,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20588,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20588,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20588,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20591,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20588,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20588,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20588,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20588,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20588,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20588,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20588,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20588,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20588,], ["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",20581,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20588,], ["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,], @@ -788,117 +790,117 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20581,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20581,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20581,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20588,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20588,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20588,], ["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",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20581,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20588,], ["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",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20581,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20588,], ["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",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20581,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20588,], ["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",20581,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20581,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20581,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20581,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20581,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20581,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20588,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20588,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20588,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20588,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20588,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20588,], ["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",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20584,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20584,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20581,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20584,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20588,], ["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",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20581,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20581,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20581,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20581,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20581,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20588,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20588,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20588,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20588,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20588,], ["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",20581,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20581,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20581,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20581,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20588,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20588,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20588,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20588,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20588,], ["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",20581,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20581,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20581,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20581,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20581,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20581,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20581,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20581,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20581,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20581,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20581,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20588,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20588,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20588,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20588,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20588,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20588,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20588,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20588,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20588,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20588,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20588,], ["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,], @@ -912,225 +914,225 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20581,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20588,], ["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","",20581,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20581,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20588,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20588,], ["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",20581,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20581,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20581,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20581,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20581,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20581,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20581,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20581,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20581,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20581,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20581,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20581,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20581,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20581,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20581,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20581,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20581,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20581,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20581,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20581,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20581,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20588,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20588,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20588,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20588,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20588,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20588,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20588,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20588,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20588,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20588,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20588,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20588,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20588,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20588,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20588,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20588,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20588,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20588,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20588,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20588,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20588,], ["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",20581,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20581,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20588,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20588,], ["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",20581,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20581,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20581,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20581,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20581,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20581,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20588,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20588,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20588,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20588,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20588,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20588,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20588,], ["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",20581,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20581,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20581,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20581,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20581,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20581,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20581,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20581,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20581,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20581,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20581,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20581,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20581,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20581,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20581,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20581,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20588,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20588,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20588,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20588,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20588,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20588,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20588,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20588,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20588,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20588,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20588,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20588,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20588,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20588,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20588,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20588,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20588,], ["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",20581,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20581,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20581,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20581,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20581,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20588,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20588,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20588,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20588,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20588,], ["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",20581,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20581,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20588,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20588,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20581,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20581,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20581,], -["features.roomdetails.impl_RoomDetails_0_en","",20581,], -["features.roomdetails.impl_RoomDetails_10_en","",20581,], -["features.roomdetails.impl_RoomDetails_11_en","",20581,], -["features.roomdetails.impl_RoomDetails_12_en","",20581,], -["features.roomdetails.impl_RoomDetails_13_en","",20581,], -["features.roomdetails.impl_RoomDetails_14_en","",20581,], -["features.roomdetails.impl_RoomDetails_15_en","",20581,], -["features.roomdetails.impl_RoomDetails_16_en","",20581,], -["features.roomdetails.impl_RoomDetails_17_en","",20581,], -["features.roomdetails.impl_RoomDetails_18_en","",20581,], -["features.roomdetails.impl_RoomDetails_19_en","",20581,], -["features.roomdetails.impl_RoomDetails_1_en","",20581,], -["features.roomdetails.impl_RoomDetails_20_en","",20581,], -["features.roomdetails.impl_RoomDetails_21_en","",20581,], -["features.roomdetails.impl_RoomDetails_22_en","",20581,], -["features.roomdetails.impl_RoomDetails_2_en","",20581,], -["features.roomdetails.impl_RoomDetails_3_en","",20581,], -["features.roomdetails.impl_RoomDetails_4_en","",20581,], -["features.roomdetails.impl_RoomDetails_5_en","",20581,], -["features.roomdetails.impl_RoomDetails_6_en","",20581,], -["features.roomdetails.impl_RoomDetails_7_en","",20581,], -["features.roomdetails.impl_RoomDetails_8_en","",20581,], -["features.roomdetails.impl_RoomDetails_9_en","",20581,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20581,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20581,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20581,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20581,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20581,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20581,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20581,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20581,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20581,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20588,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20588,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20588,], +["features.roomdetails.impl_RoomDetails_0_en","",20588,], +["features.roomdetails.impl_RoomDetails_10_en","",20588,], +["features.roomdetails.impl_RoomDetails_11_en","",20588,], +["features.roomdetails.impl_RoomDetails_12_en","",20588,], +["features.roomdetails.impl_RoomDetails_13_en","",20588,], +["features.roomdetails.impl_RoomDetails_14_en","",20588,], +["features.roomdetails.impl_RoomDetails_15_en","",20588,], +["features.roomdetails.impl_RoomDetails_16_en","",20588,], +["features.roomdetails.impl_RoomDetails_17_en","",20588,], +["features.roomdetails.impl_RoomDetails_18_en","",20588,], +["features.roomdetails.impl_RoomDetails_19_en","",20588,], +["features.roomdetails.impl_RoomDetails_1_en","",20588,], +["features.roomdetails.impl_RoomDetails_20_en","",20588,], +["features.roomdetails.impl_RoomDetails_21_en","",20588,], +["features.roomdetails.impl_RoomDetails_22_en","",20588,], +["features.roomdetails.impl_RoomDetails_2_en","",20588,], +["features.roomdetails.impl_RoomDetails_3_en","",20588,], +["features.roomdetails.impl_RoomDetails_4_en","",20588,], +["features.roomdetails.impl_RoomDetails_5_en","",20588,], +["features.roomdetails.impl_RoomDetails_6_en","",20588,], +["features.roomdetails.impl_RoomDetails_7_en","",20588,], +["features.roomdetails.impl_RoomDetails_8_en","",20588,], +["features.roomdetails.impl_RoomDetails_9_en","",20588,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20588,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20588,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20588,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20588,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20588,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20588,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20588,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20588,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20588,], ["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",20581,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20581,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20581,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20581,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20581,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20581,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20581,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20581,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20581,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20581,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20581,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20588,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20588,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20588,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20588,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20588,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20588,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20588,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20588,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20588,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20588,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20588,], ["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",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20581,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20581,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20581,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20588,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20588,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20588,], ["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",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20581,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20588,], ["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",20581,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20581,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20581,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20581,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20581,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20588,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20588,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20588,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20588,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20588,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20588,], ["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,], @@ -1153,16 +1155,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20581,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20588,], ["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",20581,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20588,], ["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,], @@ -1171,119 +1173,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",20581,], ["features.login.impl.screens.classic.root_RootView_Day_0_en","features.login.impl.screens.classic.root_RootView_Night_0_en",0,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20581,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20581,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20588,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20588,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20588,], ["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",20581,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20581,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20581,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20581,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20581,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20581,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20581,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20581,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20588,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20588,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20588,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20588,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20588,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20588,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20588,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20588,], ["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","",20581,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20588,], ["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","",20581,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20581,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20581,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20581,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20581,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20581,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20581,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20581,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20581,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20581,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20581,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20581,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20581,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20581,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20581,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20588,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20588,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20588,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20588,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20588,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20588,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20588,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20588,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20588,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20588,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20588,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20588,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20588,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20588,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20588,], ["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,], @@ -1306,35 +1308,37 @@ 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",20581,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20581,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20581,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20581,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20581,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20581,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20581,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20581,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20581,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20581,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20581,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20581,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20581,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20581,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20581,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20588,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20588,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20588,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20588,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20588,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20588,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20588,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20588,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20588,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20588,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20588,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20588,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20588,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20588,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20588,], +["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20591,], +["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20591,], ["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",20581,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20581,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20581,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20581,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20581,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20581,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20581,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20581,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20581,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20581,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20581,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20588,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20588,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20588,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20588,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20588,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20588,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20588,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20588,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20588,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20588,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20588,], ["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,], @@ -1344,106 +1348,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",20581,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20588,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20581,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20581,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20581,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20581,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20581,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20588,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20588,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20588,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20588,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20588,], ["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",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20581,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20581,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20581,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20581,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20581,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20581,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20581,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20581,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20581,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20581,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20581,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20581,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20581,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20581,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20588,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20588,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20588,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20588,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20588,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20588,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20588,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20588,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20588,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20588,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20588,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20588,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20588,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20588,], ["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",20581,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20581,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20581,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20581,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20581,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20581,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20588,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20588,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20588,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20588,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20588,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20588,], ["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",20581,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20588,], ["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",20581,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20588,], ["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",20581,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20581,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20581,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20581,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20581,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20581,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20581,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20581,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20581,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20581,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20581,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20581,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20581,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20581,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20581,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20588,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20588,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20588,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20588,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20588,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20588,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20588,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20588,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20588,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20588,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20588,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20588,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20588,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20588,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20588,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20588,], ["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",20581,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20588,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20588,], ["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,], @@ -1456,17 +1460,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20581,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20581,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20588,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20588,], ["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","",20581,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20581,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20588,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20588,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20588,], ["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",20581,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20581,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20588,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20588,], ["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,], @@ -1476,18 +1480,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",20581,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20588,], ["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",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20588,], ["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,], @@ -1495,18 +1499,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",20581,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20588,], ["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",20581,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20581,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20588,], ["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",20581,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20588,], ["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,], @@ -1515,44 +1519,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20588,], ["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",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20588,], ["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",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20588,], ["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","",20581,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20588,], ["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",20581,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20588,], ["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",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20588,], ["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",20581,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20581,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20581,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20588,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20588,], ["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",20581,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20588,], ["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",20581,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20588,], ["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,], @@ -1561,8 +1565,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",20581,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20588,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20588,], ["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,], @@ -1577,8 +1581,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",20581,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20588,], ["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,], @@ -1601,84 +1605,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",20581,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20581,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20581,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20588,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20588,], ["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",20581,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20588,], ["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",20581,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20588,], ["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",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20581,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20588,], ["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",20581,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20581,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20581,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20581,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20581,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20588,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20588,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20588,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20588,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20588,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20588,], ["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","",20581,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20588,], ["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",20581,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20581,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20581,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20581,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20588,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20588,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20588,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20588,], ["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",20581,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20588,], ["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",20581,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20588,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20581,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20581,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20581,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20581,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20581,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20581,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20581,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20581,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20581,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20581,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20581,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20581,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20581,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20588,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20588,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20588,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20588,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20588,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20588,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20588,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20588,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20588,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20588,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20588,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20588,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20588,], ["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",20581,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20581,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20588,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20588,], ["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",20581,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20588,], ["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,], From ef7d1a10bf1845a1202bdca9ce68c5b376970b59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 09:17:07 +0200 Subject: [PATCH 0429/1083] Merge pull request #6783 from element-hq/renovate/camera Update camera to v1.6.1 --- 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 a8158a638f..7f6830cc7f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ constraintlayout_compose = "1.1.1" lifecycle = "2.10.0" activity = "1.13.0" media3 = "1.10.0" -camera = "1.6.0" +camera = "1.6.1" work = "2.11.2" # Compose From 1c317d1ffd510c72abd5964d1e3e007cdc7b9378 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 09:21:46 +0200 Subject: [PATCH 0430/1083] Update dependency androidx.webkit:webkit to v1.16.0 (#6786) 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 7f6830cc7f..62f19b0ff3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -117,7 +117,7 @@ androidx_activity_activity = { module = "androidx.activity:activity", version.re androidx_activity_compose = { module = "androidx.activity:activity-compose", version.ref = "activity" } androidx_startup = "androidx.startup:startup-runtime:1.2.0" androidx_preference = "androidx.preference:preference:1.2.1" -androidx_webkit = "androidx.webkit:webkit:1.15.0" +androidx_webkit = "androidx.webkit:webkit:1.16.0" androidx_compose_bom = { module = "androidx.compose:compose-bom", version.ref = "compose_bom" } androidx_compose_material3 = { module = "androidx.compose.material3:material3", version = '1.5.0-alpha15' } From a89d37297f69ee518d4d0da9f9179423a5501d38 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 09:22:20 +0200 Subject: [PATCH 0431/1083] Update dependency com.google.firebase:firebase-bom to v34.13.0 (#6789) 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 62f19b0ff3..442d56c349 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -80,7 +80,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:34.12.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.13.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } From e6c3a8ff1d720dd97a513fa97aabbfd327ac8f15 Mon Sep 17 00:00:00 2001 From: cizra Date: Mon, 18 May 2026 08:06:47 +0000 Subject: [PATCH 0432/1083] Add MIDI playback (#6770) * Add MIDI playback * Implement PR suggestions --- gradle/libs.versions.toml | 1 + libraries/mediaviewer/impl/build.gradle.kts | 1 + .../impl/local/audio/MediaAudioView.kt | 2 +- .../impl/local/player/ExoPlayerFactory.kt | 15 +++++++++++++-- .../impl/local/video/MediaVideoView.kt | 2 +- settings.gradle.kts | 2 ++ 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 442d56c349..831cff5052 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -111,6 +111,7 @@ androidx_media3_ui = { module = "androidx.media3:media3-ui", version.ref = "medi androidx_media3_transformer = { module = "androidx.media3:media3-transformer", version.ref = "media3" } androidx_media3_effect = { module = "androidx.media3:media3-effect", version.ref = "media3" } androidx_media3_common = { module = "androidx.media3:media3-common", version.ref = "media3" } +androidx_media3_exoplayer_midi = { module = "androidx.media3:media3-exoplayer-midi", version.ref = "media3" } androidx_biometric = "androidx.biometric:biometric-ktx:1.4.0-alpha02" androidx_activity_activity = { module = "androidx.activity:activity", version.ref = "activity" } diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index cd1579d50d..f2dbf1aacf 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { implementation(libs.coroutines.core) implementation(libs.coil.compose) implementation(libs.androidx.media3.exoplayer) + implementation(libs.androidx.media3.exoplayer.midi) implementation(libs.androidx.media3.ui) implementation(libs.telephoto.zoomableimage) implementation(libs.vanniktech.blurhash) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt index cb9d6ae9c8..3ac578196d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/audio/MediaAudioView.kt @@ -88,7 +88,7 @@ fun MediaAudioView( modifier: Modifier = Modifier, isDisplayed: Boolean = true, ) { - val exoPlayer = rememberExoPlayer() + val exoPlayer = rememberExoPlayer(forAudioOnly = true) ExoPlayerMediaAudioView( isDisplayed = isDisplayed, localMediaViewState = localMediaViewState, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/ExoPlayerFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/ExoPlayerFactory.kt index d0043c657a..ccd628dbc5 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/ExoPlayerFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/ExoPlayerFactory.kt @@ -8,14 +8,18 @@ package io.element.android.libraries.mediaviewer.impl.local.player +import androidx.annotation.OptIn import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalInspectionMode +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.DefaultRenderersFactory import androidx.media3.exoplayer.ExoPlayer +@OptIn(UnstableApi::class) @Composable -fun rememberExoPlayer(): ExoPlayer { +fun rememberExoPlayer(forAudioOnly: Boolean): ExoPlayer { return if (LocalInspectionMode.current) { remember { ExoPlayerForPreview() @@ -23,7 +27,14 @@ fun rememberExoPlayer(): ExoPlayer { } else { val context = LocalContext.current remember { - ExoPlayer.Builder(context).build() + if (forAudioOnly) { + // Required for media3-exoplayer-midi to decode MIDI samples produced by DefaultExtractorsFactory. + val renderersFactory = DefaultRenderersFactory(context) + .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON) + ExoPlayer.Builder(context, renderersFactory).build() + } else { + ExoPlayer.Builder(context).build() + } } } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt index 082dc0571c..9d5e290857 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt @@ -73,7 +73,7 @@ fun MediaVideoView( audioFocus: AudioFocus?, modifier: Modifier = Modifier, ) { - val exoPlayer = rememberExoPlayer() + val exoPlayer = rememberExoPlayer(forAudioOnly = false) ExoPlayerMediaVideoView( isDisplayed = isDisplayed, localMediaViewState = localMediaViewState, diff --git a/settings.gradle.kts b/settings.gradle.kts index 8c7b608465..db03a32f18 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,6 +21,8 @@ dependencyResolutionManagement { url = uri("https://www.jitpack.io") content { includeModule("com.github.matrix-org", "matrix-analytics-events") + // Required transitively by androidx.media3:media3-exoplayer-midi for MIDI playback. + includeModule("com.github.philburk", "jsyn") } } google() From 2954174c5664416f9abd123d10627e5a662ed352 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 18 May 2026 10:29:14 +0200 Subject: [PATCH 0433/1083] Only load full media on media viewer when it's the visible item (#6794) * Only load full media on media viewer when it's the visible item * Allow cancelling ongoing media loading if scrolling fast --- .../impl/viewer/MediaViewerDataSource.kt | 22 ++++++++++++++++--- .../impl/viewer/MediaViewerEvent.kt | 1 + .../impl/viewer/MediaViewerPresenter.kt | 3 +++ .../impl/viewer/MediaViewerView.kt | 14 ++++++++---- .../impl/viewer/MediaViewerViewTest.kt | 16 ++++++++++++++ 5 files changed, 49 insertions(+), 7 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 eadbd544fc..01ec68a336 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 @@ -19,6 +19,7 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.extensions.mapCatchingExceptions import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaFile +import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint.MediaViewerMode import io.element.android.libraries.mediaviewer.api.local.LocalMedia @@ -40,6 +41,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext import timber.log.Timber +import java.util.concurrent.ConcurrentHashMap class MediaViewerDataSource( mode: MediaViewerMode, @@ -51,7 +53,7 @@ class MediaViewerDataSource( private val pagerKeysHandler: PagerKeysHandler, ) { // List of media files that are currently being loaded - private val mediaFiles: MutableList = mutableListOf() + private val mediaFiles: ConcurrentHashMap = ConcurrentHashMap() private val galleryMode = when (mode) { MediaViewerMode.SingleMedia, @@ -69,7 +71,7 @@ class MediaViewerDataSource( fun dispose() { Timber.d("Disposing MediaViewerDataSource, closing ${mediaFiles.size} media files") - mediaFiles.forEach { it.close() } + mediaFiles.values.forEach { it.close() } mediaFiles.clear() localMediaStates.clear() } @@ -163,6 +165,12 @@ class MediaViewerDataSource( } suspend fun loadMedia(data: MediaViewerPageData.MediaViewerData) { + val currentState = localMediaStates[data.mediaSource.safeUrl]?.value + // If the media is already loading or has been loaded successfully, do nothing + if (currentState?.isLoading() == true || currentState?.isSuccess() == true) { + return + } + Timber.d("loadMedia for ${data.eventId}") val localMediaState = localMediaStates.getOrPut(data.mediaSource.safeUrl) { mutableStateOf(AsyncData.Uninitialized) @@ -175,7 +183,7 @@ class MediaViewerDataSource( filename = data.mediaInfo.filename ) .onSuccess { mediaFile -> - mediaFiles.add(mediaFile) + mediaFiles[data.mediaSource] = mediaFile } .mapCatchingExceptions { mediaFile -> localMediaFactory.createFromMediaFile( @@ -190,4 +198,12 @@ class MediaViewerDataSource( localMediaState.value = AsyncData.Failure(it) } } + + fun cancelLoadingMedia(data: MediaViewerPageData.MediaViewerData) { + if (localMediaStates[data.mediaSource.safeUrl]?.value?.isLoading() == true) { + Timber.d("cancelLoadingMedia for ${data.eventId}") + mediaFiles.remove(data.mediaSource)?.close() + localMediaStates[data.mediaSource.safeUrl]?.value = AsyncData.Uninitialized + } + } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt index 1960b69e4c..53d287075d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvent.kt @@ -29,4 +29,5 @@ sealed interface MediaViewerEvent { data class Delete(val eventId: EventId) : MediaViewerEvent data class OnNavigateTo(val index: Int) : MediaViewerEvent data class LoadMore(val direction: Timeline.PaginationDirection) : MediaViewerEvent + data class CancelLoadingMedia(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent } 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 138c73c383..d40026dd37 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 @@ -100,6 +100,9 @@ class MediaViewerPresenter( is MediaViewerEvent.LoadMedia -> { coroutineScope.downloadMedia(data = event.data) } + is MediaViewerEvent.CancelLoadingMedia -> { + dataSource.cancelLoadingMedia(event.data) + } is MediaViewerEvent.ClearLoadingError -> { dataSource.clearLoadingError(event.data) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 8bc5088187..5e9ced7d77 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -52,6 +52,7 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.layout.onVisibilityChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource @@ -208,11 +209,16 @@ fun MediaViewerView( } is MediaViewerPageData.MediaViewerData -> { var bottomPaddingInPixels by remember { mutableIntStateOf(defaultBottomPaddingInPixels) } - LaunchedEffect(Unit) { - state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) - } Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .onVisibilityChanged(minDurationMs = 200L) { isVisible -> + if (isVisible) { + state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) + } else { + state.eventSink(MediaViewerEvent.CancelLoadingMedia(dataForPage)) + } + } + .fillMaxSize() ) { val isDisplayed = remember(pagerState.settledPage) { // This 'item provider' lambda will be called when the data source changes with an outdated `settlePage` value diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index fdd447c4a6..b426ca50ca 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -52,6 +52,10 @@ class MediaViewerViewTest { state = state, onBackClick = callback, ) + + // Wait for enough time for the onVisibilityChanged modifier to trigger + mainClock.advanceTimeBy(200) + pressBack() } eventsRecorder.assertList( @@ -110,6 +114,10 @@ class MediaViewerViewTest { eventSink = eventsRecorder ), ) + + // Wait for enough time for the onVisibilityChanged modifier to trigger + mainClock.advanceTimeBy(200) + val contentDescription = activity!!.getString(contentDescriptionRes) onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertList( @@ -241,6 +249,10 @@ class MediaViewerViewTest { eventSink = eventsRecorder ), ) + + // Wait for enough time for the onVisibilityChanged modifier to trigger + mainClock.advanceTimeBy(200) + clickOn(CommonStrings.action_retry) eventsRecorder.assertList( listOf( @@ -263,6 +275,10 @@ class MediaViewerViewTest { eventSink = eventsRecorder ), ) + + // Wait for enough time for the onVisibilityChanged modifier to trigger + mainClock.advanceTimeBy(200) + clickOn(CommonStrings.action_cancel) eventsRecorder.assertList( listOf( From 668edbc67917bdcb50061e4b628bf3aa67c744a3 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 18 May 2026 09:50:54 +0100 Subject: [PATCH 0434/1083] Fix scanning code from signed out device when using "Sign in with QR code" --- .../impl/auth/RustMatrixAuthenticationService.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 6cd30d4f70..837dcee5d9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -434,13 +434,23 @@ class RustMatrixAuthenticationService( qrCodeData: QrCodeData, ): Client { Timber.d("Creating client for QR Code login with simplified sliding sync") + // The 2025 versions of MSC4108 should always give us the baseUrl + val baseUrlOrServerName = qrCodeData.baseUrl() ?: qrCodeData.serverName() + + if (baseUrlOrServerName == null) { + // With the 2024 version of MSC4108 we treat the absence of serverName as meaning that + // the other device is not signed in. + Timber.e("The QR code is from a device that is not yet signed in") + throw HumanQrLoginException.OtherDeviceNotSignedIn() + } + return rustMatrixClientFactory .getBaseClientBuilder( sessionPaths = sessionPaths, passphrase = pendingPassphrase, slidingSyncType = ClientBuilderSlidingSync.Discovered, ) - .serverNameOrHomeserverUrl(qrCodeData.serverName()!!) + .serverNameOrHomeserverUrl(baseUrlOrServerName) .build() } From 9b1735e0e9d3e201a62a3f27d2a1483b7df44730 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 18 May 2026 11:26:58 +0200 Subject: [PATCH 0435/1083] Fix Maestro again after changes to the invite flow (#6796) * Fix Maestro: tap on confirmation for inviting unknown users to a room * Tap on back after inviting some user * Tap on back again * Confirm inviting someone to a DM * Make fix conditional --- .maestro/tests/roomList/createAndDeleteDM.yaml | 2 +- .maestro/tests/roomList/createAndDeleteRoom.yaml | 10 +++++++++- features/invitepeople/impl/build.gradle.kts | 1 + .../features/invitepeople/impl/InvitePeopleView.kt | 5 ++++- .../io/element/android/libraries/testtags/TestTags.kt | 2 ++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.maestro/tests/roomList/createAndDeleteDM.yaml b/.maestro/tests/roomList/createAndDeleteDM.yaml index a6279151ea..eed576c04f 100644 --- a/.maestro/tests/roomList/createAndDeleteDM.yaml +++ b/.maestro/tests/roomList/createAndDeleteDM.yaml @@ -7,7 +7,7 @@ appId: ${MAESTRO_APP_ID} - tapOn: text: ${MAESTRO_INVITEE1_MXID} index: 1 -- tapOn: "Send invite" +- tapOn: "Continue" - takeScreenshot: build/maestro/330-createAndDeleteDM - tapOn: "maestroelement2" - scroll diff --git a/.maestro/tests/roomList/createAndDeleteRoom.yaml b/.maestro/tests/roomList/createAndDeleteRoom.yaml index b53066ccd5..adf9d7cf29 100644 --- a/.maestro/tests/roomList/createAndDeleteRoom.yaml +++ b/.maestro/tests/roomList/createAndDeleteRoom.yaml @@ -24,8 +24,16 @@ appId: ${MAESTRO_APP_ID} text: ${MAESTRO_INVITEE2_MXID} index: 1 - tapOn: "Invite" +- runFlow: + when: + visible: 'Invite new contact to this room?' + commands: + - tapOn: + id: "confirm_invite_unknown" +# Close the keyboard if it's still open +- tapOn: "Back" +# Go back to the room details screen - tapOn: "Back" -- tapOn: "aRoomName" - scrollUntilVisible: direction: DOWN element: diff --git a/features/invitepeople/impl/build.gradle.kts b/features/invitepeople/impl/build.gradle.kts index 185497c25b..2ab2fcb4a3 100644 --- a/features/invitepeople/impl/build.gradle.kts +++ b/features/invitepeople/impl/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { implementation(projects.libraries.uiUtils) implementation(projects.libraries.androidutils) implementation(projects.libraries.usersearch.api) + implementation(projects.libraries.testtags) implementation(libs.coil.compose) implementation(projects.services.apperror.api) implementation(projects.libraries.featureflag.api) 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 b1f139f43c..3e9de70165 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,6 +23,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -54,6 +55,8 @@ import io.element.android.libraries.matrix.ui.components.MatrixUserRow import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getBestName +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.strings.simplePluralStringResource import kotlinx.collections.immutable.ImmutableList @@ -298,7 +301,7 @@ private fun InvitePeopleConfirmModal( text = stringResource(CommonStrings.action_remove), onClick = onRemove, leadingIcon = IconSource.Vector(CompoundIcons.Close()), - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f).testTag(TestTags.confirmInviteUnknown), ) Button( text = stringResource(CommonStrings.action_invite), diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index e564ddac41..4b3a0d6ffa 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -124,4 +124,6 @@ object TestTags { * */ val roomAddressField = TestTag("room_address_field") + + val confirmInviteUnknown = TestTag("confirm_invite_unknown") } From 458405b29f7a7ee36009957967b4f1f421292e76 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 18 May 2026 11:44:47 +0100 Subject: [PATCH 0436/1083] Iterate --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 837dcee5d9..336aa4d054 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -434,7 +434,8 @@ class RustMatrixAuthenticationService( qrCodeData: QrCodeData, ): Client { Timber.d("Creating client for QR Code login with simplified sliding sync") - // The 2025 versions of MSC4108 should always give us the baseUrl + // The 2025 version of MSC4108 will always give us the baseUrl and guarantees it to be a well-formed URL + // The 2024 version always has null baseUrl and uses the serverName instead, which can be null or malformed val baseUrlOrServerName = qrCodeData.baseUrl() ?: qrCodeData.serverName() if (baseUrlOrServerName == null) { @@ -444,6 +445,10 @@ class RustMatrixAuthenticationService( throw HumanQrLoginException.OtherDeviceNotSignedIn() } + if (baseUrlOrServerName.isBlank()) { + error("The QR code contains an empty base URL or server name, which is invalid") + } + return rustMatrixClientFactory .getBaseClientBuilder( sessionPaths = sessionPaths, From efa61f1d249261ea5d3c4fc39acf8a9e5169003e Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 18 May 2026 11:51:23 +0100 Subject: [PATCH 0437/1083] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 336aa4d054..40f4b90072 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -434,8 +434,9 @@ class RustMatrixAuthenticationService( qrCodeData: QrCodeData, ): Client { Timber.d("Creating client for QR Code login with simplified sliding sync") - // The 2025 version of MSC4108 will always give us the baseUrl and guarantees it to be a well-formed URL - // The 2024 version always has null baseUrl and uses the serverName instead, which can be null or malformed + // The 2025 version of MSC4108 provides baseUrl; the 2024 version has null baseUrl and uses + // serverName instead, which can be null or malformed. We only enforce presence/non-blankness + // here and rely on serverNameOrHomeserverUrl()/the Rust builder layer to validate structure. val baseUrlOrServerName = qrCodeData.baseUrl() ?: qrCodeData.serverName() if (baseUrlOrServerName == null) { From fb17fc7e8afb326647990c9a178b494cc0c63034 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 18 May 2026 11:52:51 +0100 Subject: [PATCH 0438/1083] Iterate --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 336aa4d054..dfc29ee6fe 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -446,7 +446,8 @@ class RustMatrixAuthenticationService( } if (baseUrlOrServerName.isBlank()) { - error("The QR code contains an empty base URL or server name, which is invalid") + Timber.e("The QR code contains an empty base URL or server name, which is invalid") + throw HumanQrLoginException.Unknown() } return rustMatrixClientFactory From 174a6cad0d8401e67d2516365a9a2efde06f009c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 18 May 2026 19:01:11 +0200 Subject: [PATCH 0439/1083] Create a new room when inviting people in a DM (#6756) * Create a new room when inviting people to a DM * Improve screenshot tests * Update screenshots --------- Co-authored-by: ElementBot --- .../android/appnav/LoggedInFlowNode.kt | 4 +- .../room/joined/JoinedRoomLoadedFlowNode.kt | 4 +- .../FakeJoinedRoomLoadedFlowNodeCallback.kt | 2 +- .../invitepeople/api/InvitePeopleEvents.kt | 1 + .../invitepeople/api/InvitePeopleState.kt | 2 + .../api/InvitePeopleStateProvider.kt | 4 ++ .../impl/DefaultInvitePeoplePresenter.kt | 48 ++++++++++++++++++- .../impl/DefaultInvitePeopleState.kt | 2 + .../impl/DefaultInvitePeopleStateProvider.kt | 3 ++ .../invitepeople/impl/InvitePeopleView.kt | 3 +- .../impl/DefaultInvitePeoplePresenterTest.kt | 48 +++++++++++++++++++ .../roomdetails/api/RoomDetailsEntryPoint.kt | 2 +- .../roomdetails/impl/RoomDetailsFlowNode.kt | 15 +++++- .../impl/RoomDetailsStateProvider.kt | 1 + .../roomdetails/impl/RoomDetailsView.kt | 34 +++++++++---- .../impl/invite/RoomInviteMembersNode.kt | 26 ++++++++++ .../impl/DefaultRoomDetailsEntryPointTest.kt | 2 +- .../roomdetails/impl/RoomDetailsViewTest.kt | 21 ++++++++ ...roomdetails.impl_RoomDetailsDark_18_en.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_en.png | 4 +- ....roomdetails.impl_RoomDetailsDark_6_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_en.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_en.png | 4 +- ...ures.roomdetails.impl_RoomDetails_6_en.png | 4 +- 26 files changed, 220 insertions(+), 34 deletions(-) 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 f2120038a6..47e5b7c5b3 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -382,9 +382,9 @@ class LoggedInFlowNode( } is NavTarget.Room -> { val joinedRoomCallback = object : JoinedRoomLoadedFlowNode.Callback { - override fun navigateToRoom(roomId: RoomId, serverNames: List) { + override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) { lifecycleScope.launch { - attachRoom(roomIdOrAlias = roomId.toRoomIdOrAlias(), serverNames = serverNames, clearBackstack = false) + attachRoom(roomIdOrAlias = roomId.toRoomIdOrAlias(), serverNames = serverNames, clearBackstack = clearBackStack) } } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index febd15e9c2..a8e5921973 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -82,7 +82,7 @@ class JoinedRoomLoadedFlowNode( plugins = plugins, ), DependencyInjectionGraphOwner { interface Callback : Plugin { - fun navigateToRoom(roomId: RoomId, serverNames: List) + fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean = false) fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun navigateToGlobalNotificationSettings() fun navigateToDeveloperSettings() @@ -150,7 +150,7 @@ class JoinedRoomLoadedFlowNode( callback.navigateToDeveloperSettings() } - override fun navigateToRoom(roomId: RoomId, serverNames: List) { + override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) { callback.navigateToRoom(roomId, serverNames) } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt b/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt index 2f17071870..b0669148dd 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt @@ -13,7 +13,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.tests.testutils.lambda.lambdaError class FakeJoinedRoomLoadedFlowNodeCallback : JoinedRoomLoadedFlowNode.Callback { - override fun navigateToRoom(roomId: RoomId, serverNames: List) = lambdaError() + override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) = lambdaError() override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() override fun navigateToGlobalNotificationSettings() = lambdaError() override fun navigateToDeveloperSettings() = lambdaError() diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleEvents.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleEvents.kt index 264aafd570..0422fac4f1 100644 --- a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleEvents.kt +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleEvents.kt @@ -11,4 +11,5 @@ package io.element.android.features.invitepeople.api interface InvitePeopleEvents { data object SendInvites : InvitePeopleEvents data object CloseSearch : InvitePeopleEvents + data object ClearError : InvitePeopleEvents } diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt index 9d342d191f..d14042cff7 100644 --- a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt @@ -9,10 +9,12 @@ package io.element.android.features.invitepeople.api import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId interface InvitePeopleState { val canInvite: Boolean val isSearchActive: Boolean val sendInvitesAction: AsyncAction + val createRoomFromDmAction: AsyncAction val eventSink: (InvitePeopleEvents) -> Unit } diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt index ce30bcc1f6..b233ed07ef 100644 --- a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.invitepeople.api import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId class InvitePeopleStateProvider : PreviewParameterProvider { override val values: Sequence @@ -25,6 +26,7 @@ private data class PreviewInvitePeopleState( override val canInvite: Boolean, override val isSearchActive: Boolean, override val sendInvitesAction: AsyncAction, + override val createRoomFromDmAction: AsyncAction, override val eventSink: (InvitePeopleEvents) -> Unit, ) : InvitePeopleState @@ -32,10 +34,12 @@ private fun aPreviewInvitePeopleState( canInvite: Boolean = false, isSearchActive: Boolean = false, sendInvitesAction: AsyncAction = AsyncAction.Uninitialized, + createRoomFromDmAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (InvitePeopleEvents) -> Unit = {}, ) = PreviewInvitePeopleState( canInvite = canInvite, isSearchActive = isSearchActive, sendInvitesAction = sendInvitesAction, + createRoomFromDmAction = createRoomFromDmAction, eventSink = eventSink ) diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt index b223d30617..44627daca3 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenter.kt @@ -38,12 +38,17 @@ import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters +import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.filterMembers +import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility +import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.recent.getRecentDirectRooms +import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.usersearch.api.UserRepository @@ -88,6 +93,7 @@ class DefaultInvitePeoplePresenter( var searchActive by rememberSaveable { mutableStateOf(false) } val showSearchLoader = rememberSaveable { mutableStateOf(false) } val sendInvitesAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } + val createRoomFromDmAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } val recentDirectRooms by produceState(emptyList(), roomMembers.value) { if (roomMembers.value.isSuccess()) { @@ -208,7 +214,13 @@ class DefaultInvitePeoplePresenter( ) } else { room.dataOrNull()?.let { - sessionCoroutineScope.sendInvites(it, selectedUsers.value, sendInvitesAction) + sessionCoroutineScope.launch { + if (it.isDm()) { + createRoomFromDm(it, selectedUsers.value, createRoomFromDmAction) + } else { + sendInvites(it, selectedUsers.value, sendInvitesAction) + } + } } } } @@ -216,6 +228,10 @@ class DefaultInvitePeoplePresenter( searchActive = false queryState.clearText() } + is InvitePeopleEvents.ClearError -> { + sendInvitesAction.value = AsyncAction.Uninitialized + createRoomFromDmAction.value = AsyncAction.Uninitialized + } } } @@ -228,6 +244,7 @@ class DefaultInvitePeoplePresenter( searchResults = searchResults.value, showSearchLoader = showSearchLoader.value, sendInvitesAction = sendInvitesAction.value, + createRoomFromDmAction = createRoomFromDmAction.value, suggestions = suggestions, eventSink = ::handleEvent, ) @@ -254,6 +271,35 @@ class DefaultInvitePeoplePresenter( } } + private fun CoroutineScope.createRoomFromDm( + currentRoom: JoinedRoom, + selectedUsers: List, + createRoomFromDmAction: MutableState>, + ) = launch { + createRoomFromDmAction.runUpdatingState { + val currentUsers = currentRoom.getMembers(limit = 100).getOrNull().orEmpty() + .filter { it.membership.isActive() } + val invitees = (currentUsers.map { it.userId } + selectedUsers.map { it.userId }) + .filter { it != matrixClient.sessionId } + .distinct() + matrixClient.createRoom( + CreateRoomParameters( + name = null, + topic = null, + isEncrypted = true, + isDirect = false, + visibility = RoomVisibility.Private, + preset = RoomPreset.PRIVATE_CHAT, + invite = invitees, + avatar = null, + joinRuleOverride = JoinRule.Invite, + historyVisibilityOverride = RoomHistoryVisibility.Invited, + isSpace = false, + ) + ) + } + } + @JvmName("toggleUserInSelectedUsers") private fun MutableState>.toggleUser(user: MatrixUser) { value = if (value.contains(user)) { diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt index 842bcf1148..46e5d9f1a5 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleState.kt @@ -14,6 +14,7 @@ import io.element.android.features.invitepeople.api.InvitePeopleState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList @@ -26,6 +27,7 @@ data class DefaultInvitePeopleState( val selectedUsers: ImmutableList, override val isSearchActive: Boolean, override val sendInvitesAction: AsyncAction, + override val createRoomFromDmAction: AsyncAction, val suggestions: ImmutableList, override val eventSink: (InvitePeopleEvents) -> Unit ) : InvitePeopleState diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt index 45b47fbc6e..93a6e03bd3 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeopleStateProvider.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.designsystem.preview.USER_NAME_CAROL import io.element.android.libraries.designsystem.preview.USER_NAME_EVE import io.element.android.libraries.designsystem.preview.USER_NAME_JUSTIN import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.matrix.api.core.RoomId 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 @@ -119,6 +120,7 @@ private fun aDefaultInvitePeopleState( isSearchActive: Boolean = false, showSearchLoader: Boolean = false, sendInvitesAction: AsyncAction = AsyncAction.Uninitialized, + createRoomFromDmAction: AsyncAction = AsyncAction.Uninitialized, suggestions: List = aMatrixUserList() .take(5) .map { user -> anInvitableUser(matrixUser = user, isSelected = user in selectedUsers) }, @@ -132,6 +134,7 @@ private fun aDefaultInvitePeopleState( isSearchActive = isSearchActive, showSearchLoader = showSearchLoader, sendInvitesAction = sendInvitesAction, + createRoomFromDmAction = createRoomFromDmAction, suggestions = suggestions.toImmutableList(), eventSink = {}, ) 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 3e9de70165..2bbd64c977 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 @@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -105,7 +106,7 @@ private fun InvitePeopleContentView( } InvitePeopleSearchBar( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.imePadding().fillMaxWidth(), queryState = state.searchQuery, showLoader = state.showSearchLoader, selectedUsers = state.selectedUsers, diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index 5d5a533bb6..4e141b2c4d 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -831,6 +831,54 @@ internal class DefaultInvitePeoplePresenterTest { } } + @Test + fun `present - inviting someone to a DM creates a new room`() = runTest { + val alice = aMatrixUser("@alice:example.com") + + val matrixClient = FakeMatrixClient( + encryptionService = FakeEncryptionService( + getUserIdentityResult = lambdaRecorder { userId: UserId -> + Result.success(IdentityState.Pinned) + } + ) + ) + val presenter = createDefaultInvitePeoplePresenter( + coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), + matrixClient = matrixClient, + joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + initialRoomInfo = aRoomInfo(isDm = true), + getMembersResult = { Result.success(listOf(aRoomMember(userId = alice.userId, membership = RoomMembershipState.JOIN))) }, + ) + ) + ) + presenter.test { + val initialState = awaitItem() + skipItems(1) + + // We want to add a new user to a DM + initialState.eventSink(DefaultInvitePeopleEvents.ToggleUser(alice)) + + // And we send the invites + initialState.eventSink(InvitePeopleEvents.SendInvites) + + skipItems(1) + + awaitItemAsDefault().run { + assertThat(canInvite).isTrue() + assertThat(sendInvitesAction.isUninitialized()).isTrue() + // Inviting to a DM should trigger the creation of a new room + assertThat(createRoomFromDmAction.isLoading()).isTrue() + } + + awaitItemAsDefault().run { + assertThat(sendInvitesAction.isUninitialized()).isTrue() + // Once the room is created, the action should be successful + assertThat(createRoomFromDmAction.isSuccess()).isTrue() + } + } + } + private suspend fun FakeUserRepository.emitStateWithUsers( users: List, isSearching: Boolean = false diff --git a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt index 07e10c65ef..bbaac0cbc1 100644 --- a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt +++ b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt @@ -40,7 +40,7 @@ interface RoomDetailsEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun navigateToGlobalNotificationSettings() fun navigateToDeveloperSettings() - fun navigateToRoom(roomId: RoomId, serverNames: List) + fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean = false) fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun startForwardEventFlow(eventId: EventId, fromPinnedEvents: Boolean) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index 818287ab68..4cf5056b4e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -263,7 +263,20 @@ class RoomDetailsFlowNode( } NavTarget.InviteMembers -> { - createNode(buildContext) + val callback = object : RoomInviteMembersNode.Callback { + override fun openCreatedRoom(roomId: RoomId) { + navigateUp() + room.roomCoroutineScope.launch { + callback.navigateToRoom( + roomId = roomId, + serverNames = emptyList(), + // Remove the invite screen from the backstack to avoid navigating back to it after the new room has been created + clearBackStack = true, + ) + } + } + } + createNode(buildContext, plugins = listOf(callback)) } is NavTarget.RoomNotificationSettings -> { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index ad627d8677..b569527d9c 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -180,6 +180,7 @@ fun aDmRoomDetailsState( roomName = roomName, isPublic = false, isEncrypted = isEncrypted, + canInvite = true, roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)), roomMemberDetailsState = aUserProfileState( isBlocked = AsyncData.Success(isDmMemberIgnored), diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index e877c24554..cf5265b145 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -208,8 +208,15 @@ fun RoomDetailsView( onClick = onSecurityAndPrivacyClick ) } + } - state.roomMemberDetailsState?.let { dmMemberDetails -> + state.roomMemberDetailsState?.let { dmMemberDetails -> + if (state.canInvite) { + PreferenceCategory { + InviteItem(onClick = invitePeople) + } + } + PreferenceCategory { ProfileItem( verificationState = dmMemberDetails.verificationState, onClick = { onProfileClick(dmMemberDetails.userId) } @@ -374,14 +381,14 @@ private fun MainActionsSection( onClick = { onCall(CallIntent.VIDEO) }, ) } + if (state.canInvite && state.roomType !is RoomDetailsType.Dm) { + MainActionButton( + title = stringResource(CommonStrings.action_invite), + imageVector = CompoundIcons.UserAdd(), + onClick = onInvitePeople, + ) + } if (state.roomType is RoomDetailsType.Room) { - if (state.canInvite) { - MainActionButton( - title = stringResource(CommonStrings.action_invite), - imageVector = CompoundIcons.UserAdd(), - onClick = onInvitePeople, - ) - } // Share CTA should be hidden for DMs MainActionButton( title = stringResource(CommonStrings.action_share), @@ -693,6 +700,17 @@ private fun MembersItem( ) } +@Composable +private fun InviteItem( + onClick: () -> Unit, +) { + ListItem( + headlineContent = { Text(stringResource(R.string.screen_room_details_invite_title)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserAdd())), + onClick = onClick, + ) +} + @Composable private fun PinnedMessagesItem( pinnedMessagesCount: Int?, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt index ea0ed1bb72..3919817313 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersNode.kt @@ -11,6 +11,7 @@ package io.element.android.features.roomdetails.impl.invite import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node @@ -19,10 +20,16 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.annotations.ContributesNode +import io.element.android.features.invitepeople.api.InvitePeopleEvents import io.element.android.features.invitepeople.api.InvitePeoplePresenter import io.element.android.features.invitepeople.api.InvitePeopleRenderer +import io.element.android.libraries.architecture.callback +import io.element.android.libraries.designsystem.components.ProgressDialog +import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.api.AnalyticsService @ContributesNode(RoomScope::class) @@ -35,6 +42,10 @@ class RoomInviteMembersNode( room: JoinedRoom, invitePeoplePresenterFactory: InvitePeoplePresenter.Factory, ) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun openCreatedRoom(roomId: RoomId) + } + init { lifecycle.subscribe( onResume = { @@ -48,6 +59,8 @@ class RoomInviteMembersNode( roomId = room.roomId, ) + private val callback = plugins.callback() + @Composable override fun View(modifier: Modifier) { val state = invitePeoplePresenter.present() @@ -59,6 +72,19 @@ class RoomInviteMembersNode( } } + AsyncActionView( + async = state.createRoomFromDmAction, + onSuccess = { roomId -> + callback.openCreatedRoom(roomId) + }, + progressDialog = { + ProgressDialog(text = stringResource(CommonStrings.common_creating_room)) + }, + onErrorDismiss = { + state.eventSink(InvitePeopleEvents.ClearError) + } + ) + RoomInviteMembersView( state = state, modifier = modifier, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt index bcf25b2aac..597cc82f7d 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -70,7 +70,7 @@ class DefaultRoomDetailsEntryPointTest { val callback = object : RoomDetailsEntryPoint.Callback { override fun navigateToGlobalNotificationSettings() = lambdaError() override fun navigateToDeveloperSettings() = lambdaError() - override fun navigateToRoom(roomId: RoomId, serverNames: List) = lambdaError() + override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) = lambdaError() override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() override fun startForwardEventFlow(eventId: EventId, fromPinnedEvents: Boolean) = lambdaError() } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 5fe0130c73..9494df5d44 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -13,6 +13,8 @@ package io.element.android.features.roomdetails.impl import androidx.activity.ComponentActivity import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onLast import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick @@ -339,6 +341,25 @@ class RoomDetailsViewTest { clickOn(R.string.screen_room_details_profile_row_title) } } + + @Config(qualifiers = "h1024dp") + @Test + fun `click on invite invokes the expected callback`() = runAndroidComposeUiTest { + ensureCalledOnce { callback -> + setRoomDetailView( + state = aRoomDetailsState( + eventSink = EventsRecorder(expectEvents = false), + roomType = RoomDetailsType.Dm( + aDmRoomMember(userId = UserId("@other:local.org")), + ), + roomMemberDetailsState = aUserProfileState(userId = A_USER_ID), + canInvite = true, + ), + invitePeople = callback, + ) + onAllNodesWithText(activity!!.getString(R.string.screen_room_details_invite_title)).onLast().performClick() + } + } } private fun AndroidComposeUiTest.setRoomDetailView( diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index ddcd78552d..9f56dab8f3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7b9375965be172b7a1a6b00be38c66dc5f73d7d76f6b07fd1cb8defbadae840 -size 41554 +oid sha256:2f239cb428d2e4cffa86e8d8397904af0c0c5e621585f31bcf3135cdd2c81a40 +size 40541 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 669af01562..81bb7961e9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7890cc2fc8e722bfdee5e1c0cdda335c386a2e70a918b710a44a788457dd8497 -size 41507 +oid sha256:3bcc557108fc16a1f63d22b3512d271d30dccc801838607e78921baf9ba490c0 +size 40509 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index 31daf341c2..2d3d2f0a74 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:105399c3ca12de9e911ccf7b4aaebe87bffeba45b1740d067b5b8e67c5647952 -size 41196 +oid sha256:76f63f6c98318762a574d7fb04c8e23ad8312b1fc9adc404669ac6d9e2c42097 +size 40127 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png index 3309d53220..bca90757f7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5da1fef365731946e08a38250187fe6f3108aff466d7771863c0ba52fb5b7728 -size 42254 +oid sha256:3063251e98ea6e797e5178cb954d99e71fc1422df19c24a59b1395531380e941 +size 41113 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index 74405c8661..3151e8d088 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fef392cb892bf6dc746ed59f1279bf9558536ef439715d1834bd88260739949d -size 42441 +oid sha256:6fb58a8db96c0e76d5a0e8c8d2a38ae206e3dade479bd924fd404902c8e69b42 +size 41322 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index dd6c6a993d..e213e801f3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9b7c26c5f0638dbe7731e239fc16bb2ba4330986af7218688a3a12ede2bfd9d -size 42313 +oid sha256:5030731135dec08034e1992499caa251aae8039cebafb09210fc83d622b06bd9 +size 41257 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index e6cae695cf..5c16501c76 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d6a5102a9dd44a6a15dc6b40ec422a115a302506a2b3808a1df84ca34cb323e -size 41972 +oid sha256:e54b946de1128b1109ece7553e73d7676199edc45e7f275014c37503336d302e +size 40862 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png index a1947b9c2c..55ab231ede 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1538aa1f1313df1f6cbbc0ed7ef92d264c85b7de0080492a7cba19bbd235131d -size 43100 +oid sha256:4f3df6d78498d2b390cf926fb1111fdfa0f38ba5dd9e023b9bd2af42c3951511 +size 41921 From 828337b343ee8493663378b7c0e2707db01590e7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 18 May 2026 20:25:36 +0200 Subject: [PATCH 0440/1083] Remove LiveLocationSharing feature flag --- .../impl/share/ShareLocationPresenter.kt | 8 +---- .../DefaultShareLocationEntryPointTest.kt | 2 -- .../impl/share/ShareLocationPresenterTest.kt | 21 +------------ .../advanced/AdvancedSettingsPresenter.kt | 14 +-------- .../advanced/AdvancedSettingsPresenterTest.kt | 30 ++----------------- .../libraries/featureflag/api/FeatureFlags.kt | 7 ----- 6 files changed, 5 insertions(+), 77 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index 6c0d2120bc..a1e45cfea2 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -40,8 +40,6 @@ import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.extensions.flatMap import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.dateformatter.api.DurationFormatter -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom @@ -66,7 +64,6 @@ class ShareLocationPresenter( private val messageComposerContext: MessageComposerContext, private val locationActions: LocationActions, private val buildMeta: BuildMeta, - private val featureFlagService: FeatureFlagService, private val client: MatrixClient, private val durationFormatter: DurationFormatter, private val liveLocationShareManager: ActiveLiveLocationShareManager, @@ -83,9 +80,6 @@ class ShareLocationPresenter( override fun present(): ShareLocationState { val permissionsState: PermissionsState = permissionsPresenter.present() var trackUserPosition: Boolean by remember { mutableStateOf(permissionsState.isAnyGranted && locationActions.isLocationEnabled()) } - val isLiveLocationSharingEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.LiveLocationSharing) - }.collectAsState(false) val appName by remember { derivedStateOf { buildMeta.applicationName } } var dialogState: ShareLocationState.Dialog by remember { mutableStateOf(ShareLocationState.Dialog.None) @@ -171,7 +165,7 @@ class ShareLocationPresenter( dialogState = dialogState, trackUserLocation = trackUserPosition, hasLocationPermission = permissionsState.isAnyGranted, - canShareLiveLocation = isLiveLocationSharingEnabled && timelineMode.canShareLiveLocation(), + canShareLiveLocation = timelineMode.canShareLiveLocation(), appName = appName, startLiveLocationAction = startLiveLocationAction.value, eventSink = ::handleEvent, diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt index 9b1a14fb51..6f20e296d9 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt @@ -17,7 +17,6 @@ import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta @@ -50,7 +49,6 @@ class DefaultShareLocationEntryPointTest { messageComposerContext = FakeMessageComposerContext(), locationActions = FakeLocationActions(), buildMeta = aBuildMeta(), - featureFlagService = FakeFeatureFlagService(), client = FakeMatrixClient(), durationFormatter = FakeDurationFormatter(), liveLocationShareManager = FakeActiveLiveLocationShareManager(), diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index dff5f05ee9..1bc4fce586 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -29,8 +29,6 @@ import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId @@ -77,7 +75,6 @@ class ShareLocationPresenterTest { private val fakeMessageComposerContext = FakeMessageComposerContext() private val fakeLocationActions = FakeLocationActions() private val fakeBuildMeta = aBuildMeta(applicationName = "app name") - private val fakeFeatureFlagService = FakeFeatureFlagService() private val fakeMatrixClient = FakeMatrixClient(sessionId = A_USER_ID) private val durationFormatter = FakeDurationFormatter() @@ -96,7 +93,6 @@ class ShareLocationPresenterTest { messageComposerContext = fakeMessageComposerContext, locationActions = locationActions, buildMeta = fakeBuildMeta, - featureFlagService = fakeFeatureFlagService, client = fakeMatrixClient, durationFormatter = durationFormatter, liveLocationShareManager = liveLocationShareManager, @@ -658,21 +654,7 @@ class ShareLocationPresenterTest { } @Test - fun `canShareLiveLocation is false when the feature is disabled`() = runTest { - fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, false) - val shareLocationPresenter = createShareLocationPresenter( - timelineMode = Timeline.Mode.Live, - ) - shareLocationPresenter.test { - skipItems(1) - val state = awaitItem() - assertThat(state.canShareLiveLocation).isFalse() - } - } - - @Test - fun `canShareLiveLocation is true when the feature is enabled`() = runTest { - fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + fun `canShareLiveLocation is true in live timeline`() = runTest { val shareLocationPresenter = createShareLocationPresenter( timelineMode = Timeline.Mode.Live, ) @@ -685,7 +667,6 @@ class ShareLocationPresenterTest { @Test fun `canShareLiveLocation is false in thread timeline`() = runTest { - fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) val shareLocationPresenter = createShareLocationPresenter( timelineMode = Timeline.Mode.Thread(A_THREAD_ID), ) 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 3d1fb3b0c7..45c136ab62 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt @@ -25,11 +25,8 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch @Inject @@ -56,17 +53,8 @@ class AdvancedSettingsPresenter( appPreferencesStore.getThemeFlow().mapToTheme(isBlackThemeAllowed) }.collectAsState(initial = Theme.System) - @OptIn(ExperimentalCoroutinesApi::class) val liveLocationMinimumDistanceUpdate by produceState(null) { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.LiveLocationSharing) - .flatMapLatest { isEnabled -> - if (isEnabled) { - appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() - } else { - emptyFlow() - } - } - .collect { value = it } + appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow().collect { value = it } } val mediaPreviewConfigState = mediaPreviewConfigStateStore.state() 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 27d91bd8de..25d7c01778 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 @@ -210,35 +210,12 @@ class AdvancedSettingsPresenterTest { } } - @Test - fun `present - live location minimum distance is null when feature is disabled`() = runTest { - val appPreferencesStore = InMemoryAppPreferencesStore( - liveLocationMinimumDistanceUpdate = 50, - ) - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.LiveLocationSharing, false) - } - val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) - - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - skipItems(1) - with(awaitItem()) { - assertThat(liveLocationMinimumDistanceUpdate).isNull() - } - } - } - @Test fun `present - exposes live location minimum distance from app preferences`() = runTest { val appPreferencesStore = InMemoryAppPreferencesStore( liveLocationMinimumDistanceUpdate = 50, ) - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) - } - val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -256,10 +233,7 @@ class AdvancedSettingsPresenterTest { val appPreferencesStore = InMemoryAppPreferencesStore( liveLocationMinimumDistanceUpdate = 10, ) - val featureFlagService = FakeFeatureFlagService().apply { - setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) - } - val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore) moleculeFlow(RecompositionMode.Immediate) { presenter.present() 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 ed8916c8b4..097df99800 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 @@ -100,13 +100,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - LiveLocationSharing( - key = "feature.liveLocationSharing", - title = "Live location sharing", - description = "Allow sharing live location in rooms.", - defaultValue = { false }, - isFinished = false, - ), ValidateNetworkWhenSchedulingNotificationFetching( key = "feature.validate_network_when_scheduling_notification_fetching", title = "Validate internet connectivity when scheduling notification fetching", From 4e3853a7188fa53382dee4590f45169e3f115e8c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 18 May 2026 22:18:52 +0200 Subject: [PATCH 0441/1083] Attempt to fix room list item duplicates at midnight (#6793) * Attempt to fix room list item duplicates at midnight This seems to happen because of a race condition between `RoomListDataSource.observeDateTimeChanges` and `RoomListDataSource.replaceWith` being called at almost the same time and the first one using the newly received items from observing the timeline items but not updating the cache which will be later reused by `replaceWith`, containing incorrect indices --- .../impl/datasource/RoomListDataSource.kt | 5 +- .../impl/datasource/RoomListDataSourceTest.kt | 63 +++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt index 3ff4339bb2..56b2c1ade4 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt @@ -83,8 +83,8 @@ class RoomListDataSource( val loadingState = roomList.loadingState - fun launchIn(coroutineScope: CoroutineScope) { - roomList + fun launchIn(coroutineScope: CoroutineScope): Job { + return roomList .summaries .onEach { roomSummaries -> replaceWith(roomSummaries) @@ -212,6 +212,7 @@ class RoomListDataSource( private suspend fun rebuildAllRoomSummaries() { lock.withLock { roomList.summaries.replayCache.firstOrNull()?.let { roomSummaries -> + diffCacheUpdater.updateWith(roomSummaries) buildAndEmitAllRooms(roomSummaries, useCache = false) } } diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt index ace1ef2eaa..6df5e05df5 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSourceTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.matrix.test.A_ROOM_ID_3 import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.roomlist.FakeDynamicRoomList @@ -197,6 +198,68 @@ class RoomListDataSourceTest { } } + @Test + fun `regression test for race with DateTimeObserver and new items`() = runTest { + val roomList = FakeDynamicRoomList(summaries = MutableStateFlow(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))) + val roomListService = FakeRoomListService( + createRoomListLambda = { roomList } + ).apply { + postState(RoomListService.State.Running) + } + val dateTimeObserver = FakeDateTimeObserver() + var dateFormatterResult = "Today" + val dateFormatter = FakeDateFormatter({ _, _, _ -> dateFormatterResult }) + val roomListDataSource = createRoomListDataSource( + roomListService = roomListService, + roomListRoomSummaryFactory = aRoomListRoomSummaryFactory( + dateFormatter = dateFormatter, + ), + dateTimeObserver = dateTimeObserver, + ) + roomListDataSource.roomSummariesFlow.test { + // Observe room list items changes + val job = roomListDataSource.launchIn(backgroundScope) + // Get the initial room list + val initialRoomList = awaitItem() + assertThat(initialRoomList).hasSize(2) + assertThat(initialRoomList[0].roomId).isEqualTo(A_ROOM_ID) + assertThat(initialRoomList[0].timestamp).isEqualTo(dateFormatterResult) + assertThat(initialRoomList[1].roomId).isEqualTo(A_ROOM_ID_2) + assertThat(initialRoomList[1].timestamp).isEqualTo(dateFormatterResult) + + // Stop processing room list updates so we can force a race condition with the date time observer updates + job.cancel() + + // Trigger a date change and a new item at the same time + dateFormatterResult = "Yesterday" + roomList.summaries.tryEmit(listOf(aRoomSummary(roomId = A_ROOM_ID), aRoomSummary(roomId = A_ROOM_ID_3), aRoomSummary(roomId = A_ROOM_ID_2))) + dateTimeObserver.given(DateTimeObserver.Event.DateChanged(Instant.MIN, Instant.now())) + + // The race condition would have caused the cache indices to be corrupted and only 2 items would be emitted + val rebuiltRoomList = awaitItem() + assertThat(rebuiltRoomList).hasSize(3) + assertThat(rebuiltRoomList[0].roomId).isEqualTo(A_ROOM_ID) + assertThat(rebuiltRoomList[0].timestamp).isEqualTo(dateFormatterResult) + assertThat(rebuiltRoomList[1].roomId).isEqualTo(A_ROOM_ID_3) + assertThat(rebuiltRoomList[1].timestamp).isEqualTo(dateFormatterResult) + assertThat(rebuiltRoomList[2].roomId).isEqualTo(A_ROOM_ID_2) + assertThat(rebuiltRoomList[2].timestamp).isEqualTo(dateFormatterResult) + + // Restart processing room list updates + roomListDataSource.launchIn(backgroundScope) + + // Check there is a new list and it's not the same as the previous one + val newRoomList = awaitItem() + assertThat(newRoomList).hasSize(3) + assertThat(newRoomList[0].roomId).isEqualTo(A_ROOM_ID) + assertThat(newRoomList[0].timestamp).isEqualTo(dateFormatterResult) + assertThat(newRoomList[1].roomId).isEqualTo(A_ROOM_ID_3) + assertThat(newRoomList[1].timestamp).isEqualTo(dateFormatterResult) + assertThat(newRoomList[2].roomId).isEqualTo(A_ROOM_ID_2) + assertThat(newRoomList[2].timestamp).isEqualTo(dateFormatterResult) + } + } + private fun TestScope.createRoomListDataSource( roomListService: FakeRoomListService = FakeRoomListService(), roomListRoomSummaryFactory: RoomListRoomSummaryFactory = aRoomListRoomSummaryFactory(), From e3d1a811d5862639b5c3f2c81fdc79dddd4710b4 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 18 May 2026 22:19:22 +0200 Subject: [PATCH 0442/1083] Disable biometric unlock when we disable pin code unlock (#6781) * Disable biometric unlock when we disable pin code unlock --- .../lockscreen/impl/DefaultLockScreenService.kt | 3 ++- .../impl/biometric/BiometricAuthenticatorManager.kt | 5 +++++ .../biometric/DefaultBiometricAuthenticatorManager.kt | 10 ++++++---- .../impl/settings/LockScreenSettingsPresenter.kt | 1 + .../biometric/FakeBiometricAuthenticatorManager.kt | 5 +++++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt index 7ac42feda6..49d299b3f9 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenService.kt @@ -43,7 +43,7 @@ class DefaultLockScreenService( private val coroutineScope: CoroutineScope, private val sessionObserver: SessionObserver, private val appForegroundStateService: AppForegroundStateService, - biometricAuthenticatorManager: BiometricAuthenticatorManager, + private val biometricAuthenticatorManager: BiometricAuthenticatorManager, ) : LockScreenService { private val _lockState = MutableStateFlow(LockScreenLockState.Unlocked) override val lockState: StateFlow = _lockState @@ -81,6 +81,7 @@ class DefaultLockScreenService( override suspend fun onSessionDeleted(userId: String, wasLastSession: Boolean) { if (wasLastSession) { pinCodeManager.deletePinCode() + biometricAuthenticatorManager.disable() } } }) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticatorManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticatorManager.kt index 9917845725..2ea0ed7d05 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticatorManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticatorManager.kt @@ -24,6 +24,11 @@ interface BiometricAuthenticatorManager { fun addCallback(callback: BiometricAuthenticator.Callback) fun removeCallback(callback: BiometricAuthenticator.Callback) + /** + * Disable using the biometric unlock feature and remove any data associated with it. + */ + suspend fun disable() + /** * Remember a biometric authenticator ready for unlocking the app. */ diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/DefaultBiometricAuthenticatorManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/DefaultBiometricAuthenticatorManager.kt index 8bb044fd06..117323ec0a 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/DefaultBiometricAuthenticatorManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/DefaultBiometricAuthenticatorManager.kt @@ -80,10 +80,7 @@ class DefaultBiometricAuthenticatorManager( private val internalCallback = object : DefaultBiometricUnlockCallback() { override fun onBiometricSetupError() { - coroutineScope.launch { - lockScreenStore.setIsBiometricUnlockAllowed(false) - secretKeyRepository.deleteKey(SECRET_KEY_ALIAS) - } + coroutineScope.launch { disable() } } } @@ -120,6 +117,11 @@ class DefaultBiometricAuthenticatorManager( ) } + override suspend fun disable() { + lockScreenStore.setIsBiometricUnlockAllowed(false) + secretKeyRepository.deleteKey(SECRET_KEY_ALIAS) + } + @Composable private fun rememberBiometricAuthenticator( isAvailable: Boolean, diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt index 83a0253f39..17a0213f63 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt @@ -59,6 +59,7 @@ class LockScreenSettingsPresenter( if (showRemovePinConfirmation) { showRemovePinConfirmation = false pinCodeManager.deletePinCode() + biometricAuthenticatorManager.disable() } } } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticatorManager.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticatorManager.kt index 9e9b892582..0ae8552334 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticatorManager.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticatorManager.kt @@ -15,6 +15,7 @@ class FakeBiometricAuthenticatorManager( override var isDeviceSecured: Boolean = true, override var hasAvailableAuthenticator: Boolean = false, private val createBiometricAuthenticator: () -> BiometricAuthenticator = { FakeBiometricAuthenticator() }, + private val disableLambda: suspend () -> Unit = { }, ) : BiometricAuthenticatorManager { override fun addCallback(callback: BiometricAuthenticator.Callback) { // no-op @@ -37,4 +38,8 @@ class FakeBiometricAuthenticatorManager( createBiometricAuthenticator() } } + + override suspend fun disable() { + disableLambda() + } } From c94ba068ed28b47ac7b0fa3636c7e9bb56404bb6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 07:18:13 +0000 Subject: [PATCH 0443/1083] Update dependencyAnalysis to v3.11.0 --- 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 831cff5052..8be68a0066 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.10.0" +dependencyAnalysis = "3.11.0" # DI metro = "1.0.0" From 2f406eaf413bec0ea5e12b3534431871a4fe2f4a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 09:20:06 +0200 Subject: [PATCH 0444/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.18 (#6805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency org.matrix.rustcomponents:sdk-android to v26.05.18 * Fix breaking API changes --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- gradle/libs.versions.toml | 2 +- .../matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 831cff5052..a55a8b2adb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -179,7 +179,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.13" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.18" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt index c0ecc53d4f..56cc5b9a1f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt @@ -40,7 +40,7 @@ class FakeFfiSpaceRoomList( return paginationStateResult() } - override fun rooms(): List { + override suspend fun rooms(): List { return roomsResult() } @@ -53,7 +53,7 @@ class FakeFfiSpaceRoomList( spaceRoomListPaginationStateListener?.onUpdate(state) } - override fun subscribeToRoomUpdate(listener: SpaceRoomListEntriesListener): TaskHandle { + override suspend fun subscribeToRoomUpdate(listener: SpaceRoomListEntriesListener): TaskHandle { spaceRoomListEntriesListener = listener return FakeFfiTaskHandle() } From f373c73e604392e2b9df68ae662462d60dbf7d28 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 14:43:49 +0200 Subject: [PATCH 0445/1083] Setting version for the release 26.05.2 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index a3de4327b4..5e9a8694be 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 5 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 1 +private const val versionReleaseNumber = 2 object Versions { /** From d8793ca8f610e0247d39b987382a1e8ccd31d43e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 14:44:02 +0200 Subject: [PATCH 0446/1083] Adding fastlane file for version 26.05.2 --- fastlane/metadata/android/en-US/changelogs/202605020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202605020.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202605020.txt b/fastlane/metadata/android/en-US/changelogs/202605020.txt new file mode 100644 index 0000000000..a4b397f1bb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202605020.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 5af57906b51cc2a7423703ecb2e33be4a0cccdc3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 15:23:47 +0200 Subject: [PATCH 0447/1083] Changelog for version 26.05.2 --- CHANGES.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 19665d542c..9775c2fea5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,42 @@ +Changes in Element X v26.05.2 +============================= + + + +## What's Changed +### ✨ Features +* Remove SignInWithClassic FeatureFlag to enable the feature. by @bmarty in https://github.com/element-hq/element-x-android/pull/6698 +* Create a new room when inviting people in a DM by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6756 +* Remove LiveLocationSharing feature flag by @ganfra in https://github.com/element-hq/element-x-android/pull/6811 +### 🙌 Improvements +* Disable biometric unlock when we disable pin code unlock by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6781 +### 🐛 Bugfixes +* Fix room list duplicate-detection telemetry crashing before it can report by @jennaharris7 in https://github.com/element-hq/element-x-android/pull/6791 +* Only load full media on media viewer when it's the visible item by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6794 +* Attempt to fix room list item duplicates at midnight by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6793 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6798 +### 🧱 Build +* Fix Maestro again after changes to the invite flow by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6796 +* Renovate: Keep Guava on the Android variant and ignore jre-only upgrades by @bmarty in https://github.com/element-hq/element-x-android/pull/6776 +### Dependency upgrades +* Update dependency androidx.compose:compose-bom to v2026.05.00 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6784 +* Update dependency io.sentry:sentry-android to v8.41.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6787 +* Update kotlin by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6790 +* Update camera to v1.6.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6783 +* Update dependency androidx.webkit:webkit to v1.16.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6786 +* Update dependency com.google.firebase:firebase-bom to v34.13.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6789 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.18 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6805 +### Others +* Add MIDI playback by @cizra in https://github.com/element-hq/element-x-android/pull/6770 +* Show error message when using "Sign in with QR code" with a QR from a device that is also not signed in by @hughns in https://github.com/element-hq/element-x-android/pull/6802 + +## New Contributors +* @jennaharris7 made their first contribution in https://github.com/element-hq/element-x-android/pull/6791 +* @cizra made their first contribution in https://github.com/element-hq/element-x-android/pull/6770 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.05.1...v26.05.2 + Changes in Element X v26.05.1 ============================= From 882d5577a7d36649cf5747a0b867977109485d97 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 18:06:11 +0200 Subject: [PATCH 0448/1083] Add "Mark as read", "Mark as unread" in room settings. #6398 --- features/roomdetails/impl/build.gradle.kts | 1 + .../roomdetails/impl/RoomDetailsEvent.kt | 2 + .../roomdetails/impl/RoomDetailsPresenter.kt | 38 +++++++++++++++++ .../roomdetails/impl/RoomDetailsState.kt | 1 + .../impl/RoomDetailsStateProvider.kt | 4 +- .../roomdetails/impl/RoomDetailsView.kt | 41 +++++++++++++++++++ .../impl/src/main/res/values/localazy.xml | 2 + tools/localazy/config.json | 1 + 8 files changed, 89 insertions(+), 1 deletion(-) diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index 2765a95a1e..23b23a3e62 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(projects.libraries.featureflag.api) implementation(projects.libraries.permissions.api) implementation(projects.libraries.preferences.api) + implementation(projects.libraries.push.api) implementation(projects.libraries.testtags) api(projects.features.roomdetails.api) api(projects.libraries.usersearch.api) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt index de801e8aae..a82766175d 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt @@ -14,4 +14,6 @@ sealed interface RoomDetailsEvent { data object UnmuteNotification : RoomDetailsEvent data class CopyToClipboard(val text: String) : RoomDetailsEvent data class SetFavorite(val isFavorite: Boolean) : RoomDetailsEvent + data object MarkAsRead : RoomDetailsEvent + data object MarkAsUnread : RoomDetailsEvent } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 167cc2ced5..9f61c12d64 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -44,13 +44,17 @@ import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomNotificationSettings +import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.SessionPreferencesStore +import io.element.android.libraries.push.api.notifications.NotificationCleaner import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -67,6 +71,8 @@ class RoomDetailsPresenter( private val analyticsService: AnalyticsService, private val clipboardHelper: ClipboardHelper, private val appPreferencesStore: AppPreferencesStore, + private val sessionPreferencesStore: SessionPreferencesStore, + private val notificationCleaner: NotificationCleaner, ) : Presenter { @Composable override fun present(): RoomDetailsState { @@ -79,6 +85,14 @@ class RoomDetailsPresenter( val roomTopic by remember { derivedStateOf { roomInfo.topic } } val isFavorite by remember { derivedStateOf { roomInfo.isFavorite } } val joinRule by remember { derivedStateOf { roomInfo.joinRule } } + val hasNewContent by remember { + derivedStateOf { + roomInfo.numUnreadMessages > 0 || + roomInfo.numUnreadMentions > 0 || + roomInfo.numUnreadNotifications > 0 || + roomInfo.isMarkedUnread + } + } val pinnedMessagesCount by remember { derivedStateOf { roomInfo.pinnedEventIds.size } } @@ -145,6 +159,8 @@ class RoomDetailsPresenter( clipboardHelper.copyPlainText(event.text) snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_copied_to_clipboard)) } + is RoomDetailsEvent.MarkAsRead -> scope.markAsRead() + is RoomDetailsEvent.MarkAsUnread -> scope.markAsUnread() } } @@ -188,6 +204,7 @@ class RoomDetailsPresenter( showDebugInfo = isDeveloperModeEnabled, roomVersion = roomInfo.roomVersion, roomHistoryVisibility = roomInfo.historyVisibility, + hasNewContent = hasNewContent, eventSink = ::handleEvent, ) } @@ -241,4 +258,25 @@ class RoomDetailsPresenter( analyticsService.captureInteraction(Interaction.Name.MobileRoomFavouriteToggle) } } + + private fun CoroutineScope.markAsRead() = launch { + notificationCleaner.clearMessagesForRoom(client.sessionId, room.roomId) + room.setUnreadFlag(isUnread = false) + val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) { + ReceiptType.READ + } else { + ReceiptType.READ_PRIVATE + } + room.markAsRead(receiptType) + .onSuccess { + analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle) + } + } + + private fun CoroutineScope.markAsUnread() = launch { + room.setUnreadFlag(isUnread = true) + .onSuccess { + analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle) + } + } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index 90a912e86f..bd3b90d416 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -52,6 +52,7 @@ data class RoomDetailsState( val showDebugInfo: Boolean, val roomVersion: String?, val roomHistoryVisibility: RoomHistoryVisibility, + val hasNewContent: Boolean, val eventSink: (RoomDetailsEvent) -> Unit ) { val roomBadges = buildList { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index b569527d9c..7182d2ec04 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -34,7 +34,7 @@ open class RoomDetailsStateProvider : PreviewParameterProvider override val values: Sequence get() = sequenceOf( aRoomDetailsState(displayAdminSettings = true), - aRoomDetailsState(roomTopic = RoomTopicState.Hidden, showDebugInfo = true), + aRoomDetailsState(roomTopic = RoomTopicState.Hidden, showDebugInfo = true, hasNewContent = true), aRoomDetailsState(roomTopic = RoomTopicState.CanAddTopic), aRoomDetailsState(isEncrypted = false), aRoomDetailsState(roomAlias = null), @@ -123,6 +123,7 @@ fun aRoomDetailsState( isTombstoned: Boolean = false, showDebugInfo: Boolean = false, roomHistoryVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Shared, + hasNewContent: Boolean = false, eventSink: (RoomDetailsEvent) -> Unit = {}, ) = RoomDetailsState( roomId = roomId, @@ -154,6 +155,7 @@ fun aRoomDetailsState( showDebugInfo = showDebugInfo, roomVersion = "12", roomHistoryVisibility = roomHistoryVisibility, + hasNewContent = hasNewContent, eventSink = eventSink, ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index cf5265b145..b30c73b9c8 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -8,6 +8,7 @@ package io.element.android.features.roomdetails.impl +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -188,6 +189,46 @@ fun RoomDetailsView( ) } + PreferenceCategory { + if (state.hasNewContent) { + ListItem( + headlineContent = { + Text( + text = stringResource(id = R.string.screen_roomlist_mark_as_read), + style = MaterialTheme.typography.bodyLarge, + ) + }, + onClick = { + state.eventSink(RoomDetailsEvent.MarkAsRead) + }, + leadingContent = ListItemContent.Icon( + iconSource = IconSource.Vector(CompoundIcons.MarkAsRead()) + ), + trailingContent = ListItemContent.Custom { + Box( + modifier = modifier + .size(8.dp) + .clip(CircleShape) + .background(ElementTheme.colors.iconAccentPrimary) + ) + }, + ) + } else { + ListItem( + headlineContent = { + Text( + text = stringResource(id = R.string.screen_roomlist_mark_as_unread), + ) + }, + onClick = { + state.eventSink(RoomDetailsEvent.MarkAsUnread) + }, + leadingContent = ListItemContent.Icon( + iconSource = IconSource.Vector(CompoundIcons.MarkAsUnread()) + ), + ) + } + } PreferenceCategory { if (state.roomNotificationSettings != null) { NotificationItem( diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index d7092af70e..0287b5657b 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -132,6 +132,8 @@ "Roles" "Room details" "Roles & permissions" + "Mark as read" + "Mark as unread" "Add address" "Anyone in authorised spaces can join, but everyone else must request access." "Everyone must request access." diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 6ea495439e..cb9c2ecb0d 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -221,6 +221,7 @@ "screen_notification_settings_mentions_only_disclaimer", "screen_room_change_.*", "screen_room_roles_.*", + "screen_roomlist_mark_as_.*", "screen\\.edit_room_address\\..*", "screen\\.security_and_privacy\\..*" ] From 53fe12bdda6b64a754f6b8f6308be6fece865637 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 18:37:32 +0200 Subject: [PATCH 0449/1083] "Mark as unread" navigate back to the room list. #6398 --- .../element/android/appnav/LoggedInFlowNode.kt | 4 ++++ .../room/joined/JoinedRoomLoadedFlowNode.kt | 5 +++++ .../roomdetails/api/RoomDetailsEntryPoint.kt | 1 + .../roomdetails/impl/RoomDetailsFlowNode.kt | 4 ++++ .../roomdetails/impl/RoomDetailsNavigator.kt | 12 ++++++++++++ .../roomdetails/impl/RoomDetailsNode.kt | 10 ++++++++-- .../roomdetails/impl/RoomDetailsPresenter.kt | 17 +++++++++++++++-- 7 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNavigator.kt 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 47e5b7c5b3..14230d7c5a 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -382,6 +382,10 @@ class LoggedInFlowNode( } is NavTarget.Room -> { val joinedRoomCallback = object : JoinedRoomLoadedFlowNode.Callback { + override fun onDone() { + backstack.pop() + } + override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) { lifecycleScope.launch { attachRoom(roomIdOrAlias = roomId.toRoomIdOrAlias(), serverNames = serverNames, clearBackstack = clearBackStack) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt index a8e5921973..dbe53b75ac 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/room/joined/JoinedRoomLoadedFlowNode.kt @@ -82,6 +82,7 @@ class JoinedRoomLoadedFlowNode( plugins = plugins, ), DependencyInjectionGraphOwner { interface Callback : Plugin { + fun onDone() fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean = false) fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun navigateToGlobalNotificationSettings() @@ -142,6 +143,10 @@ class JoinedRoomLoadedFlowNode( private fun createRoomDetailsNode(buildContext: BuildContext, initialTarget: RoomDetailsEntryPoint.InitialTarget): Node { val callback = object : RoomDetailsEntryPoint.Callback { + override fun onDone() { + callback.onDone() + } + override fun navigateToGlobalNotificationSettings() { callback.navigateToGlobalNotificationSettings() } diff --git a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt index bbaac0cbc1..3474711b55 100644 --- a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt +++ b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt @@ -38,6 +38,7 @@ interface RoomDetailsEntryPoint : FeatureEntryPoint { data class Params(val initialElement: InitialTarget) : NodeInputs interface Callback : Plugin { + fun onDone() fun navigateToGlobalNotificationSettings() fun navigateToDeveloperSettings() fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean = false) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index 4cf5056b4e..d4108a77e3 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -176,6 +176,10 @@ class RoomDetailsFlowNode( return when (navTarget) { NavTarget.RoomDetails -> { val roomDetailsCallback = object : RoomDetailsNode.Callback { + override fun navigateBack() { + callback.onDone() + } + override fun navigateToRoomMemberList() { backstack.push(NavTarget.RoomMemberList) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNavigator.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNavigator.kt new file mode 100644 index 0000000000..9e2b77a260 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNavigator.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdetails.impl + +interface RoomDetailsNavigator { + fun onDone() +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index e9aad5b1d2..7f22c7e111 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -42,12 +42,13 @@ import io.element.android.libraries.androidutils.R as AndroidUtilsR class RoomDetailsNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: RoomDetailsPresenter, + presenterFactory: RoomDetailsPresenter.Factory, private val room: BaseRoom, private val analyticsService: AnalyticsService, private val leaveRoomRenderer: LeaveRoomRenderer, -) : Node(buildContext, plugins = plugins) { +) : Node(buildContext, plugins = plugins), RoomDetailsNavigator { interface Callback : Plugin { + fun navigateBack() fun navigateToRoomMemberList() fun navigateToInviteMembers() fun navigateToRoomDetailsEdit() @@ -65,6 +66,7 @@ class RoomDetailsNode( fun navigateToSelectNewOwnersWhenLeaving() } + private val presenter = presenterFactory.create(this) private val callback: Callback = callback() init { @@ -144,4 +146,8 @@ class RoomDetailsNode( } ) } + + override fun onDone() { + callback.navigateBack() + } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 9f61c12d64..b27fbe2f50 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -17,7 +17,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.Interaction import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.api.knockRequestPermissions @@ -59,8 +61,9 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -@Inject +@AssistedInject class RoomDetailsPresenter( + @Assisted private val navigator: RoomDetailsNavigator, private val client: MatrixClient, private val room: JoinedRoom, private val notificationSettingsService: NotificationSettingsService, @@ -74,6 +77,13 @@ class RoomDetailsPresenter( private val sessionPreferencesStore: SessionPreferencesStore, private val notificationCleaner: NotificationCleaner, ) : Presenter { + @AssistedFactory + interface Factory { + fun create( + navigator: RoomDetailsNavigator, + ): RoomDetailsPresenter + } + @Composable override fun present(): RoomDetailsState { val scope = rememberCoroutineScope() @@ -278,5 +288,8 @@ class RoomDetailsPresenter( .onSuccess { analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle) } + .onSuccess { + navigator.onDone() + } } } From 2248cd20f3984bda53cbcdaaf93966c60b0cc416 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 16:39:00 +0000 Subject: [PATCH 0450/1083] Update dependency net.zetetic:sqlcipher-android to v4.16.0 --- 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 a55a8b2adb..25aeecd174 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -201,7 +201,7 @@ matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } -sqlcipher = "net.zetetic:sqlcipher-android:4.15.0" +sqlcipher = "net.zetetic:sqlcipher-android:4.16.0" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" unifiedpush = "org.unifiedpush.android:connector:3.3.2" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" From c59b96de667b114181de316acdd6d7c2f534fde1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 09:00:11 +0200 Subject: [PATCH 0451/1083] [Link new device] Automatically rotate the QR Code --- .../impl/LinkNewDeviceFlowNode.kt | 10 +++- .../impl/LinkNewMobileHandler.kt | 4 ++ .../impl/screens/qrcode/ShowQrCodeNode.kt | 7 ++- .../screens/qrcode/ShowQrCodePresenter.kt | 58 +++++++++++++++++++ .../impl/screens/qrcode/ShowQrCodeState.kt | 14 +++++ .../screens/qrcode/ShowQrCodeStateProvider.kt | 27 +++++++++ .../impl/screens/qrcode/ShowQrCodeView.kt | 34 ++++++++--- .../api/linknewdevice/LinkMobileHandler.kt | 1 + .../linknewdevice/RustLinkMobileHandler.kt | 9 ++- 9 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt create mode 100644 features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt create mode 100644 features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt index e90d318267..61645ead9d 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDeviceFlowNode.kt @@ -144,8 +144,14 @@ class LinkNewDeviceFlowNode( navigateToError(linkMobileStep.errorType) } is LinkMobileStep.QrReady -> { - // The QrCode is ready, navigate to its display - backstack.push(NavTarget.MobileShowQrCode(linkMobileStep.data)) + // The QrCode is ready, navigate to its display, if not already there + val navTarget = backstack.elements.value.last().key.navTarget + if (navTarget !is NavTarget.MobileShowQrCode) { + backstack.push(NavTarget.MobileShowQrCode(linkMobileStep.data)) + } + } + LinkMobileStep.QrRotating -> { + // This step is handled in ShowQrCodePresenter } is LinkMobileStep.QrScanned -> { backstack.replace(NavTarget.MobileEnterNumber) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt index 157d946eaa..12cf3af3b9 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt @@ -65,4 +65,8 @@ class LinkNewMobileHandler( linkMobileStepFlow.emit(LinkMobileStep.Uninitialized) } } + + fun rotateQrCode() { + createAndStartNewHandler() + } } diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeNode.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeNode.kt index a884c3e97f..20bd50f488 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeNode.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeNode.kt @@ -25,6 +25,7 @@ import io.element.android.libraries.di.SessionScope class ShowQrCodeNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, + showQrCodePresenterFactory: ShowQrCodePresenter.Factory, ) : Node(buildContext, plugins = plugins) { class Inputs( val data: String, @@ -36,11 +37,15 @@ class ShowQrCodeNode( private val inputs: Inputs = inputs() private val callback: Callback = callback() + private val showQrCodePresenter: ShowQrCodePresenter = showQrCodePresenterFactory.create( + initialData = inputs.data, + ) @Composable override fun View(modifier: Modifier) { + val state = showQrCodePresenter.present() ShowQrCodeView( - data = inputs.data, + state = state, modifier = modifier, onBackClick = callback::navigateBack, ) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt new file mode 100644 index 0000000000..1688a6469d --- /dev/null +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt @@ -0,0 +1,58 @@ +/* + * 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.linknewdevice.impl.screens.qrcode + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.produceState +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject +import io.element.android.features.linknewdevice.impl.LinkNewMobileHandler +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.log.logger.LoggerTag +import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep +import io.element.android.libraries.matrix.api.logs.LoggerTags +import timber.log.Timber + +private val tag = LoggerTag("ShowQrCodePresenter", LoggerTags.linkNewDevice) + +@AssistedInject +class ShowQrCodePresenter( + @Assisted private val initialData: String, + private val linkNewMobileHandler: LinkNewMobileHandler, +) : Presenter { + @AssistedFactory + interface Factory { + fun create(initialData: String): ShowQrCodePresenter + } + + @Composable + override fun present(): ShowQrCodeState { + val data by produceState>(AsyncData.Success(initialData)) { + linkNewMobileHandler.stepFlow.collect { step -> + when (step) { + is LinkMobileStep.QrReady -> { + value = AsyncData.Success(step.data) + } + is LinkMobileStep.QrRotating -> { + Timber.tag(tag.value).d("Rotating QrCode") + linkNewMobileHandler.rotateQrCode() + value = AsyncData.Loading() + } + else -> Unit + } + } + } + + return ShowQrCodeState( + data = data, + ) + } +} diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt new file mode 100644 index 0000000000..e69dde8264 --- /dev/null +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.linknewdevice.impl.screens.qrcode + +import io.element.android.libraries.architecture.AsyncData + +data class ShowQrCodeState( + val data: AsyncData, +) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt new file mode 100644 index 0000000000..0c987bc5e7 --- /dev/null +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.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.features.linknewdevice.impl.screens.qrcode + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncData + +class ShowQrCodeStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aShowQrCodeState(), + ShowQrCodeState( + data = AsyncData.Loading(), + ), + ) +} + +private fun aShowQrCodeState( + data: AsyncData.Success = AsyncData.Success("DATA"), +) = ShowQrCodeState( + data = data, +) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt index 501415f621..cc55ed374d 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt @@ -9,6 +9,7 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -21,6 +22,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.linknewdevice.impl.R @@ -30,6 +32,7 @@ import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.LocalBuildMeta +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.utils.annotatedTextWithBold import io.element.android.libraries.qrcode.QrCodeImage import kotlinx.collections.immutable.persistentListOf @@ -40,7 +43,7 @@ import kotlinx.collections.immutable.persistentListOf */ @Composable fun ShowQrCodeView( - data: String, + state: ShowQrCodeState, onBackClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -55,11 +58,24 @@ fun ShowQrCodeView( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, ) { - QrCodeImage( - data = data, - modifier = Modifier - .size(220.dp) - ) + when (val str = state.data.dataOrNull()) { + null -> { + Box( + modifier = Modifier + .size(220.dp), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator() + } + } + else -> { + QrCodeImage( + data = str, + modifier = Modifier + .size(220.dp) + ) + } + } Spacer(modifier = Modifier.height(32.dp)) NumberedListOrganism( modifier = Modifier.fillMaxSize(), @@ -81,9 +97,11 @@ fun ShowQrCodeView( @PreviewsDayNight @Composable -internal fun ShowQrCodeViewPreview() = ElementPreview { +internal fun ShowQrCodeViewPreview( + @PreviewParameter(ShowQrCodeStateProvider::class) state: ShowQrCodeState, +) = ElementPreview { ShowQrCodeView( - data = "DATA", + state = state, onBackClick = { }, ) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkMobileHandler.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkMobileHandler.kt index 0c261cdd1a..1947729c7f 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkMobileHandler.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkMobileHandler.kt @@ -18,6 +18,7 @@ sealed interface LinkMobileStep { data object Uninitialized : LinkMobileStep data object Starting : LinkMobileStep data class QrReady(val data: String) : LinkMobileStep + data object QrRotating : LinkMobileStep data class WaitingForAuth(val verificationUri: String) : LinkMobileStep data class QrScanned(val checkCodeSender: CheckCodeSender) : LinkMobileStep data class Error(val errorType: ErrorType) : LinkMobileStep diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt index 6d212d4784..77ae28acea 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt @@ -53,7 +53,14 @@ class RustLinkMobileHandler( _linkMobileStep.emit(LinkMobileStep.Done) } catch (e: HumanQrGrantLoginException) { Timber.tag(tag.value).w(e, "Error during QR login grant") - _linkMobileStep.emit(LinkMobileStep.Error(e.map())) + // Catch timeout here? + if (_linkMobileStep.value is LinkMobileStep.QrReady + && e is HumanQrGrantLoginException.NotFound) { + Timber.tag(tag.value).d("Emit QrRotating due to HumanQrGrantLoginException.NotFound") + _linkMobileStep.emit(LinkMobileStep.QrRotating) + } else { + _linkMobileStep.emit(LinkMobileStep.Error(e.map())) + } } } From a6f7c05458c7a0777e6c8c695f719188babc952c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 09:24:21 +0200 Subject: [PATCH 0452/1083] [Link new device] Automatically rotate the QR Code - limit number of rotation to 10. --- .../impl/LinkNewMobileHandler.kt | 8 ++++++++ .../screens/qrcode/ShowQrCodePresenter.kt | 19 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt index 12cf3af3b9..18d67f577a 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewMobileHandler.kt @@ -12,6 +12,7 @@ import dev.zacsweers.metro.SingleIn import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.linknewdevice.ErrorType import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileHandler import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep import io.element.android.libraries.matrix.api.logs.LoggerTags @@ -69,4 +70,11 @@ class LinkNewMobileHandler( fun rotateQrCode() { createAndStartNewHandler() } + + fun onTooManyRotation() { + reset() + sessionScope.launch { + linkMobileStepFlow.emit(LinkMobileStep.Error(ErrorType.Expired("Too many QR code rotations"))) + } + } } diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt index 1688a6469d..3deff8c603 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt @@ -9,7 +9,10 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf 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 @@ -35,6 +38,7 @@ class ShowQrCodePresenter( @Composable override fun present(): ShowQrCodeState { + var qrCodeRotationCounter by remember { mutableIntStateOf(MAX_QR_CODE_ROTATION) } val data by produceState>(AsyncData.Success(initialData)) { linkNewMobileHandler.stepFlow.collect { step -> when (step) { @@ -42,9 +46,14 @@ class ShowQrCodePresenter( value = AsyncData.Success(step.data) } is LinkMobileStep.QrRotating -> { - Timber.tag(tag.value).d("Rotating QrCode") - linkNewMobileHandler.rotateQrCode() - value = AsyncData.Loading() + if (qrCodeRotationCounter-- > 0) { + Timber.tag(tag.value).d("Rotating QrCode") + linkNewMobileHandler.rotateQrCode() + value = AsyncData.Loading() + } else { + Timber.tag(tag.value).w("Max QR code rotation reached, not rotating anymore") + linkNewMobileHandler.onTooManyRotation() + } } else -> Unit } @@ -55,4 +64,8 @@ class ShowQrCodePresenter( data = data, ) } + + companion object { + const val MAX_QR_CODE_ROTATION = 10 + } } From 18bc6a27c48622dfcbdac8fd077f3fb90f4e5af1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 10:43:47 +0200 Subject: [PATCH 0453/1083] [Link new device] Improve UI transition between QRCodes. --- .../screens/qrcode/ShowQrCodePresenter.kt | 47 +++++++++++++-- .../impl/screens/qrcode/ShowQrCodeState.kt | 4 +- .../screens/qrcode/ShowQrCodeStateProvider.kt | 17 ++++-- .../impl/screens/qrcode/ShowQrCodeView.kt | 59 +++++++++++++------ 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt index 3deff8c603..6a7e7cfcf5 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt @@ -22,6 +22,9 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep import io.element.android.libraries.matrix.api.logs.LoggerTags +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import timber.log.Timber private val tag = LoggerTag("ShowQrCodePresenter", LoggerTags.linkNewDevice) @@ -36,20 +39,54 @@ class ShowQrCodePresenter( fun create(initialData: String): ShowQrCodePresenter } + private var loadingJob: Job? = null + @Composable override fun present(): ShowQrCodeState { var qrCodeRotationCounter by remember { mutableIntStateOf(MAX_QR_CODE_ROTATION) } - val data by produceState>(AsyncData.Success(initialData)) { + val state by produceState( + initialValue = ShowQrCodeState( + data1 = AsyncData.Success(initialData), + data2 = AsyncData.Uninitialized, + dataToRender = 1, + ) + ) { linkNewMobileHandler.stepFlow.collect { step -> + val currentValue = value when (step) { is LinkMobileStep.QrReady -> { - value = AsyncData.Success(step.data) + loadingJob?.cancel() + if (currentValue.dataToRender == 1) { + value = currentValue.copy( + data2 = AsyncData.Success(step.data), + dataToRender = 2, + ) + } else { + value = currentValue.copy( + data1 = AsyncData.Success(step.data), + dataToRender = 1, + ) + } } is LinkMobileStep.QrRotating -> { if (qrCodeRotationCounter-- > 0) { Timber.tag(tag.value).d("Rotating QrCode") linkNewMobileHandler.rotateQrCode() - value = AsyncData.Loading() + // Ensure that outdated data is not rendered too long while rotating QR code + loadingJob = launch { + delay(1000) + if (currentValue.dataToRender == 1) { + value = currentValue.copy( + data2 = AsyncData.Loading(), + dataToRender = 2, + ) + } else { + value = currentValue.copy( + data1 = AsyncData.Loading(), + dataToRender = 1, + ) + } + } } else { Timber.tag(tag.value).w("Max QR code rotation reached, not rotating anymore") linkNewMobileHandler.onTooManyRotation() @@ -60,9 +97,7 @@ class ShowQrCodePresenter( } } - return ShowQrCodeState( - data = data, - ) + return state } companion object { diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt index e69dde8264..76302b71aa 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt @@ -10,5 +10,7 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode import io.element.android.libraries.architecture.AsyncData data class ShowQrCodeState( - val data: AsyncData, + val data1: AsyncData, + val data2: AsyncData, + val dataToRender: Int, ) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt index 0c987bc5e7..dc7c12b847 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt @@ -14,14 +14,23 @@ class ShowQrCodeStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aShowQrCodeState(), - ShowQrCodeState( - data = AsyncData.Loading(), + aShowQrCodeState( + data1 = AsyncData.Loading(), + ), + aShowQrCodeState( + data1 = AsyncData.Success("DATA"), + data2 = AsyncData.Success("DATA2"), + dataToRender = 2, ), ) } private fun aShowQrCodeState( - data: AsyncData.Success = AsyncData.Success("DATA"), + data1: AsyncData = AsyncData.Success("DATA"), + data2: AsyncData = AsyncData.Uninitialized, + dataToRender: Int = 1, ) = ShowQrCodeState( - data = data, + data1 = data1, + data2 = data2, + dataToRender = dataToRender, ) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt index cc55ed374d..0791847288 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt @@ -9,6 +9,9 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -58,23 +61,15 @@ fun ShowQrCodeView( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, ) { - when (val str = state.data.dataOrNull()) { - null -> { - Box( - modifier = Modifier - .size(220.dp), - contentAlignment = Alignment.Center, - ) { - CircularProgressIndicator() - } - } - else -> { - QrCodeImage( - data = str, - modifier = Modifier - .size(220.dp) - ) - } + Box { + QrCodeOrLoading( + isVisible = state.dataToRender == 1, + data = state.data1.dataOrNull(), + ) + QrCodeOrLoading( + isVisible = state.dataToRender == 2, + data = state.data2.dataOrNull(), + ) } Spacer(modifier = Modifier.height(32.dp)) NumberedListOrganism( @@ -95,6 +90,36 @@ fun ShowQrCodeView( } } +@Composable +private fun QrCodeOrLoading( + isVisible: Boolean, + data: String?, + modifier: Modifier = Modifier, +) { + AnimatedVisibility( + modifier = modifier, + visible = isVisible, + enter = fadeIn(), + exit = fadeOut(), + ) { + if (data == null) { + Box( + modifier = Modifier + .size(220.dp), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator() + } + } else { + QrCodeImage( + data = data, + modifier = Modifier + .size(220.dp) + ) + } + } +} + @PreviewsDayNight @Composable internal fun ShowQrCodeViewPreview( From 75feaa7ee7ebb1291f81d68e53d7ffec93017b01 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 10:59:39 +0200 Subject: [PATCH 0454/1083] [Link new device] Fix and add tests. --- .../screens/qrcode/ShowQrCodeStateProvider.kt | 2 +- .../screens/qrcode/ShowQrCodePresenterTest.kt | 105 ++++++++++++++++++ .../impl/screens/qrcode/ShowQrCodeViewTest.kt | 2 +- 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt index dc7c12b847..6079d0918c 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt @@ -25,7 +25,7 @@ class ShowQrCodeStateProvider : PreviewParameterProvider { ) } -private fun aShowQrCodeState( +internal fun aShowQrCodeState( data1: AsyncData = AsyncData.Success("DATA"), data2: AsyncData = AsyncData.Uninitialized, dataToRender: Int = 1, diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt new file mode 100644 index 0000000000..8ecc0ea008 --- /dev/null +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt @@ -0,0 +1,105 @@ +/* + * 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package io.element.android.features.linknewdevice.impl.screens.qrcode + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.linknewdevice.impl.LinkNewMobileHandler +import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileHandler +import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.linknewdevice.FakeLinkMobileHandler +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class ShowQrCodePresenterTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + createPresenter().test { + val initialState = awaitItem() + assertThat(initialState.data1.dataOrNull()).isEqualTo("DATA") + assertThat(initialState.data2.isUninitialized()).isTrue() + assertThat(initialState.dataToRender).isEqualTo(1) + } + } + + @Test + fun `present - when handler emits QrRotating, the presenter requests to rotate the QrCode`() = runTest { + val linkMobileHandler = FakeLinkMobileHandler( + startResult = {}, + ) + val createLinkMobileHandlerResult = lambdaRecorder> { + Result.success(linkMobileHandler) + } + val matrixClient = FakeMatrixClient( + sessionCoroutineScope = backgroundScope, + createLinkMobileHandlerResult = createLinkMobileHandlerResult, + ) + val linkNewMobileHandler = LinkNewMobileHandler(matrixClient) + linkNewMobileHandler.createAndStartNewHandler() + createPresenter( + linkNewMobileHandler = linkNewMobileHandler, + ).test { + awaitItem() + linkMobileHandler.emitStep( + LinkMobileStep.QrRotating + ) + runCurrent() + val finalState = awaitItem() + assertThat(finalState.data2.isLoading()).isTrue() + assertThat(finalState.dataToRender).isEqualTo(2) + createLinkMobileHandlerResult.assertions().isCalledExactly(2) + } + } + + @Test + fun `present - when handler emits QrRotating, the presenter requests to rotate the QrCode and the code is rotated`() = runTest { + val linkMobileHandler = FakeLinkMobileHandler( + startResult = {}, + ) + val matrixClient = FakeMatrixClient( + sessionCoroutineScope = backgroundScope, + createLinkMobileHandlerResult = { Result.success(linkMobileHandler) }, + ) + val linkNewMobileHandler = LinkNewMobileHandler(matrixClient) + linkNewMobileHandler.createAndStartNewHandler() + createPresenter( + linkNewMobileHandler = linkNewMobileHandler, + ).test { + awaitItem() + linkMobileHandler.emitStep( + LinkMobileStep.QrRotating + ) + runCurrent() + linkMobileHandler.emitStep( + LinkMobileStep.QrReady("DATA2") + ) + val finalState = awaitItem() + assertThat(finalState.data1.dataOrNull()).isEqualTo("DATA") + assertThat(finalState.data2.dataOrNull()).isEqualTo("DATA2") + assertThat(finalState.dataToRender).isEqualTo(2) + } + } + + private fun createPresenter( + linkNewMobileHandler: LinkNewMobileHandler = LinkNewMobileHandler(FakeMatrixClient()), + ) = ShowQrCodePresenter( + initialData = "DATA", + linkNewMobileHandler = linkNewMobileHandler, + ) +} diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt index d552c2bff6..7927eeed77 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeViewTest.kt @@ -37,7 +37,7 @@ class ShowQrCodeViewTest { ) { setContent { ShowQrCodeView( - data = "DATA", + state = aShowQrCodeState(), onBackClick = onBackClick, ) } From 33c7c7555035392571c8902df75de7bf3ad732bc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 14:24:02 +0200 Subject: [PATCH 0455/1083] Fix detekt issue --- .../matrix/impl/linknewdevice/RustLinkMobileHandler.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt index 77ae28acea..cb387a9d21 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt @@ -51,16 +51,18 @@ class RustLinkMobileHandler( ) // We emit Done in case the progress listener was deallocated before generate() sent the Done _linkMobileStep.emit(LinkMobileStep.Done) - } catch (e: HumanQrGrantLoginException) { + } catch (e: HumanQrGrantLoginException.NotFound) { Timber.tag(tag.value).w(e, "Error during QR login grant") // Catch timeout here? - if (_linkMobileStep.value is LinkMobileStep.QrReady - && e is HumanQrGrantLoginException.NotFound) { + if (_linkMobileStep.value is LinkMobileStep.QrReady) { Timber.tag(tag.value).d("Emit QrRotating due to HumanQrGrantLoginException.NotFound") _linkMobileStep.emit(LinkMobileStep.QrRotating) } else { _linkMobileStep.emit(LinkMobileStep.Error(e.map())) } + } catch (e: HumanQrGrantLoginException) { + Timber.tag(tag.value).w(e, "Error during QR login grant") + _linkMobileStep.emit(LinkMobileStep.Error(e.map())) } } From 1473f5e806447ca96d62b9761a42654a4abb6497 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 14:41:47 +0200 Subject: [PATCH 0456/1083] [Link new device] and add tests. --- .../RustLinkMobileHandlerTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt index 9f71cb7169..ad751cc86b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt @@ -118,6 +118,35 @@ class RustLinkMobileHandlerTest { } } + @Test + fun `when start throws HumanQrGrantLoginException_NotFound when in state QrReady, the handler emits QrRotating step`() = runTest { + val completable = CompletableDeferred() + val handler = FakeFfiGrantLoginWithQrCodeHandler( + generateResult = { + completable.await() + throw HumanQrGrantLoginException.NotFound("Timeout") + } + ) + val sut = createRustLinkMobileHandler( + handler, + ) + sut.linkMobileStep.test { + val initialItem = awaitItem() + assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized) + backgroundScope.launch { + sut.start() + } + runCurrent() + handler.emitGenerateProgress(GrantGeneratedQrLoginProgress.QrReady(FakeFfiQrCodeData(toBytesResult = { QR_CODE_DATA_RECIPROCATE }))) + val readyState = awaitItem() + assertThat(readyState).isInstanceOf(LinkMobileStep.QrReady::class.java) + // generate returns, error is emitted + completable.complete(Unit) + val qrRotatingState = awaitItem() + assertThat(qrRotatingState).isEqualTo(LinkMobileStep.QrRotating) + } + } + private fun TestScope.createRustLinkMobileHandler( handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(), ) = RustLinkMobileHandler( From 900b888044371a0f2bd53ab6a5aa4f08b1135ab7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 19 May 2026 13:27:57 +0000 Subject: [PATCH 0457/1083] Update screenshots --- ...nknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en.png | 3 +++ ...nknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png | 3 +++ ...newdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en.png | 3 +++ ...newdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en.png new file mode 100644 index 0000000000..d2ab2dcb1e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48cafd6b98791b64e4cc6a16c602f17e3a886659698c3c93bc4acaf875337e0f +size 31102 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png new file mode 100644 index 0000000000..2f06e29863 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:151eaa4b5619afd76b94de518dc2868d735b6b7a167056941e1f429520c3bf0d +size 31836 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en.png new file mode 100644 index 0000000000..c4593656d1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f6f8d1282ae47a5240aec2b2c63a137b8e3e25ec8b746cf2d82d0fa7e0c0a34 +size 30287 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png new file mode 100644 index 0000000000..99f134760d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa2303b621070608ba79673322f61bfa686b9729eb445913dd8d059d62c9764a +size 32374 From 5dd897dae81adfdf55601c7b16541180b89c9106 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 May 2026 19:00:58 +0200 Subject: [PATCH 0458/1083] Use AnimatedContent instead of reinventing the wheel. --- .../screens/qrcode/ShowQrCodePresenter.kt | 33 +++--------- .../impl/screens/qrcode/ShowQrCodeState.kt | 4 +- .../screens/qrcode/ShowQrCodeStateProvider.kt | 15 ++---- .../impl/screens/qrcode/ShowQrCodeView.kt | 52 ++++++++----------- .../screens/qrcode/ShowQrCodePresenterTest.kt | 11 ++-- ...screens.qrcode_ShowQrCodeView_Day_2_en.png | 3 -- ...reens.qrcode_ShowQrCodeView_Night_2_en.png | 3 -- 7 files changed, 37 insertions(+), 84 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt index 6a7e7cfcf5..21071a6831 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt @@ -46,27 +46,16 @@ class ShowQrCodePresenter( var qrCodeRotationCounter by remember { mutableIntStateOf(MAX_QR_CODE_ROTATION) } val state by produceState( initialValue = ShowQrCodeState( - data1 = AsyncData.Success(initialData), - data2 = AsyncData.Uninitialized, - dataToRender = 1, + data = AsyncData.Success(initialData), ) ) { linkNewMobileHandler.stepFlow.collect { step -> - val currentValue = value when (step) { is LinkMobileStep.QrReady -> { loadingJob?.cancel() - if (currentValue.dataToRender == 1) { - value = currentValue.copy( - data2 = AsyncData.Success(step.data), - dataToRender = 2, - ) - } else { - value = currentValue.copy( - data1 = AsyncData.Success(step.data), - dataToRender = 1, - ) - } + value = ShowQrCodeState( + data = AsyncData.Success(step.data), + ) } is LinkMobileStep.QrRotating -> { if (qrCodeRotationCounter-- > 0) { @@ -75,17 +64,9 @@ class ShowQrCodePresenter( // Ensure that outdated data is not rendered too long while rotating QR code loadingJob = launch { delay(1000) - if (currentValue.dataToRender == 1) { - value = currentValue.copy( - data2 = AsyncData.Loading(), - dataToRender = 2, - ) - } else { - value = currentValue.copy( - data1 = AsyncData.Loading(), - dataToRender = 1, - ) - } + value = ShowQrCodeState( + data = AsyncData.Loading(), + ) } } else { Timber.tag(tag.value).w("Max QR code rotation reached, not rotating anymore") diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt index 76302b71aa..e69dde8264 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeState.kt @@ -10,7 +10,5 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode import io.element.android.libraries.architecture.AsyncData data class ShowQrCodeState( - val data1: AsyncData, - val data2: AsyncData, - val dataToRender: Int, + val data: AsyncData, ) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt index 6079d0918c..e6d33c2544 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeStateProvider.kt @@ -15,22 +15,13 @@ class ShowQrCodeStateProvider : PreviewParameterProvider { get() = sequenceOf( aShowQrCodeState(), aShowQrCodeState( - data1 = AsyncData.Loading(), - ), - aShowQrCodeState( - data1 = AsyncData.Success("DATA"), - data2 = AsyncData.Success("DATA2"), - dataToRender = 2, + data = AsyncData.Loading(), ), ) } internal fun aShowQrCodeState( - data1: AsyncData = AsyncData.Success("DATA"), - data2: AsyncData = AsyncData.Uninitialized, - dataToRender: Int = 1, + data: AsyncData = AsyncData.Success("DATA"), ) = ShowQrCodeState( - data1 = data1, - data2 = data2, - dataToRender = dataToRender, + data = data, ) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt index 0791847288..ee38342ce2 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt @@ -9,9 +9,11 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode -import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -44,6 +46,7 @@ import kotlinx.collections.immutable.persistentListOf * QrCode display screen: * https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=2027-23617 */ +@OptIn(ExperimentalAnimationApi::class) @Composable fun ShowQrCodeView( state: ShowQrCodeState, @@ -61,14 +64,15 @@ fun ShowQrCodeView( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, ) { - Box { + AnimatedContent( + targetState = state.data.dataOrNull(), + transitionSpec = { + fadeIn().togetherWith(fadeOut()) + } + ) { data -> QrCodeOrLoading( - isVisible = state.dataToRender == 1, - data = state.data1.dataOrNull(), - ) - QrCodeOrLoading( - isVisible = state.dataToRender == 2, - data = state.data2.dataOrNull(), + modifier = modifier.size(220.dp), + data = data, ) } Spacer(modifier = Modifier.height(32.dp)) @@ -92,31 +96,21 @@ fun ShowQrCodeView( @Composable private fun QrCodeOrLoading( - isVisible: Boolean, data: String?, modifier: Modifier = Modifier, ) { - AnimatedVisibility( - modifier = modifier, - visible = isVisible, - enter = fadeIn(), - exit = fadeOut(), - ) { - if (data == null) { - Box( - modifier = Modifier - .size(220.dp), - contentAlignment = Alignment.Center, - ) { - CircularProgressIndicator() - } - } else { - QrCodeImage( - data = data, - modifier = Modifier - .size(220.dp) - ) + if (data == null) { + Box( + modifier = modifier, + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator() } + } else { + QrCodeImage( + modifier = modifier, + data = data, + ) } } diff --git a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt index 8ecc0ea008..f92cf66102 100644 --- a/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt +++ b/features/linknewdevice/impl/src/test/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodePresenterTest.kt @@ -32,9 +32,7 @@ class ShowQrCodePresenterTest { fun `present - initial state`() = runTest { createPresenter().test { val initialState = awaitItem() - assertThat(initialState.data1.dataOrNull()).isEqualTo("DATA") - assertThat(initialState.data2.isUninitialized()).isTrue() - assertThat(initialState.dataToRender).isEqualTo(1) + assertThat(initialState.data.dataOrNull()).isEqualTo("DATA") } } @@ -61,8 +59,7 @@ class ShowQrCodePresenterTest { ) runCurrent() val finalState = awaitItem() - assertThat(finalState.data2.isLoading()).isTrue() - assertThat(finalState.dataToRender).isEqualTo(2) + assertThat(finalState.data.isLoading()).isTrue() createLinkMobileHandlerResult.assertions().isCalledExactly(2) } } @@ -90,9 +87,7 @@ class ShowQrCodePresenterTest { LinkMobileStep.QrReady("DATA2") ) val finalState = awaitItem() - assertThat(finalState.data1.dataOrNull()).isEqualTo("DATA") - assertThat(finalState.data2.dataOrNull()).isEqualTo("DATA2") - assertThat(finalState.dataToRender).isEqualTo(2) + assertThat(finalState.data.dataOrNull()).isEqualTo("DATA2") } } diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png deleted file mode 100644 index 2f06e29863..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:151eaa4b5619afd76b94de518dc2868d735b6b7a167056941e1f429520c3bf0d -size 31836 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png deleted file mode 100644 index 99f134760d..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa2303b621070608ba79673322f61bfa686b9729eb445913dd8d059d62c9764a -size 32374 From dc05388ccaf8bd662583c9c8e6fd82b60d0407f8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 10:53:50 +0200 Subject: [PATCH 0459/1083] Update tests. --- .../FakeJoinedRoomLoadedFlowNodeCallback.kt | 1 + features/roomdetails/impl/build.gradle.kts | 1 + .../roomdetails/impl/RoomDetailsPresenter.kt | 2 - .../impl/DefaultRoomDetailsEntryPointTest.kt | 1 + .../impl/FakeRoomDetailsNavigator.kt | 16 ++++ .../roomdetails/impl/MatrixRoomFixture.kt | 9 +- .../impl/RoomDetailsPresenterTest.kt | 94 ++++++++++++++++++- 7 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/FakeRoomDetailsNavigator.kt diff --git a/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt b/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt index b0669148dd..ec36f3d32d 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/room/joined/FakeJoinedRoomLoadedFlowNodeCallback.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.tests.testutils.lambda.lambdaError class FakeJoinedRoomLoadedFlowNodeCallback : JoinedRoomLoadedFlowNode.Callback { + override fun onDone() = lambdaError() override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) = lambdaError() override fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() override fun navigateToGlobalNotificationSettings() = lambdaError() diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index 23b23a3e62..77e2d0c229 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -70,6 +70,7 @@ dependencies { testImplementation(projects.libraries.mediaviewer.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.preferences.test) + testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.usersearch.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.features.call.test) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index b27fbe2f50..e6617d1dd5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -287,8 +287,6 @@ class RoomDetailsPresenter( room.setUnreadFlag(isUnread = true) .onSuccess { analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle) - } - .onSuccess { navigator.onDone() } } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt index 597cc82f7d..9a97380d21 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -68,6 +68,7 @@ class DefaultRoomDetailsEntryPointTest { ) } val callback = object : RoomDetailsEntryPoint.Callback { + override fun onDone() = lambdaError() override fun navigateToGlobalNotificationSettings() = lambdaError() override fun navigateToDeveloperSettings() = lambdaError() override fun navigateToRoom(roomId: RoomId, serverNames: List, clearBackStack: Boolean) = lambdaError() diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/FakeRoomDetailsNavigator.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/FakeRoomDetailsNavigator.kt new file mode 100644 index 0000000000..b416902dab --- /dev/null +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/FakeRoomDetailsNavigator.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdetails.impl + +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeRoomDetailsNavigator( + private val onDoneResult: () -> Unit = { lambdaError() } +) : RoomDetailsNavigator { + override fun onDone() = onDoneResult() +} diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt index 2d85744345..edb9115a7e 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/MatrixRoomFixture.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions +import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -28,7 +29,7 @@ import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.tests.testutils.lambda.lambdaError -fun aRoom( +fun aFakeBaseRoom( sessionId: SessionId = A_SESSION_ID, roomId: RoomId = A_ROOM_ID, displayName: String = A_ROOM_NAME, @@ -49,6 +50,7 @@ fun aRoom( getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, userRoleResult: () -> Result = { lambdaError() }, setIsFavoriteResult: (Boolean) -> Result = { lambdaError() }, + markAsReadResult: (ReceiptType) -> Result = { lambdaError() }, ) = FakeBaseRoom( sessionId = sessionId, roomId = roomId, @@ -57,6 +59,7 @@ fun aRoom( getUpdatedMemberResult = getUpdatedMemberResult, userRoleResult = userRoleResult, setIsFavoriteResult = setIsFavoriteResult, + markAsReadResult = markAsReadResult, roomPermissions = roomPermissions, initialRoomInfo = aRoomInfo( name = displayName, @@ -106,6 +109,7 @@ fun aJoinedRoom( publishRoomAliasInRoomDirectoryResult: (RoomAlias) -> Result = { lambdaError() }, removeRoomAliasFromRoomDirectoryResult: (RoomAlias) -> Result = { lambdaError() }, setIsFavoriteResult: (Boolean) -> Result = { lambdaError() }, + markAsReadResult: (ReceiptType) -> Result = { lambdaError() }, ) = FakeJoinedRoom( roomNotificationSettingsService = notificationSettingsService, setNameResult = setNameResult, @@ -118,7 +122,7 @@ fun aJoinedRoom( updateCanonicalAliasResult = updateCanonicalAliasResult, publishRoomAliasInRoomDirectoryResult = publishRoomAliasInRoomDirectoryResult, removeRoomAliasFromRoomDirectoryResult = removeRoomAliasFromRoomDirectoryResult, - baseRoom = aRoom( + baseRoom = aFakeBaseRoom( sessionId = sessionId, roomId = roomId, roomPermissions = roomPermissions, @@ -139,5 +143,6 @@ fun aJoinedRoom( joinedMemberCount = joinedMemberCount, activeMemberCount = activeMemberCount, invitedMemberCount = invitedMemberCount, + markAsReadResult = markAsReadResult, ) ) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index 9c116f5a9d..5a845c3331 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -21,6 +21,8 @@ import io.element.android.libraries.androidutils.clipboard.ClipboardHelper import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMembersState @@ -28,6 +30,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions +import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME @@ -41,7 +44,11 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore +import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore +import io.element.android.libraries.push.api.notifications.NotificationCleaner +import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.EventsRecorder @@ -79,7 +86,10 @@ class RoomDetailsPresenterTest { analyticsService: AnalyticsService = FakeAnalyticsService(), encryptionService: FakeEncryptionService = FakeEncryptionService(), clipboardHelper: ClipboardHelper = FakeClipboardHelper(), - appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore() + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), + navigator: RoomDetailsNavigator = FakeRoomDetailsNavigator(), + notificationCleaner: NotificationCleaner = FakeNotificationCleaner(), + sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), ): RoomDetailsPresenter { val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { @@ -96,6 +106,7 @@ class RoomDetailsPresenterTest { } } return RoomDetailsPresenter( + navigator = navigator, client = matrixClient, room = room, notificationSettingsService = matrixClient.notificationSettingsService, @@ -106,6 +117,8 @@ class RoomDetailsPresenterTest { analyticsService = analyticsService, clipboardHelper = clipboardHelper, appPreferencesStore = appPreferencesStore, + notificationCleaner = notificationCleaner, + sessionPreferencesStore = sessionPreferencesStore, ) } @@ -598,6 +611,85 @@ class RoomDetailsPresenterTest { } } + @Test + fun `present - mark as read`() = runTest { + val markAsReadResult = lambdaRecorder> { _ -> Result.success(Unit) } + val room = aJoinedRoom( + markAsReadResult = markAsReadResult, + ) + val clearMessagesForRoomResult = lambdaRecorder { _, _ -> Result.success(Unit) } + val notificationCleaner = FakeNotificationCleaner( + clearMessagesForRoomLambda = clearMessagesForRoomResult, + ) + val presenter = createRoomDetailsPresenter( + room = room, + notificationCleaner = notificationCleaner, + ) + presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { + skipItems(1) + with(awaitItem()) { + eventSink(RoomDetailsEvent.MarkAsRead) + } + assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(false) + markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ)) + clearMessagesForRoomResult.assertions().isCalledOnce().with( + value(room.sessionId), value(room.roomId) + ) + } + } + + @Test + fun `present - mark as read - private`() = runTest { + val markAsReadResult = lambdaRecorder> { _ -> Result.success(Unit) } + val room = aJoinedRoom( + markAsReadResult = markAsReadResult, + ) + val sessionPreferencesStore = InMemorySessionPreferencesStore( + isSendPublicReadReceiptsEnabled = false, + ) + val clearMessagesForRoomResult = lambdaRecorder { _, _ -> Result.success(Unit) } + val notificationCleaner = FakeNotificationCleaner( + clearMessagesForRoomLambda = clearMessagesForRoomResult, + ) + val presenter = createRoomDetailsPresenter( + room = room, + notificationCleaner = notificationCleaner, + sessionPreferencesStore = sessionPreferencesStore, + ) + presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { + skipItems(1) + with(awaitItem()) { + eventSink(RoomDetailsEvent.MarkAsRead) + } + assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(false) + markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ_PRIVATE)) + clearMessagesForRoomResult.assertions().isCalledOnce().with( + value(room.sessionId), value(room.roomId) + ) + } + } + + @Test + fun `present - mark as unread`() = runTest { + val room = aJoinedRoom() + val onDoneResult = lambdaRecorder { } + val navigator = FakeRoomDetailsNavigator( + onDoneResult = onDoneResult + ) + val presenter = createRoomDetailsPresenter( + room = room, + navigator = navigator, + ) + presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { + skipItems(1) + with(awaitItem()) { + eventSink(RoomDetailsEvent.MarkAsUnread) + } + onDoneResult.assertions().isCalledOnce() + assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(true) + } + } + private fun roomPermissions( canInvite: Boolean = true, canKick: Boolean = true, From 94392f3ebd260ff8b49c2699c5709163a878517a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 09:16:18 +0000 Subject: [PATCH 0460/1083] Update kotlin to v2.3.8 --- 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 25aeecd174..9e2b86d7b5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ android_gradle_plugin = "8.13.2" # When updating this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.3.21" kotlinpoet = "2.3.0" -ksp = "2.3.7" +ksp = "2.3.8" firebaseAppDistribution = "5.2.1" # AndroidX From 42c141109fa4b382010b5c41135c5751a276832c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 20 May 2026 11:32:32 +0200 Subject: [PATCH 0461/1083] Fix media viewer flickering (#6800) * Fix media viewer flickering This was caused by the data being loaded triggering an index update that got out of sync with the displayed items, and for an instant, the pager index pointed to the wrong data until it was refreshed * Reuse the same 'displayer' function for both forwards and backwards pagination * Make `dataFlow` a property so we don't create a new instance every time we access it * Remove `pageDataComparator` as it prevented new items from being loaded when a pagination returned no valid items to display but has more items to load Make sure we modify the current index when loading new data only if it was pointing to the input event id. * Fix `MediaViewerDataSource` overriding the provided timestamp for `Loading` items Test emitting different loading items from the data source results in the state displaying the different items, so they will trigger a new pagination attempt * Add regression test to check loading -> error -> loading states will still trigger 2 separate `LoadMore` events --- .../impl/datasource/MediaGalleryDataSource.kt | 12 +- .../impl/gallery/MediaGalleryPresenter.kt | 4 +- .../impl/viewer/MediaViewerDataSource.kt | 86 ++++++++----- .../impl/viewer/MediaViewerNode.kt | 2 + .../impl/viewer/MediaViewerPresenter.kt | 104 +++++++-------- .../impl/viewer/MediaViewerState.kt | 2 + .../impl/viewer/MediaViewerView.kt | 9 +- .../viewer/SingleMediaGalleryDataSource.kt | 2 + .../impl/DefaultMediaViewerEntryPointTest.kt | 6 + .../datasource/FakeMediaGalleryDataSource.kt | 12 +- .../impl/viewer/MediaViewerDataSourceTest.kt | 32 +++-- .../impl/viewer/MediaViewerPresenterTest.kt | 120 +++++++++++++----- .../impl/viewer/MediaViewerViewTest.kt | 69 +++++++++- 13 files changed, 312 insertions(+), 148 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt index f5418c76c9..7bdd4872a3 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt @@ -32,6 +32,7 @@ import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean interface MediaGalleryDataSource { + val isReady: Boolean fun start(coroutineScope: CoroutineScope) fun groupedMediaItemsFlow(): Flow> fun getLastData(): AsyncData @@ -49,7 +50,7 @@ class TimelineMediaGalleryDataSource( ) : MediaGalleryDataSource { private var timeline: Timeline? = null - private val groupedMediaItemsFlow = MutableSharedFlow>(replay = 1) + private val groupedMediaItemsFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = 10) override fun groupedMediaItemsFlow(): Flow> = groupedMediaItemsFlow @@ -59,9 +60,12 @@ class TimelineMediaGalleryDataSource( private val isStarted = AtomicBoolean(false) + override val isReady: Boolean get() = isStarted.get() && timeline != null + @OptIn(ExperimentalCoroutinesApi::class) override fun start(coroutineScope: CoroutineScope) { if (!isStarted.compareAndSet(false, true)) { + Timber.w("MediaGalleryDataSource for room ${room.roomId} is already started, ignoring subsequent start call") return } flow { @@ -73,10 +77,12 @@ class TimelineMediaGalleryDataSource( } mediaTimeline.getTimeline().fold( { + Timber.d("Timeline media data source flow started for room ${room.roomId}") timeline = it emit(it) }, { + Timber.e(it, "Failed to get media timeline for room ${room.roomId}") groupedMediaItemsFlow.emit(AsyncData.Failure(it)) }, ) @@ -107,13 +113,13 @@ class TimelineMediaGalleryDataSource( } override suspend fun loadMore(direction: Timeline.PaginationDirection) { - timeline?.paginate(direction) + timeline?.paginate(direction) ?: Timber.w("Timeline is not ready yet, cannot load more media items for room ${room.roomId}") } override suspend fun deleteItem(eventId: EventId) { timeline?.redactEvent( eventOrTransactionId = eventId.toEventOrTransactionId(), reason = null, - ) + ) ?: Timber.w("Timeline is not ready yet, cannot delete media item with eventId $eventId for room ${room.roomId}") } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index e7caa12f2e..2c2fb31020 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -94,7 +94,9 @@ class MediaGalleryPresenter( mode = event.mode } is MediaGalleryEvent.LoadMore -> coroutineScope.launch { - mediaGalleryDataSource.loadMore(event.direction) + if (mediaGalleryDataSource.isReady) { + mediaGalleryDataSource.loadMore(event.direction) + } } is MediaGalleryEvent.Delete -> coroutineScope.launch { mediaGalleryDataSource.deleteItem(event.eventId) 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 01ec68a336..b0b81bbde0 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 @@ -11,12 +11,13 @@ package io.element.android.libraries.mediaviewer.impl.viewer import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState +import androidx.compose.runtime.ProduceStateScope import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.produceState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.extensions.mapCatchingExceptions +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaFile import io.element.android.libraries.matrix.api.media.MediaSource @@ -37,14 +38,17 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext import timber.log.Timber import java.util.concurrent.ConcurrentHashMap class MediaViewerDataSource( mode: MediaViewerMode, + coroutineScope: CoroutineScope, private val dispatcher: CoroutineDispatcher, private val galleryDataSource: MediaGalleryDataSource, private val mediaLoader: MatrixMediaLoader, @@ -76,40 +80,58 @@ class MediaViewerDataSource( localMediaStates.clear() } + /** + * Helper function to translate the [dataFlow] result to a Compose [State] that can be observed in the UI. + */ @Composable - fun collectAsState(): State> { - return remember { dataFlow() }.collectAsState(initialData()) + fun produceState( + producer: suspend ProduceStateScope>.(StateFlow>) -> Unit + ): State> { + return produceState(initialValue = initialData()) { + producer(dataFlow) + } + } + + /** + * Find the index of the page corresponding to the given eventId, or null if not found. + */ + fun findEventIndex(eventId: EventId?): Int? { + if (eventId == null) return null + return dataFlow.value.indexOfFirst { (it as? MediaViewerPageData.MediaViewerData)?.eventId == eventId }.takeIf { it >= 0 } } @VisibleForTesting - internal fun dataFlow(): Flow> { - return galleryDataSource.groupedMediaItemsFlow() - .map { groupedItems -> - when (groupedItems) { - AsyncData.Uninitialized, - is AsyncData.Loading -> { - persistentListOf( - MediaViewerPageData.Loading( - direction = Timeline.PaginationDirection.BACKWARDS, - timestamp = systemClock.epochMillis(), - pagerKey = Long.MIN_VALUE, - ) + internal val dataFlow: StateFlow> = galleryDataSource.groupedMediaItemsFlow() + .map { groupedItems -> + when (groupedItems) { + AsyncData.Uninitialized, + is AsyncData.Loading -> { + persistentListOf( + MediaViewerPageData.Loading( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = systemClock.epochMillis(), + pagerKey = Long.MIN_VALUE, ) - } - is AsyncData.Failure -> { - persistentListOf( - MediaViewerPageData.Failure(groupedItems.error), - ) - } - is AsyncData.Success -> { - withContext(dispatcher) { - val mediaItems = groupedItems.data.getItems(galleryMode) - buildMediaViewerPageList(mediaItems) - } + ) + } + is AsyncData.Failure -> { + persistentListOf( + MediaViewerPageData.Failure(groupedItems.error), + ) + } + is AsyncData.Success -> { + withContext(dispatcher) { + val mediaItems = groupedItems.data.getItems(galleryMode) + buildMediaViewerPageList(mediaItems) } } } - } + } + .stateIn( + scope = CoroutineScope(coroutineScope.coroutineContext + dispatcher), + started = SharingStarted.Lazily, + initialValue = initialData(), + ) private fun initialData(): ImmutableList { val initialMediaItems = @@ -148,7 +170,7 @@ class MediaViewerDataSource( is MediaItem.LoadingIndicator -> add( MediaViewerPageData.Loading( direction = mediaItem.direction, - timestamp = systemClock.epochMillis(), + timestamp = mediaItem.timestamp, pagerKey = pagerKeysHandler.getKey(mediaItem), ) ) @@ -161,7 +183,9 @@ class MediaViewerDataSource( } suspend fun loadMore(direction: Timeline.PaginationDirection) { - galleryDataSource.loadMore(direction) + if (galleryDataSource.isReady) { + galleryDataSource.loadMore(direction) + } } suspend fun loadMedia(data: MediaViewerPageData.MediaViewerData) { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt index d834534e3e..e594daeb41 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.lifecycle.lifecycleScope import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin @@ -118,6 +119,7 @@ class MediaViewerNode( navigator = this, dataSource = MediaViewerDataSource( mode = inputs.mode, + coroutineScope = lifecycleScope, dispatcher = coroutineDispatchers.computation, galleryDataSource = mediaGallerySource, mediaLoader = mediaLoader, 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 d40026dd37..296f20ef4c 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 @@ -14,14 +14,12 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.IntState import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject @@ -45,10 +43,7 @@ import io.element.android.libraries.mediaviewer.impl.model.mediaPermissions import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import io.element.android.libraries.androidutils.R as UtilsR @@ -75,12 +70,27 @@ class MediaViewerPresenter( @Composable override fun present(): MediaViewerState { val coroutineScope = rememberCoroutineScope() - val data = dataSource.collectAsState() - val currentIndex = remember { mutableIntStateOf(searchIndex(data.value, inputs.eventId)) } + val currentIndex = remember { mutableIntStateOf(dataSource.findEventIndex(inputs.eventId) ?: 0) } + val data = dataSource.produceState { flow -> + flow.collectLatest { new -> + val existingItem = value.getOrNull(currentIndex.intValue) + val newItem = new.getOrNull(currentIndex.intValue) + if (existingItem is MediaViewerPageData.MediaViewerData && existingItem.eventId == inputs.eventId && newItem != existingItem) { + currentIndex.intValue = dataSource.findEventIndex(inputs.eventId) ?: 0 + } else if (currentIndex.intValue > 0 && value.firstOrNull() is MediaViewerPageData.Loading && + new.firstOrNull() !is MediaViewerPageData.Loading) { + // Restore index based on the eventId after the initial items have been loaded + currentIndex.intValue = dataSource.findEventIndex(inputs.eventId) ?: 0 + } + value = new + } + } + val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() - NoMoreItemsBackwardSnackBarDisplayer(currentIndex, data) - NoMoreItemsForwardSnackBarDisplayer(currentIndex, data) + // Add both forward and backward pagination state checks to display a snackbar when there is no more items to load in either direction + NoMoreItemsSnackBarDisplayer(currentIndex, data, Timeline.PaginationDirection.FORWARDS) + NoMoreItemsSnackBarDisplayer(currentIndex, data, Timeline.PaginationDirection.BACKWARDS) val permissions by room.permissionsAsState(MediaPermissions.DEFAULT) { perms -> perms.mediaPermissions() @@ -176,52 +186,39 @@ class MediaViewerPresenter( } @Composable - private fun NoMoreItemsBackwardSnackBarDisplayer( + private fun NoMoreItemsSnackBarDisplayer( currentIndex: IntState, data: State>, + direction: Timeline.PaginationDirection, ) { - // With newest-first ordering, backward loading indicator is at the last index - val isRenderingLoadingBackward by remember { - derivedStateOf { - currentIndex.intValue == data.value.lastIndex && - data.value.size > 1 && - data.value.lastOrNull() is MediaViewerPageData.Loading + var previousIndex by remember { mutableIntStateOf(currentIndex.intValue) } + var previousDataSize by remember { mutableIntStateOf(data.value.size) } + var wasLoading: Boolean? by remember { mutableStateOf(null) } + LaunchedEffect(currentIndex.intValue, data.value) { + fun isLoading(index: Int, data: List, direction: Timeline.PaginationDirection): Boolean { + return when (direction) { + Timeline.PaginationDirection.BACKWARDS -> index == data.lastIndex && data.lastOrNull() is MediaViewerPageData.Loading + Timeline.PaginationDirection.FORWARDS -> index == 0 && data.firstOrNull() is MediaViewerPageData.Loading + } } - } - if (isRenderingLoadingBackward) { - LaunchedEffect(Unit) { - // Observe the loading data vanishing - snapshotFlow { data.value.lastOrNull() is MediaViewerPageData.Loading } - .distinctUntilChanged() - .filter { !it } - .onEach { showNoMoreItemsSnackbar() } - .launchIn(this) + // Reset the effect when the user navigate to another item so we only take into account index changes caused by data changes + if (previousIndex != currentIndex.intValue) { + wasLoading = null + previousIndex = currentIndex.intValue + } + // If we were navigating backwards and the data size grew, we can discard the previous value: it means we received new items + if (direction == Timeline.PaginationDirection.BACKWARDS && previousDataSize < data.value.size) { + wasLoading = null } - } - } - @Composable - private fun NoMoreItemsForwardSnackBarDisplayer( - currentIndex: IntState, - data: State>, - ) { - // With newest-first ordering, forward loading indicator is at the first index - val isRenderingLoadingForward by remember { - derivedStateOf { - currentIndex.intValue == 0 && - data.value.size > 1 && - data.value.firstOrNull() is MediaViewerPageData.Loading - } - } - if (isRenderingLoadingForward) { - LaunchedEffect(Unit) { - // Observe the loading data vanishing - snapshotFlow { data.value.firstOrNull() is MediaViewerPageData.Loading } - .distinctUntilChanged() - .filter { !it } - .onEach { showNoMoreItemsSnackbar() } - .launchIn(this) + val isLoading = isLoading(currentIndex.intValue, data.value, direction) + + if (wasLoading == true && !isLoading) { + showNoMoreItemsSnackbar() } + + previousDataSize = data.value.size + wasLoading = isLoading } } @@ -293,13 +290,4 @@ class MediaViewerPresenter( CommonStrings.error_unknown } } - - private fun searchIndex(data: List, eventId: EventId?): Int { - if (eventId == null) { - return 0 - } - return data.indexOfFirst { - (it as? MediaViewerPageData.MediaViewerData)?.eventId == eventId - }.coerceAtLeast(0) - } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt index 8a4da2aac3..a51d3c44e9 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.mediaviewer.impl.viewer +import androidx.compose.runtime.Immutable import androidx.compose.runtime.State import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage @@ -29,6 +30,7 @@ data class MediaViewerState( val eventSink: (MediaViewerEvent) -> Unit, ) +@Immutable sealed interface MediaViewerPageData { val pagerKey: Long diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 5e9ced7d77..d52db124ea 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -44,7 +44,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -179,9 +178,11 @@ fun MediaViewerView( val pagerState = rememberPagerState(state.currentIndex, 0f) { state.listData.size } - LaunchedEffect(pagerState) { - snapshotFlow { pagerState.currentPage }.collect { page -> - state.eventSink(MediaViewerEvent.OnNavigateTo(page)) + + LaunchedEffect(pagerState.targetPage, state.currentIndex) { + // Only emit an index navigation change when it's triggered by the user scrolling + if (pagerState.targetPage != state.currentIndex && pagerState.isScrollInProgress) { + state.eventSink(MediaViewerEvent.OnNavigateTo(pagerState.targetPage)) } } HorizontalPager( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt index 7bbf397171..146ace8620 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSource.kt @@ -30,6 +30,8 @@ class SingleMediaGalleryDataSource( override fun groupedMediaItemsFlow() = flowOf(AsyncData.Success(data)) override fun getLastData(): AsyncData = AsyncData.Success(data) + override val isReady: Boolean = true + override suspend fun loadMore(direction: Timeline.PaginationDirection) = Unit override suspend fun deleteItem(eventId: EventId) = Unit diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt index b848ea2a7b..e7d45f433a 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt @@ -33,16 +33,21 @@ import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import io.element.android.tests.testutils.testCoroutineDispatchers import io.mockk.mockk +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain import org.junit.Rule import org.junit.Test +@OptIn(ExperimentalCoroutinesApi::class) class DefaultMediaViewerEntryPointTest { @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() @Test fun `test node builder`() = runTest { + Dispatchers.setMain(testCoroutineDispatchers().main) val entryPoint = DefaultMediaViewerEntryPoint() val mockMediaUri: Uri = mockk("localMediaUri") val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) @@ -89,6 +94,7 @@ class DefaultMediaViewerEntryPointTest { @Test fun `test node builder avatar`() = runTest { + Dispatchers.setMain(testCoroutineDispatchers().main) val entryPoint = DefaultMediaViewerEntryPoint() val mockMediaUri: Uri = mockk("localMediaUri") val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt index 4a64f02a33..5839f33ce6 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FakeMediaGalleryDataSource.kt @@ -15,18 +15,20 @@ import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow class FakeMediaGalleryDataSource( + initialData: AsyncData = AsyncData.Uninitialized, + private val isReadyResult: () -> Boolean = { true }, private val startLambda: () -> Unit = { lambdaError() }, private val loadMoreLambda: (Timeline.PaginationDirection) -> Unit = { lambdaError() }, private val deleteItemLambda: (EventId) -> Unit = { lambdaError() }, - ) : MediaGalleryDataSource { +) : MediaGalleryDataSource { override fun start(coroutineScope: CoroutineScope) = startLambda() - private val groupedMediaItemsFlow = MutableSharedFlow>( - replay = 1 - ) + private val groupedMediaItemsFlow = MutableStateFlow(initialData) + + override val isReady: Boolean get() = isReadyResult() override fun groupedMediaItemsFlow(): Flow> { return groupedMediaItemsFlow diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt index c3f1ab9a0d..d7ba547ee4 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt @@ -62,15 +62,20 @@ class MediaViewerDataSourceTest { @Test fun `test dataFlow uninitialized, loading and error`() = runTest { - val galleryDataSource = FakeMediaGalleryDataSource() + val galleryDataSource = FakeMediaGalleryDataSource( + initialData = AsyncData.Uninitialized, + ) val sut = createMediaViewerDataSource( galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { + // The flow starts with an empty result + assertThat(awaitItem()).isEmpty() galleryDataSource.emitGroupedMediaItems(AsyncData.Uninitialized) assertThat(awaitItem().first()).isInstanceOf(MediaViewerPageData.Loading::class.java) galleryDataSource.emitGroupedMediaItems(AsyncData.Loading()) - assertThat(awaitItem().first()).isInstanceOf(MediaViewerPageData.Loading::class.java) + // No items emitted, we were already loading data + ensureAllEventsConsumed() galleryDataSource.emitGroupedMediaItems(AsyncData.Failure(AN_EXCEPTION)) assertThat(awaitItem().first()).isEqualTo(MediaViewerPageData.Failure(AN_EXCEPTION)) } @@ -82,7 +87,7 @@ class MediaViewerDataSourceTest { val sut = createMediaViewerDataSource( galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -102,7 +107,8 @@ class MediaViewerDataSourceTest { val sut = createMediaViewerDataSource( galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { + skipItems(1) galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -141,7 +147,8 @@ class MediaViewerDataSourceTest { mode = MediaViewerMode.TimelineImagesAndVideos(timelineMode = Timeline.Mode.Media), galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { + skipItems(1) galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -163,7 +170,8 @@ class MediaViewerDataSourceTest { mode = MediaViewerMode.TimelineFilesAndAudios(timelineMode = Timeline.Mode.Media), galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { + skipItems(1) galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -184,7 +192,8 @@ class MediaViewerDataSourceTest { val sut = createMediaViewerDataSource( galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { + skipItems(1) galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -217,7 +226,8 @@ class MediaViewerDataSourceTest { val sut = createMediaViewerDataSource( galleryDataSource = galleryDataSource, ) - sut.dataFlow().test { + sut.dataFlow.test { + skipItems(1) galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -241,7 +251,8 @@ class MediaViewerDataSourceTest { galleryDataSource = galleryDataSource, mediaLoader = mediaLoader, ) - sut.dataFlow().test { + sut.dataFlow.test { + skipItems(1) galleryDataSource.emitGroupedMediaItems( AsyncData.Success( aGroupedMediaItems( @@ -271,6 +282,7 @@ class MediaViewerDataSourceTest { mediaLoader: MatrixMediaLoader = FakeMatrixMediaLoader(), localMediaFactory: LocalMediaFactory = FakeLocalMediaFactory(mockMediaUrl), ) = MediaViewerDataSource( + coroutineScope = backgroundScope, mode = mode, dispatcher = testCoroutineDispatchers().computation, galleryDataSource = galleryDataSource, 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 86689859ad..459d30b8d5 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 @@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 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.media.FakeMatrixMediaLoader @@ -51,6 +52,8 @@ import io.mockk.mockk import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -97,6 +100,8 @@ class MediaViewerPresenterTest { assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.canShowInfo).isTrue() assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) + + cancelAndIgnoreRemainingEvents() } } @@ -120,6 +125,8 @@ class MediaViewerPresenterTest { assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.canShowInfo).isFalse() assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) + + cancelAndIgnoreRemainingEvents() } } @@ -143,6 +150,8 @@ class MediaViewerPresenterTest { assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.canShowInfo).isTrue() assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) + + cancelAndIgnoreRemainingEvents() } } @@ -167,6 +176,8 @@ class MediaViewerPresenterTest { assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.canShowInfo).isTrue() assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) + + cancelAndIgnoreRemainingEvents() } } @@ -555,6 +566,8 @@ class MediaViewerPresenterTest { ) val finalState = awaitItem() assertThat(finalState.currentIndex).isEqualTo(1) + + cancelAndIgnoreRemainingEvents() } } @@ -578,32 +591,34 @@ class MediaViewerPresenterTest { mode: MediaViewerEntryPoint.MediaViewerMode, expectedSnackbarResId: Int, ) = runTest { + val image = anImage.copy(eventId = AN_EVENT_ID) val mediaGalleryDataSource = FakeMediaGalleryDataSource( + initialData = AsyncData.Success( + if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { + GroupedMediaItems( + imageAndVideoItems = persistentListOf(), + fileItems = persistentListOf(aForwardLoadingIndicator, image, aBackwardLoadingIndicator), + ) + } else { + GroupedMediaItems( + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, image, aBackwardLoadingIndicator), + fileItems = persistentListOf(), + ) + } + ), startLambda = { }, ) val presenter = createMediaViewerPresenter( + eventId = AN_EVENT_ID, localMediaFactory = localMediaFactory, mode = mode, mediaGalleryDataSource = mediaGalleryDataSource, ) presenter.test { - awaitFirstItem() - mediaGalleryDataSource.emitGroupedMediaItems( - AsyncData.Success( - if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { - GroupedMediaItems( - imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), - ) - } else { - GroupedMediaItems( - imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), - fileItems = persistentListOf(), - ) - } - ) - ) - val updatedState = awaitItem() + val updatedState = awaitFirstItem() + + advanceUntilIdle() + runCurrent() // User navigate to the first item (forward loading indicator) updatedState.eventSink( MediaViewerEvent.OnNavigateTo(0) @@ -614,17 +629,17 @@ class MediaViewerPresenterTest { if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(anImage, aBackwardLoadingIndicator), + fileItems = persistentListOf(image, aBackwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(anImage, aBackwardLoadingIndicator), + imageAndVideoItems = persistentListOf(image, aBackwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) - skipItems(1) + skipItems(2) val stateWithSnackbar = awaitItem() assertThat(stateWithSnackbar.snackbarMessage!!.messageResId).isEqualTo(expectedSnackbarResId) } @@ -707,21 +722,19 @@ class MediaViewerPresenterTest { fun `present - no snackbar displayed when there is no more items but not displaying a loading item`() = runTest { val mediaGalleryDataSource = FakeMediaGalleryDataSource( startLambda = { }, + initialData = AsyncData.Success( + GroupedMediaItems( + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, anImage.copy(eventId = AN_EVENT_ID_2), aBackwardLoadingIndicator), + fileItems = persistentListOf(), + ) + ) ) val presenter = createMediaViewerPresenter( + eventId = AN_EVENT_ID, localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) presenter.test { - awaitFirstItem() - mediaGalleryDataSource.emitGroupedMediaItems( - AsyncData.Success( - GroupedMediaItems( - imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), - fileItems = persistentListOf(), - ) - ) - ) val updatedState = awaitItem() // User navigate to the media updatedState.eventSink( @@ -774,6 +787,51 @@ class MediaViewerPresenterTest { } } + @Test + fun `present - receiving loading items with different timestamps emits different items too`() = runTest { + val loadMoreLambda = lambdaRecorder { } + val mediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + loadMoreLambda = loadMoreLambda, + ) + val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, + mediaGalleryDataSource = mediaGalleryDataSource, + ) + val anImage = aMediaItemImage( + mediaSourceUrl = aUrl, + ) + presenter.test { + awaitFirstItem() + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + GroupedMediaItems( + imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), + fileItems = persistentListOf(), + ) + ) + ) + val updatedState = awaitItem() + + // Get the exact same items, but with new timestamps for the loading indicators + mediaGalleryDataSource.emitGroupedMediaItems( + AsyncData.Success( + GroupedMediaItems( + imageAndVideoItems = persistentListOf( + aForwardLoadingIndicator.copy(timestamp = 1234L), + anImage, + aBackwardLoadingIndicator.copy(timestamp = 1234L), + ), + fileItems = persistentListOf(), + ) + ) + ) + + // We should get a new list of items, which should not be equal to the previous one + assertThat(updatedState.listData).isNotEqualTo(awaitItem().listData) + } + } + @Test fun `present - view in timeline hides the bottom sheet and invokes the navigator`() = runTest { val onViewInTimelineClickLambda = lambdaRecorder { } @@ -794,6 +852,7 @@ class MediaViewerPresenterTest { presenter.test { val initialState = awaitItem() initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) + skipItems(1) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) initialState.eventSink(MediaViewerEvent.ViewInTimeline(AN_EVENT_ID)) @@ -823,6 +882,7 @@ class MediaViewerPresenterTest { presenter.test { val initialState = awaitItem() initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) + skipItems(1) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) initialState.eventSink(MediaViewerEvent.Forward(AN_EVENT_ID)) @@ -854,6 +914,7 @@ class MediaViewerPresenterTest { presenter.test { val initialState = awaitItem() initialState.eventSink(MediaViewerEvent.OpenInfo(aMediaViewerPageData())) + skipItems(1) val withBottomSheetState = awaitItem() assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.Details::class.java) initialState.eventSink(MediaViewerEvent.Forward(AN_EVENT_ID)) @@ -892,6 +953,7 @@ internal fun TestScope.createMediaViewerPresenter( ), navigator = mediaViewerNavigator, dataSource = MediaViewerDataSource( + coroutineScope = backgroundScope, mode = mode, dispatcher = testCoroutineDispatchers().computation, galleryDataSource = mediaGalleryDataSource, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index b426ca50ca..6521f450f5 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -13,6 +13,11 @@ package io.element.android.libraries.mediaviewer.impl.viewer import android.net.Uri import androidx.activity.ComponentActivity import androidx.annotation.StringRes +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assertHasClickAction @@ -23,6 +28,7 @@ import androidx.compose.ui.test.swipeDown import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia import io.element.android.libraries.ui.strings.CommonStrings @@ -33,9 +39,11 @@ import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.setSafeContent import io.mockk.mockk +import kotlinx.coroutines.delay import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config +import kotlin.time.Duration.Companion.milliseconds @RunWith(AndroidJUnit4::class) class MediaViewerViewTest { @@ -60,7 +68,6 @@ class MediaViewerViewTest { } eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), ) ) @@ -122,7 +129,6 @@ class MediaViewerViewTest { onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(data), expectedEvent, ) @@ -178,7 +184,6 @@ class MediaViewerViewTest { clickOn(textRes) eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(data), expectedEvent, ) @@ -208,7 +213,6 @@ class MediaViewerViewTest { .assertDoesNotExist() eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), ) ) @@ -231,7 +235,6 @@ class MediaViewerViewTest { } eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(state.listData.first() as MediaViewerPageData.MediaViewerData), ) ) @@ -256,7 +259,6 @@ class MediaViewerViewTest { clickOn(CommonStrings.action_retry) eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(data), MediaViewerEvent.LoadMedia(data), ) @@ -282,12 +284,65 @@ class MediaViewerViewTest { clickOn(CommonStrings.action_cancel) eventsRecorder.assertList( listOf( - MediaViewerEvent.OnNavigateTo(0), MediaViewerEvent.LoadMedia(data), MediaViewerEvent.ClearLoadingError(data) ) ) } + + @Test + fun `loading event after an error triggers load more Event`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + val states = listOf( + aMediaViewerState( + listData = listOf(aMediaViewerPageDataLoading(timestamp = 0L)), + eventSink = eventsRecorder, + ), + aMediaViewerState( + listData = listOf(MediaViewerPageData.Failure(IllegalStateException("error"))), + eventSink = eventsRecorder, + ), + aMediaViewerState( + listData = listOf(aMediaViewerPageDataLoading(timestamp = 0L)), + eventSink = eventsRecorder, + ), + // This one should be ignored since it has the same timestamp as the last one, it should not trigger a recomposition + aMediaViewerState( + listData = listOf(aMediaViewerPageDataLoading(timestamp = 0L)), + eventSink = eventsRecorder, + ), + ) + setSafeContent { + // Iterate over the states with a delay to give the view some time to trigger the `LoadMore` Event + var state by remember { mutableStateOf(states.first()) } + LaunchedEffect(Unit) { + val iterator = states.iterator() + while (iterator.hasNext()) { + delay(200.milliseconds) + state = iterator.next() + } + } + MediaViewerView( + state = state, + textFileViewer = { _, _ -> }, + onBackClick = EnsureNeverCalled(), + audioFocus = null, + ) + } + + // Advance time to let the states update + mainClock.advanceTimeBy(3_000) + + // `LoadMore` should be called twice, once for the first loading state, and once for the second one even though they have the same timestamp because + // of the intermediate error state. + // The third one will be ignored since it has the same timestamp as the second one and it'll be discarded by the Compose's equality diffing. + eventsRecorder.assertList( + listOf( + MediaViewerEvent.LoadMore(direction = Timeline.PaginationDirection.BACKWARDS), + MediaViewerEvent.LoadMore(direction = Timeline.PaginationDirection.BACKWARDS), + ) + ) + } } private fun AndroidComposeUiTest.setMediaViewerView( From 64d933690180126f2fab1c1d964aa780d4a0cb1c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 20 May 2026 14:26:44 +0200 Subject: [PATCH 0462/1083] Fix 'Conversation label cannot be empty' error (#6823) This happens when building a `ShortcutInfoCompat` in `DefaultNotificationConversationService.onSendMessage` when the provided room name is not null but it's empty. --- .../impl/messagecomposer/MessageComposerPresenter.kt | 2 +- .../conversations/NotificationConversationService.kt | 2 +- .../DefaultNotificationConversationService.kt | 7 ++++--- .../conversations/FakeNotificationConversationService.kt | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index d93fe0ee86..b42cda7dfc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -571,7 +571,7 @@ class MessageComposerPresenter( notificationConversationService.onSendMessage( sessionId = room.sessionId, roomId = roomInfo.id, - roomName = roomInfo.name ?: roomInfo.id.value, + roomName = roomInfo.name, roomIsDirect = roomInfo.isDm, roomAvatarUrl = roomInfo.avatarUrl ?: roomMembers.getDirectRoomMember(roomInfo = roomInfo, sessionId = room.sessionId)?.avatarUrl, ) diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/conversations/NotificationConversationService.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/conversations/NotificationConversationService.kt index 504adacdb6..4ea80e4ce8 100644 --- a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/conversations/NotificationConversationService.kt +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/conversations/NotificationConversationService.kt @@ -22,7 +22,7 @@ interface NotificationConversationService { suspend fun onSendMessage( sessionId: SessionId, roomId: RoomId, - roomName: String, + roomName: String?, roomIsDirect: Boolean, roomAvatarUrl: String?, ) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt index ce20234385..f898e4a9ed 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/conversations/DefaultNotificationConversationService.kt @@ -76,7 +76,7 @@ class DefaultNotificationConversationService( override suspend fun onSendMessage( sessionId: SessionId, roomId: RoomId, - roomName: String, + roomName: String?, roomIsDirect: Boolean, roomAvatarUrl: String?, ) { @@ -93,10 +93,11 @@ class DefaultNotificationConversationService( val imageLoader = imageLoaderHolder.get(client) val defaultShortcutIconSize = ShortcutManagerCompat.getIconMaxWidth(context) + val name = roomName?.takeIf { it.isNotBlank() } ?: roomId.value val icon = bitmapLoader.getRoomBitmap( avatarData = AvatarData( id = roomId.value, - name = roomName, + name = name, url = roomAvatarUrl, size = AvatarSize.RoomDetailsHeader, ), @@ -105,7 +106,7 @@ class DefaultNotificationConversationService( )?.let(IconCompat::createWithBitmap) val shortcutInfo = ShortcutInfoCompat.Builder(context, createShortcutId(sessionId, roomId)) - .setShortLabel(roomName) + .setShortLabel(name) .setIcon(icon) .setIntent(intentProvider.getViewRoomIntent(sessionId, roomId, threadId = null, eventId = null)) .setCategories(categories) diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/conversations/FakeNotificationConversationService.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/conversations/FakeNotificationConversationService.kt index 0c8d870448..a2022ea22d 100644 --- a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/conversations/FakeNotificationConversationService.kt +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/conversations/FakeNotificationConversationService.kt @@ -16,7 +16,7 @@ class FakeNotificationConversationService : NotificationConversationService { override suspend fun onSendMessage( sessionId: SessionId, roomId: RoomId, - roomName: String, + roomName: String?, roomIsDirect: Boolean, roomAvatarUrl: String?, ) = Unit From 3d85cf4fd24dbc32d0e4f3bfc5b24f07a6602005 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 14:27:38 +0200 Subject: [PATCH 0463/1083] Format --- .../features/roomdetails/impl/RoomDetailsPresenterTest.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index 5a845c3331..51a6f97ab0 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -633,7 +633,8 @@ class RoomDetailsPresenterTest { assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(false) markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ)) clearMessagesForRoomResult.assertions().isCalledOnce().with( - value(room.sessionId), value(room.roomId) + value(room.sessionId), + value(room.roomId), ) } } @@ -664,7 +665,8 @@ class RoomDetailsPresenterTest { assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(false) markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ_PRIVATE)) clearMessagesForRoomResult.assertions().isCalledOnce().with( - value(room.sessionId), value(room.roomId) + value(room.sessionId), + value(room.roomId), ) } } From 260ea4a7d26546d6ca93ee01136ffbcd508ace39 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 20 May 2026 12:44:42 +0000 Subject: [PATCH 0464/1083] Update screenshots --- .../images/features.roomdetails.impl_RoomDetailsA11y_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_0_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_10_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_11_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_12_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_13_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_14_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_15_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_16_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_17_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_18_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_19_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_1_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_20_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_21_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_22_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_2_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_3_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_4_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_5_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_6_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_7_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_8_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_9_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_0_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_10_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_11_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_12_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_13_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_14_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_15_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_16_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_17_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_18_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_19_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_1_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_20_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_21_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_22_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_2_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_3_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_4_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_5_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_6_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_7_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_8_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_9_en.png | 4 ++-- 47 files changed, 94 insertions(+), 94 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png index 43a49f7320..25302db21d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34ce2f0451fb1681648c91771316256e67b1f295f4deb97f6115ae593d82f2ef -size 83472 +oid sha256:d7c187e173ae6d02d6c95c03bcc24cce91b0922e6aa5a08677732748aab0fc30 +size 85320 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png index bb68ee4d65..739ff5f268 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eeb2355a693a7ac522028833fea4f0506e1b455e4aee888ed314c2700a9a87af -size 45454 +oid sha256:8979ec6209ad6e0deb6946e00ce227f3db41a565218afe31b72b889bee224daa +size 46268 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png index 77bc91df06..7609f5e725 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b45d35b68d232fc5cbaf3b01156127a77618bcf2197375ad42f61bc7ad8ec400 -size 44161 +oid sha256:16200632461dcbbf0f6211b7064b61a1e2fa04cd34e14946beb12b9e9f4d7b7f +size 43901 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png index 9f23841e1d..ef1954720c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a7efaa997737bfc6db898987b78077ec3c8039a6d0cce84d770bcabcbdc815e -size 43161 +oid sha256:2279893a284e620cf487f6370982a14278fd57bb278e53932a5fd7c5cab8e95e +size 43033 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png index 308c764795..a0cee002e6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8de9a9297383ff1ec552304a49040c44236654dd16ba9ae5f54fddf3e14c617 -size 44764 +oid sha256:5d4da60a94c56b13b65efb797825c54c1e107fe4440f56b1fcac5d47779cbf64 +size 44502 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png index 13403ea92d..eb330780d8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff4c856028887c1390df7b313462e37e0723ff98b9f92aa769b2fc9133ab6ec5 -size 44673 +oid sha256:ee2899f7870b09f287b45b327d5d0462b423ba65afa1087dec1be862507378de +size 44411 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png index 59ac3c53af..e09c2dfd95 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:162a9cd8b10b8ec7c33dc926c63d2d04986ca0e29a6cd036771ffc137176e28c -size 45079 +oid sha256:78ba2ddfdfc47febc0503daa0985a5fdf04ef15bdc391b4a88c3c630b1946b35 +size 46004 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png index 9d934ba726..cc49f40494 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcd3e86c18e34e96a2b535340a27a8cb248d48697ce75d1c7c62cde27b3e2ccb -size 45577 +oid sha256:4a832b0e395498b15e176529ea55c50ed129f6d2330fbec4ff1f8e3dcaeab93f +size 46543 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png index cfd42f8af2..e8c0ec1046 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5a20887fa9a6dd7c96f328f24608e1fcea0326b60cf8a7b43e2387fa19595f5 -size 44932 +oid sha256:d8e738bd873339d195b4190f65a18016f2f0eb1bbc9f513a2b25467cb5f5828c +size 44745 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png index b45fd6c6f1..5098ecb3a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8087a634dd7bf3893697d8ab599f9694169e878b4484b0d8e9821307a8423d63 -size 44243 +oid sha256:892dd301ab08c6a302e8286d3f86878178130a22baf550402f2102ba98f0d21c +size 43982 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index 9f56dab8f3..899ef403a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f239cb428d2e4cffa86e8d8397904af0c0c5e621585f31bcf3135cdd2c81a40 -size 40541 +oid sha256:809c597757d6f1385803c1378a494f24309b533168df59c7e06852c1ce34b8d3 +size 41408 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 81bb7961e9..0625fcfe05 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bcc557108fc16a1f63d22b3512d271d30dccc801838607e78921baf9ba490c0 -size 40509 +oid sha256:3756793e5d92f0fac18e96a49e69ac7ed6901c1195d3e6526088027405e82dbf +size 41361 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png index 6b89622e9d..346c9cf052 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7b4d5f81f605a0858994e50d72fbd17d2f82e0b2e4673ff9baf6e25a103ef55 -size 40392 +oid sha256:099f571485ce8476d4b8a2313610b6c1d03a7d7420132e06d6258b483d640a08 +size 39130 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png index b0a44326fd..a58193c18f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fef854b4c908e206ece79491c655fbf0fd5b51883f3d77045c579664331b9058 -size 45195 +oid sha256:66fd2cfb9f343c77b8db0a4fbc0d7a1571a4dfe1d70c78823a4ba03bfbc846eb +size 44934 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png index 637549dfc7..37bb88b0fb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dde778a13f36958fefba950fe0d3470b7277d22fe4eac189c77b0838b3728ef3 -size 44940 +oid sha256:465ecd337f705262c8f533b3b01daa6a548c6ee88752be405609660ddfaf56b1 +size 44676 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png index cafc853f58..6356cec349 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5870cd12f6de78ecf72a9dc8e3716e0e3476ecf2f29647fc1eca900f5e030f9 -size 44652 +oid sha256:3cca233c171b6c6709a94163ca1f0024a42ff66200383fdbcaf57b321251522e +size 44390 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png index 12efcf7526..3846aec585 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1281394671737e78232cb7d9785b57b8ef2ca50c125f0c0854d101d27efaa939 -size 37910 +oid sha256:9e5e8b39197d115c6190b89fd54033b3319b36dfbf5c6f152dd84e6c79147bbb +size 37877 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png index 3d6f26c63c..08ca4ad1e6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec2b5711ea9ffacc6aad4f7b16efdcc78603e9eaa9d33abfaa0d867db5aead67 -size 42355 +oid sha256:4899d2ffcc6da1f414f7fb223440b8463250dc5ac07558cfaee2947f95c93362 +size 42236 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png index 90dd2364d3..062c440463 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4adfa037ff619098067d03f252ba0af1c3c89553ea0c81dcda41f7f0b655baad -size 42450 +oid sha256:577381a33e7f0a88ceebb7f2be6528c3e99417cf1351b74c134aab948664cc64 +size 42149 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index 2d3d2f0a74..1ff34bd6e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76f63f6c98318762a574d7fb04c8e23ad8312b1fc9adc404669ac6d9e2c42097 -size 40127 +oid sha256:b2bc2699d8dcf770103726c571a6966eacf173cbbad05c4fa6188815aa9ae231 +size 41052 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png index bca90757f7..c1decbd918 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3063251e98ea6e797e5178cb954d99e71fc1422df19c24a59b1395531380e941 -size 41113 +oid sha256:9cba49398954a404def6b37f3cde057cb88d6f59249b943f1689403ccd902326 +size 42024 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png index fc66173002..379f61db22 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d5b8a9f7bc2e7f654b018b2f66b5971c21326dd6b64371f330299649daea4c0 -size 45755 +oid sha256:405a29c158295616560152c5790f189a8019bd635a53a69b581c8aa595e6e9ea +size 45494 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png index d4ff65b44f..d0ffc70f42 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dd6b524bd146b4e66621fea59515e6784055f52f6d1d08c393b5be208e5f29a -size 44657 +oid sha256:3f948e9cc2eb7bc73b0441fbdea72d582a042895b3404c8302b7e182c3481fae +size 44425 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png index 4264857e69..2894ac3c71 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73a27b8df68182a3d0ae4872a14688ae10e5651ec85490c1e46186acc2c60028 -size 44671 +oid sha256:b4702b18ad5d203050140e6e1a18553344f52eb5482fcaf6ab497698b9ec59fd +size 44432 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png index f0751a53cd..afabfcecf5 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9bedc6d0b55d94586de728cb4039303c9ecbd8b3a090c401331ae1bf6e0ba426 -size 46396 +oid sha256:4189b58dd1263a81566ea86d9881c02f053ecb2a91ba9442553fbe0f230e6860 +size 47105 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png index f5f4d4cf3c..9f07ad1624 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d47a7207e83fe770d4925b91b4bb0eee6cb2c494c46b1f3d5d6d0720464392d6 -size 44992 +oid sha256:3fced9019f81e5804ea57c0b1a2750868626ad35b9a7227009a796d289595556 +size 44659 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png index 54890aa7bd..74c4a9eef1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:605ea373238bbaa4d3820adf13bf3896d9a5c5b6ceb6c022a7f3b8ae817f921f -size 43927 +oid sha256:be9bb839a503d169d67d4332a133ce2b3d76b3ff4c52c063436521f8a74c973e +size 43894 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png index 385ca39bc9..bd85882fde 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4dab72328925eb45cd529913972670587ea4257d2ff7affd708295d68e783d7 -size 45579 +oid sha256:82c2781c37b7cefa198f2061a2c8e900b27bd57653db88733be5ff55dfaf5eee +size 45251 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png index 064cfc5b27..cac488f3b8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76cc029a07c0fb568d9e15864be667478cd9927095f66ec2f590a1466c58a291 -size 45497 +oid sha256:36feab599a6a2d4269b68f42149a6f82832ac0f6f0e9f01fb49adc21b3a58d93 +size 45172 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png index 3bcd7d1de4..3e7cfcf672 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42a8b9b5abe3a5a3fe61e27924ca75ea7925e857005d5de3cd3ceb81500f73c2 -size 45981 +oid sha256:04bedd62b5ceba766197dd18da9efb0ff086c2c01c9c19446f8a3c42ed43ad87 +size 46813 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png index 5dc96aaa2c..27ec9f7a25 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19cc2df1da3b685668afe309bd305d5ac8447d0997c7ad902685d44daa26239f -size 46556 +oid sha256:828b065aaeeccd826e98e9601069819d7a75ffabab9820a834cacb627416edc0 +size 47409 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png index 2b4718d729..f96e1aec74 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5625bb01c24d969adeecdb536e145ba549ef1c10d99e16f7a68c3bd577fbefbc -size 45804 +oid sha256:4740bcd118f8583334dd1c03b5011e33c5384ea6810d1c83711f538cf9f1d165 +size 45521 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png index 4f40cab65a..4d88149a93 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bdd0b00fddd9fc62b5c9c97b5ff766591c0a1822730bd249059ed02508a65ee -size 45353 +oid sha256:7fab53a63021ddae8384aed8eaf0a3803d06e8c80645ecc13f79a7f5cced6e68 +size 45024 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index 3151e8d088..fa7e99aef2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fb58a8db96c0e76d5a0e8c8d2a38ae206e3dade479bd924fd404902c8e69b42 -size 41322 +oid sha256:89a2c619412ad9ca43c79cb76ebe72b827da71743dda7044a9b44de2990f160b +size 42388 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index e213e801f3..9b27b61083 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5030731135dec08034e1992499caa251aae8039cebafb09210fc83d622b06bd9 -size 41257 +oid sha256:56ceed440bb51039ffe7e4419477a57a235eed153a0188838e6265c241896a82 +size 42262 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png index 02be5d5da0..0542085126 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4dd437c614c904bf210e5b51fe017f26cf849e7572b09966e834ac6fd429d347 -size 41380 +oid sha256:3b03e9da2d73cc0e3d0485b73470e576d7ebd4b8b5f375f2a478f1c1524772fa +size 39948 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png index 7c037817b4..a320657a26 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:380fbdd2caa485b9fe84a331e64139ccb23998ce1d95158c6345364daa3810b8 -size 46048 +oid sha256:a686a2596b9b85b17c6882aa986b12e13a83a47ed217c4eb6de6aa2cb3ec2d50 +size 45717 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png index 7b74e5750c..920b670806 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4610f8488c8c8edf05e2cd3e09470660b2c4db14650907c28367d2b38bce852 -size 45792 +oid sha256:d6bda369c1754e2c07216f4bff0285e017f87b550fe0dc6bb5f127845d52c9b6 +size 45462 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png index a2e1108c0c..aeaa04b269 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efb795d2808d7ae5e38eda42105101dce377154c794844f752e4cb80dcabd681 -size 45462 +oid sha256:285045769d912e98df0371c829affd925642c8a20cd0b6b09dfa92ab5f143538 +size 45131 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png index 2d38f9d8b1..e7fe0e7cef 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7dca0800e7e68e65bd27814b4c86123da40385d6e85153e003ba58ca7689b5f8 -size 38742 +oid sha256:463548e170b48509d68c0993acb000748b19921e5d4be784b07ce83252c8a5bb +size 38613 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png index 1fc42278e2..76eb564d8c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:351183a1b0fb44dc42c790a625ee6aa5740b27fa95b138252b72bf67268f5a16 -size 43015 +oid sha256:c1d19c2b8c6b3c80b68214da2bb9f54a6897a279aa70e2d8cab88c291332cece +size 42980 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png index da0c4a9dde..40ab9e310a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31f92cc4d97c7129bc37da51e6f0a10612d4f61803762b1709c5d72f1cda86f1 -size 43337 +oid sha256:2057479cad5d3b9a89ec835ee1d06705c6c459f7810c2875bea26b975944bcf7 +size 42960 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index 5c16501c76..e549a92821 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e54b946de1128b1109ece7553e73d7676199edc45e7f275014c37503336d302e -size 40862 +oid sha256:073addf26e8d0b638bce93db99d1fe9740abd89613a1eb8ef5bb4324e489d6fa +size 41924 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png index 55ab231ede..29a8b0b4b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f3df6d78498d2b390cf926fb1111fdfa0f38ba5dd9e023b9bd2af42c3951511 -size 41921 +oid sha256:56d72cab4a9d7af568cc497b68d6ca9055874544cfd462c93da37fe368801fdf +size 42984 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png index ae9d249cb2..91cf700f52 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e15030fc182998a37493228d91c888d6b499b6a684b1a4e15d402c9156a40ba -size 46678 +oid sha256:9141f5fa4e054dc5cf70126309830bc38d564d467a215eaa1130f3601b15e761 +size 46350 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png index 214dee1111..fe0b629925 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b773cce165a6410140afbf0daf3ec526233b97ea707811a3794e591704237398 -size 45536 +oid sha256:a062b8cbe4dfbd94a5b068b1f7c4654ed8b697a7e98ae4c2bcb6c3e5bf473b49 +size 45289 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png index 41946442cb..26d59539db 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f28bec4fb21e827f3467bc08ab0f33e917cf76360903b6e7df6282a7589cae7e -size 45545 +oid sha256:46aafd39e1a93f8d357def4c5f3f024ad0ee13931ebdb9f72475dbc911fd7532 +size 45266 From 67c668990e3f798d980685e12804fe68ca462f11 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 14:50:26 +0200 Subject: [PATCH 0465/1083] Hide edit pencil from accessibility Closes #6378 --- .../libraries/matrix/ui/components/AvatarPickerView.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt index e743a2447c..4d3ba4dc6b 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt @@ -42,6 +42,7 @@ import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.hideFromAccessibility import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp @@ -196,7 +197,10 @@ private fun BoxScope.OverlayEditButton( .clip(CircleShape) .clickable(interactionSource = interactionSource, onClick = onClick, indication = null) .background(ElementTheme.colors.bgCanvasDefault) - .border(BorderStroke(1.dp, ElementTheme.colors.borderInteractiveSecondary), shape = CircleShape), + .border(BorderStroke(1.dp, ElementTheme.colors.borderInteractiveSecondary), shape = CircleShape) + .clearAndSetSemantics { + hideFromAccessibility() + }, contentAlignment = Alignment.Center, ) { Icon( From 42566b4b1f28cd737cdbd0fceef5d15f27a703b7 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 20 May 2026 15:23:03 +0200 Subject: [PATCH 0466/1083] Release proximity wakelock on Element Call when call ends (#6825) The `CoroutineScope` that launched this logic was cancelled by that point, so the wakelock was never released. --- .../features/call/impl/utils/WebViewAudioManager.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index 2d674d21af..febd919149 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -201,12 +201,9 @@ class WebViewAudioManager( return } - coroutineScope.launch { - proximitySensorMutex.withLock { - if (proximitySensorWakeLock?.isHeld == true) { - proximitySensorWakeLock?.release() - } - } + // Since this should run when the call is no longer running, it should be OK to not use the mutex here + if (proximitySensorWakeLock?.isHeld == true) { + proximitySensorWakeLock?.release() } audioManager.mode = AudioManager.MODE_NORMAL From 620f1865e8db8fc46a005aa1fb822d7e7fb6ab7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:39:11 +0200 Subject: [PATCH 0467/1083] [a11y] Improve accessibility of screen headers. --- .../impl/threads/list/ThreadsListView.kt | 16 ++++++++++++- .../impl/topbars/MessagesViewTopBar.kt | 8 +++---- .../messages/impl/topbars/ThreadTopBar.kt | 23 +++++++++++++------ .../src/main/res/values/localazy.xml | 2 ++ 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt index 1beabcd3fa..5e26d849a5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt @@ -31,6 +31,9 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.heading import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -79,7 +82,18 @@ fun ThreadsListView( topBar = { TopAppBar( title = { - Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) { + val description = stringResource( + CommonStrings.a11y_threads_in_room, + state.roomName, + ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clearAndSetSemantics { + heading() + contentDescription = description + }, + ) { Avatar( avatarData = AvatarData( id = state.roomId.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index 639092fc6c..4f023ad2bd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -80,7 +80,8 @@ internal fun MessagesViewTopBar( Row( modifier = Modifier .clip(roundedCornerShape) - .clickable { onRoomDetailsClick() }, + .clickable { onRoomDetailsClick() } + .semantics { heading() }, horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically, ) { @@ -158,10 +159,7 @@ private fun RoomAvatarAndNameRow( ) Text( modifier = Modifier - .padding(start = 8.dp) - .semantics { - heading() - }, + .padding(start = 8.dp), text = roomName ?: stringResource(CommonStrings.common_no_room_name), style = ElementTheme.typography.fontBodyLgMedium, fontStyle = FontStyle.Italic.takeIf { roomName == null }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt index e73b6b19b7..5ef4541f06 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/ThreadTopBar.kt @@ -17,8 +17,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.heading -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -58,7 +59,18 @@ internal fun ThreadTopBar( BackButton(onClick = onBackClick) }, title = { - Row(verticalAlignment = Alignment.CenterVertically) { + val name = roomName ?: stringResource(CommonStrings.common_no_room_name) + val description = stringResource( + CommonStrings.a11y_thread_in_room, + name, + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clearAndSetSemantics { + heading() + contentDescription = description + }, + ) { Avatar( avatarData = roomAvatarData, avatarType = AvatarType.Room( @@ -69,17 +81,14 @@ internal fun ThreadTopBar( Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp), ) { Text( text = stringResource(CommonStrings.common_thread), style = ElementTheme.typography.fontBodyLgMedium, ) Text( - text = roomName ?: stringResource(CommonStrings.common_no_room_name), + text = name, style = ElementTheme.typography.fontBodySmRegular, fontStyle = FontStyle.Italic.takeIf { roomName == null }, color = ElementTheme.colors.textSecondary, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ee0f51000a..6fa5436f96 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -54,6 +54,8 @@ "Start a call" "Start a video call" "Start a voice call" + "Thread in %1$s" + "Threads in %1$s" "Tombstoned room" "User avatar" "User menu" From 5b2970f78906cb22312dcbcc0c37036c114804a8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:49:18 +0200 Subject: [PATCH 0468/1083] [a11y] Improve accessibility of screen headers. --- .../mediaviewer/impl/viewer/MediaViewerView.kt | 14 +++++++++++--- .../ui-strings/src/main/res/values/localazy.xml | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index d52db124ea..3a7c006593 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -55,6 +55,8 @@ import androidx.compose.ui.layout.onVisibilityChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextOverflow @@ -495,14 +497,20 @@ private fun MediaViewerTopBar( TopAppBar( title = { if (senderName != null && dateSent != null) { + val description = stringResource( + CommonStrings.a11y_sent_by_sender_at_date, + senderName, + dateSent, + ) Column( modifier = Modifier .fillMaxWidth() + .clearAndSetSemantics { + heading() + contentDescription = description + }, ) { Text( - modifier = Modifier.semantics { - heading() - }, text = senderName, style = ElementTheme.typography.fontBodyMdMedium, color = ElementTheme.colors.textPrimary, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 6fa5436f96..1c94927623 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -48,6 +48,7 @@ "Room avatar" "Send files" "Sender location" + "Sent by %1$s at %2$s" "Time limited action required, you have one minute to verify" "Settings, action required" "Show password" From c2e357cbcdc4aa519cbc38690da7c860cafeaf94 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:52:46 +0200 Subject: [PATCH 0469/1083] [a11y] Improve accessibility of screen headers. --- .../android/features/space/impl/root/SpaceView.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt index 05fb75ee5e..29898a1f63 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceView.kt @@ -354,7 +354,8 @@ private fun EmptySpaceView( title = stringResource(R.string.screen_space_empty_state_title), subTitle = null, iconStyle = BigIcon.Style.Default(vectorIcon = CompoundIcons.Room(), usePrimaryTint = true), - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(top = 40.dp, start = 24.dp, end = 24.dp, bottom = 24.dp), ) ButtonColumnMolecule( @@ -425,6 +426,7 @@ private fun SpaceViewTopBar( modifier = Modifier .clip(roundedCornerShape) .clickable(enabled = canAccessSpaceSettings, onClick = onSettingsClick) + .semantics { heading() } ) }, actions = { @@ -532,6 +534,7 @@ private fun ManageModeTopBar( Text( text = pluralStringResource(CommonPlurals.common_selected_count, selectedCount, selectedCount), style = ElementTheme.typography.fontBodyLgMedium, + modifier = Modifier.semantics { heading() }, ) }, actions = { @@ -585,10 +588,7 @@ private fun SpaceAvatarAndNameRow( ) Text( modifier = Modifier - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp), text = name ?: stringResource(CommonStrings.common_no_space_name), style = ElementTheme.typography.fontBodyLgMedium, fontStyle = FontStyle.Italic.takeIf { name == null }, From df9a3fe9c2b2aee793618b92c4f24fc43fb59af9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 15:53:08 +0200 Subject: [PATCH 0470/1083] [a11y] Improve accessibility of screen headers. --- .../element/android/features/joinroom/impl/JoinRoomView.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 35cfbb1594..977308178d 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -609,6 +609,7 @@ private fun JoinRoomTopBar( val roundedCornerShape = RoundedCornerShape(8.dp) val titleModifier = Modifier .clip(roundedCornerShape) + .semantics { heading() } if (contentState.name != null) { Row( modifier = titleModifier, @@ -621,10 +622,7 @@ private fun JoinRoomTopBar( ) Text( modifier = Modifier - .padding(horizontal = 8.dp) - .semantics { - heading() - }, + .padding(horizontal = 8.dp), text = contentState.name, style = ElementTheme.typography.fontBodyLgMedium, maxLines = 1, From bd01b275174c2931729478ccaefe6c672e0996cf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 16:21:06 +0200 Subject: [PATCH 0471/1083] [a11y] Ensure that video overlay with controls is never hidden when screen reader is enabled. --- libraries/mediaviewer/impl/build.gradle.kts | 1 + .../impl/local/video/MediaVideoView.kt | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index f2dbf1aacf..b723578829 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixmedia.api) implementation(projects.libraries.uiStrings) + implementation(projects.libraries.uiUtils) implementation(projects.libraries.voiceplayer.api) implementation(projects.services.toolbox.api) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt index 9d5e290857..d89762b72e 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt @@ -57,6 +57,7 @@ import io.element.android.libraries.mediaviewer.impl.local.player.rememberExoPla import io.element.android.libraries.mediaviewer.impl.local.player.seekToEnsurePlaying import io.element.android.libraries.mediaviewer.impl.local.player.togglePlay import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState +import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import kotlinx.coroutines.delay import me.saket.telephoto.zoomable.zoomable import timber.log.Timber @@ -162,12 +163,20 @@ private fun ExoPlayerMediaVideoView( var autoHideController by remember { mutableIntStateOf(0) } - LaunchedEffect(autoHideController) { - delay(5.seconds) - if (exoPlayer.isPlaying) { + val isTalkbackActive = isTalkbackActive() + LaunchedEffect(autoHideController, isTalkbackActive) { + if (isTalkbackActive) { + // Ensure that the controller is always visible when talkback is active mediaPlayerControllerState = mediaPlayerControllerState.copy( - isVisible = false, + isVisible = true, ) + } else { + delay(5.seconds) + if (exoPlayer.isPlaying) { + mediaPlayerControllerState = mediaPlayerControllerState.copy( + isVisible = false, + ) + } } } From 4641ae666ef0d870b0621d95c310636b10e458f6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 17:04:24 +0200 Subject: [PATCH 0472/1083] [a11y] Improve accessibility of media controller --- .../local/player/MediaPlayerControllerView.kt | 39 +++++++++++++++---- .../src/main/res/values/localazy.xml | 2 + 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt index b06b97f491..8d94ba9d2e 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt @@ -28,6 +28,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -100,36 +103,54 @@ fun MediaPlayerControllerView( contentColor = ElementTheme.colors.iconOnSolidPrimary, ) } + val a11yPause = stringResource(CommonStrings.a11y_pause) + val a11yPlay = stringResource(CommonStrings.a11y_play) IconButton( modifier = Modifier - .size(36.dp), + .size(36.dp) + .semantics { + stateDescription = if (state.isPlaying) a11yPause else a11yPlay + }, onClick = onTogglePlay, colors = colors, ) { if (state.isPlaying) { Icon( imageVector = CompoundIcons.PauseSolid(), - contentDescription = stringResource(CommonStrings.a11y_pause) + contentDescription = null, ) } else { Icon( imageVector = CompoundIcons.PlaySolid(), - contentDescription = stringResource(CommonStrings.a11y_play) + contentDescription = null, ) } } + val position = state.displayProgressInMillis.toHumanReadableDuration() + val a11yPosition = stringResource(CommonStrings.a11y_position, position) Text( modifier = Modifier .widthIn(min = 48.dp) - .padding(horizontal = 8.dp), - text = state.displayProgressInMillis.toHumanReadableDuration(), + .padding(horizontal = 8.dp) + .semantics { + contentDescription = a11yPosition + }, + text = position, textAlign = TextAlign.Center, color = ElementTheme.colors.textPrimary, style = ElementTheme.typography.fontBodyXsMedium, ) var lastSelectedValue by remember { mutableFloatStateOf(-1f) } Slider( - modifier = Modifier.weight(1f), + modifier = Modifier + .weight(1f) + .semantics { + // Speak out a progress percent instead of milliseconds + stateDescription = buildString { + append((state.progressAsFloat * 100).toInt()) + append("%") + } + }, valueRange = 0f..state.durationInMillis.toFloat(), value = lastSelectedValue.takeIf { it >= 0 } ?: state.seekingToMillis?.toFloat() @@ -146,10 +167,14 @@ fun MediaPlayerControllerView( val formattedDuration = remember(state.durationInMillis) { state.durationInMillis.toHumanReadableDuration() } + val a11yDuration = stringResource(CommonStrings.a11y_duration, formattedDuration) Text( modifier = Modifier .widthIn(min = 48.dp) - .padding(horizontal = 8.dp), + .padding(horizontal = 8.dp) + .semantics { + contentDescription = a11yDuration + }, text = formattedDuration, textAlign = TextAlign.Center, color = ElementTheme.colors.textPrimary, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ee0f51000a..fd3679a140 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -9,6 +9,7 @@ "%1$d digit entered" "%1$d digits entered" + "Duration: %1$s" "Edit avatar" "The full address will be %1$s" "Encryption details" @@ -33,6 +34,7 @@ "Playback speed" "Poll" "Ended poll" + "Position: %1$s" "QR Code" "React with %1$s" "React with other emojis" From a33d717aa0965e8ed9f1ff2c85f4998329914c7f Mon Sep 17 00:00:00 2001 From: cizra Date: Wed, 20 May 2026 15:19:08 +0000 Subject: [PATCH 0473/1083] Don't compress images sent through the Files attachment picker (#6755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Don't compress images sent through the Files attachment picker Images and videos picked through the "Attachment" picker are now uploaded without re-encoding, regardless of the "Optimize media quality" setting. The gallery and camera pickers keep the existing behaviour, matching what Element Web/Desktop and most other messengers do. Fixes #6365 Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Make sure we select the right video preset for sending as file Wait for the video size estimations to be calculated before preprocessing the video file --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jorge Martín --- .../messages/impl/attachments/Attachment.kt | 9 +- .../preview/AttachmentsPreviewPresenter.kt | 49 +++++++++- ...faultMediaOptimizationSelectorPresenter.kt | 38 ++++---- .../MediaOptimizationSelectorPresenter.kt | 1 + .../video/VideoCompressionPresetSelector.kt | 31 +++++++ .../MessageComposerPresenter.kt | 5 +- .../AttachmentsPreviewPresenterTest.kt | 83 ++++++++++++++++- ...tMediaOptimizationSelectorPresenterTest.kt | 69 ++++++++++++++ .../VideoCompressionPresetSelectorTest.kt | 92 +++++++++++++++++++ .../impl/fixtures/MediaAttachmentFixtures.kt | 3 +- ...diaOptimizationSelectorPresenterFactory.kt | 2 +- .../mediaupload/test/FakeMediaPreProcessor.kt | 5 + 12 files changed, 357 insertions(+), 30 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoCompressionPresetSelector.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/VideoCompressionPresetSelectorTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/Attachment.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/Attachment.kt index d989b34ab3..73fa55228d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/Attachment.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/Attachment.kt @@ -16,5 +16,12 @@ import kotlinx.parcelize.Parcelize @Immutable sealed interface Attachment : Parcelable { @Parcelize - data class Media(val localMedia: LocalMedia) : Attachment + data class Media( + val localMedia: LocalMedia, + // When true, the media was picked through the "Files" picker and should be + // uploaded without image recompression; videos still use the highest available + // / best-fit preset rather than an additional size-reduction optimization pass. + // See https://github.com/element-hq/element-x-android/issues/6365 + val sendAsFile: Boolean = false, + ) : Attachment } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index 8e92e53f6a..fc7f3034a6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -23,6 +23,8 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorPresenter +import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState +import io.element.android.features.messages.impl.attachments.video.VideoCompressionPresetSelector import io.element.android.libraries.androidutils.file.TemporaryUriDeleter import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.androidutils.hash.hash @@ -61,6 +63,7 @@ class AttachmentsPreviewPresenter( private val permalinkBuilder: PermalinkBuilder, private val temporaryUriDeleter: TemporaryUriDeleter, private val mediaOptimizationSelectorPresenterFactory: MediaOptimizationSelectorPresenter.Factory, + private val videoCompressionPresetSelector: VideoCompressionPresetSelector, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val dispatchers: CoroutineDispatchers, private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider, @@ -96,7 +99,10 @@ class AttachmentsPreviewPresenter( val mediaAttachment = attachment as Attachment.Media val mediaOptimizationSelectorPresenter = remember { - mediaOptimizationSelectorPresenterFactory.create(mediaAttachment.localMedia) + mediaOptimizationSelectorPresenterFactory.create( + localMedia = mediaAttachment.localMedia, + sendAsFile = mediaAttachment.sendAsFile, + ) } val mediaOptimizationSelectorState by rememberUpdatedState(mediaOptimizationSelectorPresenter.present()) @@ -104,14 +110,25 @@ class AttachmentsPreviewPresenter( var displayFileTooLargeError by remember { mutableStateOf(false) } - LaunchedEffect(mediaOptimizationSelectorState.displayMediaSelectorViews) { + LaunchedEffect( + mediaOptimizationSelectorState.displayMediaSelectorViews, + mediaOptimizationSelectorState.videoSizeEstimations, + ) { // If the media optimization selector is not displayed, we can pre-process the media // to prepare it for sending. This is done to avoid blocking the UI thread when the // user clicks on the send button. - if (mediaOptimizationSelectorState.displayMediaSelectorViews == false) { - preprocessMediaJob = preProcessAttachment( + if (mediaOptimizationSelectorState.displayMediaSelectorViews == false && preprocessMediaJob == null) { + if (mediaAttachment.localMedia.info.mimeType.isMimeTypeVideo() && mediaOptimizationSelectorState.videoSizeEstimations.dataOrNull() == null) { + Timber.d("Waiting for video size estimations to be able to select the best video compression preset before pre-processing the media") + return@LaunchedEffect + } + val config = getAutoPreprocessMediaOptimizationConfig( + mediaAttachment = mediaAttachment, + mediaOptimizationSelectorState = mediaOptimizationSelectorState, + ) ?: return@LaunchedEffect + preprocessMediaJob = coroutineScope.preProcessAttachment( attachment = attachment, - mediaOptimizationConfig = mediaOptimizationConfigProvider.get(), + mediaOptimizationConfig = config, displayProgress = false, sendActionState = sendActionState, ) @@ -233,6 +250,28 @@ class AttachmentsPreviewPresenter( ) } + private suspend fun getAutoPreprocessMediaOptimizationConfig( + mediaAttachment: Attachment.Media, + mediaOptimizationSelectorState: MediaOptimizationSelectorState, + ): MediaOptimizationConfig? { + return if (mediaAttachment.sendAsFile) { + // If we're sending the media as a file, we can skip image compression and we should select the highest video compression preset that still fits + // the upload limit (if the estimations are available) + val videoCompressionPreset = videoCompressionPresetSelector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.HIGH, + videoSizeEstimations = mediaOptimizationSelectorState.videoSizeEstimations, + ).dataOrNull() ?: VideoCompressionPreset.HIGH + + MediaOptimizationConfig( + compressImages = false, + videoCompressionPreset = videoCompressionPreset, + ) + } else { + // Otherwise, we just rely on the user preferences for media optimization + mediaOptimizationConfigProvider.get() + } + } + private fun CoroutineScope.preProcessAttachment( attachment: Attachment, mediaOptimizationConfig: MediaOptimizationConfig, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt index c81c306f90..abc0264b2f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenter.kt @@ -37,9 +37,11 @@ import kotlin.math.roundToLong @AssistedInject class DefaultMediaOptimizationSelectorPresenter( @Assisted private val localMedia: LocalMedia, + @Assisted private val sendAsFile: Boolean, private val maxUploadSizeProvider: MaxUploadSizeProvider, private val featureFlagService: FeatureFlagService, private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider, + private val videoCompressionPresetSelector: VideoCompressionPresetSelector, mediaExtractorFactory: VideoMetadataExtractor.Factory, ) : MediaOptimizationSelectorPresenter { @ContributesBinding(SessionScope::class) @@ -47,6 +49,7 @@ class DefaultMediaOptimizationSelectorPresenter( interface Factory : MediaOptimizationSelectorPresenter.Factory { override fun create( localMedia: LocalMedia, + sendAsFile: Boolean, ): DefaultMediaOptimizationSelectorPresenter } @@ -55,7 +58,9 @@ class DefaultMediaOptimizationSelectorPresenter( @Composable override fun present(): MediaOptimizationSelectorState { val displayMediaSelectorViews by produceState(null) { - value = featureFlagService.isFeatureEnabled(FeatureFlags.SelectableMediaQuality) + // When sending as a raw file, never show the optimization selector: images skip + // recompression, while videos use the highest available best-fit preset. + value = !sendAsFile && featureFlagService.isFeatureEnabled(FeatureFlags.SelectableMediaQuality) } var displayVideoPresetSelectorDialog by remember { mutableStateOf(false) } @@ -123,12 +128,23 @@ class DefaultMediaOptimizationSelectorPresenter( var selectedVideoOptimizationPreset by remember { mutableStateOf>(AsyncData.Loading()) } LaunchedEffect(videoSizeEstimations.dataOrNull()) { + if (sendAsFile) { + // Send-as-file path: pin to no image compression, and pick the highest-quality + // video preset that still fits the upload limit (we have no true "do not re-encode + // video" path in the pre-processor right now). + selectedImageOptimization = AsyncData.Success(false) + selectedVideoOptimizationPreset = videoCompressionPresetSelector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.HIGH, + videoSizeEstimations = videoSizeEstimations, + ) + return@LaunchedEffect + } val mediaOptimizationConfig = mediaOptimizationConfigProvider.get() selectedImageOptimization = AsyncData.Success(mediaOptimizationConfig.compressImages) // Find the best video preset based on the default preset and the video size estimations // Since the estimation for the current preset may be way too large to upload, we check the ones that provide lower file sizes - selectedVideoOptimizationPreset = findBestVideoPreset( - defaultVideoPreset = mediaOptimizationConfig.videoCompressionPreset, + selectedVideoOptimizationPreset = videoCompressionPresetSelector.selectBestVideoPreset( + expectedVideoPreset = mediaOptimizationConfig.videoCompressionPreset, videoSizeEstimations = videoSizeEstimations, ) } @@ -176,20 +192,4 @@ class DefaultMediaOptimizationSelectorPresenter( eventSink = ::handleEvent, ) } - - private fun findBestVideoPreset( - defaultVideoPreset: VideoCompressionPreset, - videoSizeEstimations: AsyncData>, - ): AsyncData { - val estimations = videoSizeEstimations.dataOrNull() ?: return AsyncData.Loading() - // This will find the best video preset that can be used to produce a video that can be uploaded - val bestEstimation = estimations.find { it.preset.ordinal >= defaultVideoPreset.ordinal && it.canUpload }?.preset - return if (bestEstimation != null) { - AsyncData.Success(bestEstimation) - } else { - AsyncData.Failure( - IllegalStateException("No suitable video preset found for default preset: $defaultVideoPreset") - ) - } - } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/MediaOptimizationSelectorPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/MediaOptimizationSelectorPresenter.kt index 80cdfd9467..f1e17ef0a6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/MediaOptimizationSelectorPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/MediaOptimizationSelectorPresenter.kt @@ -15,6 +15,7 @@ fun interface MediaOptimizationSelectorPresenter : Presenter>, + ): AsyncData { + val estimations = videoSizeEstimations.dataOrNull() ?: return AsyncData.Loading() + val bestEstimation = estimations.find { it.preset.ordinal >= expectedVideoPreset.ordinal && it.canUpload }?.preset + return if (bestEstimation != null) { + AsyncData.Success(bestEstimation) + } else { + AsyncData.Failure( + IllegalStateException("No suitable video preset found for expected preset: $expectedVideoPreset") + ) + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index b42cda7dfc..e226318345 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -179,7 +179,7 @@ class MessageComposerPresenter( handlePickedMedia(uri, mimeType) } val filesPicker = mediaPickerProvider.registerFilePicker(AnyMimeTypes) { uri, mimeType -> - handlePickedMedia(uri, mimeType ?: MimeTypes.OctetStream) + handlePickedMedia(uri, mimeType ?: MimeTypes.OctetStream, sendAsFile = true) } val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker { uri -> handlePickedMedia(uri, MimeTypes.Jpeg) @@ -605,6 +605,7 @@ class MessageComposerPresenter( private fun handlePickedMedia( uri: Uri?, mimeType: String? = null, + sendAsFile: Boolean = false, ) { uri ?: return val localMedia = localMediaFactory.createFromUri( @@ -613,7 +614,7 @@ class MessageComposerPresenter( name = null, formattedFileSize = null ) - val mediaAttachment = Attachment.Media(localMedia) + val mediaAttachment = Attachment.Media(localMedia, sendAsFile = sendAsFile) val inReplyToEventId = (messageComposerContext.composerMode as? MessageComposerMode.Reply)?.eventId navigator.navigateToPreviewAttachments(persistentListOf(mediaAttachment), inReplyToEventId) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 384b78471d..9a9dc08834 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -17,6 +17,7 @@ import io.element.android.features.messages.impl.attachments.preview.Attachments import io.element.android.features.messages.impl.attachments.preview.OnDoneListener import io.element.android.features.messages.impl.attachments.preview.SendActionState import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState +import io.element.android.features.messages.impl.attachments.video.VideoCompressionPresetSelector import io.element.android.features.messages.impl.attachments.video.VideoUploadEstimation import io.element.android.features.messages.impl.fixtures.aMediaAttachment import io.element.android.features.messages.test.attachments.video.FakeMediaOptimizationSelectorPresenterFactory @@ -45,6 +46,7 @@ import io.element.android.libraries.mediaupload.test.FakeMediaOptimizationConfig import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.mediaviewer.api.aVideoMediaInfo import io.element.android.libraries.mediaviewer.api.anApkMediaInfo +import io.element.android.libraries.mediaviewer.api.anImageMediaInfo import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia import io.element.android.libraries.preferences.api.store.VideoCompressionPreset @@ -548,10 +550,87 @@ class AttachmentsPreviewPresenterTest { } } + @Test + fun `present - sendAsFile attachment is pre-processed without image compression`() = runTest { + // Even though the user has enabled "Optimize media quality" globally, picking the file + // through the Files picker (sendAsFile = true) must skip compression. Regression test + // for https://github.com/element-hq/element-x-android/issues/6365 + val mediaPreProcessor = FakeMediaPreProcessor() + val presenter = createAttachmentsPreviewPresenter( + localMedia = aLocalMedia(mockMediaUrl, anImageMediaInfo()), + sendAsFile = true, + mediaPreProcessor = mediaPreProcessor, + // Selector views are hidden in the sendAsFile flow, which triggers the auto pre-process path. + displayMediaQualitySelectorViews = false, + mediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider( + config = MediaOptimizationConfig( + compressImages = true, + videoCompressionPreset = VideoCompressionPreset.STANDARD, + ) + ), + ) + + presenter.test { + consumeItemsUntilPredicate { mediaPreProcessor.processCallCount > 0 } + assertThat(mediaPreProcessor.lastMediaOptimizationConfig).isEqualTo( + MediaOptimizationConfig( + compressImages = false, + videoCompressionPreset = VideoCompressionPreset.HIGH, + ) + ) + } + } + + @Test + fun `present - sendAsFile video is pre-processed with best fitting preset`() = runTest { + val mediaPreProcessor = FakeMediaPreProcessor() + val presenter = createAttachmentsPreviewPresenter( + localMedia = aLocalMedia(mockMediaUrl, aVideoMediaInfo()), + sendAsFile = true, + mediaPreProcessor = mediaPreProcessor, + // Selector views are hidden in the sendAsFile flow, which triggers the auto pre-process path. + displayMediaQualitySelectorViews = false, + mediaOptimizationSelectorPresenterFactory = FakeMediaOptimizationSelectorPresenterFactory { + MediaOptimizationSelectorState( + maxUploadSize = AsyncData.Success(250_000_000L), + videoSizeEstimations = AsyncData.Success( + persistentListOf( + VideoUploadEstimation(VideoCompressionPreset.HIGH, sizeInBytes = 513_216_000L, canUpload = false), + VideoUploadEstimation(VideoCompressionPreset.STANDARD, sizeInBytes = 228_096_000L, canUpload = true), + VideoUploadEstimation(VideoCompressionPreset.LOW, sizeInBytes = 57_024_000L, canUpload = true), + ) + ), + isImageOptimizationEnabled = false, + selectedVideoPreset = VideoCompressionPreset.STANDARD, + displayMediaSelectorViews = false, + displayVideoPresetSelectorDialog = false, + eventSink = {}, + ) + }, + mediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider( + config = MediaOptimizationConfig( + compressImages = true, + videoCompressionPreset = VideoCompressionPreset.LOW, + ) + ), + ) + + presenter.test { + consumeItemsUntilPredicate { mediaPreProcessor.processCallCount > 0 } + assertThat(mediaPreProcessor.lastMediaOptimizationConfig).isEqualTo( + MediaOptimizationConfig( + compressImages = false, + videoCompressionPreset = VideoCompressionPreset.STANDARD, + ) + ) + } + } + private fun TestScope.createAttachmentsPreviewPresenter( localMedia: LocalMedia = aLocalMedia( uri = mockMediaUrl, ), + sendAsFile: Boolean = false, room: JoinedRoom = FakeJoinedRoom(), timelineMode: Timeline.Mode = Timeline.Mode.Live, permalinkBuilder: PermalinkBuilder = FakePermalinkBuilder(), @@ -573,9 +652,10 @@ class AttachmentsPreviewPresenterTest { } ), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + videoCompressionPresetSelector: VideoCompressionPresetSelector = VideoCompressionPresetSelector(), ): AttachmentsPreviewPresenter { return AttachmentsPreviewPresenter( - attachment = aMediaAttachment(localMedia), + attachment = aMediaAttachment(localMedia, sendAsFile = sendAsFile), onDoneListener = onDoneListener, mediaSenderFactory = MediaSenderFactory { timelineMode -> DefaultMediaSender( @@ -592,6 +672,7 @@ class AttachmentsPreviewPresenterTest { sessionCoroutineScope = this, dispatchers = testCoroutineDispatchers(), mediaOptimizationSelectorPresenterFactory = mediaOptimizationSelectorPresenterFactory, + videoCompressionPresetSelector = videoCompressionPresetSelector, timelineMode = timelineMode, inReplyToEventId = null, mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt index 106fff7375..e06f4ad4cd 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt @@ -210,19 +210,88 @@ class DefaultMediaOptimizationSelectorPresenterTest { } } + @Test + fun `present - sendAsFile hides selector views and disables image compression for images`() = runTest { + val presenter = createDefaultMediaOptimizationSelectorPresenter( + localMedia = aLocalMedia(mockMediaUrl, anImageMediaInfo()), + // Even with the feature flag on, sendAsFile must hide the selector. + featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SelectableMediaQuality.key to true)), + // And it must override the user's "optimize images" preference. + mediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + sendAsFile = true, + ) + presenter.test { + // Initial loading state + skipItems(1) + awaitItem().run { + assertThat(displayMediaSelectorViews).isFalse() + assertThat(isImageOptimizationEnabled).isFalse() + } + } + } + + @Test + fun `present - sendAsFile picks HIGH video preset when the video fits the upload limit`() = runTest { + val presenter = createDefaultMediaOptimizationSelectorPresenter( + // Plenty of room: even HIGH preset will fit. + maxUploadSizeProvider = MaxUploadSizeProvider { Result.success(Long.MAX_VALUE) }, + mediaExtractorFactory = FakeVideoMetadataExtractorFactory( + FakeVideoMetadataExtractor( + sizeResult = Result.success(Size(1920, 1080)), + duration = Result.success(10.minutes) + ) + ), + sendAsFile = true, + ) + presenter.test { + // Initial loading state, then the one with size estimations loaded. + skipItems(1) + awaitItem().run { + assertThat(displayMediaSelectorViews).isFalse() + assertThat(selectedVideoPreset).isEqualTo(VideoCompressionPreset.HIGH) + } + } + } + + @Test + fun `present - sendAsFile picks lower video preset when HIGH exceeds the upload limit`() = runTest { + val presenter = createDefaultMediaOptimizationSelectorPresenter( + maxUploadSizeProvider = MaxUploadSizeProvider { Result.success(250_000_000L) }, + mediaExtractorFactory = FakeVideoMetadataExtractorFactory( + FakeVideoMetadataExtractor( + sizeResult = Result.success(Size(1920, 1080)), + duration = Result.success(10.minutes) + ) + ), + sendAsFile = true, + ) + presenter.test { + // Initial loading state, then the one with size estimations loaded. + skipItems(1) + awaitItem().run { + assertThat(displayMediaSelectorViews).isFalse() + assertThat(selectedVideoPreset).isEqualTo(VideoCompressionPreset.STANDARD) + } + } + } + private fun createDefaultMediaOptimizationSelectorPresenter( localMedia: LocalMedia = aLocalMedia(mockMediaUrl, aVideoMediaInfo()), maxUploadSizeProvider: MaxUploadSizeProvider = MaxUploadSizeProvider { Result.success(1_000L) }, featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SelectableMediaQuality.key to true)), mediaExtractorFactory: FakeVideoMetadataExtractorFactory = FakeVideoMetadataExtractorFactory(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + videoCompressionPresetSelector: VideoCompressionPresetSelector = VideoCompressionPresetSelector(), + sendAsFile: Boolean = false, ): DefaultMediaOptimizationSelectorPresenter { return DefaultMediaOptimizationSelectorPresenter( localMedia = localMedia, + sendAsFile = sendAsFile, maxUploadSizeProvider = maxUploadSizeProvider, featureFlagService = featureFlagService, mediaExtractorFactory = mediaExtractorFactory, mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, + videoCompressionPresetSelector = videoCompressionPresetSelector, ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/VideoCompressionPresetSelectorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/VideoCompressionPresetSelectorTest.kt new file mode 100644 index 0000000000..d3864794c2 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/VideoCompressionPresetSelectorTest.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.video + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.preferences.api.store.VideoCompressionPreset +import kotlinx.collections.immutable.persistentListOf +import org.junit.Test + +class VideoCompressionPresetSelectorTest { + private val selector = VideoCompressionPresetSelector() + + @Test + fun `selectBestVideoPreset - returns expected preset when it can upload`() { + val result = selector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.HIGH, + videoSizeEstimations = AsyncData.Success( + persistentListOf( + VideoUploadEstimation(VideoCompressionPreset.HIGH, sizeInBytes = 100, canUpload = true), + VideoUploadEstimation(VideoCompressionPreset.STANDARD, sizeInBytes = 50, canUpload = true), + VideoUploadEstimation(VideoCompressionPreset.LOW, sizeInBytes = 25, canUpload = true), + ) + ) + ) + + assertThat(result.dataOrNull()).isEqualTo(VideoCompressionPreset.HIGH) + } + + @Test + fun `selectBestVideoPreset - falls back to the highest fitting preset`() { + val result = selector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.HIGH, + videoSizeEstimations = AsyncData.Success( + persistentListOf( + VideoUploadEstimation(VideoCompressionPreset.HIGH, sizeInBytes = 100, canUpload = false), + VideoUploadEstimation(VideoCompressionPreset.STANDARD, sizeInBytes = 50, canUpload = true), + VideoUploadEstimation(VideoCompressionPreset.LOW, sizeInBytes = 25, canUpload = true), + ) + ) + ) + + assertThat(result.dataOrNull()).isEqualTo(VideoCompressionPreset.STANDARD) + } + + @Test + fun `selectBestVideoPreset - starts from the expected preset`() { + val result = selector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.STANDARD, + videoSizeEstimations = AsyncData.Success( + persistentListOf( + VideoUploadEstimation(VideoCompressionPreset.HIGH, sizeInBytes = 100, canUpload = true), + VideoUploadEstimation(VideoCompressionPreset.STANDARD, sizeInBytes = 50, canUpload = true), + VideoUploadEstimation(VideoCompressionPreset.LOW, sizeInBytes = 25, canUpload = true), + ) + ) + ) + + assertThat(result.dataOrNull()).isEqualTo(VideoCompressionPreset.STANDARD) + } + + @Test + fun `selectBestVideoPreset - returns failure when no preset can upload`() { + val result = selector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.HIGH, + videoSizeEstimations = AsyncData.Success( + persistentListOf( + VideoUploadEstimation(VideoCompressionPreset.HIGH, sizeInBytes = 100, canUpload = false), + VideoUploadEstimation(VideoCompressionPreset.STANDARD, sizeInBytes = 50, canUpload = false), + VideoUploadEstimation(VideoCompressionPreset.LOW, sizeInBytes = 25, canUpload = false), + ) + ) + ) + + assertThat(result).isInstanceOf(AsyncData.Failure::class.java) + } + + @Test + fun `selectBestVideoPreset - returns loading while estimations are missing`() { + val result = selector.selectBestVideoPreset( + expectedVideoPreset = VideoCompressionPreset.HIGH, + videoSizeEstimations = AsyncData.Loading(), + ) + + assertThat(result).isInstanceOf(AsyncData.Loading::class.java) + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MediaAttachmentFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MediaAttachmentFixtures.kt index 77207d6b52..1dde33714f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MediaAttachmentFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MediaAttachmentFixtures.kt @@ -11,6 +11,7 @@ package io.element.android.features.messages.impl.fixtures import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.libraries.mediaviewer.api.local.LocalMedia -fun aMediaAttachment(localMedia: LocalMedia) = Attachment.Media( +fun aMediaAttachment(localMedia: LocalMedia, sendAsFile: Boolean = false) = Attachment.Media( localMedia = localMedia, + sendAsFile = sendAsFile, ) diff --git a/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeMediaOptimizationSelectorPresenterFactory.kt b/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeMediaOptimizationSelectorPresenterFactory.kt index 02a6918ad8..fff3ede5d3 100644 --- a/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeMediaOptimizationSelectorPresenterFactory.kt +++ b/features/messages/test/src/main/kotlin/io/element/android/features/messages/test/attachments/video/FakeMediaOptimizationSelectorPresenterFactory.kt @@ -26,7 +26,7 @@ class FakeMediaOptimizationSelectorPresenterFactory( ) } ) : MediaOptimizationSelectorPresenter.Factory { - override fun create(localMedia: LocalMedia): MediaOptimizationSelectorPresenter { + override fun create(localMedia: LocalMedia, sendAsFile: Boolean): MediaOptimizationSelectorPresenter { return fakePresenter } } diff --git a/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt b/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt index c07ebb6ec9..3750060eef 100644 --- a/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt +++ b/libraries/mediaupload/test/src/main/kotlin/io/element/android/libraries/mediaupload/test/FakeMediaPreProcessor.kt @@ -31,6 +31,10 @@ class FakeMediaPreProcessor( var cleanUpCallCount = 0 private set + /** The [MediaOptimizationConfig] passed to the most recent [process] call, or `null` if it was never called. */ + var lastMediaOptimizationConfig: MediaOptimizationConfig? = null + private set + private var result: Result = Result.success( MediaUploadInfo.AnyFile( File("test"), @@ -51,6 +55,7 @@ class FakeMediaPreProcessor( ): Result = simulateLongTask { processLatch?.await() processCallCount++ + lastMediaOptimizationConfig = mediaOptimizationConfig result } From 44df2d2c17d25c508246e7a647407e72482a074c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2026 17:23:30 +0200 Subject: [PATCH 0474/1083] [a11y] Improve accessibility of media controller --- .../impl/local/player/MediaPlayerControllerView.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt index 8d94ba9d2e..1f2b0b93d2 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt @@ -181,20 +181,26 @@ fun MediaPlayerControllerView( style = ElementTheme.typography.fontBodyXsMedium, ) if (state.canMute) { + val a11yUnmute = stringResource(CommonStrings.common_unmute) + val a11yMute = stringResource(CommonStrings.common_mute) IconButton( onClick = onToggleMute, + modifier = Modifier + .semantics { + stateDescription = if (state.isMuted) a11yUnmute else a11yMute + }, ) { if (state.isMuted) { Icon( imageVector = CompoundIcons.VolumeOffSolid(), tint = ElementTheme.colors.iconPrimary, - contentDescription = stringResource(CommonStrings.common_unmute) + contentDescription = null, ) } else { Icon( imageVector = CompoundIcons.VolumeOnSolid(), tint = ElementTheme.colors.iconPrimary, - contentDescription = stringResource(CommonStrings.common_mute) + contentDescription = null, ) } } From 19397b6fa7ed85182dd55eefee13dfab456ebbc2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2026 09:10:43 +0200 Subject: [PATCH 0475/1083] Fix warning --- .../kotlin/io/element/android/libraries/qrcode/QrCodeImage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeImage.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeImage.kt index e045e42f17..b50b202e2c 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeImage.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeImage.kt @@ -57,8 +57,8 @@ private fun BitMatrix.toBitmap( @Composable fun QrCodeImage( data: String, - forceMaxBrightness: Boolean = true, modifier: Modifier = Modifier, + forceMaxBrightness: Boolean = true, ) { if (forceMaxBrightness) { ForceMaxBrightness() From b4f23d9d9e1d994de465d0ec91d506cf9c372917 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2026 09:14:18 +0200 Subject: [PATCH 0476/1083] Fix wrong 'modifier' usage. --- .../linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt index ee38342ce2..f2cd07f4a5 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/qrcode/ShowQrCodeView.kt @@ -65,13 +65,13 @@ fun ShowQrCodeView( horizontalAlignment = Alignment.CenterHorizontally, ) { AnimatedContent( + modifier = Modifier.size(220.dp), targetState = state.data.dataOrNull(), transitionSpec = { fadeIn().togetherWith(fadeOut()) } ) { data -> QrCodeOrLoading( - modifier = modifier.size(220.dp), data = data, ) } From eed183be5385456a572afd2b8cb7da5476253199 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 10:10:13 +0200 Subject: [PATCH 0477/1083] Update metro to v1.1.1 (#6832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update metro to v1.1.1 * Fix `@ContributesBinding` usage with `@AssistedInject` in `DefaultVideoMetadataExtractor` --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- .../messages/impl/attachments/video/VideoMetadataExtractor.kt | 1 - gradle/libs.versions.toml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt index a6945b5ebe..b0ff50dc72 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/video/VideoMetadataExtractor.kt @@ -30,7 +30,6 @@ interface VideoMetadataExtractor : AutoCloseable { } } -@ContributesBinding(AppScope::class) @AssistedInject class DefaultVideoMetadataExtractor( @ApplicationContext private val context: Context, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 90b90b562e..ff7eede510 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.11.0" # DI -metro = "1.0.0" +metro = "1.1.1" # Auto service autoservice = "1.1.1" From 4607681c5f0143551ce222c27c7f4d0c23883edb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 08:15:40 +0000 Subject: [PATCH 0478/1083] Update dependency io.element.android:element-call-embedded to v0.19.4 --- 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 ff7eede510..90740da3c5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -235,7 +235,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.19.3" +element_call_embedded = "io.element.android:element-call-embedded:0.19.4" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From 7e42dd1529905467302d4769aa1808ce57c8867e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 12:27:29 +0200 Subject: [PATCH 0479/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.20 (#6831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency org.matrix.rustcomponents:sdk-android to v26.05.20 * Fix API breaks: - Handle new `ClientBuildException.InvalidRawKey` variant. - `RoomInfo` now has a `fullyReadEventId` . --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- .../android/features/space/impl/root/SpaceStateProvider.kt | 1 + gradle/libs.versions.toml | 2 +- .../io/element/android/libraries/matrix/api/room/RoomInfo.kt | 1 + .../libraries/matrix/impl/auth/AuthenticationException.kt | 1 + .../android/libraries/matrix/impl/room/RoomInfoMapper.kt | 1 + .../libraries/matrix/impl/fixtures/factories/RoomInfo.kt | 2 ++ .../android/libraries/matrix/impl/room/RoomInfoMapperTest.kt | 4 ++++ .../android/libraries/matrix/test/room/RoomInfoFixture.kt | 2 ++ .../android/libraries/matrix/test/room/RoomSummaryFixture.kt | 2 ++ 9 files changed, 15 insertions(+), 1 deletion(-) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt index 20f4918a98..6824cc6c10 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt @@ -140,6 +140,7 @@ private fun aSpaceInfo( privilegedCreatorRole = false, isLowPriority = false, activeCallIntentConsensus = CallIntentConsensus.None, + fullyReadEventId = null, ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9e0ab8c30b..2c0785abdb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -179,7 +179,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.18" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.20" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt index b9ed8d61b1..e590976cab 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt @@ -79,6 +79,7 @@ data class RoomInfo( val privilegedCreatorRole: Boolean, val isLowPriority: Boolean, val activeCallIntentConsensus: CallIntentConsensus, + val fullyReadEventId: EventId?, ) { val aliases: List get() = listOfNotNull(canonicalAlias) + alternativeAliases diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index 20dbf76a31..fac5227f6a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -28,6 +28,7 @@ fun Throwable.mapAuthenticationException(): AuthenticationException { } is ClientBuildException.WellKnownLookupFailed -> AuthenticationException.Generic(message) is ClientBuildException.EventCache -> AuthenticationException.Generic(message) + is ClientBuildException.InvalidRawKey -> AuthenticationException.Generic(message) } is OAuthException -> when (this) { is OAuthException.Generic -> AuthenticationException.OAuth(message) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt index 0e9aadc65b..a972b3c130 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt @@ -77,6 +77,7 @@ class RoomInfoMapper { privilegedCreatorRole = it.privilegedCreatorsRole, isLowPriority = it.isLowPriority, activeCallIntentConsensus = it.activeRoomCallConsensusIntent.map(), + fullyReadEventId = it.fullyReadEventId?.let(::EventId) ) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt index 2ce64154f7..cb5e221dc9 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt @@ -64,6 +64,7 @@ internal fun aRustRoomInfo( activeRoomCallConsensusIntent: RtcCallIntentConsensus = RtcCallIntentConsensus.None, activeServiceMembersCount: Int = 0, isDm: Boolean = false, + fullyReadEventId: String? = null, ) = RoomInfo( id = id, displayName = displayName, @@ -105,4 +106,5 @@ internal fun aRustRoomInfo( activeRoomCallConsensusIntent = activeRoomCallConsensusIntent, activeServiceMembersCount = activeServiceMembersCount.toULong(), isDm = isDm, + fullyReadEventId = fullyReadEventId, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt index 56b480d97f..dc3b16ca3c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt @@ -87,6 +87,7 @@ class RoomInfoMapperTest { isLowPriority = true, activeRoomCallConsensusIntent = RtcCallIntentConsensus.Full(RtcCallIntent.AUDIO), isDm = true, + fullyReadEventId = AN_EVENT_ID.value, ) ) ).isEqualTo( @@ -138,6 +139,7 @@ class RoomInfoMapperTest { isLowPriority = true, activeCallIntentConsensus = CallIntentConsensus.Full(CallIntent.AUDIO), isDm = true, + fullyReadEventId = AN_EVENT_ID, ) ) } @@ -184,6 +186,7 @@ class RoomInfoMapperTest { isLowPriority = true, activeRoomCallConsensusIntent = RtcCallIntentConsensus.None, isDm = false, + fullyReadEventId = AN_EVENT_ID.value, ) ) ).isEqualTo( @@ -229,6 +232,7 @@ class RoomInfoMapperTest { isLowPriority = true, activeCallIntentConsensus = CallIntentConsensus.None, isDm = false, + fullyReadEventId = AN_EVENT_ID, ) ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt index c15330e9dc..3293570eec 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt @@ -72,6 +72,7 @@ fun aRoomInfo( isLowPriority: Boolean = false, activeCallIntentConsensus: CallIntentConsensus = CallIntentConsensus.None, isDm: Boolean = false, + fullyReadEventId: EventId? = null, ) = RoomInfo( id = id, name = name, @@ -111,4 +112,5 @@ fun aRoomInfo( isLowPriority = isLowPriority, activeCallIntentConsensus = activeCallIntentConsensus, isDm = isDm, + fullyReadEventId = fullyReadEventId, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index 32635a7eea..392aa880c9 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -81,6 +81,7 @@ fun aRoomSummary( privilegedCreatorRole: Boolean = false, isLowPriority: Boolean = false, activeCallIntentConsensus: CallIntentConsensus = CallIntentConsensus.None, + fullyReadEventId: EventId? = null, ) = RoomSummary( info = RoomInfo( id = roomId, @@ -121,6 +122,7 @@ fun aRoomSummary( isLowPriority = isLowPriority, activeCallIntentConsensus = activeCallIntentConsensus, isDm = false, + fullyReadEventId = fullyReadEventId, ), latestEvent = latestEvent, ) From d6ef5052603d040a8f5b4028e5a2edcf191e23d6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 15:01:00 +0200 Subject: [PATCH 0480/1083] Merge pull request #6816 from element-hq/renovate/media3 Update media3 to v1.10.1 --- 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 2c0785abdb..3d49f2cda1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ constraintlayout = "2.2.1" constraintlayout_compose = "1.1.1" lifecycle = "2.10.0" activity = "1.13.0" -media3 = "1.10.0" +media3 = "1.10.1" camera = "1.6.1" work = "2.11.2" From 00efd9a01c97d6d55d885405d170b7314feca61b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 15:01:35 +0200 Subject: [PATCH 0481/1083] Update peaceiris/actions-gh-pages action to v4.1.0 (#6820) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/generate_github_pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 55a300dd88..8de21b3ef1 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -36,7 +36,7 @@ jobs: mkdir -p screenshots/en cp tests/uitests/src/test/snapshots/images/* screenshots/en - name: Deploy GitHub Pages - uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 + uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./screenshots From bcad1f9dce2bebd9ae76a03ddf9d98309880b410 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Thu, 21 May 2026 15:08:26 +0200 Subject: [PATCH 0482/1083] Add crop and rotate editing before sending images (#6363) * feat(messages): add crop and rotate before image upload * Update screenshots * chore: trigger CI after screenshot update * fix: resolve detekt violations in image editor and media viewer modules * fix: require explicit edits param, use plurals for rotation a11y, remove redundant @Inject * fix: require explicit edits param, use plurals for rotation a11y, remove redundant @Inject * fix: use semantically correct RotateRight icon for image rotation action * Update screenshots * chore: trigger CI after screenshot update --------- Co-authored-by: ElementBot Co-authored-by: Benoit Marty --- features/messages/impl/build.gradle.kts | 1 + .../preview/AttachmentMediaInfo.kt | 44 ++ .../preview/AttachmentsPreviewEvent.kt | 8 + .../preview/AttachmentsPreviewPresenter.kt | 151 ++++- .../preview/AttachmentsPreviewState.kt | 5 + .../AttachmentsPreviewStateProvider.kt | 10 + .../preview/AttachmentsPreviewView.kt | 121 +++- .../imageeditor/AttachmentImageEditModels.kt | 126 +++++ .../imageeditor/AttachmentImageEditor.kt | 191 +++++++ .../imageeditor/AttachmentImageEditorView.kt | 522 ++++++++++++++++++ .../impl/src/main/res/values/temporary.xml | 8 + .../AttachmentsPreviewPresenterTest.kt | 225 ++++++++ .../AttachmentImageEditModelsTest.kt | 78 +++ .../impl/local/AndroidLocalMediaFactory.kt | 41 +- .../local/AndroidLocalMediaFactoryTest.kt | 29 +- ...tor_AttachmentImageEditorView_Day_0_en.png | 3 + ...r_AttachmentImageEditorView_Night_0_en.png | 3 + 17 files changed, 1517 insertions(+), 49 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentMediaInfo.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt create mode 100644 features/messages/impl/src/main/res/values/temporary.xml create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 6ff7f7e322..2661f7e330 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -70,6 +70,7 @@ dependencies { implementation(libs.jsoup) implementation(libs.androidx.constraintlayout) implementation(libs.androidx.constraintlayout.compose) + implementation(libs.androidx.exifinterface) implementation(libs.androidx.media3.exoplayer) implementation(libs.androidx.media3.ui) implementation(libs.sigpwned.emoji4j) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentMediaInfo.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentMediaInfo.kt new file mode 100644 index 0000000000..7feeff18dd --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentMediaInfo.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview + +import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAnimatedImage +import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage +import io.element.android.libraries.mediaviewer.api.MediaInfo +import java.util.Locale + +internal fun MediaInfo.canEditImage(): Boolean { + val resolvedMimeType = resolvedImageMimeType() ?: return false + return resolvedMimeType.isMimeTypeImage() && + !resolvedMimeType.isMimeTypeAnimatedImage() && + resolvedMimeType != MimeTypes.Svg +} + +internal fun MediaInfo.isImageAttachment(): Boolean { + return resolvedImageMimeType().isMimeTypeImage() +} + +internal fun MediaInfo.resolvedImageMimeType(): String? { + return mimeType.takeIf { it.isMimeTypeImage() } ?: fileExtension.toImageMimeTypeOrNull() +} + +private fun String.toImageMimeTypeOrNull(): String? { + return when (lowercase(Locale.ROOT)) { + "png" -> MimeTypes.Png + "jpg", "jpeg" -> MimeTypes.Jpeg + "gif" -> MimeTypes.Gif + "webp" -> MimeTypes.WebP + "svg" -> MimeTypes.Svg + "bmp" -> "image/bmp" + "heic" -> "image/heic" + "heif" -> "image/heif" + "avif" -> "image/avif" + else -> null + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt index d473d4c3f4..1957a8b0f7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt @@ -8,8 +8,16 @@ package io.element.android.features.messages.impl.attachments.preview +import io.element.android.features.messages.impl.attachments.preview.imageeditor.NormalizedCropRect + sealed interface AttachmentsPreviewEvent { data object SendAttachment : AttachmentsPreviewEvent data object CancelAndDismiss : AttachmentsPreviewEvent data object CancelAndClearSendState : AttachmentsPreviewEvent + data object OpenImageEditor : AttachmentsPreviewEvent + data object CloseImageEditor : AttachmentsPreviewEvent + data object RotateImage : AttachmentsPreviewEvent + data object ApplyImageEdits : AttachmentsPreviewEvent + data class UpdateImageCropRect(val cropRect: NormalizedCropRect) : AttachmentsPreviewEvent + data object ClearImageEditError : AttachmentsPreviewEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index fc7f3034a6..b5cb13e3e3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -22,6 +22,9 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import io.element.android.features.messages.impl.attachments.Attachment +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEditor +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEditorState +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEdits import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorPresenter import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState import io.element.android.features.messages.impl.attachments.video.VideoCompressionPresetSelector @@ -32,7 +35,6 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.firstInstanceOf import io.element.android.libraries.core.extensions.runCatchingExceptions -import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.core.EventId @@ -51,7 +53,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import timber.log.Timber +import java.io.File @AssistedInject class AttachmentsPreviewPresenter( @@ -62,6 +66,7 @@ class AttachmentsPreviewPresenter( mediaSenderFactory: MediaSenderFactory, private val permalinkBuilder: PermalinkBuilder, private val temporaryUriDeleter: TemporaryUriDeleter, + private val attachmentImageEditor: AttachmentImageEditor, private val mediaOptimizationSelectorPresenterFactory: MediaOptimizationSelectorPresenter.Factory, private val videoCompressionPresetSelector: VideoCompressionPresetSelector, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, @@ -87,6 +92,14 @@ class AttachmentsPreviewPresenter( val sendActionState = remember { mutableStateOf(SendActionState.Idle) } + val originalLocalMedia = remember { (attachment as Attachment.Media).localMedia } + var currentAttachment by remember { mutableStateOf(attachment) } + var canEditImage by remember { mutableStateOf(originalLocalMedia.info.canEditImage()) } + var imageEditorState by remember { mutableStateOf(null) } + var appliedImageEdits by remember { mutableStateOf(AttachmentImageEdits()) } + var isApplyingImageEdits by remember { mutableStateOf(false) } + var displayImageEditError by remember { mutableStateOf(false) } + var editedTempFile by remember { mutableStateOf(null) } val markdownTextEditorState = rememberMarkdownTextEditorState(initialText = null, initialFocus = false) val textEditorState by rememberUpdatedState( @@ -97,7 +110,7 @@ class AttachmentsPreviewPresenter( var preprocessMediaJob by remember { mutableStateOf(null) } - val mediaAttachment = attachment as Attachment.Media + val mediaAttachment = currentAttachment as Attachment.Media val mediaOptimizationSelectorPresenter = remember { mediaOptimizationSelectorPresenterFactory.create( localMedia = mediaAttachment.localMedia, @@ -113,11 +126,17 @@ class AttachmentsPreviewPresenter( LaunchedEffect( mediaOptimizationSelectorState.displayMediaSelectorViews, mediaOptimizationSelectorState.videoSizeEstimations, + currentAttachment, + imageEditorState, + isApplyingImageEdits, ) { // If the media optimization selector is not displayed, we can pre-process the media // to prepare it for sending. This is done to avoid blocking the UI thread when the // user clicks on the send button. - if (mediaOptimizationSelectorState.displayMediaSelectorViews == false && preprocessMediaJob == null) { + if (mediaOptimizationSelectorState.displayMediaSelectorViews == false && + preprocessMediaJob == null && + imageEditorState == null && + !isApplyingImageEdits) { if (mediaAttachment.localMedia.info.mimeType.isMimeTypeVideo() && mediaOptimizationSelectorState.videoSizeEstimations.dataOrNull() == null) { Timber.d("Waiting for video size estimations to be able to select the best video compression preset before pre-processing the media") return@LaunchedEffect @@ -127,7 +146,7 @@ class AttachmentsPreviewPresenter( mediaOptimizationSelectorState = mediaOptimizationSelectorState, ) ?: return@LaunchedEffect preprocessMediaJob = coroutineScope.preProcessAttachment( - attachment = attachment, + attachment = currentAttachment, mediaOptimizationConfig = config, displayProgress = false, sendActionState = sendActionState, @@ -135,10 +154,14 @@ class AttachmentsPreviewPresenter( } } + LaunchedEffect(originalLocalMedia) { + canEditImage = originalLocalMedia.info.canEditImage() || attachmentImageEditor.canEdit(originalLocalMedia) + } + val maxUploadSize = mediaOptimizationSelectorState.maxUploadSize.dataOrNull() LaunchedEffect(maxUploadSize) { // Check file upload size if the media won't be processed for upload - val isImageFile = mediaAttachment.localMedia.info.mimeType.isMimeTypeImage() + val isImageFile = mediaAttachment.localMedia.info.isImageAttachment() val isVideoFile = mediaAttachment.localMedia.info.mimeType.isMimeTypeVideo() if (maxUploadSize != null && !(isImageFile || isVideoFile)) { // If file size is not known, we're permissive and allow sending. The SDK will cancel the upload if needed. @@ -169,7 +192,7 @@ class AttachmentsPreviewPresenter( videoCompressionPreset = mediaOptimizationSelectorState.selectedVideoPreset ?: VideoCompressionPreset.STANDARD, ) preprocessMediaJob = preProcessAttachment( - attachment = attachment, + attachment = currentAttachment, mediaOptimizationConfig = config, displayProgress = true, sendActionState = sendActionState, @@ -188,6 +211,9 @@ class AttachmentsPreviewPresenter( val caption = markdownTextEditorState.getMessageMarkdown(permalinkBuilder) .takeIf { it.isNotEmpty() } + val editedTempFileToDelete = editedTempFile + editedTempFile = null + // If we're supposed to send the media as a background job, we can dismiss this screen already if (coroutineContext.isActive) { onDoneListener() @@ -195,33 +221,36 @@ class AttachmentsPreviewPresenter( // Send the media using the session coroutine scope so it doesn't matter if this screen or the chat one are closed sessionCoroutineScope.launch(dispatchers.io) { - sendPreProcessedMedia( - mediaUploadInfo = mediaUploadInfo, - caption = caption, - sendActionState = sendActionState, - dismissAfterSend = false, - inReplyToEventId = inReplyToEventId, - ) - - // Clean up the pre-processed media after it's been sent - mediaSender.cleanUp() + try { + sendPreProcessedMedia( + mediaUploadInfo = mediaUploadInfo, + caption = caption, + sendActionState = sendActionState, + dismissAfterSend = false, + inReplyToEventId = inReplyToEventId, + ) + } finally { + editedTempFileToDelete?.safeDelete() + // Clean up the pre-processed media after it's been sent + mediaSender.cleanUp() + } } } } AttachmentsPreviewEvent.CancelAndDismiss -> { displayFileTooLargeError = false + displayImageEditError = false + isApplyingImageEdits = false // Cancel media preprocessing and sending preprocessMediaJob?.cancel() + preprocessMediaJob = null // If we couldn't send the pre-processed media, remove it mediaSender.cleanUp() ongoingSendAttachmentJob.value?.cancel() // Dismiss the screen - dismiss( - attachment, - sendActionState, - ) + dismiss(sendActionState, editedTempFile) } AttachmentsPreviewEvent.CancelAndClearSendState -> { // Cancel media sending @@ -237,11 +266,82 @@ class AttachmentsPreviewPresenter( SendActionState.Idle } } + AttachmentsPreviewEvent.OpenImageEditor -> { + val resolvedCanEditImage = canEditImage || originalLocalMedia.info.canEditImage() + if (resolvedCanEditImage) { + preprocessMediaJob?.cancel() + preprocessMediaJob = null + resetPreparedMedia(sendActionState) + imageEditorState = AttachmentImageEditorState( + localMedia = originalLocalMedia, + edits = appliedImageEdits, + ) + } + } + AttachmentsPreviewEvent.CloseImageEditor -> { + imageEditorState = null + } + is AttachmentsPreviewEvent.UpdateImageCropRect -> { + val pendingState = imageEditorState ?: return + imageEditorState = pendingState.copy( + edits = pendingState.edits.copy(cropRect = event.cropRect) + ) + } + AttachmentsPreviewEvent.RotateImage -> { + val pendingState = imageEditorState ?: return + imageEditorState = pendingState.copy( + edits = pendingState.edits.rotateClockwise() + ) + } + AttachmentsPreviewEvent.ApplyImageEdits -> { + val pendingState = imageEditorState ?: return + if (!pendingState.edits.hasChanges) { + editedTempFile?.safeDelete() + editedTempFile = null + appliedImageEdits = pendingState.edits + currentAttachment = Attachment.Media(originalLocalMedia) + imageEditorState = null + resetPreparedMedia(sendActionState) + return + } + isApplyingImageEdits = true + displayImageEditError = false + coroutineScope.launch { + val result = withContext(dispatchers.io) { + attachmentImageEditor.exportEdits( + localMedia = originalLocalMedia, + edits = pendingState.edits, + ) + } + result.fold( + onSuccess = { editedMedia -> + editedTempFile?.safeDelete() + editedTempFile = editedMedia.file + appliedImageEdits = pendingState.edits + currentAttachment = Attachment.Media(editedMedia.localMedia) + imageEditorState = null + resetPreparedMedia(sendActionState) + }, + onFailure = { + Timber.e(it, "Failed to apply image edits") + displayImageEditError = true + } + ) + isApplyingImageEdits = false + } + } + AttachmentsPreviewEvent.ClearImageEditError -> { + displayImageEditError = false + } } } return AttachmentsPreviewState( - attachment = attachment, + attachment = currentAttachment, + imageEditorState = imageEditorState, + canEditImage = canEditImage, + isApplyingImageEdits = isApplyingImageEdits, + displayImageEditError = displayImageEditError, sendActionState = sendActionState.value, textEditorState = textEditorState, mediaOptimizationSelectorState = mediaOptimizationSelectorState, @@ -318,8 +418,8 @@ class AttachmentsPreviewPresenter( } private fun dismiss( - attachment: Attachment, sendActionState: MutableState, + editedTempFile: File?, ) { // Delete the temporary file when (attachment) { @@ -330,6 +430,7 @@ class AttachmentsPreviewPresenter( } } } + editedTempFile?.safeDelete() // Reset the sendActionState to ensure that dialog is closed before the screen sendActionState.value = SendActionState.Done onDoneListener() @@ -343,6 +444,12 @@ class AttachmentsPreviewPresenter( } } + private fun resetPreparedMedia(sendActionState: MutableState) { + sendActionState.value.mediaUploadInfo()?.let(::cleanUp) + mediaSender.cleanUp() + sendActionState.value = SendActionState.Idle + } + private suspend fun sendPreProcessedMedia( mediaUploadInfo: MediaUploadInfo, caption: String?, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt index 97ca230d77..463479fe55 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt @@ -10,12 +10,17 @@ package io.element.android.features.messages.impl.attachments.preview import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.attachments.Attachment +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEditorState import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.textcomposer.model.TextEditorState data class AttachmentsPreviewState( val attachment: Attachment, + val imageEditorState: AttachmentImageEditorState?, + val canEditImage: Boolean, + val isApplyingImageEdits: Boolean, + val displayImageEditError: Boolean, val sendActionState: SendActionState, val textEditorState: TextEditorState, val mediaOptimizationSelectorState: MediaOptimizationSelectorState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt index 70d7ab006e..ced90550c3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt @@ -11,6 +11,8 @@ package io.element.android.features.messages.impl.attachments.preview import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.core.net.toUri import io.element.android.features.messages.impl.attachments.Attachment +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEditorState +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEdits import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState import io.element.android.features.messages.impl.attachments.video.VideoUploadEstimation import io.element.android.libraries.architecture.AsyncData @@ -42,6 +44,9 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider false + is SendActionState.Sending.Processing -> !state.sendActionState.displayProgress + SendActionState.Done -> false + else -> true + } + fun postSendAttachment() { state.eventSink(AttachmentsPreviewEvent.SendAttachment) } @@ -93,33 +102,75 @@ fun AttachmentsPreviewView( state.eventSink(AttachmentsPreviewEvent.CancelAndClearSendState) } - BackHandler(enabled = state.sendActionState !is SendActionState.Sending.Uploading && state.sendActionState !is SendActionState.Done) { - postCancel() + fun postOpenImageEditor() { + state.eventSink(AttachmentsPreviewEvent.OpenImageEditor) } - Scaffold( - modifier = modifier, - topBar = { - TopAppBar( - navigationIcon = { - BackButton( - imageVector = CompoundIcons.Close(), - onClick = ::postCancel, - ) - }, - title = {}, + fun postCloseImageEditor() { + state.eventSink(AttachmentsPreviewEvent.CloseImageEditor) + } + + fun postApplyImageEdits() { + state.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) + } + + BackHandler(enabled = state.sendActionState !is SendActionState.Sending.Uploading && state.sendActionState !is SendActionState.Done) { + if (state.imageEditorState != null) { + postCloseImageEditor() + } else { + postCancel() + } + } + + if (state.imageEditorState != null) { + AttachmentImageEditorView( + state = state.imageEditorState, + onCropRectChange = { cropRect -> + state.eventSink(AttachmentsPreviewEvent.UpdateImageCropRect(cropRect)) + }, + onRotateClick = { state.eventSink(AttachmentsPreviewEvent.RotateImage) }, + onCancelClick = ::postCloseImageEditor, + onDoneClick = ::postApplyImageEdits, + modifier = modifier, + ) + } else { + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + navigationIcon = { + BackButton( + imageVector = CompoundIcons.Close(), + onClick = ::postCancel, + ) + }, + title = {}, + actions = { + if (state.canEditImage && canShowEditAction) { + IconButton(onClick = ::postOpenImageEditor) { + Icon( + imageVector = CompoundIcons.Edit(), + contentDescription = stringResource(CommonStrings.action_edit), + ) + } + } + } + ) + } + ) { paddingValues -> + AttachmentPreviewContent( + modifier = Modifier.padding(paddingValues), + state = state, + localMediaRenderer = localMediaRenderer, + onSendClick = ::postSendAttachment, ) } - ) { paddingValues -> - AttachmentPreviewContent( - modifier = Modifier.padding(paddingValues), - state = state, - localMediaRenderer = localMediaRenderer, - onSendClick = ::postSendAttachment, - ) } AttachmentSendStateView( sendActionState = state.sendActionState, + isApplyingImageEdits = state.isApplyingImageEdits, + displayImageEditError = state.displayImageEditError, + onDismissImageEditError = { state.eventSink(AttachmentsPreviewEvent.ClearImageEditError) }, onDismissClick = ::postClearSendState, onRetryClick = ::postSendAttachment ) @@ -128,10 +179,29 @@ fun AttachmentsPreviewView( @Composable private fun AttachmentSendStateView( sendActionState: SendActionState, + isApplyingImageEdits: Boolean, + displayImageEditError: Boolean, + onDismissImageEditError: () -> Unit, onDismissClick: () -> Unit, onRetryClick: () -> Unit ) { - when (sendActionState) { + when { + isApplyingImageEdits -> { + ProgressDialog( + type = ProgressDialogType.Indeterminate, + text = stringResource(CommonStrings.common_preparing), + showCancelButton = false, + onDismissRequest = {}, + ) + } + displayImageEditError -> { + AlertDialog( + title = stringResource(CommonStrings.common_error), + content = stringResource(CommonStrings.common_something_went_wrong_message), + onDismiss = onDismissImageEditError, + ) + } + else -> when (sendActionState) { is SendActionState.Sending.Processing -> { if (sendActionState.displayProgress) { ProgressDialog( @@ -158,6 +228,7 @@ private fun AttachmentSendStateView( ) } else -> Unit + } } } @@ -184,10 +255,10 @@ private fun AttachmentPreviewContent( } } } - val mimeType = (state.attachment as? Attachment.Media)?.localMedia?.info?.mimeType - if (mimeType?.isMimeTypeImage() == true) { + val mediaInfo = (state.attachment as? Attachment.Media)?.localMedia?.info + if (mediaInfo?.isImageAttachment() == true) { ImageOptimizationSelector(state.mediaOptimizationSelectorState) - } else if (mimeType?.isMimeTypeVideo() == true) { + } else if (mediaInfo?.mimeType?.isMimeTypeVideo() == true) { VideoPresetSelector(state = state.mediaOptimizationSelectorState) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt new file mode 100644 index 0000000000..90872df4f2 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import androidx.compose.runtime.Immutable +import io.element.android.libraries.mediaviewer.api.local.LocalMedia + +private const val DEFAULT_CROP_MARGIN = 0.1f +private const val MIN_CROP_SIZE = 0.1f + +@Immutable +data class AttachmentImageEditorState( + val localMedia: LocalMedia, + val edits: AttachmentImageEdits, +) + +@Immutable +data class AttachmentImageEdits( + val cropRect: NormalizedCropRect = NormalizedCropRect.default(), + val rotationQuarterTurns: Int = 0, +) { + val normalizedRotationQuarterTurns: Int + get() = (rotationQuarterTurns % 4 + 4) % 4 + + val rotationDegrees: Int + get() = normalizedRotationQuarterTurns * 90 + + val hasChanges: Boolean + get() = cropRect != NormalizedCropRect.default() || normalizedRotationQuarterTurns != 0 + + fun rotateClockwise(): AttachmentImageEdits { + return copy(rotationQuarterTurns = (normalizedRotationQuarterTurns + 1) % 4) + } +} + +@Immutable +data class NormalizedCropRect( + val left: Float, + val top: Float, + val right: Float, + val bottom: Float, +) { + init { + require(left in 0f..1f) + require(top in 0f..1f) + require(right in 0f..1f) + require(bottom in 0f..1f) + require(left < right) + require(top < bottom) + } + + val width: Float + get() = right - left + + val height: Float + get() = bottom - top + + fun translate(deltaX: Float, deltaY: Float): NormalizedCropRect { + val clampedLeft = (left + deltaX).coerceIn(0f, 1f - width) + val clampedTop = (top + deltaY).coerceIn(0f, 1f - height) + return copy( + left = clampedLeft, + top = clampedTop, + right = clampedLeft + width, + bottom = clampedTop + height, + ) + } + + fun resize(dragTarget: CropDragTarget, deltaX: Float, deltaY: Float): NormalizedCropRect = when (dragTarget) { + CropDragTarget.Move -> translate(deltaX, deltaY) + CropDragTarget.TopLeft -> copy( + left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), + top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), + ) + CropDragTarget.Top -> copy( + top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), + ) + CropDragTarget.TopRight -> copy( + right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), + top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), + ) + CropDragTarget.Right -> copy( + right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), + ) + CropDragTarget.BottomRight -> copy( + right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), + bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), + ) + CropDragTarget.Bottom -> copy( + bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), + ) + CropDragTarget.BottomLeft -> copy( + left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), + bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), + ) + CropDragTarget.Left -> copy( + left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), + ) + } + + companion object { + fun default() = NormalizedCropRect( + left = DEFAULT_CROP_MARGIN, + top = DEFAULT_CROP_MARGIN, + right = 1f - DEFAULT_CROP_MARGIN, + bottom = 1f - DEFAULT_CROP_MARGIN, + ) + } +} + +enum class CropDragTarget { + Move, + TopLeft, + Top, + TopRight, + Right, + BottomRight, + Bottom, + BottomLeft, + Left, +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt new file mode 100644 index 0000000000..f003c19084 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Matrix +import android.net.Uri +import androidx.exifinterface.media.ExifInterface +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.features.messages.impl.attachments.preview.resolvedImageMimeType +import io.element.android.libraries.androidutils.bitmap.rotateToExifMetadataOrientation +import io.element.android.libraries.androidutils.bitmap.writeBitmap +import io.element.android.libraries.androidutils.file.createTmpFile +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAnimatedImage +import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.mediaviewer.api.local.LocalMedia +import kotlinx.coroutines.withContext +import java.io.File +import kotlin.math.roundToInt + +private const val EDITED_MEDIA_DIR_NAME = "edited-media" + +interface AttachmentImageEditor { + suspend fun canEdit(localMedia: LocalMedia): Boolean + + suspend fun exportEdits( + localMedia: LocalMedia, + edits: AttachmentImageEdits, + ): Result +} + +data class EditedLocalMedia( + val localMedia: LocalMedia, + val file: File, +) + +@ContributesBinding(AppScope::class) +class DefaultAttachmentImageEditor( + @ApplicationContext private val context: Context, + private val dispatchers: CoroutineDispatchers, +) : AttachmentImageEditor { + override suspend fun canEdit(localMedia: LocalMedia): Boolean = withContext(dispatchers.io) { + localMedia.info.resolvedImageMimeType() + ?.takeIf { it.isEditableStillImageMimeType() } + ?.let { return@withContext true } + + val decodedMimeType = context.contentResolver.openInputStream(localMedia.uri)?.use { input -> + val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } + BitmapFactory.decodeStream(input, null, options) + options.outMimeType + } + + decodedMimeType.isEditableStillImageMimeType() + } + + override suspend fun exportEdits( + localMedia: LocalMedia, + edits: AttachmentImageEdits, + ): Result = withContext(dispatchers.io) { + runCatchingExceptions { + val sourceMimeType = localMedia.info.resolvedImageMimeType() ?: localMedia.info.mimeType + val exportedMimeType = exportedMimeTypeFor(sourceMimeType) + val exifOrientation = context.contentResolver.openInputStream(localMedia.uri)?.let { input -> + input.use { + ExifInterface(it).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED) + } + } ?: ExifInterface.ORIENTATION_UNDEFINED + + val decodedBitmap = context.contentResolver.openInputStream(localMedia.uri)?.use { input -> + BitmapFactory.decodeStream(input) + } ?: error("Unable to decode image from ${localMedia.uri}") + + val normalizedBitmap = decodedBitmap.rotateToExifMetadataOrientation(exifOrientation) + if (normalizedBitmap !== decodedBitmap) { + decodedBitmap.recycle() + } + + val rotatedBitmap = normalizedBitmap.rotateQuarterTurns(edits.rotationQuarterTurns) + if (rotatedBitmap !== normalizedBitmap) { + normalizedBitmap.recycle() + } + + val cropRect = edits.cropRect.toPixelRect( + imageWidth = rotatedBitmap.width, + imageHeight = rotatedBitmap.height, + ) + val isCropUnchanged = cropRect.left == 0 && cropRect.top == 0 && + cropRect.width() == rotatedBitmap.width && cropRect.height() == rotatedBitmap.height + val croppedBitmap = if (isCropUnchanged) { + rotatedBitmap + } else { + Bitmap.createBitmap( + rotatedBitmap, + cropRect.left, + cropRect.top, + cropRect.width(), + cropRect.height(), + ) + } + if (croppedBitmap !== rotatedBitmap) { + rotatedBitmap.recycle() + } + + val editedMediaDir = File(context.cacheDir, EDITED_MEDIA_DIR_NAME).apply { mkdirs() } + val outputFile = context.createTmpFile(baseDir = editedMediaDir, extension = compressFileExtension(exportedMimeType)) + outputFile.writeBitmap( + bitmap = croppedBitmap, + format = compressFormat(exportedMimeType), + quality = 90, + ) + croppedBitmap.recycle() + + EditedLocalMedia( + localMedia = localMedia.copy( + uri = Uri.fromFile(outputFile), + info = localMedia.info.copy(mimeType = exportedMimeType), + ), + file = outputFile, + ) + } + } +} + +internal fun exportedMimeTypeFor(sourceMimeType: String?): String { + return if (sourceMimeType == MimeTypes.Png) { + MimeTypes.Png + } else { + MimeTypes.Jpeg + } +} + +private fun Bitmap.rotateQuarterTurns(quarterTurns: Int): Bitmap { + val normalizedTurns = (quarterTurns % 4 + 4) % 4 + if (normalizedTurns == 0) return this + val matrix = Matrix().apply { + postRotate(normalizedTurns * 90f) + } + return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true) +} + +private data class PixelCropRect( + val left: Int, + val top: Int, + val right: Int, + val bottom: Int, +) { + fun width() = right - left + fun height() = bottom - top +} + +private fun NormalizedCropRect.toPixelRect(imageWidth: Int, imageHeight: Int): PixelCropRect { + val leftPx = (left * imageWidth).roundToInt().coerceIn(0, imageWidth - 1) + val topPx = (top * imageHeight).roundToInt().coerceIn(0, imageHeight - 1) + val rightPx = (right * imageWidth).roundToInt().coerceIn(leftPx + 1, imageWidth) + val bottomPx = (bottom * imageHeight).roundToInt().coerceIn(topPx + 1, imageHeight) + return PixelCropRect( + left = leftPx, + top = topPx, + right = rightPx, + bottom = bottomPx, + ) +} + +private fun compressFormat(mimeType: String) = when (mimeType) { + "image/png" -> Bitmap.CompressFormat.PNG + else -> Bitmap.CompressFormat.JPEG +} + +private fun compressFileExtension(mimeType: String) = when (mimeType) { + "image/png" -> "png" + else -> "jpeg" +} + +private fun String?.isEditableStillImageMimeType(): Boolean { + return this != null && + this.isMimeTypeImage() && + !this.isMimeTypeAnimatedImage() && + this != MimeTypes.Svg +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt new file mode 100644 index 0000000000..bf3958e83f --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectDragGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.stateDescription +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.dp +import androidx.core.net.toUri +import coil3.compose.AsyncImage +import coil3.compose.AsyncImagePainter +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.R +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +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.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.CommonDrawables +import io.element.android.libraries.mediaviewer.api.anImageMediaInfo +import io.element.android.libraries.mediaviewer.api.local.LocalMedia +import io.element.android.libraries.ui.strings.CommonStrings + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AttachmentImageEditorView( + state: AttachmentImageEditorState, + onCropRectChange: (NormalizedCropRect) -> Unit, + onRotateClick: () -> Unit, + onCancelClick: () -> Unit, + onDoneClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val rotateContentDescription = stringResource(R.string.screen_media_upload_preview_rotate) + val rotationStateDescription = pluralStringResource( + R.plurals.a11y_media_upload_preview_rotation_degrees, + state.edits.rotationDegrees, + state.edits.rotationDegrees, + ) + val rotateButtonBackground = ElementTheme.colors.bgSubtlePrimary + + Scaffold( + modifier = modifier.fillMaxSize(), + topBar = { + TopAppBar( + navigationIcon = { + BackButton( + imageVector = CompoundIcons.Close(), + onClick = onCancelClick, + ) + }, + title = {}, + ) + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .background(ElementTheme.colors.bgCanvasDefault) + .padding(paddingValues) + ) { + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.Center, + ) { + CropEditorCanvas( + state = state, + onCropRectChange = onCropRectChange, + ) + } + + Box( + modifier = Modifier + .fillMaxWidth() + .height(132.dp) + .background(ElementTheme.colors.bgCanvasDefault) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(start = 20.dp, top = 18.dp, end = 20.dp, bottom = 10.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterStart, + ) { + TextButton( + text = stringResource(CommonStrings.action_cancel), + onClick = onCancelClick, + ) + } + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.Center, + ) { + IconButton( + onClick = onRotateClick, + modifier = Modifier + .size(72.dp) + .background( + color = rotateButtonBackground, + shape = CircleShape, + ) + .clearAndSetSemantics { + contentDescription = rotateContentDescription + stateDescription = rotationStateDescription + } + ) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Spacer(modifier = Modifier.height(2.dp)) + Icon( + modifier = Modifier + .size(22.dp), + imageVector = CompoundIcons.RotateRight(), + contentDescription = null, + ) + Spacer(modifier = Modifier.height(3.dp)) + Text( + text = "${state.edits.rotationDegrees}°", + style = ElementTheme.typography.fontBodyXsMedium, + color = ElementTheme.colors.textSecondary, + ) + } + } + } + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterEnd, + ) { + TextButton( + text = stringResource(CommonStrings.action_done), + onClick = onDoneClick, + ) + } + } + } + } + } +} + +@Composable +private fun CropEditorCanvas( + state: AttachmentImageEditorState, + onCropRectChange: (NormalizedCropRect) -> Unit, +) { + var imageSize by remember(state.localMedia.uri) { mutableStateOf(IntSize.Zero) } + val rotationQuarterTurns = state.edits.normalizedRotationQuarterTurns + + BoxWithConstraints( + modifier = Modifier + .fillMaxSize() + ) { + val displayedSize = remember(maxWidth, maxHeight, imageSize, rotationQuarterTurns) { + val sourceWidth = imageSize.width.takeIf { it > 0 } ?: 1 + val sourceHeight = imageSize.height.takeIf { it > 0 } ?: 1 + val aspectRatio = if (rotationQuarterTurns % 2 == 0) { + sourceWidth.toFloat() / sourceHeight.toFloat() + } else { + sourceHeight.toFloat() / sourceWidth.toFloat() + } + fitSize( + containerWidth = constraints.maxWidth.toFloat(), + containerHeight = constraints.maxHeight.toFloat(), + aspectRatio = aspectRatio, + ) + } + val density = LocalDensity.current + val displayedWidthDp = with(density) { displayedSize.width.toDp() } + val displayedHeightDp = with(density) { displayedSize.height.toDp() } + val imageLayoutSize = remember(displayedSize, rotationQuarterTurns) { + if (rotationQuarterTurns % 2 == 0) { + displayedSize + } else { + Size( + width = displayedSize.height, + height = displayedSize.width, + ) + } + } + val imageLayoutWidthDp = with(density) { imageLayoutSize.width.toDp() } + val imageLayoutHeightDp = with(density) { imageLayoutSize.height.toDp() } + + Box( + modifier = Modifier + .size(displayedWidthDp, displayedHeightDp) + .align(Alignment.Center), + contentAlignment = Alignment.Center, + ) { + if (LocalInspectionMode.current) { + Image( + painter = painterResource(id = CommonDrawables.sample_background), + contentDescription = null, + modifier = Modifier + .requiredSize(imageLayoutWidthDp, imageLayoutHeightDp) + .graphicsLayer { rotationZ = rotationQuarterTurns * 90f }, + contentScale = ContentScale.Fit, + ) + } else { + AsyncImage( + model = state.localMedia.uri, + contentDescription = stringResource(CommonStrings.common_image), + modifier = Modifier + .requiredSize(imageLayoutWidthDp, imageLayoutHeightDp) + .graphicsLayer { rotationZ = rotationQuarterTurns * 90f }, + contentScale = ContentScale.Fit, + onState = { painterState -> + if (painterState is AsyncImagePainter.State.Success) { + imageSize = IntSize( + width = painterState.result.image.width, + height = painterState.result.image.height, + ) + } + } + ) + } + + CropOverlay( + cropRect = state.edits.cropRect, + onCropRectChange = onCropRectChange, + ) + } + } +} + +@Composable +private fun CropOverlay( + cropRect: NormalizedCropRect, + onCropRectChange: (NormalizedCropRect) -> Unit, +) { + var dragTarget by remember { mutableStateOf(null) } + val latestCropRect by rememberUpdatedState(cropRect) + val borderColor = ElementTheme.colors.textPrimary + val guideColor = ElementTheme.colors.textSecondary + + Canvas( + modifier = Modifier + .fillMaxSize() + .pointerInput(Unit) { + detectDragGestures( + onDragStart = { offset -> + dragTarget = detectDragTarget( + touchPoint = offset, + cropRect = latestCropRect, + canvasSize = Size(size.width.toFloat(), size.height.toFloat()), + handleTouchRadius = 32.dp.toPx(), + ) + }, + onDragCancel = { + dragTarget = null + }, + onDragEnd = { + dragTarget = null + }, + ) { change, dragAmount -> + val activeTarget = dragTarget ?: return@detectDragGestures + change.consume() + onCropRectChange( + latestCropRect.resize( + dragTarget = activeTarget, + deltaX = dragAmount.x / size.width.toFloat(), + deltaY = dragAmount.y / size.height.toFloat(), + ) + ) + } + } + ) { + val cropLeft = cropRect.left * size.width + val cropTop = cropRect.top * size.height + val cropRight = cropRect.right * size.width + val cropBottom = cropRect.bottom * size.height + // Hardcoded black: the crop overlay must always darken the image regardless of theme. + // No semantic token exists for this use case in the Compound design system. + val overlayColor = Color.Black.copy(alpha = 0.48f) + + drawRect( + color = overlayColor, + topLeft = Offset.Zero, + size = Size(width = size.width, height = cropTop), + ) + drawRect( + color = overlayColor, + topLeft = Offset(0f, cropTop), + size = Size(width = cropLeft, height = cropBottom - cropTop), + ) + drawRect( + color = overlayColor, + topLeft = Offset(cropRight, cropTop), + size = Size(width = size.width - cropRight, height = cropBottom - cropTop), + ) + drawRect( + color = overlayColor, + topLeft = Offset(0f, cropBottom), + size = Size(width = size.width, height = size.height - cropBottom), + ) + + drawRect( + color = borderColor, + topLeft = Offset(cropLeft, cropTop), + size = Size(width = cropRight - cropLeft, height = cropBottom - cropTop), + style = Stroke(width = 2.dp.toPx()), + ) + + val thirdWidth = (cropRight - cropLeft) / 3f + val thirdHeight = (cropBottom - cropTop) / 3f + repeat(2) { index -> + val offsetX = cropLeft + thirdWidth * (index + 1) + val offsetY = cropTop + thirdHeight * (index + 1) + drawLine( + color = guideColor, + start = Offset(offsetX, cropTop), + end = Offset(offsetX, cropBottom), + strokeWidth = 1.dp.toPx(), + ) + drawLine( + color = guideColor, + start = Offset(cropLeft, offsetY), + end = Offset(cropRight, offsetY), + strokeWidth = 1.dp.toPx(), + ) + } + + val handleLength = 16.dp.toPx() + val handleColor = borderColor + drawCornerHandle(cropLeft, cropTop, handleLength, handleColor, true, true) + drawCornerHandle(cropRight, cropTop, handleLength, handleColor, false, true) + drawCornerHandle(cropLeft, cropBottom, handleLength, handleColor, true, false) + drawCornerHandle(cropRight, cropBottom, handleLength, handleColor, false, false) + drawEdgeHandle( + center = Offset((cropLeft + cropRight) / 2f, cropTop), + horizontal = true, + handleLength = handleLength, + color = handleColor, + ) + drawEdgeHandle( + center = Offset(cropRight, (cropTop + cropBottom) / 2f), + horizontal = false, + handleLength = handleLength, + color = handleColor, + ) + drawEdgeHandle( + center = Offset((cropLeft + cropRight) / 2f, cropBottom), + horizontal = true, + handleLength = handleLength, + color = handleColor, + ) + drawEdgeHandle( + center = Offset(cropLeft, (cropTop + cropBottom) / 2f), + horizontal = false, + handleLength = handleLength, + color = handleColor, + ) + } +} + +private fun fitSize( + containerWidth: Float, + containerHeight: Float, + aspectRatio: Float, +): Size { + val widthBasedHeight = containerWidth / aspectRatio + return if (widthBasedHeight <= containerHeight) { + Size(width = containerWidth, height = widthBasedHeight) + } else { + Size(width = containerHeight * aspectRatio, height = containerHeight) + } +} + +private fun detectDragTarget( + touchPoint: Offset, + cropRect: NormalizedCropRect, + canvasSize: Size, + handleTouchRadius: Float, +): CropDragTarget? { + val corners = mapOf( + CropDragTarget.TopLeft to Offset(cropRect.left * canvasSize.width, cropRect.top * canvasSize.height), + CropDragTarget.Top to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.top * canvasSize.height), + CropDragTarget.TopRight to Offset(cropRect.right * canvasSize.width, cropRect.top * canvasSize.height), + CropDragTarget.Right to Offset(cropRect.right * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), + CropDragTarget.BottomRight to Offset(cropRect.right * canvasSize.width, cropRect.bottom * canvasSize.height), + CropDragTarget.Bottom to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.bottom * canvasSize.height), + CropDragTarget.BottomLeft to Offset(cropRect.left * canvasSize.width, cropRect.bottom * canvasSize.height), + CropDragTarget.Left to Offset(cropRect.left * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), + ) + corners.forEach { (target, corner) -> + if ((corner - touchPoint).getDistance() <= handleTouchRadius) { + return target + } + } + val cropLeft = cropRect.left * canvasSize.width + val cropTop = cropRect.top * canvasSize.height + val cropRight = cropRect.right * canvasSize.width + val cropBottom = cropRect.bottom * canvasSize.height + return if (touchPoint.x in cropLeft..cropRight && touchPoint.y in cropTop..cropBottom) { + CropDragTarget.Move + } else { + null + } +} + +private fun androidx.compose.ui.graphics.drawscope.DrawScope.drawCornerHandle( + x: Float, + y: Float, + handleLength: Float, + color: Color, + isLeft: Boolean, + isTop: Boolean, +) { + val horizontalEndX = if (isLeft) x + handleLength else x - handleLength + val verticalEndY = if (isTop) y + handleLength else y - handleLength + drawLine( + color = color, + start = Offset(x, y), + end = Offset(horizontalEndX, y), + strokeWidth = 3.dp.toPx(), + ) + drawLine( + color = color, + start = Offset(x, y), + end = Offset(x, verticalEndY), + strokeWidth = 3.dp.toPx(), + ) +} + +private fun androidx.compose.ui.graphics.drawscope.DrawScope.drawEdgeHandle( + center: Offset, + horizontal: Boolean, + handleLength: Float, + color: Color, +) { + val start = if (horizontal) { + Offset(center.x - handleLength / 2f, center.y) + } else { + Offset(center.x, center.y - handleLength / 2f) + } + val end = if (horizontal) { + Offset(center.x + handleLength / 2f, center.y) + } else { + Offset(center.x, center.y + handleLength / 2f) + } + drawLine( + color = color, + start = start, + end = end, + strokeWidth = 3.dp.toPx(), + ) +} + +@PreviewsDayNight +@Composable +internal fun AttachmentImageEditorViewPreview() = ElementPreview { + AttachmentImageEditorView( + state = AttachmentImageEditorState( + localMedia = LocalMedia( + uri = "file://preview-image".toUri(), + info = anImageMediaInfo(), + ), + edits = AttachmentImageEdits(), + ), + onCropRectChange = {}, + onRotateClick = {}, + onCancelClick = {}, + onDoneClick = {}, + ) +} diff --git a/features/messages/impl/src/main/res/values/temporary.xml b/features/messages/impl/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..f0050224a9 --- /dev/null +++ b/features/messages/impl/src/main/res/values/temporary.xml @@ -0,0 +1,8 @@ + + + Rotate + + %1$d degree + %1$d degrees + + diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 9a9dc08834..5cbfd331c1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -11,11 +11,16 @@ package io.element.android.features.messages.impl.attachments import android.net.Uri +import androidx.core.net.toUri import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewEvent import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewPresenter import io.element.android.features.messages.impl.attachments.preview.OnDoneListener import io.element.android.features.messages.impl.attachments.preview.SendActionState +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEditor +import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEdits +import io.element.android.features.messages.impl.attachments.preview.imageeditor.EditedLocalMedia +import io.element.android.features.messages.impl.attachments.preview.imageeditor.NormalizedCropRect import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState import io.element.android.features.messages.impl.attachments.video.VideoCompressionPresetSelector import io.element.android.features.messages.impl.attachments.video.VideoUploadEstimation @@ -73,6 +78,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import java.io.File +import kotlin.io.path.createTempFile @Suppress("LargeClass") @RunWith(RobolectricTestRunner::class) @@ -551,6 +557,85 @@ class AttachmentsPreviewPresenterTest { } @Test + fun `present - applying image edits updates the attachment`() = runTest { + val editedUri = Uri.parse("file:///tmp/edited.jpeg") + val presenter = createAttachmentsPreviewPresenter( + displayMediaQualitySelectorViews = true, + attachmentImageEditor = FakeAttachmentImageEditor { + Result.success( + EditedLocalMedia( + localMedia = aLocalMedia(uri = editedUri), + file = File("/tmp/edited.jpeg"), + ) + ) + } + ) + + presenter.test { + val initialState = awaitItem() + initialState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val editorState = awaitItem() + assertThat(editorState.imageEditorState).isNotNull() + + editorState.eventSink(AttachmentsPreviewEvent.RotateImage) + val rotatedState = awaitItem() + assertThat(rotatedState.imageEditorState?.edits?.rotationQuarterTurns).isEqualTo(1) + + rotatedState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) + assertThat(awaitItem().isApplyingImageEdits).isTrue() + + val appliedState = awaitItem() + assertThat((appliedState.attachment as Attachment.Media).localMedia.uri).isEqualTo(editedUri) + assertThat(appliedState.imageEditorState).isNull() + assertThat(appliedState.isApplyingImageEdits).isFalse() + } + } + + @Test + fun `present - reopening image editor keeps original media and previous edits`() = runTest { + val editedUri = Uri.parse("file:///tmp/edited.jpeg") + val originalLocalMedia = aLocalMedia(uri = mockMediaUrl) + val cropRect = NormalizedCropRect( + left = 0.2f, + top = 0.15f, + right = 0.85f, + bottom = 0.9f, + ) + val presenter = createAttachmentsPreviewPresenter( + localMedia = originalLocalMedia, + displayMediaQualitySelectorViews = true, + attachmentImageEditor = FakeAttachmentImageEditor { + Result.success( + EditedLocalMedia( + localMedia = aLocalMedia(uri = editedUri), + file = File("/tmp/edited.jpeg"), + ) + ) + } + ) + + presenter.test { + val initialState = awaitItem() + initialState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val editorState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() + + editorState.eventSink(AttachmentsPreviewEvent.UpdateImageCropRect(cropRect)) + val croppedState = awaitItem() + croppedState.eventSink(AttachmentsPreviewEvent.RotateImage) + val rotatedState = awaitItem() + rotatedState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) + + val appliedState = consumeItemsUntilPredicate { !it.isApplyingImageEdits && it.imageEditorState == null }.last() + assertThat((appliedState.attachment as Attachment.Media).localMedia.uri).isEqualTo(editedUri) + + appliedState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val reopenedState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() + assertThat(reopenedState.imageEditorState?.localMedia?.uri).isEqualTo(originalLocalMedia.uri) + assertThat(reopenedState.imageEditorState?.edits?.cropRect).isEqualTo(cropRect) + assertThat(reopenedState.imageEditorState?.edits?.rotationDegrees).isEqualTo(90) + } + } + fun `present - sendAsFile attachment is pre-processed without image compression`() = runTest { // Even though the user has enabled "Optimize media quality" globally, picking the file // through the Files picker (sendAsFile = true) must skip compression. Regression test @@ -581,6 +666,121 @@ class AttachmentsPreviewPresenterTest { } } + @Test + fun `present - sending edited media keeps the edited file available until upload starts`() = runTest { + val editedFile = createTempFile(suffix = ".jpeg").toFile().apply { + writeText("edited-media") + } + val sendFileResult = + lambdaRecorder> { file, _, _, _, _ -> + assertThat(file.exists()).isTrue() + Result.success(FakeMediaUploadHandler()) + } + val room = FakeJoinedRoom( + liveTimeline = FakeTimeline().apply { + sendFileLambda = sendFileResult + }, + ) + val presenter = createAttachmentsPreviewPresenter( + room = room, + displayMediaQualitySelectorViews = true, + onDoneListener = OnDoneListener {}, + mediaPreProcessor = FakeMediaPreProcessor().apply { + givenResult( + Result.success( + MediaUploadInfo.AnyFile( + file = editedFile, + fileInfo = FileInfo( + mimetype = MimeTypes.Jpeg, + size = editedFile.length(), + thumbnailInfo = null, + thumbnailSource = null, + ) + ) + ) + ) + }, + attachmentImageEditor = FakeAttachmentImageEditor { + Result.success( + EditedLocalMedia( + localMedia = aLocalMedia(uri = editedFile.toUri()), + file = editedFile, + ) + ) + } + ) + + presenter.test { + val initialState = awaitItem() + initialState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val editorState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() + + editorState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) + val appliedState = consumeItemsUntilPredicate { !it.isApplyingImageEdits && it.imageEditorState == null }.last() + + appliedState.eventSink(AttachmentsPreviewEvent.SendAttachment) + consumeItemsUntilPredicate { it.sendActionState == SendActionState.Done } + + sendFileResult.assertions().isCalledOnce() + } + } + + @Test + fun `present - image with generic mime type and png extension is still editable`() = runTest { + val localMedia = aLocalMedia( + uri = mockMediaUrl, + mediaInfo = anImageMediaInfo().copy( + mimeType = MimeTypes.OctetStream, + filename = "Screenshot.png", + fileExtension = "png", + ), + ) + val presenter = createAttachmentsPreviewPresenter(localMedia = localMedia) + + presenter.test { + val initialState = awaitItem() + assertThat(initialState.canEditImage).isTrue() + + initialState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val editorState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() + assertThat(editorState.imageEditorState).isNotNull() + } + } + + @Test + fun `present - image can still be edited when editor can decode it despite generic media info`() = runTest { + val localMedia = aLocalMedia( + uri = mockMediaUrl, + mediaInfo = anImageMediaInfo().copy( + mimeType = MimeTypes.OctetStream, + filename = "", + fileExtension = "", + ), + ) + val presenter = createAttachmentsPreviewPresenter( + localMedia = localMedia, + attachmentImageEditor = FakeAttachmentImageEditor( + canEditResult = true, + ) { + Result.success( + EditedLocalMedia( + localMedia = localMedia.copy(uri = Uri.parse("file:///tmp/decoded.jpeg")), + file = File("/tmp/decoded.jpeg"), + ) + ) + } + ) + + presenter.test { + val initialState = consumeItemsUntilPredicate { it.canEditImage }.last() + assertThat(initialState.canEditImage).isTrue() + + initialState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val editorState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() + assertThat(editorState.imageEditorState).isNotNull() + } + } + @Test fun `present - sendAsFile video is pre-processed with best fitting preset`() = runTest { val mediaPreProcessor = FakeMediaPreProcessor() @@ -652,6 +852,14 @@ class AttachmentsPreviewPresenterTest { } ), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + attachmentImageEditor: AttachmentImageEditor = FakeAttachmentImageEditor { + Result.success( + EditedLocalMedia( + localMedia = localMedia.copy(uri = Uri.parse("file:///tmp/default-edited.jpeg")), + file = File("/tmp/default-edited.jpeg"), + ) + ) + }, videoCompressionPresetSelector: VideoCompressionPresetSelector = VideoCompressionPresetSelector(), ): AttachmentsPreviewPresenter { return AttachmentsPreviewPresenter( @@ -669,6 +877,7 @@ class AttachmentsPreviewPresenterTest { }, permalinkBuilder = permalinkBuilder, temporaryUriDeleter = temporaryUriDeleter, + attachmentImageEditor = attachmentImageEditor, sessionCoroutineScope = this, dispatchers = testCoroutineDispatchers(), mediaOptimizationSelectorPresenterFactory = mediaOptimizationSelectorPresenterFactory, @@ -679,6 +888,22 @@ class AttachmentsPreviewPresenterTest { ) } + private class FakeAttachmentImageEditor( + private val canEditResult: Boolean = true, + private val result: () -> Result, + ) : AttachmentImageEditor { + override suspend fun canEdit(localMedia: LocalMedia): Boolean { + return canEditResult + } + + override suspend fun exportEdits( + localMedia: LocalMedia, + edits: AttachmentImageEdits, + ): Result { + return result() + } + } + private val mediaUploadInfo = MediaUploadInfo.AnyFile( File("test"), FileInfo( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt new file mode 100644 index 0000000000..fa9c6367f8 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.mimetype.MimeTypes +import org.junit.Test + +class AttachmentImageEditModelsTest { + @Test + fun `resize with top handle only updates the top edge`() { + val rect = NormalizedCropRect( + left = 0.2f, + top = 0.2f, + right = 0.8f, + bottom = 0.8f, + ) + + val resized = rect.resize( + dragTarget = CropDragTarget.Top, + deltaX = 0.3f, + deltaY = 0.1f, + ) + + assertThat(resized.left).isEqualTo(rect.left) + assertThat(resized.right).isEqualTo(rect.right) + assertThat(resized.bottom).isEqualTo(rect.bottom) + assertThat(resized.top).isEqualTo(0.3f) + } + + @Test + fun `translate keeps the crop rect inside bounds`() { + val rect = NormalizedCropRect( + left = 0.2f, + top = 0.2f, + right = 0.8f, + bottom = 0.8f, + ) + + val translated = rect.translate( + deltaX = 0.6f, + deltaY = 0.6f, + ) + + assertThat(translated.left).isWithin(0.0001f).of(0.4f) + assertThat(translated.top).isWithin(0.0001f).of(0.4f) + assertThat(translated.right).isWithin(0.0001f).of(1.0f) + assertThat(translated.bottom).isWithin(0.0001f).of(1.0f) + } + + @Test + fun `rotate clockwise normalizes after a full turn`() { + var edits = AttachmentImageEdits() + + repeat(4) { + edits = edits.rotateClockwise() + } + + assertThat(edits.normalizedRotationQuarterTurns).isEqualTo(0) + assertThat(edits.rotationDegrees).isEqualTo(0) + assertThat(edits.hasChanges).isFalse() + } + + @Test + fun `exported mime type preserves png`() { + assertThat(exportedMimeTypeFor(MimeTypes.Png)).isEqualTo(MimeTypes.Png) + } + + @Test + fun `exported mime type normalizes non-png images to jpeg`() { + assertThat(exportedMimeTypeFor("image/heic")).isEqualTo(MimeTypes.Jpeg) + } +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt index 83e8a17cf4..09164e36d1 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt @@ -9,7 +9,9 @@ package io.element.android.libraries.mediaviewer.impl.local import android.content.Context +import android.graphics.BitmapFactory import android.net.Uri +import android.webkit.MimeTypeMap import androidx.core.net.toUri import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding @@ -17,6 +19,7 @@ import io.element.android.libraries.androidutils.file.getFileName import io.element.android.libraries.androidutils.file.getFileSize import io.element.android.libraries.androidutils.file.getMimeType import io.element.android.libraries.androidutils.filesize.FileSizeFormatter +import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.matrix.api.core.UserId @@ -85,8 +88,12 @@ class AndroidLocalMediaFactory( waveform: List?, duration: String?, ): LocalMedia { - val resolvedMimeType = mimeType ?: context.getMimeType(uri) ?: MimeTypes.OctetStream val fileName = name ?: context.getFileName(uri) ?: "" + val resolvedMimeType = resolveMimeType( + uri = uri, + mimeType = mimeType, + fileName = fileName, + ) val fileSize = context.getFileSize(uri) val calculatedFormattedFileSize = formattedFileSize ?: fileSizeFormatter.format(fileSize) val fileExtension = fileExtensionExtractor.extractFromName(fileName) @@ -110,4 +117,36 @@ class AndroidLocalMediaFactory( ) ) } + + private fun resolveMimeType( + uri: Uri, + mimeType: String?, + fileName: String, + ): String { + val explicitMimeType = mimeType.takeUnless { it.isNullOrBlank() || it == MimeTypes.OctetStream } + if (explicitMimeType != null) return explicitMimeType + + val resolverMimeType = context.getMimeType(uri).takeUnless { it.isNullOrBlank() || it == MimeTypes.OctetStream } + if (resolverMimeType != null) return resolverMimeType + + val decodedImageMimeType = decodeImageMimeType(uri) + if (decodedImageMimeType != null) return decodedImageMimeType + + val extensionMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( + fileExtensionExtractor.extractFromName(fileName) + ) + if (!extensionMimeType.isNullOrBlank()) return extensionMimeType + + return MimeTypes.OctetStream + } + + private fun decodeImageMimeType(uri: Uri): String? { + return tryOrNull { + context.contentResolver.openInputStream(uri)?.use { inputStream -> + val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } + BitmapFactory.decodeStream(inputStream, null, options) + options.outMimeType + } + } + } } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt index f01ac1d749..26f9087b39 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt @@ -8,7 +8,9 @@ package io.element.android.libraries.mediaviewer.impl.local +import android.graphics.Bitmap import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.androidutils.file.getMimeType import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.matrix.api.media.MediaFile @@ -22,9 +24,13 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment +import java.io.File +import java.io.FileOutputStream @RunWith(RobolectricTestRunner::class) class AndroidLocalMediaFactoryTest { + private val context = RuntimeEnvironment.getApplication() + @Test fun `test AndroidLocalMediaFactory`() { val sut = createAndroidLocalMediaFactory() @@ -58,13 +64,34 @@ class AndroidLocalMediaFactoryTest { ) } + @Test + fun `createFromUri detects image mime type from content when picker mime type is generic`() { + val imageFile = File(context.cacheDir, "picked-media").apply { + FileOutputStream(this).use { outputStream -> + Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + .compress(Bitmap.CompressFormat.PNG, 100, outputStream) + } + } + + val result = createAndroidLocalMediaFactory().createFromUri( + uri = imageFile.toURI().toString().let(android.net.Uri::parse), + mimeType = MimeTypes.OctetStream, + name = imageFile.name, + formattedFileSize = null, + ) + + assertThat(context.getMimeType(result.uri)).isNull() + assertThat(result.info.mimeType).isEqualTo(MimeTypes.Png) + assertThat(result.info.fileExtension).isEmpty() + } + private fun aMediaFile(): MediaFile { return FakeMediaFile("aPath") } private fun createAndroidLocalMediaFactory(): AndroidLocalMediaFactory { return AndroidLocalMediaFactory( - RuntimeEnvironment.getApplication(), + context, FakeFileSizeFormatter(), FileExtensionExtractorWithoutValidation() ) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png new file mode 100644 index 0000000000..37cc9056e1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:490534398a7061e52f66e3ec46d6212107ee2512ff91c768d6618adb24e858f5 +size 376383 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png new file mode 100644 index 0000000000..cb129ba75a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e02017a71217184dc12c4b24b68e344fd20ca374e90e6073506170dd103e16b +size 375365 From bdb42759decb4abd89dccf947063cb53d2026227 Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Thu, 21 May 2026 07:11:53 -0700 Subject: [PATCH 0483/1083] Show jump-to-unread when read marker is outside the loaded window When the m.fully_read marker event is older than the loaded timeline window, no virtual ReadMarker item is inserted and the chevron-up FAB silently no-ops. Surfaces the SDK's new fully_read_event_id on RoomInfo and routes the tap through the existing FocusOnEvent flow so the FAB appears in catch-up scenarios and lands the user on the marker. Bumps matrix-rust-components-kotlin to 26.05.20 to pick up the FFI field; absorbs the ClientBuildException.InvalidRawKey and suspend SpaceRoomList.rooms / subscribeToRoomUpdate API breaks. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../impl/timeline/TimelinePresenter.kt | 34 ++-- .../messages/impl/timeline/TimelineState.kt | 17 +- .../impl/timeline/TimelineStateProvider.kt | 4 +- .../messages/impl/timeline/TimelineView.kt | 36 +++- .../impl/timeline/TimelinePresenterTest.kt | 178 ++++++++++++++++-- .../space/impl/root/SpaceStateProvider.kt | 1 + gradle/libs.versions.toml | 2 +- .../libraries/matrix/api/room/RoomInfo.kt | 5 + .../impl/auth/AuthenticationException.kt | 1 + .../matrix/impl/room/RoomInfoMapper.kt | 1 + .../impl/fixtures/factories/RoomInfo.kt | 2 + .../fixtures/fakes/FakeFfiSpaceRoomList.kt | 6 +- .../matrix/impl/room/RoomInfoMapperTest.kt | 3 + .../matrix/test/room/RoomInfoFixture.kt | 2 + .../matrix/test/room/RoomSummaryFixture.kt | 1 + 15 files changed, 254 insertions(+), 39 deletions(-) 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 ac08c9adfd..bfc951f6ee 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 @@ -291,20 +291,32 @@ class TimelinePresenter( // without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the // bottom of the room. // - // Limitation: when the read marker is outside the loaded window (gaps, pagination), this - // returns null and the jump-to-unread button stays hidden. Proper fix needs an SDK - // accessor for the m.fully_read marker plus FocusedOnEvent navigation on click; gated - // behind FeatureFlags.JumpToUnread until that lands. - val readMarkerIndex = remember { mutableStateOf(null) } - LaunchedEffect(timelineItems, displayJumpToUnread) { + // The state has three shapes: + // - InWindow: the SDK has materialised a virtual ReadMarker item in the loaded window; + // tapping the FAB smoothly scrolls to its index. + // - OutOfWindow: the marker event is older than the loaded window, so the SDK gives us + // only the event id via RoomInfo.fullyReadEventId; tapping triggers a focused-event + // load via the existing TimelineEvent.FocusOnEvent path. + // - Hidden: feature flag off, no marker, caught-up (marker loaded but no virtual item), + // or initial load (no items yet). + val jumpToUnread = remember { mutableStateOf(JumpToUnreadState.Hidden) } + LaunchedEffect(timelineItems, displayJumpToUnread, roomInfo.fullyReadEventId) { if (!displayJumpToUnread) { - readMarkerIndex.value = null + jumpToUnread.value = JumpToUnreadState.Hidden return@LaunchedEffect } val items = timelineItems - readMarkerIndex.value = withContext(dispatchers.computation) { - items.indexOfFirst { (it as? TimelineItem.Virtual)?.model is TimelineItemReadMarkerModel } - .takeIf { it >= 0 } + val fullyReadEventId = roomInfo.fullyReadEventId + jumpToUnread.value = withContext(dispatchers.computation) { + val markerIndex = items.indexOfFirst { + (it as? TimelineItem.Virtual)?.model is TimelineItemReadMarkerModel + } + when { + markerIndex >= 0 -> JumpToUnreadState.InWindow(markerIndex) + fullyReadEventId != null && items.isNotEmpty() && !timelineItemIndexer.isKnown(fullyReadEventId) -> + JumpToUnreadState.OutOfWindow(fullyReadEventId) + else -> JumpToUnreadState.Hidden + } } } @@ -358,7 +370,7 @@ class TimelinePresenter( displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, displayJumpToUnread = displayJumpToUnread, - readMarkerIndex = readMarkerIndex.value, + jumpToUnread = jumpToUnread.value, eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index d66dfe3031..c5b563a9c3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -36,7 +36,7 @@ data class TimelineState( val displayThreadSummaries: Boolean, val displayFloatingDateBadge: Boolean, val displayJumpToUnread: Boolean, - val readMarkerIndex: Int?, + val jumpToUnread: JumpToUnreadState, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event @@ -85,3 +85,18 @@ data class TimelineRoomInfo( val typingNotificationState: TypingNotificationState, val predecessorRoom: PredecessorRoom?, ) + +/** + * Whether the jump-to-unread FAB should be shown, and if so, how tapping it + * should bring the user to the read marker. + */ +@Immutable +sealed interface JumpToUnreadState { + data object Hidden : JumpToUnreadState + + /** The read marker is materialised at [index] in the loaded timeline — smooth scroll to it. */ + data class InWindow(val index: Int) : JumpToUnreadState + + /** The read marker event is older than the loaded window — load it via focused-event navigation. */ + data class OutOfWindow(val eventId: EventId) : JumpToUnreadState +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 2d4e22e79b..81b3134268 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -60,7 +60,7 @@ fun aTimelineState( displayThreadSummaries: Boolean = false, displayFloatingDateBadge: Boolean = false, displayJumpToUnread: Boolean = false, - readMarkerIndex: Int? = null, + jumpToUnread: JumpToUnreadState = JumpToUnreadState.Hidden, newEventState: NewEventState = NewEventState.None, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { @@ -83,7 +83,7 @@ fun aTimelineState( displayThreadSummaries = displayThreadSummaries, displayFloatingDateBadge = displayFloatingDateBadge, displayJumpToUnread = displayJumpToUnread, - readMarkerIndex = readMarkerIndex, + jumpToUnread = jumpToUnread, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index e9117d7ee7..cca3c1f96c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -155,6 +155,10 @@ fun TimelineView( state.eventSink(TimelineEvent.MarkAllAsRead) } + fun onFocusOnEvent(eventId: EventId) { + state.eventSink(TimelineEvent.FocusOnEvent(eventId)) + } + val context = LocalContext.current val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) val view = LocalView.current @@ -240,11 +244,12 @@ fun TimelineView( isLive = state.isLive, focusRequestState = state.focusRequestState, displayJumpToUnread = state.displayJumpToUnread, - readMarkerIndex = state.readMarkerIndex, + jumpToUnread = state.jumpToUnread, onScrollFinishAt = ::onScrollFinishAt, onJumpToLive = ::onJumpToLive, onFocusEventRender = ::onFocusEventRender, onMarkAllAsRead = ::onMarkAllAsRead, + onFocusOnEvent = ::onFocusOnEvent, ) if (state.displayFloatingDateBadge && useReverseLayout) { @@ -326,11 +331,12 @@ private fun BoxScope.TimelineScrollHelper( forceJumpToReadMarkerVisibility: Boolean, focusRequestState: FocusRequestState, displayJumpToUnread: Boolean, - readMarkerIndex: Int?, + jumpToUnread: JumpToUnreadState, onScrollFinishAt: (Int) -> Unit, onJumpToLive: () -> Unit, onFocusEventRender: () -> Unit, onMarkAllAsRead: () -> Unit, + onFocusOnEvent: (EventId) -> Unit, ) { val coroutineScope = rememberCoroutineScope() val isScrollFinished by remember { derivedStateOf { !lazyListState.isScrollInProgress } } @@ -339,12 +345,19 @@ private fun BoxScope.TimelineScrollHelper( lazyListState.firstVisibleItemIndex < 3 && isLive } } - val isJumpToUnreadVisible by remember(readMarkerIndex, forceJumpToReadMarkerVisibility) { + val isJumpToUnreadVisible by remember(jumpToUnread, forceJumpToReadMarkerVisibility) { derivedStateOf { if (forceJumpToReadMarkerVisibility) return@derivedStateOf true - val markerIndex = readMarkerIndex ?: return@derivedStateOf false - val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false - markerIndex > lastVisibleIndex + when (val jtu = jumpToUnread) { + JumpToUnreadState.Hidden -> false + // Marker is outside the loaded window — we have no on-screen anchor, so just show. + is JumpToUnreadState.OutOfWindow -> true + // Marker is in the loaded window — hide once it's scrolled into the visible range. + is JumpToUnreadState.InWindow -> { + val lastVisibleIndex = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: return@derivedStateOf false + jtu.index > lastVisibleIndex + } + } } } val isJumpToBottomVisible = !canAutoScroll || forceJumpToBottomVisibility || !isLive @@ -375,9 +388,12 @@ private fun BoxScope.TimelineScrollHelper( } fun jumpToReadMarker() { - val markerIndex = readMarkerIndex ?: return - coroutineScope.launch { - lazyListState.animateScrollToItemCenter(markerIndex) + when (val jtu = jumpToUnread) { + JumpToUnreadState.Hidden -> Unit + is JumpToUnreadState.InWindow -> coroutineScope.launch { + lazyListState.animateScrollToItemCenter(jtu.index) + } + is JumpToUnreadState.OutOfWindow -> onFocusOnEvent(jtu.eventId) } } @@ -630,7 +646,7 @@ private fun TimelineViewWithReadMarker( // Index points past the loaded items, mirroring the real-world state the FAB // represents: the user has scrolled past the read marker, so it's no longer in // view. The actual scroll target doesn't matter for a static preview. - readMarkerIndex = if (hasUnreadAbove) timelineItems.size else null, + jumpToUnread = if (hasUnreadAbove) JumpToUnreadState.InWindow(timelineItems.size) else JumpToUnreadState.Hidden, newEventState = if (hasUnreadBelow) NewEventState.FromOther else NewEventState.None, ), timelineProtectionState = aTimelineProtectionState(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index f5ede957c8..7cd0f1f126 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -56,6 +56,7 @@ import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2 import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline @@ -371,7 +372,7 @@ class TimelinePresenterTest { } @Test - fun `present - readMarkerIndex points at the read marker virtual item`() = runTest { + fun `present - jumpToUnread is InWindow at the read marker virtual item index`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -391,8 +392,8 @@ class TimelinePresenterTest { MatrixTimelineItem.Event(UniqueId("msg-newest"), anEventTimelineItem(content = aMessageContent())), ) ) - consumeItemsUntilPredicate { it.readMarkerIndex != null }.last().also { state -> - assertThat(state.readMarkerIndex).isEqualTo(3) + consumeItemsUntilPredicate { it.jumpToUnread is JumpToUnreadState.InWindow }.last().also { state -> + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.InWindow(index = 3)) assertThat(state.displayJumpToUnread).isTrue() } cancelAndIgnoreRemainingEvents() @@ -400,7 +401,7 @@ class TimelinePresenterTest { } @Test - fun `present - readMarkerIndex is null when no read marker present`() = runTest { + fun `present - jumpToUnread is Hidden when no read marker and no fullyReadEventId`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -416,16 +417,16 @@ class TimelinePresenterTest { ) ) consumeItemsUntilPredicate { - it.timelineItems.size == 2 && it.readMarkerIndex == null + it.timelineItems.size == 2 && it.jumpToUnread == JumpToUnreadState.Hidden }.last().also { state -> - assertThat(state.readMarkerIndex).isNull() + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden) } cancelAndIgnoreRemainingEvents() } } @Test - fun `present - readMarkerIndex stays null when JumpToUnread feature flag is disabled`() = runTest { + fun `present - jumpToUnread is Hidden when JumpToUnread feature flag is disabled`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -443,7 +444,7 @@ class TimelinePresenterTest { ) consumeItemsUntilPredicate { it.timelineItems.size == 3 }.last().also { state -> assertThat(state.displayJumpToUnread).isFalse() - assertThat(state.readMarkerIndex).isNull() + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden) } cancelAndIgnoreRemainingEvents() } @@ -579,7 +580,7 @@ class TimelinePresenterTest { } @Test - fun `present - readMarkerIndex is 0 when the read marker is the only item`() = runTest { + fun `present - jumpToUnread is InWindow at index 0 when the read marker is the only item`() = runTest { val timelineItems = MutableStateFlow(emptyList()) val timeline = FakeTimeline(timelineItems = timelineItems) val presenter = createTimelinePresenter( @@ -591,8 +592,163 @@ class TimelinePresenterTest { timelineItems.emit( listOf(MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker)) ) - consumeItemsUntilPredicate { it.readMarkerIndex != null }.last().also { state -> - assertThat(state.readMarkerIndex).isEqualTo(0) + consumeItemsUntilPredicate { it.jumpToUnread is JumpToUnreadState.InWindow }.last().also { state -> + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.InWindow(index = 0)) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - jumpToUnread is OutOfWindow when fullyReadEventId is set but not in the loaded window`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val fullyReadEventId = EventId("\$older-than-loaded-window") + val room = FakeJoinedRoom( + liveTimeline = timeline, + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + initialRoomInfo = aRoomInfo(fullyReadEventId = fullyReadEventId), + ), + ) + val presenter = createTimelinePresenter( + timeline = timeline, + room = room, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) + presenter.test { + awaitFirstItem() + // Loaded items don't include the fullyReadEventId and the SDK didn't materialise a ReadMarker. + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(eventId = AN_EVENT_ID, content = aMessageContent())), + MatrixTimelineItem.Event(UniqueId("2"), anEventTimelineItem(eventId = AN_EVENT_ID_2, content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.jumpToUnread is JumpToUnreadState.OutOfWindow }.last().also { state -> + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.OutOfWindow(eventId = fullyReadEventId)) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - jumpToUnread is Hidden when fullyReadEventId IS in the loaded window`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val room = FakeJoinedRoom( + liveTimeline = timeline, + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + // The user is caught up: the marker event is loaded, but the SDK didn't insert a + // virtual ReadMarker because there are no items newer than it. + initialRoomInfo = aRoomInfo(fullyReadEventId = AN_EVENT_ID), + ), + ) + val presenter = createTimelinePresenter( + timeline = timeline, + room = room, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) + presenter.test { + awaitFirstItem() + // A loaded item has eventId == AN_EVENT_ID (default of anEventTimelineItem). + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 }.last().also { state -> + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - jumpToUnread is Hidden when fullyReadEventId is set but the timeline is empty`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val room = FakeJoinedRoom( + liveTimeline = timeline, + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + initialRoomInfo = aRoomInfo(fullyReadEventId = AN_EVENT_ID), + ), + ) + val presenter = createTimelinePresenter( + timeline = timeline, + room = room, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) + presenter.test { + val initialState = awaitFirstItem() + // Without any timeline items, the FAB must stay hidden — the user is mid-load. + assertThat(initialState.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden) + advanceUntilIdle() + val drained = consumeItemsUntilTimeout() + assertThat(drained.any { it.jumpToUnread != JumpToUnreadState.Hidden }).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - jumpToUnread is Hidden when fullyReadEventId is set but the feature flag is off`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val room = FakeJoinedRoom( + liveTimeline = timeline, + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + initialRoomInfo = aRoomInfo(fullyReadEventId = AN_EVENT_ID), + ), + ) + val presenter = createTimelinePresenter( + timeline = timeline, + room = room, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to false)), + ) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.timelineItems.size == 1 }.last().also { state -> + assertThat(state.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden) + } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - jumpToUnread prefers InWindow when both a virtual marker and fullyReadEventId are present`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline(timelineItems = timelineItems) + val room = FakeJoinedRoom( + liveTimeline = timeline, + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + initialRoomInfo = aRoomInfo(fullyReadEventId = AN_EVENT_ID), + ), + ) + val presenter = createTimelinePresenter( + timeline = timeline, + room = room, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("msg-old"), anEventTimelineItem(content = aMessageContent())), + MatrixTimelineItem.Virtual(UniqueId("read-marker"), VirtualTimelineItem.ReadMarker), + MatrixTimelineItem.Event(UniqueId("msg-newest"), anEventTimelineItem(content = aMessageContent())), + ) + ) + consumeItemsUntilPredicate { it.jumpToUnread is JumpToUnreadState.InWindow }.last().also { state -> + assertThat(state.jumpToUnread).isInstanceOf(JumpToUnreadState.InWindow::class.java) } cancelAndIgnoreRemainingEvents() } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt index 20f4918a98..6b8d714cb7 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt @@ -131,6 +131,7 @@ private fun aSpaceInfo( numUnreadMessages = 0, numUnreadNotifications = 0, numUnreadMentions = 0, + fullyReadEventId = null, heroes = persistentListOf(), pinnedEventIds = persistentListOf(), creators = persistentListOf(), diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7a79320530..cf95945d05 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.7" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.20" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt index b9ed8d61b1..715c7348a1 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt @@ -70,6 +70,11 @@ data class RoomInfo( * notification settings. */ val numUnreadMentions: Long, + /** + * Event ID of the user's `m.fully_read` marker for this room, if any. + * Can be set even when the event is older than the loaded timeline window. + */ + val fullyReadEventId: EventId?, val heroes: ImmutableList, val pinnedEventIds: ImmutableList, val creators: ImmutableList, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index 20dbf76a31..fac5227f6a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -28,6 +28,7 @@ fun Throwable.mapAuthenticationException(): AuthenticationException { } is ClientBuildException.WellKnownLookupFailed -> AuthenticationException.Generic(message) is ClientBuildException.EventCache -> AuthenticationException.Generic(message) + is ClientBuildException.InvalidRawKey -> AuthenticationException.Generic(message) } is OAuthException -> when (this) { is OAuthException.Generic -> AuthenticationException.OAuth(message) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt index 0e9aadc65b..a1d0dd5cd3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt @@ -71,6 +71,7 @@ class RoomInfoMapper { numUnreadMessages = it.numUnreadMessages.toLong(), numUnreadMentions = it.numUnreadMentions.toLong(), numUnreadNotifications = it.numUnreadNotifications.toLong(), + fullyReadEventId = it.fullyReadEventId?.let(::EventId), historyVisibility = it.historyVisibility.map(), successorRoom = it.successorRoom?.map(), roomVersion = it.roomVersion, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt index 2ce64154f7..a809f16803 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt @@ -52,6 +52,7 @@ internal fun aRustRoomInfo( numUnreadMessages: ULong = 0uL, numUnreadNotifications: ULong = 0uL, numUnreadMentions: ULong = 0uL, + fullyReadEventId: String? = null, pinnedEventIds: List = listOf(), roomCreators: List? = emptyList(), joinRule: JoinRule? = null, @@ -93,6 +94,7 @@ internal fun aRustRoomInfo( numUnreadMessages = numUnreadMessages, numUnreadNotifications = numUnreadNotifications, numUnreadMentions = numUnreadMentions, + fullyReadEventId = fullyReadEventId, pinnedEventIds = pinnedEventIds, creators = roomCreators, joinRule = joinRule, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt index c0ecc53d4f..c85fb287b7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSpaceRoomList.kt @@ -40,8 +40,8 @@ class FakeFfiSpaceRoomList( return paginationStateResult() } - override fun rooms(): List { - return roomsResult() + override suspend fun rooms(): List = simulateLongTask { + roomsResult() } override fun subscribeToPaginationStateUpdates(listener: SpaceRoomListPaginationStateListener): TaskHandle { @@ -53,7 +53,7 @@ class FakeFfiSpaceRoomList( spaceRoomListPaginationStateListener?.onUpdate(state) } - override fun subscribeToRoomUpdate(listener: SpaceRoomListEntriesListener): TaskHandle { + override suspend fun subscribeToRoomUpdate(listener: SpaceRoomListEntriesListener): TaskHandle { spaceRoomListEntriesListener = listener return FakeFfiTaskHandle() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt index 56b480d97f..75386964ca 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt @@ -79,6 +79,7 @@ class RoomInfoMapperTest { numUnreadMessages = 12uL, numUnreadNotifications = 13uL, numUnreadMentions = 14uL, + fullyReadEventId = AN_EVENT_ID.value, pinnedEventIds = listOf(AN_EVENT_ID.value), roomCreators = listOf(A_USER_ID.value), historyVisibility = RustRoomHistoryVisibility.Joined, @@ -131,6 +132,7 @@ class RoomInfoMapperTest { numUnreadMessages = 12L, numUnreadNotifications = 13L, numUnreadMentions = 14L, + fullyReadEventId = AN_EVENT_ID, historyVisibility = RoomHistoryVisibility.Joined, successorRoom = null, roomVersion = "12", @@ -223,6 +225,7 @@ class RoomInfoMapperTest { numUnreadMessages = 12L, numUnreadNotifications = 13L, numUnreadMentions = 14L, + fullyReadEventId = null, historyVisibility = RoomHistoryVisibility.Joined, roomVersion = "12", privilegedCreatorRole = true, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt index c15330e9dc..7fba39c909 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt @@ -66,6 +66,7 @@ fun aRoomInfo( numUnreadMessages: Long = 0, numUnreadNotifications: Long = 0, numUnreadMentions: Long = 0, + fullyReadEventId: EventId? = null, historyVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Joined, roomVersion: String? = "11", privilegedCreatorRole: Boolean = false, @@ -105,6 +106,7 @@ fun aRoomInfo( numUnreadMessages = numUnreadMessages, numUnreadNotifications = numUnreadNotifications, numUnreadMentions = numUnreadMentions, + fullyReadEventId = fullyReadEventId, historyVisibility = historyVisibility, roomVersion = roomVersion, privilegedCreatorRole = privilegedCreatorRole, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index 32635a7eea..57f89101b7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -115,6 +115,7 @@ fun aRoomSummary( numUnreadMessages = numUnreadMessages, numUnreadNotifications = numUnreadNotifications, numUnreadMentions = numUnreadMentions, + fullyReadEventId = null, historyVisibility = historyVisibility, roomVersion = roomVersion, privilegedCreatorRole = privilegedCreatorRole, From 0399dab1da02b729fe0a5a2130b11b99fa95baba Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Thu, 21 May 2026 08:48:38 -0700 Subject: [PATCH 0484/1083] Dismiss mark as unread button eagerly --- .../impl/timeline/TimelinePresenter.kt | 16 +++++++- .../impl/timeline/TimelinePresenterTest.kt | 38 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) 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 bfc951f6ee..30117b90fd 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 @@ -138,6 +138,12 @@ class TimelinePresenter( val newEventState = remember { mutableStateOf(NewEventState.None) } val messageShieldDialogData: MutableState = remember { mutableStateOf(null) } + // Forces [JumpToUnreadState.Hidden] until the next RoomInfo push. Set after a + // [TimelineEvent.MarkAllAsRead] await completes so the FAB hides without waiting for + // the SDK to push a refreshed fully-read marker; the after-await ordering means any + // RoomInfo update racing the mark-as-read call has already landed and can't undo this. + val suppressJumpToUnread = remember { mutableStateOf(false) } + val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() val isSendPublicReadReceiptsEnabled by remember { sessionPreferencesStore.isSendPublicReadReceiptsEnabled() @@ -234,6 +240,7 @@ class TimelinePresenter( null } ?: return@launch markAsFullyRead(room.roomId, latestEventId) + suppressJumpToUnread.value = true } is TimelineEvent.ShowShieldDialog -> messageShieldDialogData.value = event.messageShieldData is TimelineEvent.ComputeVerifiedUserSendFailure -> { @@ -300,8 +307,13 @@ class TimelinePresenter( // - Hidden: feature flag off, no marker, caught-up (marker loaded but no virtual item), // or initial load (no items yet). val jumpToUnread = remember { mutableStateOf(JumpToUnreadState.Hidden) } - LaunchedEffect(timelineItems, displayJumpToUnread, roomInfo.fullyReadEventId) { - if (!displayJumpToUnread) { + // The SDK is authoritative again once it pushes a new fully-read marker, so drop the + // post-mark-as-read suppression and let the recompute below pick up the new value. + LaunchedEffect(roomInfo.fullyReadEventId) { + suppressJumpToUnread.value = false + } + LaunchedEffect(timelineItems, displayJumpToUnread, roomInfo.fullyReadEventId, suppressJumpToUnread.value) { + if (!displayJumpToUnread || suppressJumpToUnread.value) { jumpToUnread.value = JumpToUnreadState.Hidden return@LaunchedEffect } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 7cd0f1f126..bd40fccf71 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -754,6 +754,44 @@ class TimelinePresenterTest { } } + @Test + fun `present - jumpToUnread hides eagerly after MarkAllAsRead even before a new RoomInfo arrives`() = runTest { + val timelineItems = MutableStateFlow(emptyList()) + val timeline = FakeTimeline( + timelineItems = timelineItems, + getLatestEventIdResult = { Result.success(AN_EVENT_ID_2) }, + ) + val fullyReadEventId = EventId("\$older-than-loaded-window") + val room = FakeJoinedRoom( + liveTimeline = timeline, + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + initialRoomInfo = aRoomInfo(fullyReadEventId = fullyReadEventId), + ), + ) + val presenter = createTimelinePresenter( + timeline = timeline, + room = room, + featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)), + ) + presenter.test { + awaitFirstItem() + timelineItems.emit( + listOf( + MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(eventId = AN_EVENT_ID, content = aMessageContent())), + ) + ) + val outOfWindow = consumeItemsUntilPredicate { it.jumpToUnread is JumpToUnreadState.OutOfWindow }.last() + assertThat(outOfWindow.jumpToUnread).isEqualTo(JumpToUnreadState.OutOfWindow(eventId = fullyReadEventId)) + + outOfWindow.eventSink(TimelineEvent.MarkAllAsRead) + // RoomInfo is intentionally NOT updated — eager hide must fire on the await alone. + val afterMark = consumeItemsUntilPredicate { it.jumpToUnread == JumpToUnreadState.Hidden }.last() + assertThat(afterMark.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden) + cancelAndIgnoreRemainingEvents() + } + } + @Test fun `present - reaction ordering`() = runTest { val timelineItems = MutableStateFlow(emptyList()) From 5277382e6d9faf24174e4f2188cb15783695cf50 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 07:57:00 +0200 Subject: [PATCH 0485/1083] Update dependencyAnalysis to v3.12.0 (#6840) 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 3d49f2cda1..a328218d79 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.11.0" +dependencyAnalysis = "3.12.0" # DI metro = "1.1.1" From bb2779549e6f94689f9e71be66b835d1616d4e7b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2026 18:04:49 +0200 Subject: [PATCH 0486/1083] Update design and UX Update and add tests Improve preview --- .../preview/AttachmentsPreviewEvent.kt | 3 +- .../preview/AttachmentsPreviewPresenter.kt | 9 +- .../preview/AttachmentsPreviewView.kt | 86 +++-- .../imageeditor/AttachmentImageEditModels.kt | 85 +++-- .../imageeditor/AttachmentImageEditor.kt | 4 +- .../AttachmentImageEditorStateProvider.kt | 61 ++++ .../imageeditor/AttachmentImageEditorView.kt | 323 ++++++++++-------- .../impl/src/main/res/values/localazy.xml | 7 + .../impl/src/main/res/values/temporary.xml | 8 - .../AttachmentsPreviewPresenterTest.kt | 4 +- .../AttachmentImageEditModelsTest.kt | 78 ----- .../imageeditor/AttachmentImageEditsTest.kt | 45 +++ .../DefaultAttachmentImageEditorTest.kt | 24 ++ .../imageeditor/NormalizedCropRectTest.kt | 137 ++++++++ .../src/main/res/values/localazy.xml | 1 + tools/localazy/config.json | 1 + 16 files changed, 575 insertions(+), 301 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt delete mode 100644 features/messages/impl/src/main/res/values/temporary.xml delete mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/DefaultAttachmentImageEditorTest.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt index 1957a8b0f7..a7c64845d1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt @@ -16,8 +16,9 @@ sealed interface AttachmentsPreviewEvent { data object CancelAndClearSendState : AttachmentsPreviewEvent data object OpenImageEditor : AttachmentsPreviewEvent data object CloseImageEditor : AttachmentsPreviewEvent - data object RotateImage : AttachmentsPreviewEvent + data object RotateImageToTheLeft : AttachmentsPreviewEvent data object ApplyImageEdits : AttachmentsPreviewEvent + data object ResetImageEdits : AttachmentsPreviewEvent data class UpdateImageCropRect(val cropRect: NormalizedCropRect) : AttachmentsPreviewEvent data object ClearImageEditError : AttachmentsPreviewEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index b5cb13e3e3..7e8bfbdc3f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -287,10 +287,15 @@ class AttachmentsPreviewPresenter( edits = pendingState.edits.copy(cropRect = event.cropRect) ) } - AttachmentsPreviewEvent.RotateImage -> { + AttachmentsPreviewEvent.RotateImageToTheLeft -> { val pendingState = imageEditorState ?: return imageEditorState = pendingState.copy( - edits = pendingState.edits.rotateClockwise() + edits = pendingState.edits.rotateAntiClockwise() + ) + } + AttachmentsPreviewEvent.ResetImageEdits -> { + imageEditorState = imageEditorState?.copy( + edits = AttachmentImageEdits() ) } AttachmentsPreviewEvent.ApplyImageEdits -> { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt index 2c51fa4499..1714a8b8dc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt @@ -31,11 +31,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview 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.messages.impl.R import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError @@ -56,12 +57,11 @@ import io.element.android.libraries.designsystem.modifiers.niceClickable import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.PreviewsDayNight -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.ListItem import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Switch import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.mediaviewer.api.local.LocalMedia @@ -76,6 +76,9 @@ import io.element.android.wysiwyg.display.TextDisplay import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +/** + * Ref: https://www.figma.com/design/zftpgS6LjiczobJZ1GUNpt/Updates-to-Media---File-Upload?node-id=51-3514 + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun AttachmentsPreviewView( @@ -110,6 +113,10 @@ fun AttachmentsPreviewView( state.eventSink(AttachmentsPreviewEvent.CloseImageEditor) } + fun postResetImageEditor() { + state.eventSink(AttachmentsPreviewEvent.ResetImageEdits) + } + fun postApplyImageEdits() { state.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) } @@ -128,8 +135,9 @@ fun AttachmentsPreviewView( onCropRectChange = { cropRect -> state.eventSink(AttachmentsPreviewEvent.UpdateImageCropRect(cropRect)) }, - onRotateClick = { state.eventSink(AttachmentsPreviewEvent.RotateImage) }, + onRotateClick = { state.eventSink(AttachmentsPreviewEvent.RotateImageToTheLeft) }, onCancelClick = ::postCloseImageEditor, + onResetClick = ::postResetImageEditor, onDoneClick = ::postApplyImageEdits, modifier = modifier, ) @@ -140,19 +148,23 @@ fun AttachmentsPreviewView( TopAppBar( navigationIcon = { BackButton( - imageVector = CompoundIcons.Close(), onClick = ::postCancel, ) }, - title = {}, + title = { + Text( + modifier = Modifier.semantics { + heading() + }, + text = stringResource(R.string.screen_media_upload_preview_title), + ) + }, actions = { if (state.canEditImage && canShowEditAction) { - IconButton(onClick = ::postOpenImageEditor) { - Icon( - imageVector = CompoundIcons.Edit(), - contentDescription = stringResource(CommonStrings.action_edit), - ) - } + TextButton( + stringResource(CommonStrings.action_edit), + onClick = ::postOpenImageEditor + ) } } ) @@ -202,32 +214,32 @@ private fun AttachmentSendStateView( ) } else -> when (sendActionState) { - is SendActionState.Sending.Processing -> { - if (sendActionState.displayProgress) { + is SendActionState.Sending.Processing -> { + if (sendActionState.displayProgress) { + ProgressDialog( + type = ProgressDialogType.Indeterminate, + text = stringResource(CommonStrings.common_preparing), + showCancelButton = true, + onDismissRequest = onDismissClick, + ) + } + } + is SendActionState.Sending.Uploading -> { ProgressDialog( type = ProgressDialogType.Indeterminate, - text = stringResource(CommonStrings.common_preparing), + text = stringResource(id = CommonStrings.common_sending), showCancelButton = true, onDismissRequest = onDismissClick, ) } - } - is SendActionState.Sending.Uploading -> { - ProgressDialog( - type = ProgressDialogType.Indeterminate, - text = stringResource(id = CommonStrings.common_sending), - showCancelButton = true, - onDismissRequest = onDismissClick, - ) - } - is SendActionState.Failure -> { - RetryDialog( - content = stringResource(sendAttachmentError(sendActionState.error)), - onDismiss = onDismissClick, - onRetry = onRetryClick - ) - } - else -> Unit + is SendActionState.Failure -> { + RetryDialog( + content = stringResource(sendAttachmentError(sendActionState.error)), + onDismiss = onDismissClick, + onRetry = onRetryClick + ) + } + else -> Unit } } } @@ -291,7 +303,8 @@ private fun AttachmentPreviewContent( private fun ImageOptimizationSelector(state: MediaOptimizationSelectorState) { if (state.displayMediaSelectorViews == true) { Row( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .niceClickable { state.isImageOptimizationEnabled?.let { value -> state.eventSink(MediaOptimizationSelectorEvent.SelectImageOptimization(!value)) @@ -300,7 +313,9 @@ private fun ImageOptimizationSelector(state: MediaOptimizationSelectorState) { .padding(horizontal = 16.dp, vertical = 16.dp) ) { Text( - modifier = Modifier.weight(1f).align(Alignment.CenterVertically), + modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically), text = stringResource(R.string.screen_media_upload_preview_optimize_image_quality_title), style = ElementTheme.typography.fontBodyLgRegular, ) @@ -326,7 +341,8 @@ private fun VideoPresetSelector( if (state.displayMediaSelectorViews == true && videoPresets != null && state.selectedVideoPreset != null) { Column( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 16.dp) .niceClickable { state.eventSink(MediaOptimizationSelectorEvent.OpenVideoPresetSelectorDialog) } ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt index 90872df4f2..3143f2462e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt @@ -10,7 +10,7 @@ package io.element.android.features.messages.impl.attachments.preview.imageedito import androidx.compose.runtime.Immutable import io.element.android.libraries.mediaviewer.api.local.LocalMedia -private const val DEFAULT_CROP_MARGIN = 0.1f +private const val DEFAULT_CROP_MARGIN = 0f private const val MIN_CROP_SIZE = 0.1f @Immutable @@ -25,7 +25,7 @@ data class AttachmentImageEdits( val rotationQuarterTurns: Int = 0, ) { val normalizedRotationQuarterTurns: Int - get() = (rotationQuarterTurns % 4 + 4) % 4 + get() = rotationQuarterTurns % 4 val rotationDegrees: Int get() = normalizedRotationQuarterTurns * 90 @@ -33,8 +33,17 @@ data class AttachmentImageEdits( val hasChanges: Boolean get() = cropRect != NormalizedCropRect.default() || normalizedRotationQuarterTurns != 0 - fun rotateClockwise(): AttachmentImageEdits { - return copy(rotationQuarterTurns = (normalizedRotationQuarterTurns + 1) % 4) + fun rotateAntiClockwise(): AttachmentImageEdits { + return copy( + rotationQuarterTurns = (normalizedRotationQuarterTurns + 3) % 4, + // Also update the crop rect to keep the same selected area + cropRect = NormalizedCropRect( + left = cropRect.top, + top = 1f - cropRect.right, + right = cropRect.bottom, + bottom = 1f - cropRect.left, + ) + ) } } @@ -60,7 +69,13 @@ data class NormalizedCropRect( val height: Float get() = bottom - top - fun translate(deltaX: Float, deltaY: Float): NormalizedCropRect { + fun applyChange(dragTarget: CropDragTarget, deltaX: Float, deltaY: Float): NormalizedCropRect = when (dragTarget) { + is CropDragTarget.Move -> translate(deltaX, deltaY) + is CropDragTarget.Corner -> dragWithCorner(dragTarget, deltaX, deltaY) + is CropDragTarget.Edge -> dragWithEdge(dragTarget, deltaX, deltaY) + } + + private fun translate(deltaX: Float, deltaY: Float): NormalizedCropRect { val clampedLeft = (left + deltaX).coerceIn(0f, 1f - width) val clampedTop = (top + deltaY).coerceIn(0f, 1f - height) return copy( @@ -71,34 +86,36 @@ data class NormalizedCropRect( ) } - fun resize(dragTarget: CropDragTarget, deltaX: Float, deltaY: Float): NormalizedCropRect = when (dragTarget) { - CropDragTarget.Move -> translate(deltaX, deltaY) - CropDragTarget.TopLeft -> copy( + private fun dragWithCorner(dragTarget: CropDragTarget.Corner, deltaX: Float, deltaY: Float) = when (dragTarget) { + CropDragTarget.Corner.TopLeft -> copy( left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), ) - CropDragTarget.Top -> copy( - top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), - ) - CropDragTarget.TopRight -> copy( + CropDragTarget.Corner.TopRight -> copy( right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), ) - CropDragTarget.Right -> copy( - right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), - ) - CropDragTarget.BottomRight -> copy( + CropDragTarget.Corner.BottomRight -> copy( right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), ) - CropDragTarget.Bottom -> copy( - bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), - ) - CropDragTarget.BottomLeft -> copy( + CropDragTarget.Corner.BottomLeft -> copy( left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), ) - CropDragTarget.Left -> copy( + } + + private fun dragWithEdge(dragTarget: CropDragTarget.Edge, deltaX: Float, deltaY: Float) = when (dragTarget) { + CropDragTarget.Edge.Top -> copy( + top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), + ) + CropDragTarget.Edge.Right -> copy( + right = (right + deltaX).coerceIn(left + MIN_CROP_SIZE, 1f), + ) + CropDragTarget.Edge.Bottom -> copy( + bottom = (bottom + deltaY).coerceIn(top + MIN_CROP_SIZE, 1f), + ) + CropDragTarget.Edge.Left -> copy( left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), ) } @@ -113,14 +130,20 @@ data class NormalizedCropRect( } } -enum class CropDragTarget { - Move, - TopLeft, - Top, - TopRight, - Right, - BottomRight, - Bottom, - BottomLeft, - Left, +sealed interface CropDragTarget { + data object Move : CropDragTarget + + sealed interface Corner : CropDragTarget { + data object TopLeft : Corner + data object TopRight : Corner + data object BottomRight : Corner + data object BottomLeft : Corner + } + + sealed interface Edge : CropDragTarget { + data object Top : Edge + data object Right : Edge + data object Bottom : Edge + data object Left : Edge + } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt index f003c19084..cb66802184 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt @@ -174,12 +174,12 @@ private fun NormalizedCropRect.toPixelRect(imageWidth: Int, imageHeight: Int): P } private fun compressFormat(mimeType: String) = when (mimeType) { - "image/png" -> Bitmap.CompressFormat.PNG + MimeTypes.Png -> Bitmap.CompressFormat.PNG else -> Bitmap.CompressFormat.JPEG } private fun compressFileExtension(mimeType: String) = when (mimeType) { - "image/png" -> "png" + MimeTypes.Png -> "png" else -> "jpeg" } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt new file mode 100644 index 0000000000..d6f4a835bc --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.core.net.toUri +import io.element.android.libraries.mediaviewer.api.anImageMediaInfo +import io.element.android.libraries.mediaviewer.api.local.LocalMedia + +open class AttachmentImageEditorStateProvider : PreviewParameterProvider { + private val caterpillarCrop = NormalizedCropRect( + left = 0.3f, + top = 0.3f, + right = 0.8f, + bottom = 0.75f, + ) + + override val values: Sequence + get() = sequenceOf( + anAttachmentImageEditorState( + edits = AttachmentImageEdits( + // Cheat a bit so that the crop match the sample image size (1024 * 682) + cropRect = 0.17f.let { correction -> + NormalizedCropRect( + left = 0f, + top = correction, + right = 1f, + bottom = 1 - correction, + ) + }, + ), + ), + anAttachmentImageEditorState( + edits = AttachmentImageEdits( + cropRect = caterpillarCrop, + ), + ), + anAttachmentImageEditorState( + edits = AttachmentImageEdits( + cropRect = caterpillarCrop, + ).rotateAntiClockwise(), + ), + ) +} + +private fun anAttachmentImageEditorState( + localMedia: LocalMedia = LocalMedia( + uri = "file://preview-image".toUri(), + info = anImageMediaInfo(), + ), + edits: AttachmentImageEdits = AttachmentImageEdits(), +) = + AttachmentImageEditorState( + localMedia = localMedia, + edits = edits, + ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt index bf3958e83f..7f8a42322a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt @@ -10,20 +10,19 @@ package io.element.android.features.messages.impl.attachments.preview.imageedito import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.gestures.detectDragGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable @@ -37,6 +36,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput @@ -48,18 +48,20 @@ import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.heading +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.stateDescription +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import androidx.core.net.toUri import coil3.compose.AsyncImage import coil3.compose.AsyncImagePainter import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.R import io.element.android.libraries.designsystem.components.button.BackButton -import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.preview.ElementPreviewDark 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.Scaffold @@ -67,27 +69,29 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.mediaviewer.api.anImageMediaInfo -import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.ui.strings.CommonStrings +/** + * Ref: https://www.figma.com/design/zftpgS6LjiczobJZ1GUNpt/Updates-to-Media---File-Upload?node-id=51-3539 + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun AttachmentImageEditorView( state: AttachmentImageEditorState, onCropRectChange: (NormalizedCropRect) -> Unit, onRotateClick: () -> Unit, + onResetClick: () -> Unit, onCancelClick: () -> Unit, onDoneClick: () -> Unit, modifier: Modifier = Modifier, ) { - val rotateContentDescription = stringResource(R.string.screen_media_upload_preview_rotate) + val rotateContentDescription = stringResource(R.string.screen_image_edition_a11y_rotate_to_the_left) val rotationStateDescription = pluralStringResource( - R.plurals.a11y_media_upload_preview_rotation_degrees, + R.plurals.screen_image_edition_a11y_rotation_state, state.edits.rotationDegrees, state.edits.rotationDegrees, ) - val rotateButtonBackground = ElementTheme.colors.bgSubtlePrimary + val rotateButtonBackground = ElementTheme.colors.bgCanvasDefault Scaffold( modifier = modifier.fillMaxSize(), @@ -99,7 +103,14 @@ fun AttachmentImageEditorView( onClick = onCancelClick, ) }, - title = {}, + title = { + Text( + modifier = Modifier.semantics { + heading() + }, + text = stringResource(R.string.screen_image_edition_title), + ) + }, ) } ) { paddingValues -> @@ -118,79 +129,59 @@ fun AttachmentImageEditorView( onCropRectChange = onCropRectChange, ) } - - Box( + Row( modifier = Modifier - .fillMaxWidth() - .height(132.dp) - .background(ElementTheme.colors.bgCanvasDefault) + .align(Alignment.CenterHorizontally) + .widthIn(max = 360.dp) + .navigationBarsPadding() + .padding(start = 20.dp, top = 18.dp, end = 20.dp, bottom = 18.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, ) { - Row( - modifier = Modifier - .fillMaxWidth() - .align(Alignment.BottomCenter) - .navigationBarsPadding() - .padding(start = 20.dp, top = 18.dp, end = 20.dp, bottom = 10.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterStart, ) { - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.CenterStart, - ) { - TextButton( - text = stringResource(CommonStrings.action_cancel), - onClick = onCancelClick, - ) - } - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.Center, - ) { - IconButton( - onClick = onRotateClick, - modifier = Modifier - .size(72.dp) - .background( - color = rotateButtonBackground, - shape = CircleShape, - ) - .clearAndSetSemantics { - contentDescription = rotateContentDescription - stateDescription = rotationStateDescription - } - ) { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - Spacer(modifier = Modifier.height(2.dp)) - Icon( - modifier = Modifier - .size(22.dp), - imageVector = CompoundIcons.RotateRight(), - contentDescription = null, - ) - Spacer(modifier = Modifier.height(3.dp)) - Text( - text = "${state.edits.rotationDegrees}°", - style = ElementTheme.typography.fontBodyXsMedium, - color = ElementTheme.colors.textSecondary, - ) + TextButton( + text = stringResource(CommonStrings.action_reset), + destructive = true, + onClick = onResetClick, + ) + } + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.Center, + ) { + IconButton( + onClick = onRotateClick, + modifier = Modifier + .background( + color = rotateButtonBackground, + shape = CircleShape, + ) + .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, CircleShape) + .clearAndSetSemantics { + contentDescription = rotateContentDescription + stateDescription = rotationStateDescription } - } - } - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.CenterEnd, ) { - TextButton( - text = stringResource(CommonStrings.action_done), - onClick = onDoneClick, + Icon( + modifier = Modifier + .size(22.dp), + imageVector = CompoundIcons.RotateLeft(), + contentDescription = null, ) } } + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterEnd, + ) { + TextButton( + text = stringResource(CommonStrings.action_done), + onClick = onDoneClick, + ) + } } } } @@ -207,6 +198,7 @@ private fun CropEditorCanvas( BoxWithConstraints( modifier = Modifier .fillMaxSize() + .padding(20.dp), ) { val displayedSize = remember(maxWidth, maxHeight, imageSize, rotationQuarterTurns) { val sourceWidth = imageSize.width.takeIf { it > 0 } ?: 1 @@ -287,9 +279,9 @@ private fun CropOverlay( ) { var dragTarget by remember { mutableStateOf(null) } val latestCropRect by rememberUpdatedState(cropRect) - val borderColor = ElementTheme.colors.textPrimary - val guideColor = ElementTheme.colors.textSecondary - + val borderColor = ElementTheme.colors.iconPrimary + val guideColor = ElementTheme.colors.iconPrimary + val drawGuidelines = dragTarget == CropDragTarget.Move Canvas( modifier = Modifier .fillMaxSize() @@ -313,7 +305,7 @@ private fun CropOverlay( val activeTarget = dragTarget ?: return@detectDragGestures change.consume() onCropRectChange( - latestCropRect.resize( + latestCropRect.applyChange( dragTarget = activeTarget, deltaX = dragAmount.x / size.width.toFloat(), deltaY = dragAmount.y / size.height.toFloat(), @@ -329,80 +321,120 @@ private fun CropOverlay( // Hardcoded black: the crop overlay must always darken the image regardless of theme. // No semantic token exists for this use case in the Compound design system. val overlayColor = Color.Black.copy(alpha = 0.48f) - + // Overlay above the crop area drawRect( color = overlayColor, topLeft = Offset.Zero, size = Size(width = size.width, height = cropTop), ) + // Overlay on the left of the crop area drawRect( color = overlayColor, topLeft = Offset(0f, cropTop), size = Size(width = cropLeft, height = cropBottom - cropTop), ) + // Overlay on the right of the crop area drawRect( color = overlayColor, topLeft = Offset(cropRight, cropTop), size = Size(width = size.width - cropRight, height = cropBottom - cropTop), ) + // Overlay below the crop area drawRect( color = overlayColor, topLeft = Offset(0f, cropBottom), size = Size(width = size.width, height = size.height - cropBottom), ) - + // Main frame of the crop area drawRect( color = borderColor, topLeft = Offset(cropLeft, cropTop), size = Size(width = cropRight - cropLeft, height = cropBottom - cropTop), - style = Stroke(width = 2.dp.toPx()), + style = Stroke(width = 1.dp.toPx()), ) - - val thirdWidth = (cropRight - cropLeft) / 3f - val thirdHeight = (cropBottom - cropTop) / 3f - repeat(2) { index -> - val offsetX = cropLeft + thirdWidth * (index + 1) - val offsetY = cropTop + thirdHeight * (index + 1) - drawLine( - color = guideColor, - start = Offset(offsetX, cropTop), - end = Offset(offsetX, cropBottom), - strokeWidth = 1.dp.toPx(), - ) - drawLine( - color = guideColor, - start = Offset(cropLeft, offsetY), - end = Offset(cropRight, offsetY), - strokeWidth = 1.dp.toPx(), - ) + // Guide lines dividing the crop area into 9 equal parts + if (drawGuidelines) { + val thirdWidth = (cropRight - cropLeft) / 3f + val thirdHeight = (cropBottom - cropTop) / 3f + (1..2).forEach { index -> + val offsetX = cropLeft + thirdWidth * index + val offsetY = cropTop + thirdHeight * index + // Vertical guide line + drawLine( + color = guideColor, + start = Offset(offsetX, cropTop), + end = Offset(offsetX, cropBottom), + strokeWidth = 1.dp.toPx(), + ) + // Horizontal guide line + drawLine( + color = guideColor, + start = Offset(cropLeft, offsetY), + end = Offset(cropRight, offsetY), + strokeWidth = 1.dp.toPx(), + ) + } } - - val handleLength = 16.dp.toPx() + // Corner handles + val handleLength = 18.dp.toPx() + val handleOffset = 2.dp.toPx() + // Top left corner + drawCornerHandle( + x = cropLeft - handleOffset, + y = cropTop - handleOffset, + handleLength = handleLength, + color = borderColor, + position = CropDragTarget.Corner.TopLeft, + ) + // Top right corner + drawCornerHandle( + x = cropRight + handleOffset, + y = cropTop - handleOffset, + handleLength = handleLength, + color = borderColor, + position = CropDragTarget.Corner.TopRight, + ) + // Bottom left corner + drawCornerHandle( + x = cropLeft - handleOffset, + y = cropBottom + handleOffset, + handleLength = handleLength, + color = borderColor, + position = CropDragTarget.Corner.BottomLeft, + ) + // Bottom right corner + drawCornerHandle( + x = cropRight + handleOffset, + y = cropBottom + handleOffset, + handleLength = handleLength, + color = borderColor, + position = CropDragTarget.Corner.BottomRight, + ) val handleColor = borderColor - drawCornerHandle(cropLeft, cropTop, handleLength, handleColor, true, true) - drawCornerHandle(cropRight, cropTop, handleLength, handleColor, false, true) - drawCornerHandle(cropLeft, cropBottom, handleLength, handleColor, true, false) - drawCornerHandle(cropRight, cropBottom, handleLength, handleColor, false, false) + // Top handle drawEdgeHandle( - center = Offset((cropLeft + cropRight) / 2f, cropTop), + center = Offset((cropLeft + cropRight) / 2f, cropTop - handleOffset), horizontal = true, handleLength = handleLength, color = handleColor, ) + // Right handle drawEdgeHandle( - center = Offset(cropRight, (cropTop + cropBottom) / 2f), + center = Offset(cropRight + handleOffset, (cropTop + cropBottom) / 2f), horizontal = false, handleLength = handleLength, color = handleColor, ) + // Bottom handle drawEdgeHandle( - center = Offset((cropLeft + cropRight) / 2f, cropBottom), + center = Offset((cropLeft + cropRight) / 2f, cropBottom + handleOffset), horizontal = true, handleLength = handleLength, color = handleColor, ) + // Left handle drawEdgeHandle( - center = Offset(cropLeft, (cropTop + cropBottom) / 2f), + center = Offset(cropLeft - handleOffset, (cropTop + cropBottom) / 2f), horizontal = false, handleLength = handleLength, color = handleColor, @@ -430,14 +462,14 @@ private fun detectDragTarget( handleTouchRadius: Float, ): CropDragTarget? { val corners = mapOf( - CropDragTarget.TopLeft to Offset(cropRect.left * canvasSize.width, cropRect.top * canvasSize.height), - CropDragTarget.Top to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.top * canvasSize.height), - CropDragTarget.TopRight to Offset(cropRect.right * canvasSize.width, cropRect.top * canvasSize.height), - CropDragTarget.Right to Offset(cropRect.right * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), - CropDragTarget.BottomRight to Offset(cropRect.right * canvasSize.width, cropRect.bottom * canvasSize.height), - CropDragTarget.Bottom to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.bottom * canvasSize.height), - CropDragTarget.BottomLeft to Offset(cropRect.left * canvasSize.width, cropRect.bottom * canvasSize.height), - CropDragTarget.Left to Offset(cropRect.left * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), + CropDragTarget.Corner.TopLeft to Offset(cropRect.left * canvasSize.width, cropRect.top * canvasSize.height), + CropDragTarget.Edge.Top to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.top * canvasSize.height), + CropDragTarget.Corner.TopRight to Offset(cropRect.right * canvasSize.width, cropRect.top * canvasSize.height), + CropDragTarget.Edge.Right to Offset(cropRect.right * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), + CropDragTarget.Corner.BottomRight to Offset(cropRect.right * canvasSize.width, cropRect.bottom * canvasSize.height), + CropDragTarget.Edge.Bottom to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.bottom * canvasSize.height), + CropDragTarget.Corner.BottomLeft to Offset(cropRect.left * canvasSize.width, cropRect.bottom * canvasSize.height), + CropDragTarget.Edge.Left to Offset(cropRect.left * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), ) corners.forEach { (target, corner) -> if ((corner - touchPoint).getDistance() <= handleTouchRadius) { @@ -455,31 +487,40 @@ private fun detectDragTarget( } } -private fun androidx.compose.ui.graphics.drawscope.DrawScope.drawCornerHandle( +// x and y are the coordinates of the corner +private fun DrawScope.drawCornerHandle( x: Float, y: Float, handleLength: Float, color: Color, - isLeft: Boolean, - isTop: Boolean, + position: CropDragTarget.Corner, ) { - val horizontalEndX = if (isLeft) x + handleLength else x - handleLength - val verticalEndY = if (isTop) y + handleLength else y - handleLength + val strokeWidth = 4.dp.toPx() + val correction = strokeWidth / 2 + val horizontalCorrection = if (position.isLeft()) -correction else correction + val horizontalEndX = if (position.isLeft()) x + handleLength else x - handleLength + val verticalEndY = if (position.isTop()) y + handleLength else y - handleLength + val verticalCorrection = if (position.isTop()) -correction else correction + // Horizontal line drawLine( color = color, - start = Offset(x, y), - end = Offset(horizontalEndX, y), - strokeWidth = 3.dp.toPx(), + start = Offset(x + horizontalCorrection, y), + end = Offset(horizontalEndX + horizontalCorrection, y), + strokeWidth = strokeWidth, ) + // Vertical line drawLine( color = color, - start = Offset(x, y), - end = Offset(x, verticalEndY), - strokeWidth = 3.dp.toPx(), + start = Offset(x, y + verticalCorrection), + end = Offset(x, verticalEndY + verticalCorrection), + strokeWidth = strokeWidth, ) } -private fun androidx.compose.ui.graphics.drawscope.DrawScope.drawEdgeHandle( +private fun CropDragTarget.Corner.isLeft() = this == CropDragTarget.Corner.TopLeft || this == CropDragTarget.Corner.BottomLeft +private fun CropDragTarget.Corner.isTop() = this == CropDragTarget.Corner.TopLeft || this == CropDragTarget.Corner.TopRight + +private fun DrawScope.drawEdgeHandle( center: Offset, horizontal: Boolean, handleLength: Float, @@ -499,23 +540,21 @@ private fun androidx.compose.ui.graphics.drawscope.DrawScope.drawEdgeHandle( color = color, start = start, end = end, - strokeWidth = 3.dp.toPx(), + strokeWidth = 4.dp.toPx(), ) } -@PreviewsDayNight +// Only preview in dark, dark theme is forced on the Node. +@Preview @Composable -internal fun AttachmentImageEditorViewPreview() = ElementPreview { +internal fun AttachmentImageEditorViewPreview( + @PreviewParameter(AttachmentImageEditorStateProvider::class) state: AttachmentImageEditorState, +) = ElementPreviewDark { AttachmentImageEditorView( - state = AttachmentImageEditorState( - localMedia = LocalMedia( - uri = "file://preview-image".toUri(), - info = anImageMediaInfo(), - ), - edits = AttachmentImageEdits(), - ), + state = state, onCropRectChange = {}, onRotateClick = {}, + onResetClick = {}, onCancelClick = {}, onDoneClick = {}, ) diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index f5629f5e2d..908646b048 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -16,6 +16,12 @@ "Travel & Places" "Recent emojis" "Symbols" + "Rotate the image to the left" + + "%1$d degree" + "%1$d degrees" + + "Edit photo" "Captions might not be visible to people using older apps." "Tap to change the video upload quality" "The file could not be uploaded." @@ -26,6 +32,7 @@ "Item %1$d of %2$d" "Optimise image quality" "Processing…" + "Add media" "Block user" "Check if you want to hide all current and future messages from this user" "This message will be reported to your homeserver’s administrator. They will not be able to read any encrypted messages." diff --git a/features/messages/impl/src/main/res/values/temporary.xml b/features/messages/impl/src/main/res/values/temporary.xml deleted file mode 100644 index f0050224a9..0000000000 --- a/features/messages/impl/src/main/res/values/temporary.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - Rotate - - %1$d degree - %1$d degrees - - diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 5cbfd331c1..962f800764 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -577,7 +577,7 @@ class AttachmentsPreviewPresenterTest { val editorState = awaitItem() assertThat(editorState.imageEditorState).isNotNull() - editorState.eventSink(AttachmentsPreviewEvent.RotateImage) + editorState.eventSink(AttachmentsPreviewEvent.RotateImageToTheLeft) val rotatedState = awaitItem() assertThat(rotatedState.imageEditorState?.edits?.rotationQuarterTurns).isEqualTo(1) @@ -621,7 +621,7 @@ class AttachmentsPreviewPresenterTest { editorState.eventSink(AttachmentsPreviewEvent.UpdateImageCropRect(cropRect)) val croppedState = awaitItem() - croppedState.eventSink(AttachmentsPreviewEvent.RotateImage) + croppedState.eventSink(AttachmentsPreviewEvent.RotateImageToTheLeft) val rotatedState = awaitItem() rotatedState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt deleted file mode 100644 index fa9c6367f8..0000000000 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModelsTest.kt +++ /dev/null @@ -1,78 +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.features.messages.impl.attachments.preview.imageeditor - -import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.core.mimetype.MimeTypes -import org.junit.Test - -class AttachmentImageEditModelsTest { - @Test - fun `resize with top handle only updates the top edge`() { - val rect = NormalizedCropRect( - left = 0.2f, - top = 0.2f, - right = 0.8f, - bottom = 0.8f, - ) - - val resized = rect.resize( - dragTarget = CropDragTarget.Top, - deltaX = 0.3f, - deltaY = 0.1f, - ) - - assertThat(resized.left).isEqualTo(rect.left) - assertThat(resized.right).isEqualTo(rect.right) - assertThat(resized.bottom).isEqualTo(rect.bottom) - assertThat(resized.top).isEqualTo(0.3f) - } - - @Test - fun `translate keeps the crop rect inside bounds`() { - val rect = NormalizedCropRect( - left = 0.2f, - top = 0.2f, - right = 0.8f, - bottom = 0.8f, - ) - - val translated = rect.translate( - deltaX = 0.6f, - deltaY = 0.6f, - ) - - assertThat(translated.left).isWithin(0.0001f).of(0.4f) - assertThat(translated.top).isWithin(0.0001f).of(0.4f) - assertThat(translated.right).isWithin(0.0001f).of(1.0f) - assertThat(translated.bottom).isWithin(0.0001f).of(1.0f) - } - - @Test - fun `rotate clockwise normalizes after a full turn`() { - var edits = AttachmentImageEdits() - - repeat(4) { - edits = edits.rotateClockwise() - } - - assertThat(edits.normalizedRotationQuarterTurns).isEqualTo(0) - assertThat(edits.rotationDegrees).isEqualTo(0) - assertThat(edits.hasChanges).isFalse() - } - - @Test - fun `exported mime type preserves png`() { - assertThat(exportedMimeTypeFor(MimeTypes.Png)).isEqualTo(MimeTypes.Png) - } - - @Test - fun `exported mime type normalizes non-png images to jpeg`() { - assertThat(exportedMimeTypeFor("image/heic")).isEqualTo(MimeTypes.Jpeg) - } -} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt new file mode 100644 index 0000000000..43c893dd05 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +class AttachmentImageEditsTest { + @Test + fun `rotate normalizes after a full turn`() { + var edits = AttachmentImageEdits() + repeat(4) { + edits = edits.rotateAntiClockwise() + } + assertThat(edits.normalizedRotationQuarterTurns).isEqualTo(0) + assertThat(edits.rotationDegrees).isEqualTo(0) + assertThat(edits.hasChanges).isFalse() + } + + @Test + fun `rotate updates rotation and crop`() { + val sut = AttachmentImageEdits( + cropRect = NormalizedCropRect( + left = 0.2f, + top = 0.3f, + right = 0.8f, + bottom = 0.9f, + ), + rotationQuarterTurns = 0, + ) + val result = sut.rotateAntiClockwise() + assertThat(result.normalizedRotationQuarterTurns).isEqualTo(3) + assertThat(result.rotationDegrees).isEqualTo(270) + assertThat(result.cropRect.left).isWithin(0.0001f).of(0.3f) + assertThat(result.cropRect.top).isWithin(0.0001f).of(0.2f) + assertThat(result.cropRect.right).isWithin(0.0001f).of(0.9f) + assertThat(result.cropRect.bottom).isWithin(0.0001f).of(0.8f) + assertThat(result.hasChanges).isTrue() + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/DefaultAttachmentImageEditorTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/DefaultAttachmentImageEditorTest.kt new file mode 100644 index 0000000000..f9db4f35f9 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/DefaultAttachmentImageEditorTest.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.mimetype.MimeTypes +import org.junit.Test + +class DefaultAttachmentImageEditorTest { + @Test + fun `exported mime type preserves png`() { + assertThat(exportedMimeTypeFor(MimeTypes.Png)).isEqualTo(MimeTypes.Png) + } + + @Test + fun `exported mime type normalizes non-png images to jpeg`() { + assertThat(exportedMimeTypeFor("image/heic")).isEqualTo(MimeTypes.Jpeg) + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt new file mode 100644 index 0000000000..b51f10727c --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments.preview.imageeditor + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +class NormalizedCropRectTest { + private val rect = NormalizedCropRect( + left = 0.1f, + top = 0.2f, + right = 0.7f, + bottom = 0.8f, + ) + + @Test + fun `applyChange with top handle only updates the top edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Edge.Top, + deltaX = 0.3f, + deltaY = 0.1f, + ) + assertThat(result.left).isEqualTo(rect.left) + assertThat(result.right).isEqualTo(rect.right) + assertThat(result.bottom).isEqualTo(rect.bottom) + assertThat(result.top).isWithin(0.0001f).of(0.3f) + } + + @Test + fun `applyChange with left handle only updates the left edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Edge.Left, + deltaX = 0.1f, + deltaY = 0.3f, + ) + assertThat(result.top).isEqualTo(rect.top) + assertThat(result.right).isEqualTo(rect.right) + assertThat(result.bottom).isEqualTo(rect.bottom) + assertThat(result.left).isWithin(0.0001f).of(0.2f) + } + + @Test + fun `applyChange with right handle only updates the right edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Edge.Right, + deltaX = -0.1f, + deltaY = 0.3f, + ) + assertThat(result.top).isEqualTo(rect.top) + assertThat(result.left).isEqualTo(rect.left) + assertThat(result.bottom).isEqualTo(rect.bottom) + assertThat(result.right).isWithin(0.0001f).of(0.6f) + } + + @Test + fun `applyChange with bottom handle target only updates the bottem edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Edge.Bottom, + deltaX = -0.1f, + deltaY = -0.3f, + ) + assertThat(result.top).isEqualTo(rect.top) + assertThat(result.left).isEqualTo(rect.left) + assertThat(result.right).isEqualTo(rect.right) + assertThat(result.bottom).isWithin(0.0001f).of(0.5f) + } + + @Test + fun `applyChange with top left handle updates the top and left bottem edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Corner.TopLeft, + deltaX = 0.1f, + deltaY = 0.1f, + ) + assertThat(result.top).isWithin(0.0001f).of(0.3f) + assertThat(result.left).isWithin(0.0001f).of(0.2f) + assertThat(result.right).isEqualTo(rect.right) + assertThat(result.bottom).isEqualTo(rect.bottom) + } + + @Test + fun `applyChange with top right handle updates the top and right bottem edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Corner.TopRight, + deltaX = -0.1f, + deltaY = 0.1f, + ) + assertThat(result.top).isWithin(0.0001f).of(0.3f) + assertThat(result.right).isWithin(0.0001f).of(0.6f) + assertThat(result.left).isEqualTo(rect.left) + assertThat(result.bottom).isEqualTo(rect.bottom) + } + + @Test + fun `applyChange with bottom left handle updates the bottom and left bottem edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Corner.BottomLeft, + deltaX = 0.1f, + deltaY = -0.1f, + ) + assertThat(result.bottom).isWithin(0.0001f).of(0.7f) + assertThat(result.left).isWithin(0.0001f).of(0.2f) + assertThat(result.top).isEqualTo(rect.top) + assertThat(result.right).isEqualTo(rect.right) + } + + @Test + fun `applyChange with bottom right handle updates the bottom and right bottem edge`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Corner.BottomRight, + deltaX = -0.1f, + deltaY = -0.1f, + ) + assertThat(result.bottom).isWithin(0.0001f).of(0.7f) + assertThat(result.right).isWithin(0.0001f).of(0.6f) + assertThat(result.top).isEqualTo(rect.top) + assertThat(result.left).isEqualTo(rect.left) + } + + @Test + fun `translate keeps the crop rect inside bounds`() { + val result = rect.applyChange( + dragTarget = CropDragTarget.Move, + deltaX = 0.6f, + deltaY = 0.6f, + ) + assertThat(result.left).isWithin(0.0001f).of(0.4f) + assertThat(result.top).isWithin(0.0001f).of(0.4f) + assertThat(result.right).isWithin(0.0001f).of(1.0f) + assertThat(result.bottom).isWithin(0.0001f).of(1.0f) + } +} diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index e89d45b228..5608486d0e 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -18,6 +18,7 @@ "Info" "Join call" "Jump to bottom" + "Jump to unread" "Move the map to my location" "Mentions only" "Muted" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index cb9c2ecb0d..9936341cee 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -273,6 +273,7 @@ "screen_room_timeline.*", "screen\\.room_timeline.*", "screen_room_typing.*", + "screen\\.image_edition\\..*", "screen\\.media_upload.*" ] }, From aa92bb61c1a4d0aae94d05147481c361a68d4aa3 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 22 May 2026 08:45:58 +0000 Subject: [PATCH 0487/1083] Update screenshots --- ...nts.preview.imageeditor_AttachmentImageEditorView_0_en.png | 3 +++ ...nts.preview.imageeditor_AttachmentImageEditorView_1_en.png | 3 +++ ...nts.preview.imageeditor_AttachmentImageEditorView_2_en.png | 3 +++ ...preview.imageeditor_AttachmentImageEditorView_Day_0_en.png | 3 --- ...eview.imageeditor_AttachmentImageEditorView_Night_0_en.png | 3 --- ...s.impl.attachments.preview_AttachmentsPreviewView_0_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_1_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_2_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_3_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_4_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_5_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_6_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_7_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_8_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_9_en.png | 3 +++ 15 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png new file mode 100644 index 0000000000..3bd0c2ba54 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51f0b3f7e4bb16728f21055de37b7b2780fd2a1fc65b6bd4564334daeab20763 +size 329042 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png new file mode 100644 index 0000000000..bf0a11f093 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5febc6580e4f0bda75a27445157ace7f1acb620c17cba55ca5d2a9330743c1de +size 283397 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png new file mode 100644 index 0000000000..553c54a63d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d99c470fd5134e0a84b284ed32f4c93de01561e630ef32d7c22a4b476bb871b1 +size 277852 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png deleted file mode 100644 index 37cc9056e1..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:490534398a7061e52f66e3ec46d6212107ee2512ff91c768d6618adb24e858f5 -size 376383 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png deleted file mode 100644 index cb129ba75a..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6e02017a71217184dc12c4b24b68e344fd20ca374e90e6073506170dd103e16b -size 375365 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png index 586bf84274..ccca24ef6a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22e3d682c4866bd5c519ab88d08290708929af805438a0bd093200cddcbd41b2 -size 399376 +oid sha256:a14113653096095323ecb94cb3dd694985717b8585c8cfc6b7a45cf7a2483a79 +size 402427 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png index 27d8600ab5..c511e0e162 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02bb9e9de3b0ef480cedbed50483bdd3a899497ecc40ead72491106c6f6b6611 -size 399030 +oid sha256:95c64e1e7055dd048b88f0e19a57fe696ee93505d74f96bc4f1915fcce769d7d +size 402072 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png index f1cde998de..f229a2a82e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:947ccb947f4a961ff7d17b936f2c866d66fea0361879d51ad4c65d18465c1a9f -size 59226 +oid sha256:4ee2ee54c694a45316bbdcfba7038391fe808f5292356748e9e66f46135a9ae8 +size 61457 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png index 586bf84274..ccca24ef6a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22e3d682c4866bd5c519ab88d08290708929af805438a0bd093200cddcbd41b2 -size 399376 +oid sha256:a14113653096095323ecb94cb3dd694985717b8585c8cfc6b7a45cf7a2483a79 +size 402427 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png index dd5a1e333c..09e08632b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d9e221ec2f4ee764967e94c32f52b1615b25dec8fc7697dd5bcd01fc4da8d69 -size 59098 +oid sha256:44c7b0e86781ff6112c3be5b575b548c5ae6e9530f6f27a070ebb008d606a20c +size 61326 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png index d695d41c94..f8fbf8c1a1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:547bf4e3bec05c219f5a72cfd8d506eb7c39429970cced5c2b8f2999ae390265 -size 86149 +oid sha256:ccedfe061af8a77da7ddf6b20d23899bfff986fd6c74b87480b588e148ddd8de +size 89013 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png index 4a6e1cd828..fbff934ed8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d326595038160376db620a07a180de7af37ebfc76d4927ed1176ef6f4370aab -size 72700 +oid sha256:f52a267ee2aa300185191aa3e610787c58d7222bc8e4a7570879d4c5fd37133d +size 328936 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png index fa4beb6dfb..5f90adbd8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8e8bcb6fdffb2d8673e4ee4e16e21672ffe99e717c48fd35b8411a8aa0530e9 -size 405064 +oid sha256:1feeb32f9dce486c54db41727d9d9801f606353008945988331c2ce391dec451 +size 75364 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png index d789e92297..d7cdc540f7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3caecb171d3095ef5c3593c6289b2d99e6cd6a6c635d822ad24061e502bdeb2e -size 82790 +oid sha256:2bfda29fcaade9508e0d742b0de7ac230d41a358e98755e4b08f1ed7d5affe30 +size 408106 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png new file mode 100644 index 0000000000..f06abb6c7b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1fdc4e2d82297927d2062586398fda3f3b7f6febfde8888a062229caf713ff54 +size 85154 From a158da1d18a421e5feb95af159318cb45916ae75 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 22 May 2026 12:13:09 +0200 Subject: [PATCH 0488/1083] For quality issue and improve preview --- .../preview/AttachmentsPreviewPresenter.kt | 1 + .../AttachmentsPreviewStateProvider.kt | 4 ++-- .../imageeditor/AttachmentImageEditModels.kt | 2 ++ .../AttachmentImageEditorStateProvider.kt | 19 +++++++++++++------ .../imageeditor/AttachmentImageEditorView.kt | 8 +++++--- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index 7e8bfbdc3f..78dd6c2e82 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -133,6 +133,7 @@ class AttachmentsPreviewPresenter( // If the media optimization selector is not displayed, we can pre-process the media // to prepare it for sending. This is done to avoid blocking the UI thread when the // user clicks on the send button. + @Suppress("ComplexCondition") if (mediaOptimizationSelectorState.displayMediaSelectorViews == false && preprocessMediaJob == null && imageEditorState == null && diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt index ced90550c3..a2df440a12 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.core.net.toUri import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEditorState -import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEdits +import io.element.android.features.messages.impl.attachments.preview.imageeditor.anAttachmentImageEditorState import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState import io.element.android.features.messages.impl.attachments.video.VideoUploadEstimation import io.element.android.libraries.architecture.AsyncData @@ -45,7 +45,7 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider Unit, ) { var dragTarget by remember { mutableStateOf(null) } val latestCropRect by rememberUpdatedState(cropRect) val borderColor = ElementTheme.colors.iconPrimary val guideColor = ElementTheme.colors.iconPrimary - val drawGuidelines = dragTarget == CropDragTarget.Move + val drawGuidelines = dragTarget == CropDragTarget.Move || forceDrawGuidelines Canvas( modifier = Modifier .fillMaxSize() @@ -352,11 +354,11 @@ private fun CropOverlay( size = Size(width = cropRight - cropLeft, height = cropBottom - cropTop), style = Stroke(width = 1.dp.toPx()), ) - // Guide lines dividing the crop area into 9 equal parts + // Guidelines dividing the crop area into 9 equal parts if (drawGuidelines) { val thirdWidth = (cropRight - cropLeft) / 3f val thirdHeight = (cropBottom - cropTop) / 3f - (1..2).forEach { index -> + for (index in 1..2) { val offsetX = cropLeft + thirdWidth * index val offsetY = cropTop + thirdHeight * index // Vertical guide line From 4876b7c9304941f0cb38fdabd45d3234bfe90329 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 22 May 2026 10:29:31 +0000 Subject: [PATCH 0489/1083] Update screenshots --- ...nts.preview.imageeditor_AttachmentImageEditorView_2_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_3_en.png | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png index 553c54a63d..86b9dc57b8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d99c470fd5134e0a84b284ed32f4c93de01561e630ef32d7c22a4b476bb871b1 -size 277852 +oid sha256:7e5c43a16d24ce7efed1c90cfa9bc6d73ee12c486b2ad2823c531b87e272ac66 +size 282369 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png new file mode 100644 index 0000000000..553c54a63d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d99c470fd5134e0a84b284ed32f4c93de01561e630ef32d7c22a4b476bb871b1 +size 277852 From fe6a17e977ad9275562744c28dc6cddaef6b76d4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 22 May 2026 13:56:50 +0200 Subject: [PATCH 0490/1083] Remove default value of data class. --- .../impl/attachments/preview/AttachmentsPreviewPresenter.kt | 1 + .../preview/imageeditor/AttachmentImageEditModels.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index 78dd6c2e82..72d840c4ad 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -276,6 +276,7 @@ class AttachmentsPreviewPresenter( imageEditorState = AttachmentImageEditorState( localMedia = originalLocalMedia, edits = appliedImageEdits, + forceDrawGuidelines = false, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt index 885bd077d1..d103e6b913 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt @@ -18,7 +18,7 @@ data class AttachmentImageEditorState( val localMedia: LocalMedia, val edits: AttachmentImageEdits, // For preview only - val forceDrawGuidelines: Boolean = false, + val forceDrawGuidelines: Boolean, ) @Immutable From 94c3bb9c4103f039a5cf4c2e652a541b113a7fe2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 22 May 2026 13:59:21 +0200 Subject: [PATCH 0491/1083] Rename file. --- ...AttachmentImageEditModels.kt => AttachmentImageEditorState.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/{AttachmentImageEditModels.kt => AttachmentImageEditorState.kt} (100%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt similarity index 100% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditModels.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt From afa2a824b5c2f06206954c0c65ad6e2146a69f16 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 22 May 2026 15:28:48 +0200 Subject: [PATCH 0492/1083] Fix tests. --- .../AttachmentsPreviewPresenterTest.kt | 16 ++- .../imageeditor/NormalizedCropRectTest.kt | 116 ++++++++++++------ 2 files changed, 92 insertions(+), 40 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 962f800764..140d4f8ea3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -21,6 +21,7 @@ import io.element.android.features.messages.impl.attachments.preview.imageeditor import io.element.android.features.messages.impl.attachments.preview.imageeditor.AttachmentImageEdits import io.element.android.features.messages.impl.attachments.preview.imageeditor.EditedLocalMedia import io.element.android.features.messages.impl.attachments.preview.imageeditor.NormalizedCropRect +import io.element.android.features.messages.impl.attachments.preview.imageeditor.assertIsSimilarTo import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState import io.element.android.features.messages.impl.attachments.video.VideoCompressionPresetSelector import io.element.android.features.messages.impl.attachments.video.VideoUploadEstimation @@ -579,7 +580,7 @@ class AttachmentsPreviewPresenterTest { editorState.eventSink(AttachmentsPreviewEvent.RotateImageToTheLeft) val rotatedState = awaitItem() - assertThat(rotatedState.imageEditorState?.edits?.rotationQuarterTurns).isEqualTo(1) + assertThat(rotatedState.imageEditorState?.edits?.rotationQuarterTurns).isEqualTo(3) rotatedState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) assertThat(awaitItem().isApplyingImageEdits).isTrue() @@ -630,9 +631,16 @@ class AttachmentsPreviewPresenterTest { appliedState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) val reopenedState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() - assertThat(reopenedState.imageEditorState?.localMedia?.uri).isEqualTo(originalLocalMedia.uri) - assertThat(reopenedState.imageEditorState?.edits?.cropRect).isEqualTo(cropRect) - assertThat(reopenedState.imageEditorState?.edits?.rotationDegrees).isEqualTo(90) + assertThat(reopenedState.imageEditorState!!.localMedia.uri).isEqualTo(originalLocalMedia.uri) + val rotatedCropRect = NormalizedCropRect( + left = cropRect.top, + top = 1f - cropRect.right, + right = cropRect.bottom, + bottom = 1f - cropRect.left, + ) + reopenedState.imageEditorState.edits.cropRect.assertIsSimilarTo(rotatedCropRect) + assertThat(reopenedState.imageEditorState.edits.rotationQuarterTurns).isEqualTo(3) + assertThat(reopenedState.imageEditorState.edits.rotationDegrees).isEqualTo(270) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt index b51f10727c..14cb07eed7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt @@ -25,10 +25,14 @@ class NormalizedCropRectTest { deltaX = 0.3f, deltaY = 0.1f, ) - assertThat(result.left).isEqualTo(rect.left) - assertThat(result.right).isEqualTo(rect.right) - assertThat(result.bottom).isEqualTo(rect.bottom) - assertThat(result.top).isWithin(0.0001f).of(0.3f) + result.assertIsSimilarTo( + NormalizedCropRect( + left = rect.left, + top = 0.3f, + right = rect.right, + bottom = rect.bottom, + ) + ) } @Test @@ -38,10 +42,14 @@ class NormalizedCropRectTest { deltaX = 0.1f, deltaY = 0.3f, ) - assertThat(result.top).isEqualTo(rect.top) - assertThat(result.right).isEqualTo(rect.right) - assertThat(result.bottom).isEqualTo(rect.bottom) - assertThat(result.left).isWithin(0.0001f).of(0.2f) + result.assertIsSimilarTo( + NormalizedCropRect( + left = 0.2f, + top = rect.top, + right = rect.right, + bottom = rect.bottom, + ) + ) } @Test @@ -51,10 +59,15 @@ class NormalizedCropRectTest { deltaX = -0.1f, deltaY = 0.3f, ) - assertThat(result.top).isEqualTo(rect.top) - assertThat(result.left).isEqualTo(rect.left) - assertThat(result.bottom).isEqualTo(rect.bottom) - assertThat(result.right).isWithin(0.0001f).of(0.6f) + val s = assertThat(result) + result.assertIsSimilarTo( + NormalizedCropRect( + left = rect.left, + top = rect.top, + right = 0.6f, + bottom = rect.bottom, + ) + ) } @Test @@ -64,10 +77,14 @@ class NormalizedCropRectTest { deltaX = -0.1f, deltaY = -0.3f, ) - assertThat(result.top).isEqualTo(rect.top) - assertThat(result.left).isEqualTo(rect.left) - assertThat(result.right).isEqualTo(rect.right) - assertThat(result.bottom).isWithin(0.0001f).of(0.5f) + result.assertIsSimilarTo( + NormalizedCropRect( + left = rect.left, + top = rect.top, + right = rect.right, + bottom = 0.5f, + ) + ) } @Test @@ -77,10 +94,14 @@ class NormalizedCropRectTest { deltaX = 0.1f, deltaY = 0.1f, ) - assertThat(result.top).isWithin(0.0001f).of(0.3f) - assertThat(result.left).isWithin(0.0001f).of(0.2f) - assertThat(result.right).isEqualTo(rect.right) - assertThat(result.bottom).isEqualTo(rect.bottom) + result.assertIsSimilarTo( + NormalizedCropRect( + left = 0.2f, + top = 0.3f, + right = rect.right, + bottom = rect.bottom, + ) + ) } @Test @@ -90,10 +111,14 @@ class NormalizedCropRectTest { deltaX = -0.1f, deltaY = 0.1f, ) - assertThat(result.top).isWithin(0.0001f).of(0.3f) - assertThat(result.right).isWithin(0.0001f).of(0.6f) - assertThat(result.left).isEqualTo(rect.left) - assertThat(result.bottom).isEqualTo(rect.bottom) + result.assertIsSimilarTo( + NormalizedCropRect( + left = rect.left, + top = 0.3f, + right = 0.6f, + bottom = rect.bottom, + ) + ) } @Test @@ -103,10 +128,14 @@ class NormalizedCropRectTest { deltaX = 0.1f, deltaY = -0.1f, ) - assertThat(result.bottom).isWithin(0.0001f).of(0.7f) - assertThat(result.left).isWithin(0.0001f).of(0.2f) - assertThat(result.top).isEqualTo(rect.top) - assertThat(result.right).isEqualTo(rect.right) + result.assertIsSimilarTo( + NormalizedCropRect( + left = 0.2f, + top = rect.top, + right = rect.right, + bottom = 0.7f, + ) + ) } @Test @@ -116,10 +145,14 @@ class NormalizedCropRectTest { deltaX = -0.1f, deltaY = -0.1f, ) - assertThat(result.bottom).isWithin(0.0001f).of(0.7f) - assertThat(result.right).isWithin(0.0001f).of(0.6f) - assertThat(result.top).isEqualTo(rect.top) - assertThat(result.left).isEqualTo(rect.left) + result.assertIsSimilarTo( + NormalizedCropRect( + left = rect.left, + top = rect.top, + right = 0.6f, + bottom = 0.7f, + ) + ) } @Test @@ -129,9 +162,20 @@ class NormalizedCropRectTest { deltaX = 0.6f, deltaY = 0.6f, ) - assertThat(result.left).isWithin(0.0001f).of(0.4f) - assertThat(result.top).isWithin(0.0001f).of(0.4f) - assertThat(result.right).isWithin(0.0001f).of(1.0f) - assertThat(result.bottom).isWithin(0.0001f).of(1.0f) + result.assertIsSimilarTo( + NormalizedCropRect( + left = 0.4f, + top = 0.4f, + right = 1.0f, + bottom = 1.0f, + ) + ) } } + +internal fun NormalizedCropRect.assertIsSimilarTo(expectedResult: NormalizedCropRect) { + assertThat(left).isWithin(0.0001f).of(expectedResult.left) + assertThat(top).isWithin(0.0001f).of(expectedResult.top) + assertThat(right).isWithin(0.0001f).of(expectedResult.right) + assertThat(bottom).isWithin(0.0001f).of(expectedResult.bottom) +} From 6e7444620919ffedee1ffb6efc115c7c621d9b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 22 May 2026 16:41:44 +0200 Subject: [PATCH 0493/1083] Allow detecting touch events outside the image by applying the drag detection to the parent node and offsetting the touch events --- .../imageeditor/AttachmentImageEditorView.kt | 107 +++++++++++------- 1 file changed, 63 insertions(+), 44 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt index 2aff3aaff1..f7c5ab6c06 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.gestures.detectDragGestures import androidx.compose.foundation.layout.Arrangement 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.Row @@ -34,6 +35,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.DrawScope @@ -41,6 +43,8 @@ import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.boundsInParent +import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.painterResource @@ -53,6 +57,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage @@ -188,13 +193,15 @@ fun AttachmentImageEditorView( } @Composable -private fun CropEditorCanvas( +private fun BoxScope.CropEditorCanvas( state: AttachmentImageEditorState, onCropRectChange: (NormalizedCropRect) -> Unit, ) { var imageSize by remember(state.localMedia.uri) { mutableStateOf(IntSize.Zero) } val rotationQuarterTurns = state.edits.normalizedRotationQuarterTurns + var imageRect by remember { mutableStateOf(Rect.Zero) } + BoxWithConstraints( modifier = Modifier .fillMaxSize() @@ -233,7 +240,10 @@ private fun CropEditorCanvas( Box( modifier = Modifier .size(displayedWidthDp, displayedHeightDp) - .align(Alignment.Center), + .align(Alignment.Center) + .onPlaced { + imageRect = it.boundsInParent() + }, contentAlignment = Alignment.Center, ) { if (LocalInspectionMode.current) { @@ -263,11 +273,50 @@ private fun CropEditorCanvas( } ) } + } + val touchRadius = 56.dp + var dragTarget by remember { mutableStateOf(null) } + val latestCropRect by rememberUpdatedState(state.edits.cropRect) + val drawGuidelines = dragTarget == CropDragTarget.Move || state.forceDrawGuidelines + Box( + modifier = Modifier + .fillMaxSize() + .pointerInput(Unit) { + detectDragGestures( + onDragStart = { offset -> + dragTarget = detectDragTarget( + touchPoint = offset, + imageOffset = imageRect.topLeft, + cropRect = latestCropRect, + canvasSize = Size(imageRect.width, imageRect.height), + handleTouchRadius = touchRadius.toPx(), + ) + }, + onDragCancel = { + dragTarget = null + }, + onDragEnd = { + dragTarget = null + }, + ) { change, dragAmount -> + val activeTarget = dragTarget ?: return@detectDragGestures + change.consume() + onCropRectChange( + latestCropRect.applyChange( + dragTarget = activeTarget, + deltaX = dragAmount.x / size.width.toFloat(), + deltaY = dragAmount.y / size.height.toFloat(), + ) + ) + } + }, + contentAlignment = Alignment.Center, + ) { CropOverlay( + imageSize = DpSize(displayedWidthDp, displayedHeightDp), cropRect = state.edits.cropRect, - forceDrawGuidelines = state.forceDrawGuidelines, - onCropRectChange = onCropRectChange, + drawGuidelines = drawGuidelines, ) } } @@ -275,46 +324,15 @@ private fun CropEditorCanvas( @Composable private fun CropOverlay( + imageSize: DpSize, cropRect: NormalizedCropRect, - forceDrawGuidelines: Boolean, - onCropRectChange: (NormalizedCropRect) -> Unit, + drawGuidelines: Boolean, ) { - var dragTarget by remember { mutableStateOf(null) } - val latestCropRect by rememberUpdatedState(cropRect) val borderColor = ElementTheme.colors.iconPrimary val guideColor = ElementTheme.colors.iconPrimary - val drawGuidelines = dragTarget == CropDragTarget.Move || forceDrawGuidelines + Canvas( - modifier = Modifier - .fillMaxSize() - .pointerInput(Unit) { - detectDragGestures( - onDragStart = { offset -> - dragTarget = detectDragTarget( - touchPoint = offset, - cropRect = latestCropRect, - canvasSize = Size(size.width.toFloat(), size.height.toFloat()), - handleTouchRadius = 32.dp.toPx(), - ) - }, - onDragCancel = { - dragTarget = null - }, - onDragEnd = { - dragTarget = null - }, - ) { change, dragAmount -> - val activeTarget = dragTarget ?: return@detectDragGestures - change.consume() - onCropRectChange( - latestCropRect.applyChange( - dragTarget = activeTarget, - deltaX = dragAmount.x / size.width.toFloat(), - deltaY = dragAmount.y / size.height.toFloat(), - ) - ) - } - } + modifier = Modifier.size(imageSize.width, imageSize.height) ) { val cropLeft = cropRect.left * size.width val cropTop = cropRect.top * size.height @@ -459,6 +477,7 @@ private fun fitSize( private fun detectDragTarget( touchPoint: Offset, + imageOffset: Offset, cropRect: NormalizedCropRect, canvasSize: Size, handleTouchRadius: Float, @@ -474,14 +493,14 @@ private fun detectDragTarget( CropDragTarget.Edge.Left to Offset(cropRect.left * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), ) corners.forEach { (target, corner) -> - if ((corner - touchPoint).getDistance() <= handleTouchRadius) { + if ((corner - touchPoint + imageOffset).getDistance() <= handleTouchRadius) { return target } } - val cropLeft = cropRect.left * canvasSize.width - val cropTop = cropRect.top * canvasSize.height - val cropRight = cropRect.right * canvasSize.width - val cropBottom = cropRect.bottom * canvasSize.height + val cropLeft = imageOffset.x + cropRect.left * canvasSize.width + val cropTop = imageOffset.y + cropRect.top * canvasSize.height + val cropRight = imageOffset.x + cropRect.right * canvasSize.width + val cropBottom = imageOffset.y + cropRect.bottom * canvasSize.height return if (touchPoint.x in cropLeft..cropRight && touchPoint.y in cropTop..cropBottom) { CropDragTarget.Move } else { From e3684e58606f6e27272fffded28754cc4d55c6f0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 20:05:07 +0000 Subject: [PATCH 0494/1083] Update dependency androidx.javascriptengine:javascriptengine to v1.1.0 --- 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 a328218d79..eb8799d1f4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -98,7 +98,7 @@ androidx_constraintlayout_compose = { module = "androidx.constraintlayout:constr androidx_camera_lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camera" } androidx_camera_view = { module = "androidx.camera:camera-view", version.ref = "camera" } androidx_camera_camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camera" } -androidx_javascriptengine = "androidx.javascriptengine:javascriptengine:1.0.0" +androidx_javascriptengine = "androidx.javascriptengine:javascriptengine:1.1.0" androidx_workmanager_runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "work" } androidx_recyclerview = "androidx.recyclerview:recyclerview:1.4.0" From b31dad4b26441b91a5ae5e7fc78d0f14940f4915 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 25 May 2026 11:31:53 +0300 Subject: [PATCH 0495/1083] Do not show membership/profile events in public rooms (#6360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Filter some membership/profile/topic events in public rooms: don't display join and leave membership events in publicly joinable rooms, and hide display name and avatar url changes in non encrypted and publicly joinable rooms. * Add empty day post-processing to the timeline based on bxdxnn's code, tweaked. --------- Co-authored-by: Jorge Martín --- .../factories/TimelineItemsFactory.kt | 26 ++- .../factories/TimelineItemsFactoryTest.kt | 160 ++++++++++++++++++ .../matrix/impl/timeline/RustTimeline.kt | 17 +- .../RoomBeginningPostProcessor.kt | 18 +- .../impl/timeline/postprocessor/Fixtures.kt | 9 + .../RoomBeginningPostProcessorTest.kt | 117 ++++++++++++- 6 files changed, 339 insertions(+), 8 deletions(-) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt index 7b369fe6b7..dc8bdddc92 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt @@ -16,6 +16,7 @@ import io.element.android.features.messages.impl.timeline.factories.event.Timeli import io.element.android.features.messages.impl.timeline.factories.virtual.TimelineItemVirtualFactory import io.element.android.features.messages.impl.timeline.groups.TimelineItemGrouper import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel import io.element.android.libraries.androidutils.diff.DiffCacheUpdater import io.element.android.libraries.androidutils.diff.MutableListDiffCache import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -96,7 +97,8 @@ class TimelineItemsFactory( } } val result = timelineItemGrouper.group(newTimelineItemStates).toImmutableList() - this._timelineItems.emit(result) + val filteredResult = filterEmptyDaySeparators(result) + this._timelineItems.emit(filteredResult) } private suspend fun buildAndCacheItem( @@ -114,3 +116,25 @@ class TimelineItemsFactory( return timelineItem } } + +// Remove day separators for days with no events after the client-side event filtering +internal fun filterEmptyDaySeparators(items: List): ImmutableList { + return buildList { + var hasEventBefore = false + for (item in items) { + when (item) { + is TimelineItem.Event, is TimelineItem.GroupedEvents -> { + hasEventBefore = true + add(item) + } + is TimelineItem.Virtual if item.model is TimelineItemDaySeparatorModel -> { + if (hasEventBefore) { + add(item) + } + hasEventBefore = false + } + else -> add(item) + } + } + }.toImmutableList() +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt new file mode 100644 index 0000000000..8df8d34f56 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.timeline.factories + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.fixtures.aMessageEvent +import io.element.android.features.messages.impl.timeline.aTimelineItemDebugInfo +import io.element.android.features.messages.impl.timeline.aTimelineItemReactions +import io.element.android.features.messages.impl.timeline.model.ReadReceiptData +import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts +import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel +import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel +import io.element.android.libraries.designsystem.components.avatar.anAvatarData +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.core.FakeSendHandle +import kotlinx.collections.immutable.toImmutableList +import org.junit.Test + +class TimelineItemsFactoryTest { + private val anEvent = TimelineItem.Event( + id = UniqueId("event"), + eventId = AN_EVENT_ID, + senderId = A_USER_ID, + senderAvatar = anAvatarData(), + senderProfile = ProfileDetails.Ready(displayName = "User", displayNameAmbiguous = false, avatarUrl = null), + content = aMessageEvent().content, + reactionsState = aTimelineItemReactions(count = 0), + readReceiptState = TimelineItemReadReceipts(emptyList().toImmutableList()), + localSendState = LocalEventSendState.Sent(AN_EVENT_ID), + isEditable = false, + canBeRepliedTo = false, + inReplyTo = null, + threadInfo = null, + origin = null, + timelineItemDebugInfoProvider = { aTimelineItemDebugInfo() }, + messageShieldProvider = { null }, + sendHandleProvider = { FakeSendHandle() }, + forwarder = null, + forwarderProfile = null, + ) + + private fun aDaySeparator(date: String) = TimelineItem.Virtual( + id = UniqueId("day_$date"), + model = aTimelineItemDaySeparatorModel(date) + ) + + @Test + fun `filterEmptyDaySeparators keeps day separator with events after it`() { + val items = listOf( + anEvent, + aDaySeparator("Today"), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).hasSize(2) + assertThat(result[0]).isEqualTo(anEvent) + assertThat(result[1]).isEqualTo(aDaySeparator("Today")) + } + + @Test + fun `filterEmptyDaySeparators removes day separator with no events after it`() { + val items = listOf( + aDaySeparator("Today"), + aDaySeparator("Yesterday"), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).isEmpty() + } + + @Test + fun `filterEmptyDaySeparators removes first day separator and keeps second when only second has events`() { + val items = listOf( + aDaySeparator("Today"), + anEvent, + aDaySeparator("Yesterday"), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).hasSize(2) + assertThat(result[0]).isEqualTo(anEvent) + assertThat(result[1]).isEqualTo(aDaySeparator("Yesterday")) + } + + @Test + fun `filterEmptyDaySeparators handles multiple day separators in a row with no events`() { + val items = listOf( + aDaySeparator("Today"), + aDaySeparator("Yesterday"), + aDaySeparator("Last week"), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).isEmpty() + } + + @Test + fun `filterEmptyDaySeparators keeps all items when no day separators`() { + val items = listOf( + anEvent, + anEvent.copy(id = UniqueId("event2")), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).hasSize(2) + } + + @Test + fun `filterEmptyDaySeparators handles grouped events after day separator`() { + val groupedEvents = TimelineItem.GroupedEvents( + id = UniqueId("grouped"), + events = listOf(anEvent).toImmutableList(), + aggregatedReadReceipts = emptyList().toImmutableList(), + ) + val items = listOf( + groupedEvents, + aDaySeparator("Today"), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).hasSize(2) + assertThat(result[0]).isEqualTo(groupedEvents) + assertThat(result[1]).isEqualTo(aDaySeparator("Today")) + } + + @Test + fun `filterEmptyDaySeparators removes day separator followed by non-event virtual item`() { + val readMarker = TimelineItem.Virtual( + id = UniqueId("readMarker"), + model = TimelineItemReadMarkerModel + ) + val items = listOf( + aDaySeparator("Today"), + readMarker, + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).hasSize(1) + assertThat(result[0]).isEqualTo(readMarker) + } + + @Test + fun `filterEmptyDaySeparators keeps day separator when non-event virtual items are between separator and event`() { + val readMarker = TimelineItem.Virtual( + id = UniqueId("readMarker"), + model = TimelineItemReadMarkerModel + ) + val items = listOf( + anEvent, + readMarker, + aDaySeparator("Today"), + ) + val result = filterEmptyDaySeparators(items) + assertThat(result).hasSize(3) + assertThat(result[2]).isEqualTo(aDaySeparator("Today")) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 5da4be408d..016204e1b1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -12,6 +12,7 @@ import io.element.android.libraries.androidutils.hash.hash import io.element.android.libraries.core.extensions.runCatchingExceptions 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.UserId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo import io.element.android.libraries.matrix.api.media.ImageInfo @@ -20,6 +21,7 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MsgType @@ -43,6 +45,7 @@ import io.element.android.libraries.matrix.impl.timeline.postprocessor.TypingNot import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper import io.element.android.libraries.matrix.impl.util.MessageEventContent import io.element.android.services.toolbox.api.systemclock.SystemClock +import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -121,6 +124,13 @@ class RustTimeline( private val lastForwardIndicatorsPostProcessor = LastForwardIndicatorsPostProcessor(mode) private val typingNotificationPostProcessor = TypingNotificationPostProcessor(mode) + private data class RoomTimelineInfo( + val roomCreators: ImmutableList, + val isDm: Boolean, + val joinRule: JoinRule?, + val isEncrypted: Boolean?, + ) + override val backwardPaginationStatus = MutableStateFlow( Timeline.PaginationStatus(isPaginating = false, hasMoreToLoad = mode != Timeline.Mode.PinnedEvents) ) @@ -220,20 +230,23 @@ class RustTimeline( _timelineItems, backwardPaginationStatus, forwardPaginationStatus, - joinedRoom.roomInfoFlow.map { it.creators to it.isDm }.distinctUntilChanged(), + joinedRoom.roomInfoFlow.map { RoomTimelineInfo(it.creators, it.isDm, it.joinRule, it.isEncrypted) }.distinctUntilChanged(), ) { timelineItems, backwardPaginationStatus, forwardPaginationStatus, - (roomCreators, isDm), + roomInfo, -> withContext(dispatcher) { + val (roomCreators, isDm, joinRule, isEncrypted) = roomInfo timelineItems .let { items -> roomBeginningPostProcessor.process( items = items, isDm = isDm, roomCreator = roomCreators.firstOrNull(), + joinRule = joinRule, + isEncrypted = isEncrypted, hasMoreToLoadBackwards = backwardPaginationStatus.hasMoreToLoad, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt index 397280231d..ec6a7a5380 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt @@ -9,33 +9,49 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange import io.element.android.libraries.matrix.api.timeline.item.event.OtherState +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent import io.element.android.libraries.matrix.api.timeline.item.event.StateContent /** * This timeline post-processor removes the room creation event and the self-join event from the timeline for DMs - * or add the RoomBeginning item. + * or add the RoomBeginning item. For rooms that aren't invite-only and aren't encrypted, it also removes join/leave and profile change events. */ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) { fun process( items: List, isDm: Boolean, roomCreator: UserId?, + joinRule: JoinRule?, + isEncrypted: Boolean?, hasMoreToLoadBackwards: Boolean, ): List { return when { items.isEmpty() -> items mode == Timeline.Mode.PinnedEvents -> items + joinRule !is JoinRule.Invite && isEncrypted == false -> filterRoomMemberEvents(items) isDm -> processForDM(items, roomCreator) hasMoreToLoadBackwards -> items else -> processForRoom(items) } } + private fun filterRoomMemberEvents(items: List): List { + return items.filter { item -> + val eventContent = (item as? MatrixTimelineItem.Event)?.event?.content + when (eventContent) { + is RoomMembershipContent -> eventContent.change !in listOf(MembershipChange.JOINED, MembershipChange.LEFT) + is ProfileChangeContent -> false + else -> true + } + } + } + private fun processForRoom(items: List): List { // No changes needed, timeline start item is already added by the SDK return items diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt index 50f8637096..cda5a07b8e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTime 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.timeline.aMessageContent +import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent @@ -36,6 +37,14 @@ internal val otherMemberJoinEvent = MatrixTimelineItem.Event( uniqueId = UniqueId("m.room.member_other"), event = anEventTimelineItem(content = aRoomMembershipContent(userId = A_USER_ID_2, change = MembershipChange.JOINED)) ) +internal val otherMemberLeaveEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member_leave"), + event = anEventTimelineItem(content = aRoomMembershipContent(userId = A_USER_ID_2, change = MembershipChange.LEFT)) +) +internal val profileChangeEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member_profile"), + event = anEventTimelineItem(content = aProfileChangeMessageContent(displayName = "New Name", prevDisplayName = "Old Name")) +) internal val messageEvent = MatrixTimelineItem.Event( uniqueId = UniqueId("m.room.message"), event = anEventTimelineItem(content = aMessageContent("hi")) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index dbeba39973..b562847d94 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test @@ -21,6 +22,8 @@ class RoomBeginningPostProcessorTest { items = emptyList(), isDm = true, roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEmpty() @@ -33,6 +36,8 @@ class RoomBeginningPostProcessorTest { items = listOf(messageEvent), isDm = true, roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEqualTo(listOf(messageEvent)) @@ -45,6 +50,8 @@ class RoomBeginningPostProcessorTest { items = listOf(messageEvent), isDm = true, roomCreator = null, + joinRule = null, + isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEqualTo(listOf(messageEvent)) @@ -62,6 +69,8 @@ class RoomBeginningPostProcessorTest { items = timelineItems, isDm = true, roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).containsExactly(timelineStartEvent) @@ -78,6 +87,8 @@ class RoomBeginningPostProcessorTest { items = timelineItems, isDm = true, roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEqualTo(timelineItems) @@ -96,7 +107,14 @@ class RoomBeginningPostProcessorTest { messageEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = false) + val processedItems = processor.process( + timelineItems, + isDm = true, + roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, + hasMoreToLoadBackwards = false + ) assertThat(processedItems).isEqualTo(expected) } @@ -107,7 +125,14 @@ class RoomBeginningPostProcessorTest { roomCreatorJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) + val processedItems = processor.process( + timelineItems, + isDm = true, + roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, + hasMoreToLoadBackwards = true + ) assertThat(processedItems).isEmpty() } @@ -117,7 +142,14 @@ class RoomBeginningPostProcessorTest { roomCreatorJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) + val processedItems = processor.process( + timelineItems, + isDm = true, + roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, + hasMoreToLoadBackwards = true + ) assertThat(processedItems).isEmpty() } @@ -128,7 +160,84 @@ class RoomBeginningPostProcessorTest { otherMemberJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) + val processedItems = processor.process( + timelineItems, + isDm = true, + roomCreator = A_USER_ID, + joinRule = null, + isEncrypted = null, + hasMoreToLoadBackwards = true + ) assertThat(processedItems).isEqualTo(listOf(otherMemberJoinEvent)) } + + @Test + fun `processor removes join, leave, and profile events in unencrypted public rooms`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + otherMemberJoinEvent, + messageEvent, + otherMemberLeaveEvent, + profileChangeEvent, + ) + val expected = listOf( + roomCreateEvent, + messageEvent, + ) + val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) + val processedItems = processor.process( + timelineItems, + isDm = false, + roomCreator = A_USER_ID, + joinRule = JoinRule.Public, + isEncrypted = false, + hasMoreToLoadBackwards = false + ) + assertThat(processedItems).isEqualTo(expected) + } + + @Test + fun `processor keeps all events in encrypted public rooms`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + otherMemberJoinEvent, + messageEvent, + otherMemberLeaveEvent, + profileChangeEvent, + ) + val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) + val processedItems = processor.process( + timelineItems, + isDm = false, + roomCreator = A_USER_ID, + joinRule = JoinRule.Public, + isEncrypted = true, + hasMoreToLoadBackwards = false + ) + assertThat(processedItems).isEqualTo(timelineItems) + } + + @Test + fun `processor keeps membership events in invite-only rooms`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + otherMemberJoinEvent, + messageEvent, + otherMemberLeaveEvent, + profileChangeEvent, + ) + val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) + val processedItems = processor.process( + timelineItems, + isDm = false, + roomCreator = A_USER_ID, + joinRule = JoinRule.Invite, + isEncrypted = null, + hasMoreToLoadBackwards = false + ) + assertThat(processedItems).isEqualTo(timelineItems) + } } From 3df85017afb43d24610a955889bca90eab325a87 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 25 May 2026 12:40:25 +0300 Subject: [PATCH 0496/1083] Fix formatting inconsistencies in latest event summaries (#6855) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix message type prefixes formatting inconsistencies * Use new string for the poll summary prefix instead of the A11y text. Also add tests check for the bold spans. --------- Co-authored-by: Jorge Martín --- .../impl/DefaultRoomLatestEventFormatter.kt | 8 ++--- .../eventformatter/impl/PrefixWith.kt | 6 +++- .../DefaultRoomLatestEventFormatterTest.kt | 31 +++++++++++++++++-- .../src/main/res/values/localazy.xml | 1 + 4 files changed, 38 insertions(+), 8 deletions(-) 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 d234e7b239..e8a462da16 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 @@ -93,8 +93,8 @@ class DefaultRoomLatestEventFormatter( message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is StickerContent -> { - val message = sp.getString(CommonStrings.common_sticker) + " (" + content.bestDescription + ")" - message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) + content.bestDescription.prefixWith(sp.getString(CommonStrings.common_sticker)) + .prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is UnableToDecryptContent -> { val message = sp.getString(CommonStrings.common_waiting_for_decryption_key) @@ -110,8 +110,8 @@ class DefaultRoomLatestEventFormatter( stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.RoomList) } is PollContent -> { - val message = sp.getString(CommonStrings.common_poll_summary, content.question) - message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) + content.question.prefixWith(sp.getString(CommonStrings.common_poll_summary_prefix)) + .prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> { val message = sp.getString(CommonStrings.common_unsupported_event) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt index 51fdccf256..1a04893e07 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/PrefixWith.kt @@ -20,6 +20,10 @@ internal fun CharSequence.prefixWith(prefix: String): AnnotatedString { append(prefix) } append(": ") - append(this@prefixWith) + if (this@prefixWith is AnnotatedString) { + append(this@prefixWith) + } else { + append(this@prefixWith.toString()) + } } } diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt index e0613ed008..2e55fb0999 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.eventformatter.impl import android.content.Context import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.font.FontWeight import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import io.element.android.libraries.matrix.api.core.UserId @@ -103,7 +104,14 @@ class DefaultRoomLatestEventFormatterTest { val info = ImageInfo(null, null, null, null, null, null, null) val message = createLatestEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url"))) val result = formatter.format(message, false) - val expectedBody = someoneElseId.value + ": Sticker (a sticker body)" + val expectedBody = someoneElseId.value + ": Sticker: a sticker body" + // Check we have formatting + assertThat(result is AnnotatedString).isTrue() + // And there is a bold span for the 'Sticker' part + val boldSpanStyle = (result as AnnotatedString).spanStyles.lastOrNull { it.item.fontWeight == FontWeight.Bold } + assertThat(boldSpanStyle).isNotNull() + val spanStart = someoneElseId.value.length + 2 + assertThat(boldSpanStyle!!.start..boldSpanStyle.end).isEqualTo(spanStart..spanStart + 7) assertThat(result.toString()).isEqualTo(expectedBody) } @@ -909,10 +917,18 @@ class DefaultRoomLatestEventFormatterTest { val pollContent = aPollContent() val mineContentEvent = createLatestEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent) - assertThat(formatter.format(mineContentEvent, true)).isEqualTo("Poll: Do you like polls?") + assertThat(formatter.format(mineContentEvent, true).toString()).isEqualTo("Poll: Do you like polls?") val contentEvent = createLatestEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) - assertThat(formatter.format(contentEvent, true)).isEqualTo("Poll: Do you like polls?") + assertThat(formatter.format(contentEvent, true).toString()).isEqualTo("Poll: Do you like polls?") + + val result = formatter.format(contentEvent, true) + // Check we have formatting + assertThat(result is AnnotatedString).isTrue() + // And there is a bold span for the 'Poll' part + val boldSpanStyle = (result as AnnotatedString).spanStyles.lastOrNull { it.item.fontWeight == FontWeight.Bold } + assertThat(boldSpanStyle).isNotNull() + assertThat(boldSpanStyle!!.start..boldSpanStyle.end).isEqualTo(0..4) } @Test @@ -925,6 +941,15 @@ class DefaultRoomLatestEventFormatterTest { val contentEvent = createLatestEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) assertThat(formatter.format(contentEvent, false).toString()).isEqualTo("Bob: Poll: Do you like polls?") + + val result = formatter.format(contentEvent, false) + // Check we have formatting + assertThat(result is AnnotatedString).isTrue() + // And there is a bold span for the 'Poll' part + val boldSpanStyle = (result as AnnotatedString).spanStyles.lastOrNull { it.item.fontWeight == FontWeight.Bold } + assertThat(boldSpanStyle).isNotNull() + val spanStart = "Bob".length + 2 + assertThat(boldSpanStyle!!.start..boldSpanStyle.end).isEqualTo(spanStart..spanStart + 4) } // endregion diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index e89d45b228..e5bc31396f 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -303,6 +303,7 @@ Reason: %1$s." "Please wait…" "Are you sure you want to end this poll?" "Poll: %1$s" + "Poll" "Total votes: %1$s" "Results will show after the poll has ended" From 8a4ff4c45663cf49eaef64b961785131ae989abc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 25 May 2026 21:16:12 +0200 Subject: [PATCH 0497/1083] Improve touch detection. --- .../preview/AttachmentsPreviewPresenter.kt | 2 +- .../imageeditor/AttachmentImageEditorState.kt | 29 ++++-- .../AttachmentImageEditorStateProvider.kt | 30 +++++- .../imageeditor/AttachmentImageEditorView.kt | 93 ++++++++++++++++--- 4 files changed, 128 insertions(+), 26 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index 72d840c4ad..cab00d99c1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -276,7 +276,7 @@ class AttachmentsPreviewPresenter( imageEditorState = AttachmentImageEditorState( localMedia = originalLocalMedia, edits = appliedImageEdits, - forceDrawGuidelines = false, + previewDebug = false, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt index d103e6b913..3c8af52ce8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt @@ -7,6 +7,7 @@ package io.element.android.features.messages.impl.attachments.preview.imageeditor +import androidx.annotation.FloatRange import androidx.compose.runtime.Immutable import io.element.android.libraries.mediaviewer.api.local.LocalMedia @@ -18,7 +19,7 @@ data class AttachmentImageEditorState( val localMedia: LocalMedia, val edits: AttachmentImageEdits, // For preview only - val forceDrawGuidelines: Boolean, + val previewDebug: Boolean, ) @Immutable @@ -51,10 +52,10 @@ data class AttachmentImageEdits( @Immutable data class NormalizedCropRect( - val left: Float, - val top: Float, - val right: Float, - val bottom: Float, + @FloatRange(from = 0.0, to = 1.0) val left: Float, + @FloatRange(from = 0.0, to = 1.0) val top: Float, + @FloatRange(from = 0.0, to = 1.0) val right: Float, + @FloatRange(from = 0.0, to = 1.0) val bottom: Float, ) { init { require(left in 0f..1f) @@ -71,7 +72,11 @@ data class NormalizedCropRect( val height: Float get() = bottom - top - fun applyChange(dragTarget: CropDragTarget, deltaX: Float, deltaY: Float): NormalizedCropRect = when (dragTarget) { + fun applyChange( + dragTarget: CropDragTarget, + deltaX: Float, + deltaY: Float, + ): NormalizedCropRect = when (dragTarget) { is CropDragTarget.Move -> translate(deltaX, deltaY) is CropDragTarget.Corner -> dragWithCorner(dragTarget, deltaX, deltaY) is CropDragTarget.Edge -> dragWithEdge(dragTarget, deltaX, deltaY) @@ -88,7 +93,11 @@ data class NormalizedCropRect( ) } - private fun dragWithCorner(dragTarget: CropDragTarget.Corner, deltaX: Float, deltaY: Float) = when (dragTarget) { + private fun dragWithCorner( + dragTarget: CropDragTarget.Corner, + deltaX: Float, + deltaY: Float, + ) = when (dragTarget) { CropDragTarget.Corner.TopLeft -> copy( left = (left + deltaX).coerceIn(0f, right - MIN_CROP_SIZE), top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), @@ -107,7 +116,11 @@ data class NormalizedCropRect( ) } - private fun dragWithEdge(dragTarget: CropDragTarget.Edge, deltaX: Float, deltaY: Float) = when (dragTarget) { + private fun dragWithEdge( + dragTarget: CropDragTarget.Edge, + deltaX: Float, + deltaY: Float, + ) = when (dragTarget) { CropDragTarget.Edge.Top -> copy( top = (top + deltaY).coerceIn(0f, bottom - MIN_CROP_SIZE), ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt index 09a4390202..df4bb5257f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt @@ -44,13 +44,37 @@ open class AttachmentImageEditorStateProvider : PreviewParameterProvider(null) } val latestCropRect by rememberUpdatedState(state.edits.cropRect) - val drawGuidelines = dragTarget == CropDragTarget.Move || state.forceDrawGuidelines + val drawGuidelines = dragTarget == CropDragTarget.Move || state.previewDebug Box( modifier = Modifier .fillMaxSize() @@ -290,7 +304,7 @@ private fun BoxScope.CropEditorCanvas( imageOffset = imageRect.topLeft, cropRect = latestCropRect, canvasSize = Size(imageRect.width, imageRect.height), - handleTouchRadius = touchRadius.toPx(), + handleTouchRadius = touchRadiusPx, ) }, onDragCancel = { @@ -317,6 +331,9 @@ private fun BoxScope.CropEditorCanvas( imageSize = DpSize(displayedWidthDp, displayedHeightDp), cropRect = state.edits.cropRect, drawGuidelines = drawGuidelines, + previewDebug = state.previewDebug, + touchRadiusPx = touchRadiusPx, + dragTarget = dragTarget, ) } } @@ -327,6 +344,9 @@ private fun CropOverlay( imageSize: DpSize, cropRect: NormalizedCropRect, drawGuidelines: Boolean, + previewDebug: Boolean, + touchRadiusPx: Float, + dragTarget: CropDragTarget?, ) { val borderColor = ElementTheme.colors.iconPrimary val guideColor = ElementTheme.colors.iconPrimary @@ -459,6 +479,32 @@ private fun CropOverlay( handleLength = handleLength, color = handleColor, ) + + if (previewDebug) { + // Draw disk around touchable area + listOf( + CropDragTarget.Edge.Top, + CropDragTarget.Edge.Right, + CropDragTarget.Edge.Bottom, + CropDragTarget.Edge.Left, + CropDragTarget.Corner.TopLeft, + CropDragTarget.Corner.TopRight, + CropDragTarget.Corner.BottomRight, + CropDragTarget.Corner.BottomLeft, + CropDragTarget.Move, + ).forEach { target -> + val color = when (target) { + is CropDragTarget.Move -> Color.Red + is CropDragTarget.Corner -> Color.Blue + is CropDragTarget.Edge -> Color.Green + }.copy(alpha = if (dragTarget == target) 9f else 0.5f) + drawCircle( + color = color, + radius = touchRadiusPx, + center = computeOffset(target, cropRect, Size(size.width, size.height)), + ) + } + } } } @@ -482,17 +528,20 @@ private fun detectDragTarget( canvasSize: Size, handleTouchRadius: Float, ): CropDragTarget? { - val corners = mapOf( - CropDragTarget.Corner.TopLeft to Offset(cropRect.left * canvasSize.width, cropRect.top * canvasSize.height), - CropDragTarget.Edge.Top to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.top * canvasSize.height), - CropDragTarget.Corner.TopRight to Offset(cropRect.right * canvasSize.width, cropRect.top * canvasSize.height), - CropDragTarget.Edge.Right to Offset(cropRect.right * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), - CropDragTarget.Corner.BottomRight to Offset(cropRect.right * canvasSize.width, cropRect.bottom * canvasSize.height), - CropDragTarget.Edge.Bottom to Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.bottom * canvasSize.height), - CropDragTarget.Corner.BottomLeft to Offset(cropRect.left * canvasSize.width, cropRect.bottom * canvasSize.height), - CropDragTarget.Edge.Left to Offset(cropRect.left * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f), + // Give priority on Move (extra detection of the center of crop area) + // to ensure that user can move a small crop, then to corners and at last to edges. + val handlesArea = mapOf( + CropDragTarget.Move to computeOffset(CropDragTarget.Move, cropRect, canvasSize), + CropDragTarget.Corner.TopLeft to computeOffset(CropDragTarget.Corner.TopLeft, cropRect, canvasSize), + CropDragTarget.Corner.TopRight to computeOffset(CropDragTarget.Corner.TopRight, cropRect, canvasSize), + CropDragTarget.Corner.BottomRight to computeOffset(CropDragTarget.Corner.BottomRight, cropRect, canvasSize), + CropDragTarget.Corner.BottomLeft to computeOffset(CropDragTarget.Corner.BottomLeft, cropRect, canvasSize), + CropDragTarget.Edge.Top to computeOffset(CropDragTarget.Edge.Top, cropRect, canvasSize), + CropDragTarget.Edge.Right to computeOffset(CropDragTarget.Edge.Right, cropRect, canvasSize), + CropDragTarget.Edge.Bottom to computeOffset(CropDragTarget.Edge.Bottom, cropRect, canvasSize), + CropDragTarget.Edge.Left to computeOffset(CropDragTarget.Edge.Left, cropRect, canvasSize), ) - corners.forEach { (target, corner) -> + handlesArea.forEach { (target, corner) -> if ((corner - touchPoint + imageOffset).getDistance() <= handleTouchRadius) { return target } @@ -508,6 +557,22 @@ private fun detectDragTarget( } } +private fun computeOffset( + target: CropDragTarget, + cropRect: NormalizedCropRect, + canvasSize: Size, +) = when (target) { + CropDragTarget.Move -> Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f) + CropDragTarget.Corner.TopLeft -> Offset(cropRect.left * canvasSize.width, cropRect.top * canvasSize.height) + CropDragTarget.Edge.Top -> Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.top * canvasSize.height) + CropDragTarget.Corner.TopRight -> Offset(cropRect.right * canvasSize.width, cropRect.top * canvasSize.height) + CropDragTarget.Edge.Right -> Offset(cropRect.right * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f) + CropDragTarget.Corner.BottomRight -> Offset(cropRect.right * canvasSize.width, cropRect.bottom * canvasSize.height) + CropDragTarget.Edge.Bottom -> Offset((cropRect.left + cropRect.right) * canvasSize.width / 2f, cropRect.bottom * canvasSize.height) + CropDragTarget.Corner.BottomLeft -> Offset(cropRect.left * canvasSize.width, cropRect.bottom * canvasSize.height) + CropDragTarget.Edge.Left -> Offset(cropRect.left * canvasSize.width, (cropRect.top + cropRect.bottom) * canvasSize.height / 2f) +} + // x and y are the coordinates of the corner private fun DrawScope.drawCornerHandle( x: Float, From 1f6824d285925951b56f8200927c437ccd89675c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 25 May 2026 19:34:34 +0000 Subject: [PATCH 0498/1083] Update screenshots --- ...nts.preview.imageeditor_AttachmentImageEditorView_2_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_4_en.png | 3 +++ ...nts.preview.imageeditor_AttachmentImageEditorView_5_en.png | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png index 86b9dc57b8..2ae328d7eb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e5c43a16d24ce7efed1c90cfa9bc6d73ee12c486b2ad2823c531b87e272ac66 -size 282369 +oid sha256:34b6dfe4e65612615c3dc87e5f65bd0b160d97527c4a4749b496bf8d48819d96 +size 256641 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png new file mode 100644 index 0000000000..6c3a6f4bf6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b15a04a861812e3e4dee0a6a30c6afef4ab171c5261d1e5bd5a234bb7296d97 +size 251908 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png new file mode 100644 index 0000000000..530c5e5bb6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c32b4744750b9f18612bded2e292dde151e2bfdd8a69a36c88044f5ca3a76f8e +size 311315 From f4475606650e45197650cd445d203fcbdb4821fd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 07:59:33 +0200 Subject: [PATCH 0499/1083] Update codecov/codecov-action action to v6.0.1 (#6864) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 87551c4360..842c8113f4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -108,7 +108,7 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From 6cef5cec1bd581bbba2de772a7c4dcca7d906771 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 26 May 2026 09:22:43 +0200 Subject: [PATCH 0500/1083] Remove useless line. --- .../attachments/preview/imageeditor/NormalizedCropRectTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt index 14cb07eed7..c70c6169e1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/NormalizedCropRectTest.kt @@ -59,7 +59,6 @@ class NormalizedCropRectTest { deltaX = -0.1f, deltaY = 0.3f, ) - val s = assertThat(result) result.assertIsSimilarTo( NormalizedCropRect( left = rect.left, From 51aa8208e0e65d71393a964cbceb0b8f5d033100 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Tue, 26 May 2026 07:36:57 +0000 Subject: [PATCH 0501/1083] Add `/myroomnick` slash command --- .../impl/timeline/TimelinePresenter.kt | 27 +++++++++---- .../factories/TimelineItemsFactory.kt | 39 +++++++++++++++++++ .../libraries/matrix/api/room/JoinedRoom.kt | 7 ++++ .../matrix/impl/room/JoinedRustRoom.kt | 6 +++ .../matrix/test/room/FakeJoinedRoom.kt | 5 +++ .../libraries/slashcommands/impl/Command.kt | 2 +- .../slashcommands/impl/CommandExecutor.kt | 6 +-- .../slashcommands/impl/CommandExecutorTest.kt | 16 ++++++-- 8 files changed, 92 insertions(+), 16 deletions(-) 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 0b99c45e06..3af7326ff5 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 @@ -51,6 +51,7 @@ import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin @@ -254,15 +255,25 @@ class TimelinePresenter( } .launchIn(this) + var previousItems: List? = null combine(timelineController.timelineItems(), room.membersStateFlow) { items, membersState -> - val parent = analyticsService.getLongRunningTransaction(DisplayFirstTimelineItems) - val transaction = parent?.startChild("timelineItemsFactory.replaceWith", "Processing timeline items") - transaction?.putExtraData(AnalyticsUserData.TIMELINE_ITEM_COUNT, items.count().toString()) - timelineItemsFactory.replaceWith( - timelineItems = items, - roomMembers = membersState.roomMembers().orEmpty() - ) - transaction?.finish() + val roomMembers = membersState.roomMembers().orEmpty() + if (previousItems !== items) { + previousItems = items + val parent = analyticsService.getLongRunningTransaction(DisplayFirstTimelineItems) + val transaction = parent?.startChild("timelineItemsFactory.replaceWith", "Processing timeline items") + transaction?.putExtraData(AnalyticsUserData.TIMELINE_ITEM_COUNT, items.count().toString()) + timelineItemsFactory.replaceWith( + timelineItems = items, + roomMembers = roomMembers + ) + transaction?.finish() + } else { + timelineItemsFactory.updateRoomMembers( + timelineItems = items, + roomMembers = roomMembers + ) + } items } .onEach(redactedVoiceMessageManager::onEachMatrixTimelineItem) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt index dc8bdddc92..d1ec5b648a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt @@ -72,6 +72,45 @@ class TimelineItemsFactory( } } + /** + * Lightweight update that only refreshes member-derived data (e.g., read receipt display names) + * on cached items without rebuilding the diff cache or creating new items. + * Skips emission if no cached items have member-dependent state. + */ + suspend fun updateRoomMembers( + timelineItems: List, + roomMembers: List, + ) = withContext(dispatchers.computation) { + lock.withLock { + var hasUpdates = false + val updatedStates = ArrayList() + for (index in diffCache.indices().reversed()) { + val cacheItem = diffCache.get(index) + if (cacheItem is TimelineItem.Event && roomMembers.isNotEmpty()) { + val updatedItem = eventItemFactory.update( + timelineItem = cacheItem, + receivedMatrixTimelineItem = timelineItems[index] as MatrixTimelineItem.Event, + roomMembers = roomMembers + ) + diffCache[index] = updatedItem + hasUpdates = true + updatedStates.add(updatedItem) + } else if (cacheItem != null) { + updatedStates.add(cacheItem) + } else { + buildAndCacheItem(timelineItems, index, roomMembers)?.also { timelineItemState -> + updatedStates.add(timelineItemState) + } + } + } + if (hasUpdates) { + val result = timelineItemGrouper.group(updatedStates).toImmutableList() + val filteredResult = filterEmptyDaySeparators(result) + _timelineItems.emit(filteredResult) + } + } + } + private suspend fun buildAndEmitTimelineItemStates( timelineItems: List, roomMembers: List, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt index f3fefab9a8..6d8325427b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt @@ -212,4 +212,11 @@ interface JoinedRoom : BaseRoom { * @return Result indicating success or failure. */ suspend fun sendLiveLocation(geoUri: String): Result + + /** + * Sets the display name of the current user within this room. + * This is different from the global setDisplayName which updates + * the user's display name across all of their rooms. + */ + suspend fun setOwnMemberDisplayName(displayName: String): Result } 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 e75091eadc..5d85a6a625 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 @@ -546,6 +546,12 @@ class JoinedRustRoom( } } + override suspend fun setOwnMemberDisplayName(displayName: String): Result = withContext(roomDispatcher) { + runCatchingExceptions { + innerRoom.setOwnMemberDisplayName(displayName) + } + } + override fun close() = destroy() override fun destroy() { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index b4425ddd4b..dd8acacb23 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -92,6 +92,7 @@ class FakeJoinedRoom( private val startLiveLocationShareResult: (Long) -> Result = { lambdaError() }, private val stopLiveLocationShareResult: () -> Result = { lambdaError() }, private val sendLiveLocationResult: (String) -> Result = { lambdaError() }, + private val setOwnMemberDisplayNameResult: (String) -> Result = { lambdaError() }, ) : JoinedRoom, BaseRoom by baseRoom { private val sendQueueUpdates = MutableSharedFlow(extraBufferCapacity = 10) @@ -255,6 +256,10 @@ class FakeJoinedRoom( sendLiveLocationResult(geoUri) } + override suspend fun setOwnMemberDisplayName(displayName: String): Result = simulateLongTask { + setOwnMemberDisplayNameResult(displayName) + } + private suspend fun simulateSendMediaProgress(progressCallback: ProgressCallback?) { progressCallbackValues.forEach { (current, total) -> progressCallback?.onProgress(current, total) diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt index 0d9e1e8c72..5df871e361 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/Command.kt @@ -109,7 +109,7 @@ enum class Command( parameters = "", description = R.string.slash_command_description_nick_for_room, isAllowedInThread = false, - isSupported = false, + isSupported = true, ), ROOM_AVATAR( command = "/roomavatar", diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt index ad252cb224..01bac5825b 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutor.kt @@ -47,7 +47,7 @@ class CommandExecutor( is SlashCommand.ChangeAvatar -> changeAvatar() is SlashCommand.ChangeAvatarForRoom -> changeAvatarForRoom() is SlashCommand.ChangeDisplayName -> changeDisplayName(slashCommand) - is SlashCommand.ChangeDisplayNameForRoom -> changeDisplayNameForRoom() + is SlashCommand.ChangeDisplayNameForRoom -> changeDisplayNameForRoom(slashCommand) is SlashCommand.ChangeRoomAvatar -> changeRoomAvatar() is SlashCommand.ChangeRoomName -> changeRoomName(slashCommand) is SlashCommand.ChangeTopic -> changeTopic(slashCommand) @@ -171,8 +171,8 @@ class CommandExecutor( return Result.failure(Exception("Not yet implemented")) } - private fun changeDisplayNameForRoom(): Result { - return Result.failure(Exception("Not yet implemented")) + private suspend fun changeDisplayNameForRoom(slashCommand: SlashCommand.ChangeDisplayNameForRoom): Result { + return joinedRoom.setOwnMemberDisplayName(slashCommand.displayName) } private suspend fun changeDisplayName(slashCommand: SlashCommand.ChangeDisplayName): Result { diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt index 497f45c96f..800cdecfb3 100644 --- a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt @@ -185,10 +185,18 @@ class CommandExecutorTest { } @Test - fun `change display name for room is not supported`() = runTest { - val sut = createCommandExecutor() - val res = sut.proceedAdmin(SlashCommand.ChangeDisplayNameForRoom(A_USER_NAME)) - assertThat(res.isFailure).isTrue() + fun `change display name for room delegates to joined room`() = runTest { + var capturedDisplayName: String? = null + val joinedRoom = FakeJoinedRoom( + setOwnMemberDisplayNameResult = { displayName -> + capturedDisplayName = displayName + Result.success(Unit) + } + ) + val sut = createCommandExecutor(joinedRoom = joinedRoom) + val res = sut.proceedAdmin(SlashCommand.ChangeDisplayNameForRoom("room nick")) + assertThat(res.isSuccess).isTrue() + assertThat(capturedDisplayName).isEqualTo("room nick") } @Test From 7b93bfbba95dd4d815fbefc7c128560fadf93add Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 May 2026 09:40:07 +0200 Subject: [PATCH 0502/1083] Use `runBlocking` for the token refresh logic (#6863) * Use `runBlocking` for the token refresh logic The `RustClientSessionDelegate` callbacks always run in a separate thread, so they don't block the main thread. This ensures the token refresh is fully done (data saved/failed to) before the SDK continues sending the pending previously failed requests --- .../matrix/impl/RustClientSessionDelegate.kt | 49 +++++++++---------- .../matrix/impl/RustMatrixClientFactory.kt | 1 - .../impl/RustClientSessionDelegateTest.kt | 6 --- 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt index 690995ba77..c776ca8522 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt @@ -8,7 +8,7 @@ package io.element.android.libraries.matrix.impl -import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.impl.core.SdkBackgroundTaskError import io.element.android.libraries.matrix.impl.mapper.toSessionData @@ -19,6 +19,7 @@ import io.element.android.services.analytics.api.AnalyticsService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.matrix.rustcomponents.sdk.ClientDelegate import org.matrix.rustcomponents.sdk.ClientSessionDelegate import org.matrix.rustcomponents.sdk.Session @@ -41,14 +42,10 @@ class RustClientSessionDelegate( private val sessionStore: SessionStore, private val appCoroutineScope: CoroutineScope, private val analyticsService: AnalyticsService, - coroutineDispatchers: CoroutineDispatchers, ) : ClientSessionDelegate, ClientDelegate { // Used to ensure several calls to `didReceiveAuthError` don't trigger multiple logouts private val isLoggingOut = AtomicBoolean(false) - // To make sure only one coroutine affecting the token persistence can run at a time - private val updateTokensDispatcher = coroutineDispatchers.io.limitedParallelism(1) - // This Client needs to be set up as soon as possible so `didReceiveAuthError` can work properly. private var client: WeakReference = WeakReference(null) @@ -66,9 +63,10 @@ class RustClientSessionDelegate( this.client.clear() } + // This always runs on a background thread, so we *can* do blocking calls here, although we should avoid doing heavy work override fun saveSessionInKeychain(session: Session) { - appCoroutineScope.launch(updateTokensDispatcher) { - val existingData = sessionStore.getSession(session.userId) ?: return@launch + runCatchingExceptions { + val existingData = runBlocking { sessionStore.getSession(session.userId) } ?: return val (anonymizedAccessToken, anonymizedRefreshToken) = session.anonymizedTokens() Timber.tag(loggerTag.value).d( "Saving new session data with token: access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'. " + @@ -80,28 +78,27 @@ class RustClientSessionDelegate( passphrase = existingData.passphrase, sessionPaths = existingData.getSessionPaths(), ) - sessionStore.updateData(newData) + runBlocking { sessionStore.updateData(newData) } Timber.tag(loggerTag.value).d("Saved new session data with access token: '$anonymizedAccessToken'.") - }.invokeOnCompletion { - if (it != null) { - Timber.tag(loggerTag.value).e(it, "Failed to save new session data.") - } + }.onFailure { + Timber.tag(loggerTag.value).e(it, "Failed to save new session data.") } } + // This always runs on a background thread, so we *can* do blocking calls here, although we should avoid doing heavy work override fun didReceiveAuthError(isSoftLogout: Boolean) { - Timber.tag(loggerTag.value).w("didReceiveAuthError(isSoftLogout=$isSoftLogout)") - if (isLoggingOut.getAndSet(true).not()) { - Timber.tag(loggerTag.value).v("didReceiveAuthError -> do the cleanup") - // TODO handle isSoftLogout parameter. - appCoroutineScope.launch(updateTokensDispatcher) { + runCatchingExceptions { + Timber.tag(loggerTag.value).w("didReceiveAuthError(isSoftLogout=$isSoftLogout)") + if (isLoggingOut.getAndSet(true).not()) { + Timber.tag(loggerTag.value).v("didReceiveAuthError -> do the cleanup") + // TODO handle isSoftLogout parameter. val currentClient = client.get() if (currentClient == null) { Timber.tag(loggerTag.value).w("didReceiveAuthError -> no client, exiting") isLoggingOut.set(false) - return@launch + return } - val existingData = sessionStore.getSession(currentClient.sessionId.value) + val existingData = runBlocking { sessionStore.getSession(currentClient.sessionId.value) } val (anonymizedAccessToken, anonymizedRefreshToken) = existingData.anonymizedTokens() Timber.tag(loggerTag.value).d( "Removing session data with access token '$anonymizedAccessToken' " + @@ -110,19 +107,17 @@ class RustClientSessionDelegate( if (existingData != null) { // Set isTokenValid to false val newData = existingData.copy(isTokenValid = false) - sessionStore.updateData(newData) + runBlocking { sessionStore.updateData(newData) } Timber.tag(loggerTag.value).d("Invalidated session data with access token: '$anonymizedAccessToken'.") } else { Timber.tag(loggerTag.value).d("No session data found.") } - currentClient.logout(userInitiated = false, ignoreSdkError = true) - }.invokeOnCompletion { - if (it != null) { - Timber.tag(loggerTag.value).e(it, "Failed to remove session data.") - } + appCoroutineScope.launch { currentClient.logout(userInitiated = false, ignoreSdkError = true) } + } else { + Timber.tag(loggerTag.value).v("didReceiveAuthError -> already cleaning up") } - } else { - Timber.tag(loggerTag.value).v("didReceiveAuthError -> already cleaning up") + }.onFailure { + Timber.tag(loggerTag.value).e(it, "Failed to remove session data.") } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 9a573a59c1..6757edf16c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -72,7 +72,6 @@ class RustMatrixClientFactory( sessionStore = sessionStore, appCoroutineScope = appCoroutineScope, analyticsService = analyticsService, - coroutineDispatchers = coroutineDispatchers ) suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt index 6aa3ef0e5b..0036f2f962 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt @@ -16,15 +16,11 @@ import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService -import io.element.android.tests.testutils.testCoroutineDispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test import uniffi.matrix_sdk_common.BackgroundTaskFailureReason -@OptIn(ExperimentalCoroutinesApi::class) class RustClientSessionDelegateTest { @Test fun `saveSessionInKeychain should update the store`() = runTest { @@ -43,7 +39,6 @@ class RustClientSessionDelegateTest { refreshToken = "rt", ) ) - runCurrent() val result = sessionStore.getLatestSession() assertThat(result!!.accessToken).isEqualTo("at") assertThat(result.refreshToken).isEqualTo("rt") @@ -80,5 +75,4 @@ fun TestScope.aRustClientSessionDelegate( sessionStore = sessionStore, appCoroutineScope = this, analyticsService = analyticsService, - coroutineDispatchers = testCoroutineDispatchers(), ) From 0aaa80cbdc81cbf6124b3fb5f24991465d4c01a5 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Tue, 26 May 2026 10:05:07 +0200 Subject: [PATCH 0503/1083] Sync Strings from Localazy (#6856) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- app/src/main/res/xml/locales_config.xml | 1 + .../src/main/res/values-ca/translations.xml | 6 + .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 10 + .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 16 + .../src/main/res/values-ca/translations.xml | 13 + .../src/main/res/values-fi/translations.xml | 6 +- .../src/main/res/values-ru/translations.xml | 6 +- .../src/main/res/values-ca/translations.xml | 15 + .../src/main/res/values-ca/translations.xml | 49 + .../src/main/res/values-ca/translations.xml | 18 + .../src/main/res/values-ca/translations.xml | 5 + .../src/main/res/values-fi/translations.xml | 4 + .../src/main/res/values-ru/translations.xml | 4 + .../src/main/res/values-ca/translations.xml | 32 + .../src/main/res/values-ca/translations.xml | 35 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 41 + .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-ca/translations.xml | 38 + .../src/main/res/values-ca/translations.xml | 89 + .../src/main/res/values-fi/translations.xml | 2 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 10 +- .../src/main/res/values-ca/translations.xml | 17 + .../src/main/res/values-ca/translations.xml | 68 + .../src/main/res/values-ja/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 1 + .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-ca/translations.xml | 19 + .../src/main/res/values-ca/translations.xml | 70 + .../src/main/res/values-fi/translations.xml | 16 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 35 + .../src/main/res/values-pl/translations.xml | 36 +- .../src/main/res/values-ru/translations.xml | 10 + .../src/main/res/values-zh/translations.xml | 34 + .../impl/src/main/res/values/localazy.xml | 34 + .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 17 + .../src/main/res/values-ca/translations.xml | 6 + .../src/main/res/values-ca/translations.xml | 61 + .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-ca/translations.xml | 5 + .../src/main/res/values-be/translations.xml | 2 + .../src/main/res/values-bg/translations.xml | 2 + .../src/main/res/values-ca/translations.xml | 141 ++ .../src/main/res/values-cs/translations.xml | 2 + .../src/main/res/values-cy/translations.xml | 2 + .../src/main/res/values-da/translations.xml | 2 + .../src/main/res/values-de/translations.xml | 2 + .../src/main/res/values-el/translations.xml | 2 + .../src/main/res/values-es/translations.xml | 2 + .../src/main/res/values-et/translations.xml | 2 + .../src/main/res/values-eu/translations.xml | 2 + .../src/main/res/values-fa/translations.xml | 2 + .../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-in/translations.xml | 2 + .../src/main/res/values-it/translations.xml | 2 + .../src/main/res/values-ja/translations.xml | 2 + .../src/main/res/values-ka/translations.xml | 2 + .../src/main/res/values-ko/translations.xml | 2 + .../src/main/res/values-nb/translations.xml | 2 + .../src/main/res/values-nl/translations.xml | 2 + .../src/main/res/values-pl/translations.xml | 2 + .../main/res/values-pt-rBR/translations.xml | 2 + .../src/main/res/values-pt/translations.xml | 2 + .../src/main/res/values-ro/translations.xml | 2 + .../src/main/res/values-ru/translations.xml | 2 + .../src/main/res/values-sk/translations.xml | 2 + .../src/main/res/values-sv/translations.xml | 2 + .../src/main/res/values-tr/translations.xml | 2 + .../src/main/res/values-uk/translations.xml | 2 + .../src/main/res/values-ur/translations.xml | 2 + .../src/main/res/values-uz/translations.xml | 2 + .../src/main/res/values-vi/translations.xml | 2 + .../main/res/values-zh-rTW/translations.xml | 2 + .../src/main/res/values-zh/translations.xml | 2 + .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 5 + .../src/main/res/values-ca/translations.xml | 20 + .../src/main/res/values-ca/translations.xml | 69 + .../src/main/res/values-ca/translations.xml | 34 + .../src/main/res/values-ca/translations.xml | 8 + .../src/main/res/values-ca/translations.xml | 5 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-ca/translations.xml | 12 + .../src/main/res/values-ca/translations.xml | 19 + .../src/main/res/values-ca/translations.xml | 54 + .../src/main/res/values-ca/translations.xml | 4 + .../src/main/res/values-ca/translations.xml | 5 + .../src/main/res/values-ca/translations.xml | 73 + .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 21 + .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-ca/translations.xml | 7 + .../src/main/res/values-ca/translations.xml | 5 + .../src/main/res/values-ca/translations.xml | 83 + .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-ca/translations.xml | 11 + .../src/main/res/values-ca/translations.xml | 10 + .../src/main/res/values-ca/translations.xml | 31 + .../src/main/res/values-ca/translations.xml | 11 + .../src/main/res/values-ca/translations.xml | 387 +++ .../src/main/res/values-et/translations.xml | 5 + .../src/main/res/values-fi/translations.xml | 21 + .../src/main/res/values-fr/translations.xml | 14 + .../src/main/res/values-hu/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 16 +- .../src/main/res/values-pl/translations.xml | 13 + .../src/main/res/values-ru/translations.xml | 11 + .../src/main/res/values-zh/translations.xml | 25 +- .../src/main/res/values/localazy.xml | 7 + plugins/src/main/kotlin/extension/locales.kt | 1 + ...screens.qrcode_ShowQrCodeView_Day_1_de.png | 3 + ....roomdetails.impl_RoomDetailsDark_0_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_10_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_11_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_12_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_13_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_14_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_15_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_16_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_17_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_18_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_1_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_20_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_21_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_22_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_2_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_3_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_4_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_6_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_7_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_8_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_9_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_0_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_10_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_11_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_12_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_13_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_14_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_15_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_16_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_17_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_1_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_20_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_21_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_22_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_2_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_3_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_4_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_6_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_7_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_8_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_9_de.png | 4 +- screenshots/html/data.js | 2131 +++++++++-------- 174 files changed, 3234 insertions(+), 1184 deletions(-) create mode 100644 appnav/src/main/res/values-ca/translations.xml create mode 100644 features/analytics/api/src/main/res/values-ca/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-ca/translations.xml create mode 100644 features/call/impl/src/main/res/values-ca/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-ca/translations.xml create mode 100644 features/deactivation/impl/src/main/res/values-ca/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-ca/translations.xml create mode 100644 features/home/impl/src/main/res/values-ca/translations.xml create mode 100644 features/invite/impl/src/main/res/values-ca/translations.xml create mode 100644 features/invitepeople/impl/src/main/res/values-ca/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-ca/translations.xml create mode 100644 features/knockrequests/impl/src/main/res/values-ca/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-ca/translations.xml create mode 100644 features/linknewdevice/impl/src/main/res/values-ca/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-ca/translations.xml create mode 100644 features/login/impl/src/main/res/values-ca/translations.xml create mode 100644 features/logout/impl/src/main/res/values-ca/translations.xml create mode 100644 features/messages/impl/src/main/res/values-ca/translations.xml create mode 100644 features/poll/impl/src/main/res/values-ca/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-ca/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-ca/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-ca/translations.xml create mode 100644 features/reportroom/impl/src/main/res/values-ca/translations.xml create mode 100644 features/rolesandpermissions/impl/src/main/res/values-ca/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-ca/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-ca/translations.xml create mode 100644 features/roomdetailsedit/impl/src/main/res/values-ca/translations.xml create mode 100644 features/roomdirectory/impl/src/main/res/values-ca/translations.xml create mode 100644 features/roommembermoderation/impl/src/main/res/values-ca/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-ca/translations.xml create mode 100644 features/securityandprivacy/impl/src/main/res/values-ca/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-ca/translations.xml create mode 100644 features/space/impl/src/main/res/values-ca/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-ca/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-ca/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-ca/translations.xml create mode 100644 libraries/dateformatter/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-ca/translations.xml create mode 100644 libraries/mediaviewer/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-ca/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/pushproviders/firebase/src/main/res/values-ca/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-ca/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-ca/translations.xml create mode 100644 screenshots/de/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_de.png diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index c95b3a5cc0..a77f42817d 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -2,6 +2,7 @@ + diff --git a/appnav/src/main/res/values-ca/translations.xml b/appnav/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..d251b3a6b1 --- /dev/null +++ b/appnav/src/main/res/values-ca/translations.xml @@ -0,0 +1,6 @@ + + + "Tanca sessió i actualitza" + "%1$s ja no admet el protocol antic. Tanca sessió i torna a entrar per continuar utilitzant l\'aplicació." + "El servidor utilitzat ja no admet el protocol antic. Tanca sessió i torna-la a iniciar per continuar utilitzant l\'aplicació." + diff --git a/features/analytics/api/src/main/res/values-ca/translations.xml b/features/analytics/api/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..9f352d28ce --- /dev/null +++ b/features/analytics/api/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "Comparteix dades d\'ús anònimes per ajudar-nos a identificar problemes." + "Pots llegir tots els nostres termes %1$s." + "aquí" + "Comparteix dades analítiques" + diff --git a/features/analytics/impl/src/main/res/values-ca/translations.xml b/features/analytics/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..5a2b633075 --- /dev/null +++ b/features/analytics/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,10 @@ + + + "No registrarem ni elaborarem perfils de cap dada personal" + "Comparteix dades d\'ús anònimes per ajudar-nos a identificar problemes." + "Pots llegir tots els nostres termes %1$s." + "aquí" + "Ho pots desactivar en qualsevol moment" + "No compartirem les teves dades amb tercers" + "Ajuda\'ns a millorar %1$s" + diff --git a/features/call/impl/src/main/res/values-ca/translations.xml b/features/call/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..92c518dbee --- /dev/null +++ b/features/call/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "Trucada en curs" + "Toca per tornar a la trucada" + "☎️ Trucada en curs" + "Element Call entrant" + diff --git a/features/createroom/impl/src/main/res/values-ca/translations.xml b/features/createroom/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..f9e1dea0fc --- /dev/null +++ b/features/createroom/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,16 @@ + + + "Sala nova" + "Convida persones" + "S\'ha produït un error en crear la sala" + "Només s\'hi poden unir les persones convidades." + "Tothom pot trobar aquesta sala. +Pots canviar-ho en qualsevol moment a la configuració de sala." + "Qualsevol persona pot sol·licitar unir-s\'hi però un administrador o moderador l\'haurà d\'acceptar" + "Permet sol·licituds d\'unió" + "Tothom pot unir-s\'hi." + "És necessària una adreça perquè sigui visible al directori públic." + "Adreça" + "Visibilitat de sala" + "Tema (opcional)" + diff --git a/features/deactivation/impl/src/main/res/values-ca/translations.xml b/features/deactivation/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..c8ad39f7ae --- /dev/null +++ b/features/deactivation/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,13 @@ + + + "Si us plau, confirma que vols desactivar el teu compte. Aquesta acció no es pot desfer." + "Elimina tots els meus missatges" + "Avís: els futurs usuaris podrien veure converses incompletes." + "La desactivació del compte és %1$s, implica:" + "irreversible" + "%1$s el compte (no podràs tornar a iniciar sessió i el teu ID no es podrà reutilitzar)." + "Desactiva permanentment" + "Se t\'eliminarà de totes les sales o xats." + "S\'eliminarà la informació del compte del nostre servidor d\'identitat." + "Els teus missatges continuaran sent visibles per als usuaris registrats, però no estaran disponibles per a usuaris nous o no registrats si decideixes eliminar-los." + diff --git a/features/deactivation/impl/src/main/res/values-fi/translations.xml b/features/deactivation/impl/src/main/res/values-fi/translations.xml index df2543be70..148fe3d610 100644 --- a/features/deactivation/impl/src/main/res/values-fi/translations.xml +++ b/features/deactivation/impl/src/main/res/values-fi/translations.xml @@ -1,14 +1,14 @@ - "Vahvista, että haluat deaktivoida tilisi. Tätä ei voi perua." + "Vahvista, että haluat poistaa tilisi. Tätä ei voi perua." "Poista kaikki viestini" "Varoitus: Tulevaisuudessa muut voivat nähdä puutteellisia keskusteluja." - "Tilisi deaktivointia %1$s. Jos teet sen:" + "Tilisi poistamista %1$s. Jos teet sen:" "ei voi peruuttaa" "Tilisi %1$s (et voi kirjautua takaisin sisään, eikä tunnustasi voi käyttää uudelleen)." "poistetaan käytöstä pysyvästi" "Sinut poistetaan kaikista keskusteluhuoneista." "Tilitietosi poistetaan identiteettipalvelimeltamme." "Viestisi näkyvät edelleen rekisteröityneille käyttäjille, mutta ne eivät ole uusien tai rekisteröimättömien käyttäjien saatavilla, jos päätät poistaa ne." - "Deaktivoi tili" + "Poista tili" diff --git a/features/deactivation/impl/src/main/res/values-ru/translations.xml b/features/deactivation/impl/src/main/res/values-ru/translations.xml index 6f595cde29..79c25af475 100644 --- a/features/deactivation/impl/src/main/res/values-ru/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ru/translations.xml @@ -1,14 +1,14 @@ - "Вы уверены, что хотите отключить свою учётную запись? Данное действие необратимо." + "Вы уверены, что хотите удалить свою учётную запись? Данное действие необратимо." "Удалить все мои сообщения" "Внимание: в будущем пользователи могут видеть неполные переписки." - "Деактивация вашего аккаунта %1$s и означает следующее:" + "Удаление вашего аккаунта %1$s, это означает следующее:" "необратимо" "Ваша учётная запись будет %1$s (вы не сможете войти в неё снова, и другие пользователи не смогут использовать ваше имя пользователя)." "Отключить навсегда" "Вы будете удалены из всех чатов." "Данные Вашего аккаунта будут удалены с нашего сервера идентификации." "Ваши сообщения по-прежнему будут видны зарегистрированным пользователям, но не будут доступны новым или незарегистрированным пользователям, если вы решите удалить их." - "Отключить учётную запись" + "Удалить аккаунт" diff --git a/features/ftue/impl/src/main/res/values-ca/translations.xml b/features/ftue/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..1b645dd5eb --- /dev/null +++ b/features/ftue/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,15 @@ + + + "No pots confirmar-la?" + "Crea nova clau de recuperació" + "Verifica aquest dispositiu per configurar missatges segurs." + "Confirma la teva identitat" + "Utilitza un altre dispositiu" + "Utilitza clau de recuperació" + "Ara pots llegir o enviar missatges de manera segura, i qualsevol persona amb qui xategis també confiarà en aquest dispositiu." + "Dispositiu verificat" + "Utilitza un altre dispositiu" + "Esperant un altre dispositiu…" + "Pots canviar la configuració més tard." + "Permet les notificacions i no perdis cap missatge" + diff --git a/features/home/impl/src/main/res/values-ca/translations.xml b/features/home/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..e37db27f23 --- /dev/null +++ b/features/home/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,49 @@ + + + "Desactiva l\'optimització de bateria d\'aquesta aplicació per assegurar-te de rebre totes les notificacions." + "No arriben les notificacions?" + "Recupera la teva identitat criptogràfica i l\'historial de missatges amb una clau de recuperació si has perdut l\'accés a tots els teus dispositius existents." + "Configura la recuperació" + "Configura la recuperació per protegir el teu compte" + "Confirma la clau de recuperació per mantenir l\'accés a l\'emmagatzematge de claus i a l\'historial de missatges." + "Introdueix clau de recuperació" + "Has oblidat la clau de recuperació?" + "L\'emmagatzematge de claus no està sincronitzat" + "Per assegurar que mai et perdis una trucada important, canvia la configuració per permetre les notificacions en pantalla completa quan el telèfon està bloquejat." + "Millora l\'experiència de les trucades" + "Xats" + "Segur que vols rebutjar la invitació per unir-te a %1$s?" + "Rebutja invitació" + "Segur que vols rebutjar el xat privat amb %1$s?" + "Rebutja xat" + "Sense invitacions" + "%1$s (%2$s) t\'ha convidat" + "Aquest procés només s\'ha de fer una vegada, gràcies per esperar." + "Configurant compte." + "Crea un nou xat o sala" + "Comença enviant un missatge a algú." + "Encara no hi ha xats." + "Preferits" + "Pots afegir un xat a preferits a la configuració del xat. +De moment, pots desseleccionar els filtres per veure tots els xats." + "Encara no tens cap xat preferit" + "Invitacions" + "No tens cap invitació pendent." + "Prioritat baixa" + "Pots desseleccionar els filtres per veure els altres xats" + "Cap xats per a aquesta selecció" + "Persones" + "Encara no tens cap xat directe" + "Sales" + "Encara no pertanys a cap sala" + "No llegits" + "Enhorabona! +No tens missatges sense llegir!" + "Sol·licitud d\'unió enviada" + "Xats" + "Marca com a llegit" + "Marca com a no llegit" + "La sala ha estat actualitzada" + "Sembla que estàs utilitzant un dispositiu nou. Verifica\'l amb un altre dispositiu per accedir als teus missatges xifrats." + "Verifica que ets tu" + diff --git a/features/invite/impl/src/main/res/values-ca/translations.xml b/features/invite/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..0dd3e42664 --- /dev/null +++ b/features/invite/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,18 @@ + + + "No veuràs cap missatge ni invitacions a sales d\'aquest usuari." + "Bloqueja usuari" + "Denuncia aquesta sala al teu proveïdor de compte." + "Descriu el motiu de la denúncia…" + "Rebutja i bloqueja" + "Segur que vols rebutjar la invitació per unir-te a %1$s?" + "Rebutja invitació" + "Segur que vols rebutjar el xat privat amb %1$s?" + "Rebutja xat" + "Sense invitacions" + "%1$s (%2$s) t\'ha convidat" + "Sí, rebutja i bloqueja" + "Segur que vols rebutjar la invitació d\'unió a aquesta sala? Això també evitarà que %1$s et contacti i et convidi a sales." + "Rebutja la invitació i bloqueja" + "Rebutja i bloqueja" + diff --git a/features/invitepeople/impl/src/main/res/values-ca/translations.xml b/features/invitepeople/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..294d04b4a3 --- /dev/null +++ b/features/invitepeople/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,5 @@ + + + "Ja és membre" + "Ja s\'ha convidat" + diff --git a/features/invitepeople/impl/src/main/res/values-fi/translations.xml b/features/invitepeople/impl/src/main/res/values-fi/translations.xml index e347919719..d2283c7b2a 100644 --- a/features/invitepeople/impl/src/main/res/values-fi/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-fi/translations.xml @@ -2,4 +2,8 @@ "On jo jäsen" "On jo kutsuttu" + "Sinulla ei ole tällä hetkellä keskusteluja näiden yhteystietojen kanssa. Vahvista kutsusi heille tähän huoneeseen ennen kuin jatkat." + "Sinulla ei ole tällä hetkellä keskusteluja tämän yhteystiedon kanssa. Vahvista kutsusi hänelle tähän huoneeseen ennen kuin jatkat." + "Kutsutaanko uusia yhteystietoja tähän huoneeseen?" + "Kutsutaanko uusi yhteystieto tähän huoneeseen?" diff --git a/features/invitepeople/impl/src/main/res/values-ru/translations.xml b/features/invitepeople/impl/src/main/res/values-ru/translations.xml index 45e650f081..1f2455ba72 100644 --- a/features/invitepeople/impl/src/main/res/values-ru/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-ru/translations.xml @@ -2,4 +2,8 @@ "Уже участник" "Уже приглашен(а)" + "У тебя пока нет чатов с этими контактами. Подтверди приглашение в эту комнату, прежде чем продолжить." + "У вас пока нет чатов с этим контактом. Подтверди приглашение в эту комнату, прежде чем продолжить." + "Пригласить новых участников в эту комнату?" + "Пригласить нового участника в эту комнату?" diff --git a/features/joinroom/impl/src/main/res/values-ca/translations.xml b/features/joinroom/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..e26c33d40f --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,32 @@ + + + "Has estat bandejat per %1$s." + "T\'han bandejat" + "Motiu: %1$s." + "Cancel·la la sol·licitud" + "Sí, cancel·la" + "Segur que vols cancel·lar la teva sol·licitud d\'unió a aquesta sala?" + "Cancel·la la sol·licitud d\'unió" + "Sí, rebutja i bloqueja" + "Segur que vols rebutjar la invitació d\'unió a aquesta sala? Això també evitarà que %1$s et contacti i et convidi a sales." + "Rebutja la invitació i bloqueja" + "Rebutja i bloqueja" + "Ha fallat la unió" + "O t\'han de convidar per unir-te o hi pot haver restriccions d\'accés." + "Oblida" + "Per unir-te, necessites una invitació" + "Uneix-te" + "Pot ser que t\'hagin de convidar o hagis de ser membre d\'un espai per unir-t\'hi." + "Envia sol·licitud d\'unió" + "Missatge (opcional)" + "Rebràs una invitació per unir-te a la sala si la teva sol·licitud és acceptada." + "Sol·licitud d\'unió enviada" + "No s\'ha pogut mostrar la vista prèvia de la sala. Pot ser degut a problemes de xarxa o del servidor." + "No s\'ha pogut mostrar la vista prèvia de la sala" + "%1$s encara no admet els espais. Pots accedir-hi a través del navegador web." + "Espais encara no compatibles" + "Clic al botó següent i s\'avisarà a un administrador de sala. Podràs unir-te un cop t\'hagi aprovat." + "Per poder veure l\'historial de missatges has de ser un membre de la sala." + "Vols unir-te a aquesta sala?" + "Vista prèvia no disponible" + diff --git a/features/knockrequests/impl/src/main/res/values-ca/translations.xml b/features/knockrequests/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..bdf1cac21b --- /dev/null +++ b/features/knockrequests/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,35 @@ + + + "Sí, accepta-les totes" + "Segur que vols acceptar totes les sol·licituds d\'unió?" + "Accepta totes les sol·licituds" + "Accepta-les totes" + "No s\'han pogut acceptar totes les sol·licituds. Vols tornar-ho a intentar?" + "No s\'han pogut acceptar totes les sol·licituds" + "Acceptant totes les sol·licituds d\'unió" + "No s\'ha pogut acceptar la sol·licitud. Vols tornar-ho a intentar?" + "No s\'ha pogut acceptar la sol·licitud" + "Acceptant sol·licitud d\'unió" + "Sí, rebutja i bandeja" + "Segur que vols rebutjar i bandejar %1$s? L\'usuari no podrà sol·licitar de nou l\'accés d\'unió a aquesta sala." + "Rebutja i bandeja l\'accés" + "Rebutjant i bandejant l\'accés" + "Sí, rebutja" + "Segur que vols rebutjar %1$s d\'unir-se a aquesta sala?" + "Rebutja l\'accés" + "Rebutja i bandeja" + "No s\'ha pogut rebutjar la sol·licitud. Vols tornar-ho a intentar?" + "No s\'ha pogut rebutjar la sol·licitud" + "Rebutjant sol·licitud d\'unió" + "Quan algú demani unir-se a la sala, aquí podràs veure la sol·licitud." + "No hi ha sol·licituds d\'unió pendents" + "Carregant sol·licituds d\'unió…" + "Sol·licituds d\'unió" + + "%1$s +%2$d altre volen unir-se a la sala" + "%1$s +%2$d altres volen unir-se a la sala" + + "Veure totes" + "Accepta" + "%1$s vol unir-se a aquesta sala" + diff --git a/features/knockrequests/impl/src/main/res/values-zh/translations.xml b/features/knockrequests/impl/src/main/res/values-zh/translations.xml index d70632861c..d8b8f76b13 100644 --- a/features/knockrequests/impl/src/main/res/values-zh/translations.xml +++ b/features/knockrequests/impl/src/main/res/values-zh/translations.xml @@ -17,7 +17,7 @@ "是,拒绝" "你确定要拒绝 %1$s 加入此房间的申请?" "拒绝访问" - "拒绝和禁止" + "拒绝并封禁" "我们无法拒绝此申请。是否重试?" "拒绝申请失败" "拒绝加入申请" diff --git a/features/leaveroom/api/src/main/res/values-ca/translations.xml b/features/leaveroom/api/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..870e0c35f2 --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "Segur que vols sortir d\'aquest xat? El xat no és públic i no t\'hi podràs tornar a unir sense una invitació." + "Segur que vols sortir d\'aquesta sala? N\'ets l\'única persona. Si en surts, ningú s\'hi podrà unir i tu tampoc." + "Segur que vols sortir d\'aquesta sala? La sala no és pública i no podràs tornar a unir-t\'hi sense una invitació." + "Segur que vols sortir de la sala?" + diff --git a/features/linknewdevice/impl/src/main/res/values-ca/translations.xml b/features/linknewdevice/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..d78744ff85 --- /dev/null +++ b/features/linknewdevice/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,41 @@ + + + "Escaneja el QR" + "Escaneja el codi QR amb aquest dispositiu" + "Preparat per escanejar" + "El proveïdor del teu compte no admet %1$s." + "%1$s no és compatible" + "Codi QR no compatible" + "L\'inici de sessió s\'ha cancel·lat a l\'altre dispositiu." + "Sol·licitud d\'inici de sessió cancel·lada" + "Inici de sessió ha caducat. Torna-ho a provar." + "L\'inici de sessió no s\'ha completat a temps" + "Selecciona %1$s" + "No s\'ha pogut establir una connexió segura amb el dispositiu nou. Els dispositius existents continuen sent segurs, no te n\'has de preocupar." + "I ara què?" + "Prova de tornar a iniciar sessió mitjançant un codi QR si es tracta d\'un problema de xarxa." + "Si es repeteix el mateix problema, prova una xarxa wifi diferent o utilitza les dades mòbils en lloc del wifi." + "Si no funciona, inicia sessió manualment" + "Connexió no segura" + "Se\'t demanarà que introdueixis els dos dígits mostrats en aquest dispositiu." + "Introdueix el número següent a l\'altre dispositiu" + "L\'inici de sessió s\'ha cancel·lat a l\'altre dispositiu." + "Sol·licitud d\'inici de sessió cancel·lada" + "L\'inici de sessió s\'ha rebutjat a l\'altre dispositiu." + "Inici de sessió rebutjat" + "Inici de sessió ha caducat. Torna-ho a provar." + "L\'inici de sessió no s\'ha completat a temps" + "El teu altre dispositiu no admet l\'inici de sessió a %s amb codis QR. + +Prova d\'iniciar la sessió manualment o escaneja el QR amb un altre dispositiu." + "Codi QR no compatible" + "El proveïdor del teu compte no admet %1$s." + "%1$s no és compatible" + "Utilitza el codi QR que es mostra a l\'altre dispositiu." + "Torna-ho a intentar" + "Codi QR incorrecte" + "Per continuar, has donar permís a %1$s per poder utilitzar la càmera del dispositiu." + "Permet l\'accés a la càmera per poder escanejar el codi QR" + "S\'ha produït un error inesperat. Torna-ho a provar." + "Esperant el teu altre dispositiu" + diff --git a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml index cabcb5ccd0..f11f60dd61 100644 --- a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml @@ -9,7 +9,7 @@ "输入两位数字的代码" "这将验证你与其它设备的连接是否安全。" "请输入另一台设备上显示的数字" - "账户提供方不支持 %1$s." + "账户提供者不支持 %1$s." "不支持 %1$s." "你的账户提供者不支持使用二维码登录到新设备。" "二维码不受支持" @@ -48,7 +48,7 @@ 尝试手动或使用另一个设备扫描二维码." "二维码不受支持" - "账户提供方不支持 %1$s." + "账户提供者不支持 %1$s." "不支持 %1$s." "使用其它设备上显示的二维码。" "重试" 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 4a7d801f71..b35d11cd49 100644 --- a/features/location/impl/src/main/res/values-fi/translations.xml +++ b/features/location/impl/src/main/res/values-fi/translations.xml @@ -2,4 +2,5 @@ "Reaaliaikainen sijaintihistoriasi tallennetaan huoneeseen ja on jäsenten nähtävissä istunnon päätyttyä." "Valitse, kuinka kauan haluat jakaa reaaliaikaisen sijaintisi." + "Sinulla ei ole oikeuksia jakaa reaaliaikaista sijaintiasi tässä huoneessa" diff --git a/features/location/impl/src/main/res/values-ja/translations.xml b/features/location/impl/src/main/res/values-ja/translations.xml index 971693ef11..1060120ee5 100644 --- a/features/location/impl/src/main/res/values-ja/translations.xml +++ b/features/location/impl/src/main/res/values-ja/translations.xml @@ -2,4 +2,5 @@ "ライブ位置情報の履歴はルームに保管され、メンバーは後から確認することもできます。" "ライブ位置情報を共有する期間を選択してください。" + "このルームでライブ位置情報を共有する権限がありません。" diff --git a/features/location/impl/src/main/res/values-ru/translations.xml b/features/location/impl/src/main/res/values-ru/translations.xml index 3c496f1d39..97b279621c 100644 --- a/features/location/impl/src/main/res/values-ru/translations.xml +++ b/features/location/impl/src/main/res/values-ru/translations.xml @@ -2,4 +2,5 @@ "История вашего местоположения в режиме реального времени будет сохранена в комнате и станет доступна участникам после окончания сессии." "Выберите, как долго вы будете делиться своим местоположением в режиме реального времени." + "У тебя нет прав на то, чтобы делиться своим текущим местоположением в этой комнате" diff --git a/features/lockscreen/impl/src/main/res/values-ca/translations.xml b/features/lockscreen/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..5637977b97 --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,38 @@ + + + "l\'autenticació biomètrica" + "desbloqueig biomètric" + "Desbloqueja amb biometria" + "Confirma biometria" + "Has oblidat el PIN?" + "Canvia codi PIN" + "Permet desbloqueig biomètric" + "Elimina PIN" + "Segur que vols eliminar el PIN?" + "Vols eliminar el PIN?" + "Permet %1$s" + "Prefereixo utilitzar el PIN" + "Estalvia\'t temps i utilitza %1$s per desbloquejar l\'aplicació" + "Escull el PIN" + "Confirma PIN" + "Bloqueja %1$s per afegir més seguretat als teus xats. + +Escull alguna cosa que recordis. Si oblides aquest PIN, es tancarà sessió a l\'aplicació." + "Per motius de seguretat no pots utilitzar aquest codi PIN" + "Escull un PIN diferent" + "Introdueix el mateix PIN dues vegades" + "Els codis PIN no coincideixen" + "Hauràs de tornar a iniciar sessió i crear un nou PIN per continuar." + "S\'està tancant la sessió" + + "Tens %1$d intent per desbloquejar" + "Tens %1$d intents per desbloquejar" + + + "PIN incorrecte. Tens %1$d intent més" + "PIN incorrecte. Tens %1$d intents més" + + "Utilitza biometria" + "Utilitza PIN" + "S\'està tancant la sessió…" + diff --git a/features/login/impl/src/main/res/values-ca/translations.xml b/features/login/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..f079e7b071 --- /dev/null +++ b/features/login/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,89 @@ + + + "Canvia el proveïdor del compte" + "Adreça del servidor" + "Introdueix una paraula de cerca o un domini (adreça)." + "Cerca una empresa, una comunitat o un servidor privat." + "Busca un proveïdor de comptes" + "Aquí és on es guardaran els teus xats, de manera similar a utilitzar un proveïdor de correu electrònic per guardar els teus correus electrònics." + "Estàs a punt d\'iniciar sessió a %s" + "Aquí és on es guardaran els teus xats, de manera similar a utilitzar un proveïdor de correu electrònic per guardar els teus correus electrònics." + "Estàs a punt de crear un compte a %s" + "Matrix.org és un gran servidor gratuït de la xarxa pública de Matrix per a la comunicació segura i descentralitzada, gestionat per la Fundació Matrix.org." + "Altres" + "Utilitza un proveïdor de comptes diferent, com ara el teu servidor privat o un compte de feina." + "Canvia el proveïdor del compte" + "No s\'ha pogut accedir a aquest servidor. Comprova que hagis introduït correctament l\'URL del servidor. Si ja és correcte, posa\'t en contacte amb l\'administrador del servidor per a més informació." + "Servidor no disponible a causa d\'un problema al fitxer .well-known: +%1$s" + "URL del servidor" + "Introdueix un domini." + "Quina és l\'adreça del teu servidor?" + "Selecciona el teu servidor" + "Crea un compte" + "Aquest compte s\'ha desactivat." + "Usuari i/o contrasenya incorrectes" + "Identificador d\'usuari invàlid. Format esperat: ‘@usuari:servidor.org’" + "Aquest servidor està configurat per utilitzar tokens d\'actualització, però no són compatibles quan s\'utilitza l\'inici de sessió basat en contrasenya." + "El servidor seleccionat no admet contrasenya o inici de sessió OAuth. Posa\'t en contacte amb l\'administrador o tria un altre servidor." + "Introdueix les teves dades" + "Matrix és una xarxa oberta per a comunicacions segures i descentralitzades." + "Hola de nou!" + "Inicia sessió a %1$s" + "Inicia sessió manualment" + "Inicia sessió a %1$s" + "Inicia sessió amb un codi QR" + "Crea un compte" + "Et donem la benvinguda a %1$s. Més ràpid i simple que mai." + "Et donem la benvinguda a %1$s. Dissenyat per ser més ràpid i simple." + "Sigues el teu propi element" + "Establint una connexió segura" + "No s\'ha pogut establir una connexió segura amb el dispositiu nou. Els dispositius existents continuen sent segurs, no te n\'has de preocupar." + "I ara què?" + "Prova de tornar a iniciar sessió mitjançant un codi QR si es tracta d\'un problema de xarxa." + "Si es repeteix el mateix problema, prova una xarxa wifi diferent o utilitza les dades mòbils en lloc del wifi." + "Si no funciona, inicia sessió manualment" + "Connexió no segura" + "Se\'t demanarà que introdueixis els dos dígits mostrats en aquest dispositiu." + "Introdueix el número següent a l\'altre dispositiu" + "Inicia sessió a l\'altre dispositiu i torna-ho a provar o utilitza un altre dispositiu amb la sessió ja iniciada." + "No s\'ha iniciat sessió a l\'altre dispositiu" + "L\'inici de sessió s\'ha cancel·lat a l\'altre dispositiu." + "Sol·licitud d\'inici de sessió cancel·lada" + "L\'inici de sessió s\'ha rebutjat a l\'altre dispositiu." + "Inici de sessió rebutjat" + "Inici de sessió ha caducat. Torna-ho a provar." + "L\'inici de sessió no s\'ha completat a temps" + "El teu altre dispositiu no admet l\'inici de sessió a %s amb codis QR. + +Prova d\'iniciar la sessió manualment o escaneja el QR amb un altre dispositiu." + "Codi QR no compatible" + "El proveïdor del teu compte no admet %1$s." + "%1$s no és compatible" + "Preparat per escanejar" + "Obre %1$s en un dispositiu d\'escriptori" + "Clica la teva imatge" + "Selecciona %1$s" + "“Enllaça nou dispositiu”" + "Escaneja el codi QR amb aquest dispositiu" + "Només disponible si el proveïdor del compte ho admet." + "Obre %1$s en un altre dispositiu per obtenir el codi QR" + "Utilitza el codi QR que es mostra a l\'altre dispositiu." + "Torna-ho a intentar" + "Codi QR incorrecte" + "Vés a la configuració de càmera" + "Per continuar, has donar permís a %1$s per poder utilitzar la càmera del dispositiu." + "Permet l\'accés a la càmera per poder escanejar el codi QR" + "Escaneja el QR" + "Torna a començar" + "S\'ha produït un error inesperat. Torna-ho a provar." + "Esperant el teu altre dispositiu" + "Per verificar l\'inici de sessió, pot ser que el proveïdor del teu compte et demani el següent codi." + "Codi de verificació" + "Canvia el proveïdor del compte" + "Servidor privat per a treballadors d\'Element." + "Matrix és una xarxa oberta per a comunicacions segures i descentralitzades." + "Aquí és on es guardaran els teus xats, de manera similar a utilitzar un proveïdor de correu electrònic per guardar els teus correus electrònics." + "Estàs a punt d\'iniciar sessió a %1$s" + "Estàs a punt de crear un compte a %1$s" + 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 4f5225be67..8561bcfce3 100644 --- a/features/login/impl/src/main/res/values-fi/translations.xml +++ b/features/login/impl/src/main/res/values-fi/translations.xml @@ -28,7 +28,7 @@ "Mikä on palvelimesi osoite?" "Valitse palvelimesi" "Luo tili" - "Tämä tili on deaktivoitu." + "Tämä tili on poistettu." "Väärä käyttäjänimi ja/tai salasana" "Tämä ei ole kelvollinen käyttäjätunnus. Odotettu muoto: \'@käyttäjä:kotipalvelin.fi\'" "Tämä palvelin on määritetty käyttämään refresh tokeneja. Näitä ei tueta salasanapohjaisen kirjautumisen kanssa." 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 329bad30af..564fc87cac 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -28,7 +28,7 @@ "Какой адрес у вашего сервера?" "Выберите свой сервер" "Создать аккаунт" - "Данная учётная запись была отключена." + "Эта учетная запись была удалена." "Неверное имя пользователя и/или пароль" "Это некорректный идентификатор пользователя. Правильный формат: @user:homeserver.org" "Этот сервер настроен на использование токенов обновления. Они не поддерживаются при использовании входа на основе пароля." 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 8e86b51d7b..16afe7d5bd 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -1,10 +1,10 @@ - "更改账户提供方" + "更改账户提供者" "主服务器地址" "输入搜索词或域名地址。" "搜索公司、社区或私人服务器。" - "寻找账户提供方" + "查找账户提供者" "这是你的对话将存在的地方,就像你使用邮件提供者来存储电子邮件那样。" "你即将登录到 %s" "这是你的对话将存在的地方,就像你使用邮件提供者来存储电子邮件那样。" @@ -12,7 +12,7 @@ "Matrix.org 由 Matrix.org 基金会运营,是用于安全、去中心化的通信的公共 Matrix 网络上的大型免费服务器。" "其它" "使用其它账户提供者,例如你自己的私有服务器或工作账户。" - "更改账户提供方" + "更改账户提供者" "Google Play" "%1$s 要求 Element Pro。请从应用商店下载。" "需要 Element Pro" @@ -77,7 +77,7 @@ 尝试手动或使用另一个设备扫描二维码." "二维码不受支持" - "账户提供方不支持 %1$s." + "账户提供者不支持 %1$s." "不支持 %1$s." "准备进行扫描" "在桌面设备上打开 %1$s" @@ -99,7 +99,7 @@ "正在等待其它设备" "你的账户提供者可能会要求你提供以下代码以验证登录。" "你的验证码" - "更改账户提供方" + "更改账户提供者" "专为 Element 员工提供的私人服务器。" "Matrix 是一个用于安全、去中心化通信的开放网络。" "这是你的对话将存在的地方,就像你使用邮件提供者来存储电子邮件那样。" diff --git a/features/logout/impl/src/main/res/values-ca/translations.xml b/features/logout/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..eb0c82bb15 --- /dev/null +++ b/features/logout/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,17 @@ + + + "Segur que vols tancar sessió?" + "Tanca sessió" + "Tanca sessió" + "S\'està tancant la sessió…" + "Estàs a punt de tancar sessió. Si tanques sessió ara, perdràs l\'accés als missatges xifrats." + "Has desactivat la còpia de seguretat" + "Encara tens una còpia de seguretat de les teves claus i t\'has desconnectat. Torna a connectar-te per poder fer una còpia de seguretat de les teves claus abans de tancar la sessió." + "Encara s\'està fent una còpia de seguretat de les teves claus" + "Espera a que s\'hagi completat abans de tancar sessió." + "Encara s\'està fent una còpia de seguretat de les teves claus" + "Tanca sessió" + "Estàs a punt de tancar sessió a la teva última i única sessió. Si tanques sessió ara, perdràs l\'accés als missatges xifrats." + "Recuperació no configurada" + "Estàs a punt de tancar sessió. Si tanques sessió ara, pot ser que perdis l\'accés als missatges xifrats." + diff --git a/features/messages/impl/src/main/res/values-ca/translations.xml b/features/messages/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..f9b2685c7d --- /dev/null +++ b/features/messages/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,68 @@ + + + "El remitent de l\'esdeveniment no coincideix amb el propietari del dispositiu que l\'ha enviat." + "L\'autenticitat d\'aquest missatge xifrat en aquest dispositiu no es pot garantir." + "Xifrat per un usuari prèviament verificat." + "No xifrat." + "Xifrat per un dispositiu desconegut o eliminat." + "Xifrat per un dispositiu no verificat pel seu propietari." + "Xifrat per un usuari no verificat." + "Activitats" + "Banderes" + "Menjar & begudes" + "Animals i naturalesa" + "Objectes" + "Cares i persones" + "Viatges i llocs" + "Emoticones recents" + "Símbols" + "És possible que les llegendes no siguin visibles pels que utilitzin aplicacions antigues." + "No s\'ha pogut processar el contingut que s\'havia de pujar. Torna-ho a provar." + "No s\'ha pogut pujar el contingut. Torna-ho a provar." + "Bloqueja usuari" + "Marca si vols ocultar tots els missatges actuals i futurs d\'aquest usuari" + "Aquest missatge s\'enviarà a l\'administrador del teu servidor. No podrà llegir cap missatge xifrat." + "Motiu de la denúncia del contingut" + "Càmera" + "Fes una foto" + "Enregistra vídeo" + "Fitxer adjunt" + "Galeria de fotos i vídeos" + "Ubicació" + "Votació" + "Format de text" + "L\'historial de missatges no està disponible actualment." + "L\'historial de missatges no està disponible en aquesta sala. Verifica aquest dispositiu per veure l\'historial de missatges." + "Vols tornar-los a convidar-los?" + "No hi ha ningú més al xat" + "Notifica tota la sala" + "Tothom" + "Torna a enviar" + "No s\'han pogut enviar els missatges" + "Afegeix reacció" + "Aquest és el principi de %1$s." + "Principi d\'aquesta conversa." + "Trucada no compatible. Comprova si la persona que truca està utilitzant la nova aplicació Element X." + "Mostra\'n menys" + "Missatge copiat" + "No tens permís per enviar res en aquesta sala" + "Mostra\'n menys" + "Mostra\'n més" + "Nous" + + "%1$d canvi a la sala" + "%1$d canvis a la sala" + + "Aquesta sala ha estat substituïda i ja no està activa" + "Mostra els missatges antics" + "Aquesta sala és la continuació d\'una altra" + + "%1$s, %2$s i %3$d més" + "%1$s, %2$s i %3$d més" + + + "%1$s està escrivint" + "%1$s estan escrivint" + + "%1$s i %2$s" + diff --git a/features/messages/impl/src/main/res/values-ja/translations.xml b/features/messages/impl/src/main/res/values-ja/translations.xml index 037c0f7d67..93c10d13d8 100644 --- a/features/messages/impl/src/main/res/values-ja/translations.xml +++ b/features/messages/impl/src/main/res/values-ja/translations.xml @@ -26,6 +26,7 @@ "個数 %1$d / %2$d" "画像の品質を最適化" "処理中…" + "メディアを追加" "ユーザーをブロック" "このユーザーからのメッセージをすべて非表示にする場合はチェックしてください。" "このメッセージはホームサーバーの管理者に報告されます。暗号化されたメッセージを確認することはできません。" diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index efb84cd153..a0b9c24af2 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -26,6 +26,7 @@ "Pozycja %1$d z %2$d" "Zoptymalizuj jakość obrazu" "Przetwarzanie…" + "Dodaj media" "Zablokuj użytkownika" "Sprawdź, czy chcesz ukryć wszystkie bieżące i przyszłe wiadomości od tego użytkownika." "Ta wiadomość zostanie zgłoszona do administratora Twojego serwera domowego. Nie będzie mógł on przeczytać żadnych zaszyfrowanych wiadomości." diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index fc576aaf11..bdd898d26f 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -26,6 +26,7 @@ "第 %1$d 个项目,共 %2$d 个" "优化图像质量" "处理中…" + "添加媒体" "屏蔽用户" "请确认是否要隐藏该用户当前和未来的所有消息" "此消息将举报给服务器管理员。他们无法读取任何加密消息。" diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index f5629f5e2d..9e0669d92c 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -26,6 +26,7 @@ "Item %1$d of %2$d" "Optimise image quality" "Processing…" + "Add media" "Block user" "Check if you want to hide all current and future messages from this user" "This message will be reported to your homeserver’s administrator. They will not be able to read any encrypted messages." diff --git a/features/poll/impl/src/main/res/values-ca/translations.xml b/features/poll/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..21385e6473 --- /dev/null +++ b/features/poll/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,19 @@ + + + "Afegeix opció" + "Mostra els resultats només quan hagi finalitzat la votació" + "Amaga vots" + "Opció %1$d" + "Els canvis no s\'han desat. Segur que vols tornar enrere?" + "Pregunta o tema" + "De què tracta la votació?" + "Crea votació" + "Segur que vols eliminar la votació?" + "Elimina votació" + "Edita votació" + "No s\'han trobat votacions en curs." + "No s\'han trobat votacions passades." + "En curs" + "Pasades" + "Votacions" + diff --git a/features/preferences/impl/src/main/res/values-ca/translations.xml b/features/preferences/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..b2cb548d45 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,70 @@ + + + "Per assegurar que mai et perdis una trucada important, canvia la configuració per permetre les notificacions en pantalla completa quan el telèfon està bloquejat." + "Millora l\'experiència de les trucades" + "Tria com vols rebre les notificacions" + "Mode desenvolupador" + "Activa-ho per tenir accés a característiques i funcionalitats per a desenvolupadors." + "URL base d\'Element Call personalitzat" + "Estableix un URL base personalitzat d\'Element Call." + "URL invàlid, assegura\'t d\'incloure el protocol (http/https) i l\'adreça correctament." + "Amaga les previsualitzacions multimèdia a la cronologia" + "Puja fotos i vídeos més ràpidament i redueix l\'ús de dades" + "Optimitza qualitat de multimèdia" + "Moderació i seguretat" + "Proveïdor de notificacions push" + "Desactiva l\'editor de text enriquit per escriure Markdown manualment." + "Confirmacions de lectura" + "Si està desactivat, les confirmacions de lectura no s\'enviaran a ningú. Tot i així, rebràs les confirmacions de lectura d\'altres usuaris (que la tinguin activada)." + "Comparteix presència" + "Si està desactivat, no s\'enviaran ni rebràs confirmacions de lectura ni notificacions d\'escriptura." + "Amaga sempre" + "Mostra sempre" + "En sales privades" + "Els arxius multimèdia amagats es poden mostrar tocant-los." + "Mostra multimèdia a la cronologia" + "Activa l\'opció de mostrar el codi font dels missatges a la cronologia" + "No tens usuaris bloquejats" + "Desbloqueja" + "Podràs tornar a veure tots els seus missatges." + "Desbloqueja usuari" + "Desbloquejant…" + "Nom de visualització" + "El teu nom de visualització" + "S\'ha produït un error desconegut i no s\'ha pogut canviar la informació." + "No s\'ha pogut actualitzar el perfil" + "Edita perfil" + "Actualitzant perfil…" + "Configuració addicional" + "Trucades d\'àudio i vídeo" + "Configuració no coincident" + "S\'ha simplificat la configuració de notificacions per facilitar la cerca de les opcions. Algunes configuracions personalitzades anteriors no es mostren aquí, però encara estan actives. + +Si continues, és possible que alguna de les teves configuracions canviï." + "Xats directes" + "Configuració personalitzada per xat" + "S\'ha produït un error en actualitzar la configuració de notificacions." + "Tots els missatges" + "Mencions y paraules clau (només)" + "En xats directes, notifica\'m en" + "En xats de grup, notifica\'m en" + "Activa les notificacions en aquest dispositiu" + "La configuració no s\'ha corregit, torna-ho a intentar." + "Xats de grup" + "Invitacions" + "El servidor no admet aquesta opció en sales xifrades, és possible que no rebis notificacions en algunes sales." + "Mencions" + "Tot" + "Mencions" + "Notifica\'m a" + "Notifica\'m a @sala" + "Per rebre notificacions, canvia la teva %1$s." + "configuració del sistema" + "Notificacions del sistema desactivades" + "Notificacions" + "Fosc" + "Clar" + "Sistema" + "Soluciona problemes" + "Resolució de problemes de notificacions" + diff --git a/features/preferences/impl/src/main/res/values-fi/translations.xml b/features/preferences/impl/src/main/res/values-fi/translations.xml index 97da4e138a..99f900bcc1 100644 --- a/features/preferences/impl/src/main/res/values-fi/translations.xml +++ b/features/preferences/impl/src/main/res/values-fi/translations.xml @@ -11,6 +11,14 @@ "Piilota huoneiden avatarit kutsuista" "Piilota median esikatselu aikajanalla" "Labrat" + "Etäisyys, joka sinun on kuljettava päivityksen käynnistämiseksi." + "Varmista, että tälle sovellukselle on valittu \"Tarkka sijainti\". Voit muuttaa lupaa kohdassa %1$s." + "Sovellusasetukset" + "Reaaliaikaiset sijaintipäivitykset" + + "%1$d metrin välein" + "%1$d metrin välein" + "Lähetä valokuvia ja videoita nopeammin ja vähennä datan käyttöä." "Optimoi median laatu" "Moderointi ja Turvallisuus" @@ -72,10 +80,18 @@ Jos jatkat, jotkin asetukset saattavat muuttua." "Maininnat" "Ilmoita minulle" "Ilmoita minulle @room-maininnoista" + "Mukautettu ääni…" + "Virhe tiedoston poistamisessa" + "Elementin oletus" + "Virhe tiedoston tuonnissa" + "Ongelma ilmoitusäänen esikatselussa" + "Ääni" + "Ongelma ilmoitusäänen asettamisessa" "Jos haluat saada ilmoituksia, vaihda %1$s." "järjestelmäsi asetuksia" "Järjestelmän ilmoitukset on poissa päältä" "Ilmoitukset" + "Musta" "Tumma" "Vaalea" "Järjestelmän oletus" diff --git a/features/preferences/impl/src/main/res/values-fr/translations.xml b/features/preferences/impl/src/main/res/values-fr/translations.xml index 3f97b67eb8..d7f17e4ffe 100644 --- a/features/preferences/impl/src/main/res/values-fr/translations.xml +++ b/features/preferences/impl/src/main/res/values-fr/translations.xml @@ -80,6 +80,7 @@ Si vous continuez, il est possible que certains de vos paramètres soient modifi "Mentions" "Prévenez-moi pour" "Prévenez-moi si un message contient \"@room\"" + "Son personnalisé…" "Pour recevoir des notifications, veuillez modifier votre %1$s." "paramètres du système" "Les notifications du système sont désactivées" diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml index 95380cf148..5cab6bdcf8 100644 --- a/features/preferences/impl/src/main/res/values-ja/translations.xml +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -79,10 +79,45 @@ "メンション" "以下を通知" @ルームで通知を受け取る + "カスタム着信音" + "ファイルの削除に失敗" + "Element の既定" + "Elementフェード" + "ファイルの取り込みに失敗" + "通知音のプレビューで問題が発生しました" + "音" + "通知音の設定に問題が発生しました" + "アラート" + "予感" + "ベル" + "開花" + "カリプソ" + "チャイム" + "汽車ポッポ" + "下降" + "エレクトロニック" + "ファンファーレ" + "ガラス" + "ホーン" + "はしご" + "メヌエット" + "速報" + "ノワール" + "シャーウッドの森" + "スペル" + "サスペンス" + "シュッ" + "電信" + "つま先" + "トリトーン" + "さえずり" + "タイプライター" + "アップデート" "通知を受け取るには、%1$s を変更してください。" "システム設定" "システムで通知がオフです" "通知" + "ブラック" "ダーク" "ライト" "システム" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index 83b02c6fe2..ca81984032 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -65,7 +65,7 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "Czaty prywatne" - "Ustawienia własne wybranego czatu" + "Własne ustawienia dla wybranego czatu" "Wystąpił błąd podczas aktualizacji ustawienia powiadomień." "Wszystkie wiadomości" "Tylko wzmianki i słowa kluczowe" @@ -81,6 +81,40 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "Wzmianki" "Powiadamiaj mnie przez" "Powiadom mnie na @pokój" + "Własny dźwięk…" + "Błąd usuwania pliku" + "Domyślny Element" + "Element Fade" + "Błąd importowania pliku" + "Wystąpił błąd podczas podglądania dźwięku powiadomień" + "Dźwięk" + "Nie udało się ustawić dźwięku powiadomień" + "Alert" + "Oczekiwanie" + "Dzwonek" + "Rozkwit" + "Kalipso" + "Gong" + "Ciuchcia" + "Opadający" + "Elektroniczna" + "Fanfary" + "Szkło" + "Róg" + "Drabina" + "Minuet" + "Wiadomości" + "Kryminał" + "Las Sherwood" + "Zaklęcie" + "Napięcie" + "Świst" + "Telegraf" + "Na palcach" + "Trójdźwięk" + "Tweet" + "Maszyna do pisania" + "Aktualizacja" "Aby otrzymywać powiadomienia, zmień swoje%1$s." "ustawienia systemowe" "Powiadomienia systemowe wyłączone" diff --git a/features/preferences/impl/src/main/res/values-ru/translations.xml b/features/preferences/impl/src/main/res/values-ru/translations.xml index edb98feee8..eb4ad2245d 100644 --- a/features/preferences/impl/src/main/res/values-ru/translations.xml +++ b/features/preferences/impl/src/main/res/values-ru/translations.xml @@ -11,6 +11,15 @@ "Скрывать аватары в приглашениях" "Скрывать предпросмотр медиа в истории сообщений" "Лаборатория" + "Расстояние, которое нужно пройти, чтобы инициировать обновление." + "Убедитесь, что для этого приложения включена функция «Точное местоположение». Чтобы изменить разрешение, перейдите на страницу %1$s." + "Настройки приложения" + "Обновления местоположения в режиме реального времени" + + "Каждый %1$d метр" + "Каждые %1$d метра" + "Каждые %1$d метров" + "Загружайте фотографии и видео быстрее и сокращайте потребление трафика" "Оптимизировать качество мультимедиа" "Модерация и безопасность" @@ -76,6 +85,7 @@ "системные настройки" "Системные уведомления выключены" "Уведомления" + "Черный" "Темная" "Светлое" "Системное" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 8f6de8209e..3726b82206 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -79,6 +79,40 @@ "提及" "通知我以下类型" "提及所有成员(@room)时通知我" + "自定义声音…" + "删除文件时出错" + "Element 默认" + "Element 淡入" + "导入文件时出错" + "预览提示音时出现问题" + "声音" + "设置提示音时出现问题" + "提醒声" + "悉心期盼" + "铃铛" + "百花怒放" + "即兴曲调" + "风铃" + "火车鸣笛" + "渐弱" + "电子乐" + "嘹亮吹奏声" + "玻璃声" + "圆号" + "连音效果" + "小步舞曲" + "新闻快讯" + "夜色" + "绿林好汉的旋律" + "神奇魔咒" + "侦探悬念" + "嗖嗖声" + "敲打电报" + "蹑手蹑脚" + "三全音" + "鸟鸣声" + "敲打字机" + "整点新闻" "要接收通知,请更改 %1$s。" "系统设置" "系统通知已关闭" diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index a431139fd6..7389a0433c 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -80,6 +80,40 @@ If you proceed, some of your settings may change." "Mentions" "Notify me for" "Notify me on @room" + "Custom sound…" + "Error deleting file" + "Element Default" + "Element Fade" + "Error importing file" + "Problem previewing alert sound" + "Sound" + "Problem setting alert sound" + "Alert" + "Anticipate" + "Bell" + "Bloom" + "Calypso" + "Chime" + "Choo Choo" + "Descent" + "Electronic" + "Fanfare" + "Glass" + "Horn" + "Ladder" + "Minuet" + "News Flash" + "Noir" + "Sherwood Forest" + "Spell" + "Suspense" + "Swish" + "Telegraph" + "Tiptoes" + "Tri-tone" + "Tweet" + "Typewriters" + "Update" "To receive notifications, please change your %1$s." "system settings" "System notifications turned off" diff --git a/features/rageshake/api/src/main/res/values-ca/translations.xml b/features/rageshake/api/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..b5907369e6 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "%1$s ha fallat l\'últim cop que es va utilitzar. Vols enviar un informe d\'errors?" + "Sembla que sacseges el telèfon amb frustració. Vols obrir la pantalla d\'informe d\'errors?" + "La sacsejada de frustració és quan mous i sacseges el mòbil per informar d\'un error. L\'aplicació ja no és compatible amb aquesta funcionalitat però el nom encara s\'utilitza per raons històriques." + "Llindar de detecció" + diff --git a/features/rageshake/impl/src/main/res/values-ca/translations.xml b/features/rageshake/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..6586cd9dc2 --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,17 @@ + + + "Adjunta captura de pantalla" + "Pots contactar amb mi si tens comentaris addicionals." + "Contacta\'m" + "Edita captura de pantalla" + "Descriu el problema. Què has fet? Què esperaves que passés? Què va has passat realment? Si us plau, explica-ho el més detalladament possible." + "Descriu el problema…" + "Si és possible, escriu la descripció en anglès." + "Descripció massa curta. Si us plau, proporciona més detalls sobre què ha passat. Gràcies!" + "Envia registre de fallada" + "Permet registres" + "Envia captura de pantalla" + "Els registres s\'inclouran amb el missatge per intentar resoldre el problema correctament. Per enviar el missatge sense registres, desactiva aquesta opció." + "%1$s ha fallat l\'últim cop que es va utilitzar. Vols enviar un informe d\'errors?" + "Veure registres" + diff --git a/features/reportroom/impl/src/main/res/values-ca/translations.xml b/features/reportroom/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..05ca5c0fc0 --- /dev/null +++ b/features/reportroom/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,6 @@ + + + "Denuncia aquesta sala al teu administrador. Si els missatges estan xifrats, l\'administrador no els podrà llegir." + "Descriu el motiu de la denúncia…" + "Denuncia sala" + diff --git a/features/rolesandpermissions/impl/src/main/res/values-ca/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..eccea6f2df --- /dev/null +++ b/features/rolesandpermissions/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,61 @@ + + + "Només administradors" + "Bandejar usuaris" + "Eliminar missatges" + "Membre" + "Convidar persones i acceptar sol·licituds d\'unió" + "Gestiona membres" + "Missatges i contingut" + "Administradors i moderadors" + "Eliminar persones i rebutjar sol·licituds d\'unió" + "Canvia la foto de la sala" + "Edita detalls" + "Canvia el nom de la sala" + "Canvia el tema de la sala" + "Enviar missatges" + "Edita administradors" + "No podràs desfer aquesta acció. Estàs concedint a l\'usuari el mateix nivell de poder que tu." + "Afegir com a administrador?" + "Descendeix" + "No podràs desfer aquest canvi ja que t\'estàs descendint de rang, si ets l\'últim usuari de la sala amb privilegis, no podràs recuperar-los." + "Vols descendir de categoria?" + "%1$s (pendent)" + "(pendent)" + "Els administradors tenen automàticament privilegis de moderador" + "Edita moderadors" + "Administradors" + "Moderadors" + "Membres" + "Hi ha canvis sense desar." + "Desar canvis?" + "No hi ha usuaris bandejats en aquesta sala." + + "%1$d persona" + "%1$d persones" + + "Bandeja de la sala" + "Només elimina\'l" + "Desbandeja" + "Podran tornar a unir-se a aquesta sala si se\'ls convida." + "Readmet usuari" + "Bandejats" + "Membres" + "Només administradors" + "Administradors i moderadors" + "Membres de la sala" + "Readmetent %1$s" + "Administradors" + "Canvia el meu rol" + "Descendeix a membre" + "Descendeix a moderador" + "Moderació de membres" + "Missatges i contingut" + "Moderadors" + "Restableix permisos" + "Si restableixes els permisos, perdràs la configuració actual." + "Restablir permisos?" + "Rols" + "Detalls de sala" + "Rols i permisos" + diff --git a/features/rolesandpermissions/impl/src/main/res/values-fi/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-fi/translations.xml index 7c5d635b14..fdc1c17f22 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-fi/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-fi/translations.xml @@ -6,6 +6,7 @@ "Viestien poistaminen" "Jäsen" "Kutsujen antaminen" + "Jaa reaaliaikainen sijainti" "Tilan hallitseminen" "Huoneiden hallitseminen" "Jäsenien hallitseminen" diff --git a/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml index c9410e9e3c..28e1a9db89 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-ja/translations.xml @@ -6,6 +6,7 @@ "メッセージの削除" "メンバー" "ユーザーの招待" + "ライブ位置情報を共有" "スペースの管理" "ルームを管理" "メンバーの管理" diff --git a/features/rolesandpermissions/impl/src/main/res/values-ru/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-ru/translations.xml index 2b7fca0254..425da3e2ce 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-ru/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-ru/translations.xml @@ -6,6 +6,7 @@ "Удалять сообщения" "Участники" "Приглашать людей" + "Поделиться текущим местоположением" "Управление пространством" "Управление комнатами" "Управлять участниками" diff --git a/features/roomaliasresolver/impl/src/main/res/values-ca/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..ea90cabc34 --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,5 @@ + + + "No s\'ha pogut mostrar la vista prèvia de la sala" + "No s\'ha pogut obtenir l\'àlies de sala." + diff --git a/features/roomdetails/impl/src/main/res/values-be/translations.xml b/features/roomdetails/impl/src/main/res/values-be/translations.xml index 5bd33fef17..69c5be0021 100644 --- a/features/roomdetails/impl/src/main/res/values-be/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-be/translations.xml @@ -100,4 +100,6 @@ "Ролі" "Дэталі пакоя" "Ролі і дазволы" + "Пазначыць як прачытанае" + "Пазначыць як непрачытанае" diff --git a/features/roomdetails/impl/src/main/res/values-bg/translations.xml b/features/roomdetails/impl/src/main/res/values-bg/translations.xml index 2c797cb74e..7369d78f1d 100644 --- a/features/roomdetails/impl/src/main/res/values-bg/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-bg/translations.xml @@ -79,6 +79,8 @@ "Роли" "Подробности за стаята" "Роли и разрешения" + "Отбелязване като прочетено" + "Отбелязване като непрочетено" "Добавяне на адрес" "Да, включване на шифроването" "Да се включи ли шифроването?" diff --git a/features/roomdetails/impl/src/main/res/values-ca/translations.xml b/features/roomdetails/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..8b9f8d937e --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,141 @@ + + + "És necessària una adreça perquè sigui visible al directori públic." + "Edita adreça" + "S\'ha produït un error en actualitzar la configuració de notificacions." + "El servidor no admet aquesta opció en sales xifrades, és possible que no rebis notificacions en algunes sales." + "Votacions" + "Només administradors" + "Bandejar usuaris" + "Eliminar missatges" + "Membre" + "Convidar persones i acceptar sol·licituds d\'unió" + "Gestiona membres" + "Missatges i contingut" + "Administradors i moderadors" + "Eliminar persones i rebutjar sol·licituds d\'unió" + "Canvia la foto de la sala" + "Edita detalls" + "Canvia el nom de la sala" + "Canvia el tema de la sala" + "Enviar missatges" + "Edita administradors" + "No podràs desfer aquesta acció. Estàs concedint a l\'usuari el mateix nivell de poder que tu." + "Afegir com a administrador?" + "Descendeix" + "No podràs desfer aquest canvi ja que t\'estàs descendint de rang, si ets l\'últim usuari de la sala amb privilegis, no podràs recuperar-los." + "Vols descendir de categoria?" + "%1$s (pendent)" + "(pendent)" + "Els administradors tenen automàticament privilegis de moderador" + "Edita moderadors" + "Administradors" + "Moderadors" + "Membres" + "Hi ha canvis sense desar." + "Desar canvis?" + "Afegeix tema" + "Xifrada" + "No xifrada" + "Sala pública" + "Edita detalls" + "Un error desconegut ha impedit l\'intercanvi d\'informació." + "No s\'ha pogut actualitzar la sala" + "Els missatges estan protegits amb cadenats. Només tu i els destinataris teniu les úniques claus per a desbloquejar-los." + "Xifrat de missatges activat" + "S\'ha produït un error en carregar la configuració de notificacions." + "No s\'ha pogut silenciar la sala. Torna-ho a intentar." + "No s\'ha pogut deixar de silenciar la sala. Torna-ho a provar." + "Convida persones" + "Convida" + "Surt del xat" + "Surt de la sala" + "Multimèdia i documents" + "Personalitzat" + "Predeterminat" + "Notificacions" + "Missatges fixats" + "Perfil" + "Sol·licituds d\'unió" + "Rols i permisos" + "Seguretat i privadesa" + "Seguretat" + "Comparteix sala" + "Informació de sala" + "Tema" + "Actualitzant sala…" + "No hi ha usuaris bandejats en aquesta sala." + + "%1$d persona" + "%1$d persones" + + "Bandeja de la sala" + "Només elimina\'l" + "Desbandeja" + "Podran tornar a unir-se a aquesta sala si se\'ls convida." + "Readmet usuari" + "Bandejats" + "Membres" + "Només administradors" + "Administradors i moderadors" + "Membres de la sala" + "Readmetent %1$s" + "Permet la configuració personalitzada" + "Si ho actives, se substituirà la configuració predeterminada" + "Notifica\'m en aquest xat" + "Ho pots canviar al la %1$s." + "configuració global" + "Configuració predeterminada" + "Elimina la configuració personalitzada" + "S\'ha produït un error en carregar la configuració de notificacions." + "No s\'ha pogut restaurar el mode predeterminat. Torna-ho a provar." + "No s\'ha pogut configurar el mode. Torna-ho a provar." + "El servidor no admet aquesta opció en sales xifrades, no rebras notificacions en aquesta sala." + "Tots els missatges" + "Mencions y paraules clau (només)" + "En aquesta sala, notifica\'m en" + "Administradors" + "Canvia el meu rol" + "Descendeix a membre" + "Descendeix a moderador" + "Moderació de membres" + "Missatges i contingut" + "Moderadors" + "Restableix permisos" + "Si restableixes els permisos, perdràs la configuració actual." + "Restablir permisos?" + "Rols" + "Detalls de sala" + "Rols i permisos" + "Marca com a llegit" + "Marca com a no llegit" + "Afegeix adreça" + "Tothom ha de sol·licitar l\'accés." + "Sol·licita unir-t\'hi" + "Sí, activa el xifrat" + "Un cop activat, el xifrat d\'una sala no es pot desactivar. L\'històric de missatges només serà visible per als membres de la sala des que van ser convidats o des que s\'hi van unir. +Ningú a part dels membres de la sala podrà llegir els missatges. Això pot impedir que els bots i els ponts (\'bridges\') funcionin correctament. +No es recomana activar el xifrat a les sales que tothom pot trobar i unir-se." + "Vols activar el xifrat?" + "Un cop activat, el xifrat no es pot desactivar." + "Xifrat" + "Activa el xifrat d\'extrem a extrem" + "Tothom pot unir-s\'hi." + "Tothom" + "Només s\'hi poden unir les persones convidades." + "Només amb invitació" + "Accés" + "Actualment els espais no són compatibles" + "És necessària una adreça perquè sigui visible al directori públic." + "Adreça" + "Permet trobar aquesta sala cercant %1$s al directori públic de sales" + "Visible al directori públic" + "Tothom (historial públic)" + "Qui pot llegir l\'historial?" + "Membres, des de quan es van convidar" + "Membres (historial complet)" + "Les adreces de sala són maneres de trobar i accedir a les sales. Això també garanteix que puguis compartir fàcilment la teva sala amb altres persones. +Pots optar per publicar la teva sala al directori públic de sales del teu servidor local." + "Visibilitat" + "Seguretat i privadesa" + diff --git a/features/roomdetails/impl/src/main/res/values-cs/translations.xml b/features/roomdetails/impl/src/main/res/values-cs/translations.xml index d47a1c709b..190e1ae5de 100644 --- a/features/roomdetails/impl/src/main/res/values-cs/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cs/translations.xml @@ -135,6 +135,8 @@ "Role" "Podrobnosti místnosti" "Role a oprávnění" + "Označit jako přečtené" + "Označit jako nepřečtené" "Přidat adresu" "Připojit se může kdokoli v autorizovaných prostorách, ale všichni ostatní musí o přístup požádat." "Všichni musí požádat o přístup." diff --git a/features/roomdetails/impl/src/main/res/values-cy/translations.xml b/features/roomdetails/impl/src/main/res/values-cy/translations.xml index b8ec88e51a..f5d4eecac5 100644 --- a/features/roomdetails/impl/src/main/res/values-cy/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cy/translations.xml @@ -120,6 +120,8 @@ "Rolau" "Manylion yr ystafell" "Rolau a chaniatâd" + "Marcio fel wedi\'i ddarllen" + "Marcio fel heb ei ddarllen" "Ychwanegu cyfeiriad ystafell" "Gall unrhyw un ofyn am gael ymuno â\'r ystafell ond bydd rhaid i weinyddwr neu gymedrolwr dderbyn y cais." "Gofyn i gael ymuno" diff --git a/features/roomdetails/impl/src/main/res/values-da/translations.xml b/features/roomdetails/impl/src/main/res/values-da/translations.xml index 9f3b3436f0..191df9f059 100644 --- a/features/roomdetails/impl/src/main/res/values-da/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-da/translations.xml @@ -132,6 +132,8 @@ "Roller" "Detaljer om rummet" "Roller og tilladelser" + "Marker som læst" + "Marker som ulæst" "Tilføj adresse" "Alle i autoriserede klynger kan deltage, men alle andre skal anmode om adgang." "Alle skal anmode om adgang." 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 c1487d7d98..08201fdc34 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -132,6 +132,8 @@ "Rollen" "Chat-Details anpassen" "Rollen und Berechtigungen" + "Als gelesen markieren" + "Als ungelesen markieren" "Chat-Adresse hinzufügen" "Jedes Mitglied eines autorisierten Space kann beitreten, aber alle anderen müssen einen Beitritt anfragen." "Zugang nur auf Anfrage." diff --git a/features/roomdetails/impl/src/main/res/values-el/translations.xml b/features/roomdetails/impl/src/main/res/values-el/translations.xml index c1be20d7f5..5f1a3ce4ab 100644 --- a/features/roomdetails/impl/src/main/res/values-el/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-el/translations.xml @@ -132,6 +132,8 @@ "Ρόλοι" "Λεπτομέρειες αίθουσας" "Ρόλοι και δικαιώματα" + "Επισήμανση ως αναγνωσμένου" + "Επισήμανση ως μη αναγνωσμένου" "Προσθήκη διεύθυνσης" "Οποιοσδήποτε σε εξουσιοδοτημένους χώρους μπορεί να συμμετάσχει, αλλά όλοι οι άλλοι πρέπει να ζητήσουν πρόσβαση." "Όλοι πρέπει να αιτούνται πρόσβαση." diff --git a/features/roomdetails/impl/src/main/res/values-es/translations.xml b/features/roomdetails/impl/src/main/res/values-es/translations.xml index 6b92e48884..9537596d4e 100644 --- a/features/roomdetails/impl/src/main/res/values-es/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-es/translations.xml @@ -107,6 +107,8 @@ "Roles" "Detalles de la sala" "Roles y permisos" + "Marcar como leído" + "Marcar como no leído" "Agregar dirección" "Todos deben solicitar acceso." "Solicitar unirse" diff --git a/features/roomdetails/impl/src/main/res/values-et/translations.xml b/features/roomdetails/impl/src/main/res/values-et/translations.xml index f0c8c58b1f..e6962456ac 100644 --- a/features/roomdetails/impl/src/main/res/values-et/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-et/translations.xml @@ -132,6 +132,8 @@ "Rollid" "Jututoa üksikasjad" "Rollid ja õigused" + "Märgi loetuks" + "Märgi mitteloetuks" "Lisa aadress" "Liituda saavad kõik volitatud kogukondade liikmed, kuid kõik teised peavad küsima võimalust ligipääsuks." "Kõik võivad paluda jututoaga liitumist." diff --git a/features/roomdetails/impl/src/main/res/values-eu/translations.xml b/features/roomdetails/impl/src/main/res/values-eu/translations.xml index f299131852..64f32e44d9 100644 --- a/features/roomdetails/impl/src/main/res/values-eu/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-eu/translations.xml @@ -100,6 +100,8 @@ "Rolak" "Gelaren xehetasunak" "Rolak eta baimenak" + "Markatu irakurritzat" + "Markatu irakurri gabetzat" "Gehitu gelaren helbidea" "Bai, gaitu zifratzea" "Zifratzea" diff --git a/features/roomdetails/impl/src/main/res/values-fa/translations.xml b/features/roomdetails/impl/src/main/res/values-fa/translations.xml index bb7cb490b8..af0cbbe29b 100644 --- a/features/roomdetails/impl/src/main/res/values-fa/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fa/translations.xml @@ -113,6 +113,8 @@ "نقش‌ها" "جزییات اتاق" "نقش‌ها و مجوزها" + "علامت‌گذاری به عنوان خوانده شده" + "نشان به ناخوانده" "افزودن نشانی اتاق" "درخواست دعوت" "بله. به کار انداختن رمزنگاری" diff --git a/features/roomdetails/impl/src/main/res/values-fi/translations.xml b/features/roomdetails/impl/src/main/res/values-fi/translations.xml index 0d07ff4eae..4eafca087e 100644 --- a/features/roomdetails/impl/src/main/res/values-fi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fi/translations.xml @@ -132,6 +132,8 @@ "Roolit" "Huoneen tiedot" "Roolit ja oikeudet" + "Merkitse luetuksi" + "Merkitse lukemattomaksi" "Lisää osoite" "Kuka tahansa valtuutetuissa tiloissa voi liittyä, mutta kaikkien muiden on pyydettävä pääsyä." "Kaikkien on pyydettävä pääsyä." diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 3d4283145c..0d6844cb7e 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -132,6 +132,8 @@ "Rôles" "Détails du salon" "Rôles & autorisations" + "Marquer comme lu" + "Marquer comme non lu" "Ajouter une adresse" "Toute personne se trouvant dans un espace autorisé peut participer, mais toutes les autres doivent demander l’accès." "Tout le monde doit demander un accès." 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 73b6866249..5619164dd2 100644 --- a/features/roomdetails/impl/src/main/res/values-hr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hr/translations.xml @@ -135,6 +135,8 @@ "Uloge" "Pojedinosti o sobi" "Uloge i dopuštenja" + "Označi kao pročitano" + "Označi kao nepročitano" "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." diff --git a/features/roomdetails/impl/src/main/res/values-hu/translations.xml b/features/roomdetails/impl/src/main/res/values-hu/translations.xml index 937c91b68d..fed765fb45 100644 --- a/features/roomdetails/impl/src/main/res/values-hu/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hu/translations.xml @@ -132,6 +132,8 @@ "Szerepkörök" "Szoba részletei" "Szerepkörök és jogosultságok" + "Megjelölés olvasottként" + "Megjelölés olvasatlanként" "Cím hozzáadása" "Bárki csatlakozhat, az engedélyezett terekből, és mindenki másnak hozzáférést kell kérnie." "Mindenkinek hozzáférést kell kérnie." diff --git a/features/roomdetails/impl/src/main/res/values-in/translations.xml b/features/roomdetails/impl/src/main/res/values-in/translations.xml index 2cce124321..d7403329c4 100644 --- a/features/roomdetails/impl/src/main/res/values-in/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-in/translations.xml @@ -115,6 +115,8 @@ "Peran" "Detail ruangan" "Peran dan perizinan" + "Tandai sebagai dibaca" + "Tandai sebagai belum dibaca" "Tambahkan alamat" "Meminta hak akses pada administrator atau moderator." "Ijin bergabung" diff --git a/features/roomdetails/impl/src/main/res/values-it/translations.xml b/features/roomdetails/impl/src/main/res/values-it/translations.xml index 044721c345..b8a18d4421 100644 --- a/features/roomdetails/impl/src/main/res/values-it/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-it/translations.xml @@ -132,6 +132,8 @@ "Ruoli" "Dettagli della stanza" "Ruoli e autorizzazioni" + "Segna come letto" + "Segna come non letto" "Aggiungi indirizzo" "Chiunque si trovi in spazi autorizzati può partecipare, ma tutti gli altri devono richiedere l\'accesso." "Chiunque deve richiedere l\'accesso." diff --git a/features/roomdetails/impl/src/main/res/values-ja/translations.xml b/features/roomdetails/impl/src/main/res/values-ja/translations.xml index b6c7608793..5a65f1a404 100644 --- a/features/roomdetails/impl/src/main/res/values-ja/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ja/translations.xml @@ -129,6 +129,8 @@ "役割" "ルームの詳細" "役割と権限" + "既読にする" + "未読にする" "アドレスを追加" "認証済みのスペースに所属するユーザーのみが参加できます。それ以外のユーザーは参加へのリクエストが必要です。" "参加のリクエストが必須です。" diff --git a/features/roomdetails/impl/src/main/res/values-ka/translations.xml b/features/roomdetails/impl/src/main/res/values-ka/translations.xml index 317f62313d..8fd0b2c8a6 100644 --- a/features/roomdetails/impl/src/main/res/values-ka/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ka/translations.xml @@ -94,4 +94,6 @@ "როლები" "ოთახის დეტალები" "როლები და ნებართვები" + "წაკითხულად მონიშვნა" + "წაუკითხავად მონიშვნა" diff --git a/features/roomdetails/impl/src/main/res/values-ko/translations.xml b/features/roomdetails/impl/src/main/res/values-ko/translations.xml index 8c0db6eefd..4a32cab45d 100644 --- a/features/roomdetails/impl/src/main/res/values-ko/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ko/translations.xml @@ -129,6 +129,8 @@ "역할" "방 세부 정보" "역할 및 권한" + "읽음으로 표시" + "읽지 않음으로 표시" "주소 추가" "승인된 스페이스의 멤버는 누구나 참여할 수 있지만, 그 외의 인원은 액세스 요청을 해야 합니다." "모든 사용자가 액세스 권한을 요청해야 합니다." diff --git a/features/roomdetails/impl/src/main/res/values-nb/translations.xml b/features/roomdetails/impl/src/main/res/values-nb/translations.xml index 52ea87bc3d..0cb3dfc268 100644 --- a/features/roomdetails/impl/src/main/res/values-nb/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nb/translations.xml @@ -132,6 +132,8 @@ "Roller" "Romdetaljer" "Roller og tillatelser" + "Marker som lest" + "Merk som ulest" "Legg til adresse" "Alle i autoriserte områder kan bli med, men alle andre må be om tilgang." "Alle må be om tilgang." diff --git a/features/roomdetails/impl/src/main/res/values-nl/translations.xml b/features/roomdetails/impl/src/main/res/values-nl/translations.xml index e9f03d3a57..2ee5caca97 100644 --- a/features/roomdetails/impl/src/main/res/values-nl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nl/translations.xml @@ -100,4 +100,6 @@ "Rollen" "Kamergegevens" "Rollen en rechten" + "Markeren als gelezen" + "Markeren als ongelezen" diff --git a/features/roomdetails/impl/src/main/res/values-pl/translations.xml b/features/roomdetails/impl/src/main/res/values-pl/translations.xml index ccc359ed25..2979fcacdf 100644 --- a/features/roomdetails/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pl/translations.xml @@ -135,6 +135,8 @@ "Role" "Szczegóły pokoju" "Role i uprawnienia" + "Oznacz jako przeczytane" + "Oznacz jako nieprzeczytane" "Dodaj adres" "Każdy w autoryzowanych przestrzeniach może dołączyć, ale wszyscy inni muszą poprosić o dostęp." "Każdy musi poprosić o dostęp." diff --git a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml index da98e7bd5a..f2ddfb86cb 100644 --- a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml @@ -129,6 +129,8 @@ "Cargos" "Detalhes da sala" "Cargos e permissões" + "Marcar como lida" + "Marcar como não lida" "Adicionar endereço" "Qualquer um nos espaços autorizados podem entrar, mas todos os outros devem pedir acesso." "Qualquer um pode pedir acesso, mas um administrador terá que aceitar o pedido." diff --git a/features/roomdetails/impl/src/main/res/values-pt/translations.xml b/features/roomdetails/impl/src/main/res/values-pt/translations.xml index c5a9be9a4c..04ded84480 100644 --- a/features/roomdetails/impl/src/main/res/values-pt/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt/translations.xml @@ -128,6 +128,8 @@ "Cargos" "Detalhes da sala" "Cargos e permissões" + "Marcar como lida" + "Marcar como não lida" "Adicionar endereço" "Todos precisam de pedir acesso." "Pedir para entrar" diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml index 425e35a23c..f3feda811a 100644 --- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml @@ -135,6 +135,8 @@ "Roluri" "Detaliile camerei" "Roluri și permisiuni" + "Marcați ca citită" + "Marcați ca necitită" "Adăugați o adresă" "Oricine se află în spațiile autorizate se poate alătura, dar toți ceilalți trebuie să solicite accesul." "Toată lumea trebuie să solicite acces." diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index bd683009ad..bb36b3b23b 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -135,6 +135,8 @@ "Роли" "Информация о комнате" "Роли и разрешения" + "Пометить как прочитанное" + "Отметить как непрочитанное" "Добавить адрес" "Кто угодно из авторизованных пространств может присоединиться, а всем остальным необходимо запросить доступ." "Каждый должен запросить доступ." diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 6a27e375ee..122c27e058 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -132,6 +132,8 @@ "Roly" "Podrobnosti o miestnosti" "Roly a povolenia" + "Označiť ako prečítané" + "Označiť ako neprečítané" "Pridať adresu" "Pripojiť sa môže ktokoľvek z autorizovaných priestorov, ale všetci ostatní musia o prístup požiadať." "Všetci musia požiadať o prístup." diff --git a/features/roomdetails/impl/src/main/res/values-sv/translations.xml b/features/roomdetails/impl/src/main/res/values-sv/translations.xml index 02574e77e9..aa9f244498 100644 --- a/features/roomdetails/impl/src/main/res/values-sv/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sv/translations.xml @@ -116,6 +116,8 @@ "Roller" "Rumsdetaljer" "Roller och behörigheter" + "Markera som läst" + "Markera som oläst" "Lägg till adress" "Alla måste begära åtkomst." "Be om att gå med" diff --git a/features/roomdetails/impl/src/main/res/values-tr/translations.xml b/features/roomdetails/impl/src/main/res/values-tr/translations.xml index 8d11b8035a..a9bfc6fbe2 100644 --- a/features/roomdetails/impl/src/main/res/values-tr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-tr/translations.xml @@ -113,6 +113,8 @@ "Roller" "Oda bilgileri" "Roller ve izinler" + "Okundu olarak işaretle" + "Okunmamış olarak işaretle" "Oda adresi ekle" "Yetkilendirilmiş alanlardaki herkes katılabilir, diğer herkes erişim talep etmelidir." "Herkes odaya katılma isteğinde bulunabilir ancak bir yönetici veya moderatörün isteği kabul etmesi gerekir." diff --git a/features/roomdetails/impl/src/main/res/values-uk/translations.xml b/features/roomdetails/impl/src/main/res/values-uk/translations.xml index 1565e0ec48..8f566bb235 100644 --- a/features/roomdetails/impl/src/main/res/values-uk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uk/translations.xml @@ -135,6 +135,8 @@ "Ролі" "Деталі кімнати" "Ролі та дозволи" + "Позначити прочитаним" + "Позначити непрочитаним" "Додати адресу" "Будь-хто в авторизованих просторах може приєднатися, але всі інші повинні подати запит на доступ." "Усі повинні запитувати доступ." diff --git a/features/roomdetails/impl/src/main/res/values-ur/translations.xml b/features/roomdetails/impl/src/main/res/values-ur/translations.xml index d5ab09dd18..5c32811f36 100644 --- a/features/roomdetails/impl/src/main/res/values-ur/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ur/translations.xml @@ -99,4 +99,6 @@ "کردارہا" "کمرے کی تفصیلات" "کردارہا اور اجازتیں" + "بطور مقروءہ نشانزد کریں" + "بطور غیر مقروءہ نشانزد کریں" 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 fa9408b3ba..d7778f2df4 100644 --- a/features/roomdetails/impl/src/main/res/values-uz/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uz/translations.xml @@ -132,6 +132,8 @@ "Rollar" "Xona tafsilotlari" "Rollar va ruxsatlar" + "Oʻqilgan deb belgilash" + "Oʻqilmagan deb belgilash" "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" 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 5e25014c88..ecc7e4e227 100644 --- a/features/roomdetails/impl/src/main/res/values-vi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-vi/translations.xml @@ -106,6 +106,8 @@ "Vai trò" "Chi tiết phòng" "Vai trò và quyền hạn" + "Đánh dấu đã đọc" + "Đánh dấu chưa đọc" "Sau khi được kích hoạt, mã hóa cho một phòng chat không thể tắt được. Lịch sử tin nhắn chỉ hiển thị cho các thành viên phòng chat kể từ khi họ được mời hoặc kể từ khi họ tham gia phòng chat. Không ai ngoài các thành viên phòng chat có thể đọc tin nhắn. Điều này có thể ngăn chặn bot và các thiết bị kết nối hoạt động đúng cách. Chúng tôi không khuyến khích bật mã hóa cho các phòng chat mà bất kỳ ai cũng có thể tìm thấy và tham gia." 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 04ccc56adb..0e516d0c29 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 @@ -129,6 +129,8 @@ "身份" "聊天室資訊" "角色與權限" + "標為已讀" + "標為未讀" "新增地址" "任何在授權空間的人都可以加入,但其他人都必須提出申請。" "所有人都必須申請存取權。" diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index 1fef5583a3..8a5c5734ed 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -129,6 +129,8 @@ "角色" "房间详细信息" "角色与权限" + "设为已读" + "设为未读" "添加地址" "已授权空间内的任何成员都可以加入,其他人必须申请访问。" "所有用户均需申请访问权限。" diff --git a/features/roomdetailsedit/impl/src/main/res/values-ca/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..8be6967ace --- /dev/null +++ b/features/roomdetailsedit/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "Edita detalls" + "Un error desconegut ha impedit l\'intercanvi d\'informació." + "No s\'ha pogut actualitzar la sala" + "Actualitzant sala…" + diff --git a/features/roomdirectory/impl/src/main/res/values-ca/translations.xml b/features/roomdirectory/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..fc664290c1 --- /dev/null +++ b/features/roomdirectory/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,5 @@ + + + "No s\'ha pogut carregar" + "Directori de sales" + diff --git a/features/roommembermoderation/impl/src/main/res/values-ca/translations.xml b/features/roommembermoderation/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..9495112c4e --- /dev/null +++ b/features/roommembermoderation/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,20 @@ + + + "Bandeja de la sala" + "Bandeja" + "No podrà tornar a unir-se a aquesta sala encara que se\'l convidi." + "Segur que vols bandejar aquest membre?" + "Bandejant %1$s" + "Elimina" + "Podran tornar a unir-se a aquesta sala si se\'ls convida." + "Segur que vols eliminar aquest membre?" + "Veure perfil" + "Elimina de la sala" + "Vols eliminar l\'usuari i prohibir-li l\'accés en el futur?" + "Eliminant %1$s…" + "Readmet usuari" + "Desbandeja" + "Podrà tornar a unir-se a través d\'una invitació" + "Segur que vols readmetre aquest membre?" + "Readmetent %1$s" + diff --git a/features/securebackup/impl/src/main/res/values-ca/translations.xml b/features/securebackup/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..0ca99788ed --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,69 @@ + + + "Elimina l\'emmagatzematge de claus" + "Activa còpia de seguretat" + "Emmagatzema la teva identitat criptogràfica i les claus de missatge de forma segura al servidor. Això et permetrà veure l\'historial de missatges en qualsevol dispositiu nou. %1$s." + "Emmagatzematge de claus" + "L\'emmagatzematge de claus ha d\'estar activat per poder configurar la recuperació." + "Puja claus des d\'aquest dispositiu" + "Permet l\'emmagatzematge de claus" + "Canvia la clau de recuperació" + "Recupera la teva identitat criptogràfica i l\'historial de missatges amb una clau de recuperació si has perdut tots els teus dispositius existents." + "Introdueix clau de recuperació" + "L\'emmagatzematge de claus no està sincronitzat." + "Configura la recuperació" + "Obre %1$s a un dispositiu d\'escriptori" + "Torna a iniciar sessió" + "Quan se\'t demani verificar el dispositiu, selecciona %1$s" + "“Restableix-ho tot”" + "Segueix les instruccions per crear una nova clau de recuperació" + "Desa la nova clau de recuperació en un gestor de contrasenyes o en una nota xifrada" + "Restableix el xifrat del teu compte mitjançant un altre dispositiu" + "Continua el restabliment" + "Es conservaran les dades del compte, contactes, preferències i les llistes de xats." + "Perdràs tots els missatges que estiguin desats únicament al servidor." + "Hauràs de tornar a verificar tots els teus dispositius i contactes existents." + "Només restableix la teva identitat si no tens accés a cap altre dispositiu on tinguis la sessió iniciada i has perdut la clau de recuperació." + "Si no pots confirmar la teva identitat, hauràs de restablir-la." + "Desactiva" + "Perdràs els missatges xifrats si tanques sessió en tots els dispositius." + "Segur que vols desactivar la còpia de seguretat?" + "Si elimines l\'emmagatzematge de claus, s\'eliminarà la teva identitat criptogràfica i les claus de missatge del servidor i es desactivaran les funcions de seguretat següents:" + "No tindràs l\'historial de missatges xifrats als dispositius nous" + "Perdràs l\'accés als teus missatges xifrats si tanques la sessió d\'%1$s a tot arreu" + "Estàs segur que vols desactivar l\'emmagatzematge de claus i eliminar-lo?" + "Obté una nova clau de recuperació si has perdut la que tens. Després de canviar la clau de recuperació, l\'antiga deixarà de funcionar." + "Genera una nova clau de recuperació" + "No ho comparteixis amb ningú!" + "Clau de recuperació canviada" + "Vols canviar la clau de recuperació?" + "Crea nova clau de recuperació" + "Assegura\'t que ningú vegi aquesta pantalla!" + "Torna a provar l\'accés a l\'emmagatzematge de claus." + "Clau de recuperació incorrecta" + "Si tens una clau de seguretat o una frase de seguretat, també funcionaran." + "Introdueix…" + "Has perdut la clau de recuperació?" + "Clau de recuperació confirmada" + "Introdueix clau de recuperació" + "Clau de recuperació copiada" + "Generant…" + "Desa clau de recuperació" + "Anota aquesta clau de recuperació en un lloc segur, com ara un gestor de contrasenyes, una nota xifrada o una caixa forta física." + "Toca per copiar la clau de recuperació" + "Desa la clau de recuperació en un lloc segur" + "Després d\'aquest pas, no podràs accedir a la nova clau de recuperació." + "Has desat la clau de recuperació?" + "L\'emmagatzematge de claus està protegit amb una clau de recuperació. Si necessites una nova clau de recuperació després d\'haver establerta, pots tornar-la a crear seleccionant ‘Canvia clau de recuperació’." + "Genera clau de recuperació" + "No ho comparteixis amb ningú!" + "Configuració de recuperació correcta" + "Configura la recuperació" + "Sí, restableix ara" + "Aquest procés és irreversible." + "Segur que vols restablir la teva identitat?" + "S\'ha produït un error desconegut. Comprova la contrasenya del compte i torna-ho a provar." + "Introdueix…" + "Confirma que vols restablir la teva identitat." + "Introdueix la contrasenya del compte per continuar" + diff --git a/features/securityandprivacy/impl/src/main/res/values-ca/translations.xml b/features/securityandprivacy/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..4d541af9d1 --- /dev/null +++ b/features/securityandprivacy/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,34 @@ + + + "És necessària una adreça perquè sigui visible al directori públic." + "Edita adreça" + "Afegeix adreça" + "Tothom ha de sol·licitar l\'accés." + "Sol·licita unir-t\'hi" + "Sí, activa el xifrat" + "Un cop activat, el xifrat d\'una sala no es pot desactivar. L\'històric de missatges només serà visible per als membres de la sala des que van ser convidats o des que s\'hi van unir. +Ningú a part dels membres de la sala podrà llegir els missatges. Això pot impedir que els bots i els ponts (\'bridges\') funcionin correctament. +No es recomana activar el xifrat a les sales que tothom pot trobar i unir-se." + "Vols activar el xifrat?" + "Un cop activat, el xifrat no es pot desactivar." + "Xifrat" + "Activa el xifrat d\'extrem a extrem" + "Tothom pot unir-s\'hi." + "Tothom" + "Només s\'hi poden unir les persones convidades." + "Només amb invitació" + "Accés" + "Actualment els espais no són compatibles" + "És necessària una adreça perquè sigui visible al directori públic." + "Adreça" + "Permet trobar aquesta sala cercant %1$s al directori públic de sales" + "Visible al directori públic" + "Tothom (historial públic)" + "Qui pot llegir l\'historial?" + "Membres, des de quan es van convidar" + "Membres (historial complet)" + "Les adreces de sala són maneres de trobar i accedir a les sales. Això també garanteix que puguis compartir fàcilment la teva sala amb altres persones. +Pots optar per publicar la teva sala al directori públic de sales del teu servidor local." + "Visibilitat" + "Seguretat i privadesa" + diff --git a/features/signedout/impl/src/main/res/values-ca/translations.xml b/features/signedout/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..6cba810df9 --- /dev/null +++ b/features/signedout/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,8 @@ + + + "Has canviat la contrasenya en una altra sessió" + "Has eliminat la sessió des d\'una altra sessió" + "L\'administrador del teu servidor t\'ha invalidat l\'accés" + "S\'ha tancat la sessió per algun dels motius enumerats a continuació. Torna a iniciar sessió per continuar utilitzant %s." + "Has tancat sessió" + diff --git a/features/space/impl/src/main/res/values-ca/translations.xml b/features/space/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..66ebf7edc4 --- /dev/null +++ b/features/space/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,5 @@ + + + "Rols i permisos" + "Seguretat i privadesa" + diff --git a/features/space/impl/src/main/res/values-zh/translations.xml b/features/space/impl/src/main/res/values-zh/translations.xml index 784ab4bff4..cbe9d54c32 100644 --- a/features/space/impl/src/main/res/values-zh/translations.xml +++ b/features/space/impl/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ "选择所有者" - "%1$s (管理员)" + "%1$s(管理员)" "离开 %1$d 个房间和空间" diff --git a/features/startchat/impl/src/main/res/values-ca/translations.xml b/features/startchat/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..e249d61582 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,12 @@ + + + "Sala nova" + "Directori de sales" + "S\'ha produït un error en intentar iniciar un xat" + "Uneix-te a una sala mitjançant l\'adreça" + "Adreça invàlida" + "Introdueix…" + "S\'ha trobat una sala coincident" + "Sala no trobada" + "p. ex. #nom-sala:matrix.org" + diff --git a/features/userprofile/shared/src/main/res/values-ca/translations.xml b/features/userprofile/shared/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..bacb920a58 --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-ca/translations.xml @@ -0,0 +1,19 @@ + + + "Bloqueja" + "Els usuaris bloquejats no podran enviar-te missatges i tots els seus missatges s\'amagaran. Pots desbloquejar-los en qualsevol moment." + "Bloqueja usuari" + "Desbloqueja" + "Podràs tornar a veure tots els seus missatges." + "Desbloqueja usuari" + "Bloqueja" + "Els usuaris bloquejats no podran enviar-te missatges i tots els seus missatges s\'amagaran. Pots desbloquejar-los en qualsevol moment." + "Bloqueja usuari" + "Perfil" + "Desbloqueja" + "Podràs tornar a veure tots els seus missatges." + "Desbloqueja usuari" + "Utilitza l\'aplicació web per verificar aquest usuari." + "Verifica %1$s" + "S\'ha produït un error en intentar iniciar un xat" + diff --git a/features/verifysession/impl/src/main/res/values-ca/translations.xml b/features/verifysession/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..d5ca8fb167 --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,54 @@ + + + "No pots confirmar-la?" + "Crea nova clau de recuperació" + "Verifica aquest dispositiu per configurar missatges segurs." + "Confirma la teva identitat" + "Utilitza un altre dispositiu" + "Utilitza clau de recuperació" + "Ara pots llegir o enviar missatges de manera segura, i qualsevol persona amb qui xategis també confiarà en aquest dispositiu." + "Dispositiu verificat" + "Utilitza un altre dispositiu" + "Esperant un altre dispositiu…" + "Alguna cosa no ha anat bé. O bé s\'ha superat el temps màxim d\'espera de la sol·licitud o bé s\'ha denegat." + "Verifica que les emoticones següents coincideixen amb les que es mostren a l\'altre dispositiu." + "Compara emoticones" + "Verifica que les emoticones següents coincideixen amb les que es mostren al dispositiu de l\'altre usuari." + "Comprova que els números següents coincideixen amb els mostrats a l\'altra sessió." + "Compara números" + "Ara ja pots enviar i llegir missatges de manera segura al teu altre dispositiu." + "Ara pots confiar en la identitat d\'aquest usuari quan enviïs o rebis missatges." + "Dispositiu verificat" + "Introdueix clau de recuperació" + "S\'ha esgotat el temps d\'espera de la sol·licitud, s\'ha denegat la sol·licitud o ha fallat la verificació." + "Demostra que ets tu per poder accedir a l\'historial de missatges xifrats." + "Obre una sessió existent" + "Torna a intentar verificació" + "Estic a punt" + "Esperant a que coincideixin…" + "Compara un conjunt únic d\'emoticones." + "Compara les emoticones i assegura\'t que apareixen en el mateix ordre." + "Sessió iniciada" + "S\'ha esgotat el temps d\'espera de la sol·licitud, s\'ha denegat la sol·licitud o ha fallat la verificació." + "Error de verificació" + "Només continua si tu has iniciat aquesta verificació." + "Verifica l\'altre dispositiu per mantenir segur l\'historial de missatges." + "Ara ja pots enviar i llegir missatges de manera segura al teu altre dispositiu." + "Dispositiu verificat" + "Verificació sol·licitada" + "No coincideixen" + "Coincideixen" + "Assegura\'t que tens l\'aplicació oberta a l\'altre dispositiu abans d\'inicar la verificació des d\'aquí." + "Obre l\'aplicació en un altre dispositiu verificat" + "Per a més seguretat, verifica aquest usuari comparant un conjunt d\'emoticones vostres dispositius. Fes-ho a través d\'un mitjà de comunicació fiable, o en persona." + "Vols verificar aquest usuari?" + "Per a més seguretat, un altre usuari vol verificar la teva identitat. Se\'t mostrarà un conjunt d\'emoticones a comparar." + "Hauries de veure una finestra emergent a l\'altre dispositiu. Inicia, ara, la verificació des d\'allà." + "Inicia la verificació a l\'altre dispositiu" + "Inicia la verificació a l\'altre dispositiu" + "Esperant a l\'altre usuari" + "Un cop acceptat, podràs continuar amb la verificació." + "Per continuar, accepta la sol·licitud per iniciar el procés de verificació a l\'altra sessió." + "Esperant que s\'accepti la sol·licitud" + "S\'està tancant la sessió…" + diff --git a/libraries/androidutils/src/main/res/values-ca/translations.xml b/libraries/androidutils/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..aba099db1f --- /dev/null +++ b/libraries/androidutils/src/main/res/values-ca/translations.xml @@ -0,0 +1,4 @@ + + + "No s\'ha trobat cap aplicació compatible per gestionar aquesta acció." + diff --git a/libraries/dateformatter/impl/src/main/res/values-ca/translations.xml b/libraries/dateformatter/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..491793c728 --- /dev/null +++ b/libraries/dateformatter/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,5 @@ + + + "%1$s a les %2$s" + "Aquest mes" + diff --git a/libraries/eventformatter/impl/src/main/res/values-ca/translations.xml b/libraries/eventformatter/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..2caa14e8a3 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,73 @@ + + + "(la foto també ha canviat)" + "%1$s ha canviat la seva foto" + "Has canviat la teva foto" + "%1$s ha baixat a membre" + "%1$s ha baixat a moderador/a" + "%1$s han canviat el seu nom de visualització de %2$s a %3$s" + "Has canviat el teu nom de visualització de %1$s a %2$s" + "%1$s ha eliminat el seu nom de visualització (era %2$s)" + "Has eliminat el teu nom de visualització (era %1$s)" + "%1$s ha definit el seu nom de visualització a %2$s" + "Has definit el teu nom de visualització a %1$s" + "%1$s ha ascendit a administrador/a" + "%1$s ha ascendit a moderador/a" + "%1$s ha canviat la foto de la sala" + "Has canviat la foto de la sala" + "%1$s ha eliminat la foto de la sala" + "Has eliminat la foto de la sala" + "%1$s ha bandejat %2$s" + "Has bandejat %1$s" + "Has bandejat %1$s: %2$s" + "%1$s ha bandejat %2$s: %3$s" + "%1$s ha creat la sala" + "Has creat la sala" + "%1$s a convidat a %2$s" + "%1$s ha acceptat la invitació" + "Has acceptat la invitació" + "Has convidat a %1$s" + "%1$s t\'ha convidat" + "%1$s s\'ha unit a la sala" + "T\'has unit a la sala" + "%1$s ha sol·licitat unir-se" + "%1$s ha concedit l\'accés a %2$s" + "Has permès %1$s unir-se" + "Has sol·licitat unir-te" + "%1$s ha rebutjat la sol·licitud d\'unió a %2$s" + "Has rebutjat la sol·licitud d\'unió a %1$s" + "%1$s ha rebutjat la teva sol·licitud d\'unió" + "%1$s ja no es vol unir" + "Has cancel·lat la sol·licitud per unir-te" + "%1$s ha sortit de la sala" + "Has sortit de la sala" + "%1$s ha canviat el nom de la sala a: %2$s" + "Has canviat el nom de la sala a: %1$s" + "%1$s ha eliminat el nom de la sala" + "Has eliminat el nom de la sala" + "%1$s no ha fet canvis" + "No s\'han fet canvis" + "%1$s ha canviat els missatges fixats" + "Has canviat els missatges fixats" + "%1$s ha fixat un missatge" + "Has fixat un missatge" + "%1$s ha deixat de fixar un missatge" + "Has deixat de fixar un missatge" + "%1$s ha rebutjat la invitació" + "Has rebutjat la invitació" + "%1$s ha eliminat %2$s" + "Has eliminat %1$s" + "Has eliminat %1$s: %2$s" + "%1$s ha eliminat %2$s: %3$s" + "%1$s ha convidat a %2$s a la sala" + "Has convidat a %1$s a la sala" + "%1$s ha rebutjat la invitació a la sala de %2$s" + "Has rebutjat la invitació a la sala de %1$s" + "%1$s ha canviat el tema a: %2$s" + "Has canviat el tema a: %1$s" + "%1$s ha eliminat el tema de la sala" + "Has eliminat el tema de la sala" + "%1$s ha readmès %2$s" + "Has readmès %1$s" + "%1$s ha fet un canvi desconegut al seu tipus d\'usuari" + diff --git a/libraries/matrixui/src/main/res/values-ca/translations.xml b/libraries/matrixui/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..44d3e10c55 --- /dev/null +++ b/libraries/matrixui/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "Envia invitació" + "Vols iniciar un xat amb %1$s?" + "Enviar invitació?" + "%1$s (%2$s) t\'ha convidat" + diff --git a/libraries/mediaviewer/impl/src/main/res/values-ca/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..44bf749c0f --- /dev/null +++ b/libraries/mediaviewer/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,21 @@ + + + "L\'arxiu s\'eliminarà de la sala i el membres no en tindran accés." + "Eliminar el document?" + "Comprova la connexió a internet i torna-ho a provar." + "Els documents, àudios i missatges de veu que s\'hagin penjat a la sala es mostraran aquí." + "Encara no s\'han pujat documents" + "Carregant documents…" + "Carregant multimèdia…" + "Documents" + "Multimèdia" + "Les imatges i vídeos penjats a la sala es mostraran aquí." + "Encara no s\'ha pujat multimèdia" + "Multimèdia i documents" + "Format del document" + "Nom del document" + "No hi ha més fitxers a mostrar" + "No hi ha més multimèdia a mostrar" + "Pujat per" + "Pujat el" + diff --git a/libraries/mediaviewer/impl/src/main/res/values-fi/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-fi/translations.xml index b3728cb9b7..05154b293c 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-fi/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-fi/translations.xml @@ -16,6 +16,7 @@ "Tiedostonimi" "Ei enää näytettäviä tiedostoja" "Ei enää näytettävää mediaa" + "Tiedoston tiedot" "Lähettäjä" "Lähetetty" diff --git a/libraries/mediaviewer/impl/src/main/res/values-ru/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-ru/translations.xml index cdbe07f2e1..74b910faaa 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-ru/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-ru/translations.xml @@ -16,6 +16,7 @@ "Имя файла" "Больше нет файлов для отображения" "Больше нет медиа для отображения" + "Информация о файле" "Загружено" "Загружено" diff --git a/libraries/permissions/api/src/main/res/values-ca/translations.xml b/libraries/permissions/api/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..0b8527649b --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-ca/translations.xml @@ -0,0 +1,7 @@ + + + "Per permetre que l\'aplicació utilitzi la càmera, concedeix-li permís a la configuració del sistema." + "Concedeix el permís a la configuració del sistema." + "Per permetre que l\'aplicació utilitzi el micròfon, concedeix-li permís a la configuració del sistema." + "Per permetre que l\'aplicació mostri notificacions, concedeix-li permís a la configuració del sistema." + diff --git a/libraries/permissions/impl/src/main/res/values-ca/translations.xml b/libraries/permissions/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..206c416d8b --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,5 @@ + + + "Comprova que l\'aplicació pot mostrar notificacions." + "Comprova els permisos" + diff --git a/libraries/push/impl/src/main/res/values-ca/translations.xml b/libraries/push/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..56655d250d --- /dev/null +++ b/libraries/push/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,83 @@ + + + "Trucada" + "Escoltant esdeveniments" + "Notificacions sonores" + "Trucades amb so" + "Notificacions silencioses" + + "%1$s: %2$d missatge" + "%1$s: %2$d missatges" + + + "%d notificació" + "%d notificacions" + + "Tens missatges nous." + "📹 Trucada entrant" + "** No s\'ha pogut enviar. Obre la sala" + "Uneix-te" + "Rebutja" + + "%d invitació" + "%d invitacions" + + "T\'ha convidat a xatejar" + "%1$s t\'ha convidat a xatejar" + "T\'ha mencionat: %1$s" + "Missatges nous" + + "%d missatge nou" + "%d missatges nous" + + "Ha reaccionat amb %1$s" + "Marca com a llegit" + "Resposta ràpida" + "T\'ha convidat a unir-te a la sala" + "%1$s t\'ha convidat a unir-te a la sala" + "Jo" + "%1$s ha mencionat o respost" + "Estàs veient la notificació! Fes-hi clic!" + "%1$s: %2$s" + "%1$s: %2$s %3$s" + + "%d missatge notificat no llegit" + "%d missatges notificats no llegits" + + "%1$s i %2$s" + "%1$s en %2$s" + "%1$s en %2$s i %3$s" + + "%d sala" + "%d sales" + + "Sincronització en segon pla" + "Serveis de Google" + "No s\'ha trobat \'Serveis de Google Play\' vàlid. És possible que les notificacions no funcionin correctament." + "Usuaris bloquejats" + "Obté el nom del proveïdor actual." + "No s\'han seleccionat proveïdors push." + "Proveïdor actual de notificacions push: %1$s." + "Proveïdor actual de notificacions push" + "Assegura\'t que l\'aplicació admet com a mínim un proveïdor de notificacions push." + "No s\'ha trobat cap proveïdor de notificacions push." + + "S\'ha trobat %1$d proveïdor push: %2$s" + "S\'han trobat %1$d proveïdors push: %2$s" + + "L\'aplicació s\'ha creat per permetre: %1$s" + "Suport del proveïdor de notificacions Push" + "Comprova que l\'aplicació pot mostrar notificacions." + "No s\'ha fet clic a la notificació." + "No es pot mostrar la notificació." + "S\'ha fet clic a la notificació!" + "Mostrar notificació" + "Fes clic a la notificació per continuar el test." + "Assegureua\'t que l\'aplicació rep notificacions push." + "Error: el proveïdor push ha rebutjat la sol·licitud." + "Error: %1$s." + "Error, no s\'han pogut provar les notificacions push." + "Error, s\'ha acabat el temps d\'espera de la notificació push." + "El bucle de notificacions push ha tardat %1$d ms." + "Prova el bucle de notificacions push" + diff --git a/libraries/push/impl/src/main/res/values-zh/translations.xml b/libraries/push/impl/src/main/res/values-zh/translations.xml index 881dbcdc54..7532f16ba0 100644 --- a/libraries/push/impl/src/main/res/values-zh/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh/translations.xml @@ -65,7 +65,7 @@ "已屏蔽用户" "获取当前推送提供者的名称。" "未选择任何推送提供者。" - "当前推送提供这:%1$s 及当前分发器:%2$s . 但未找到分发器 %3$s。该 app 可能已被卸载?" + "当前推送提供者:%1$s 及当前分发器:%2$s。但未找到分发器 %3$s。该 app 可能已被卸载?" "当前推送提供者:%1$s ,但尚未配置分发器。" "当前推送提供者:%1$s。" "当前推送提供者:%1$s(%2$s)" diff --git a/libraries/pushproviders/firebase/src/main/res/values-ca/translations.xml b/libraries/pushproviders/firebase/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..acd61bab06 --- /dev/null +++ b/libraries/pushproviders/firebase/src/main/res/values-ca/translations.xml @@ -0,0 +1,11 @@ + + + "Assegura\'t que Firebase estigui disponible." + "Firebase no està disponible." + "Firebase està disponible." + "Comprova Firebase" + "Assegura\'t que el token de Firebase està disponible." + "Token de Firebase desconegut." + "Token de Firebase: %1$s." + "Comprova el token de Firebase" + diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-ca/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..51096a1cfa --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-ca/translations.xml @@ -0,0 +1,10 @@ + + + "Assegura\'t que hi hagi distribuïdors d\'UnifiedPush disponibles." + "No s\'han trobat distribuïdors push." + + "%1$d distribuïdor trobat: %2$s." + "%1$d distribuïdors trobats: %2$s." + + "Prova UnifiedPush" + diff --git a/libraries/textcomposer/impl/src/main/res/values-ca/translations.xml b/libraries/textcomposer/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..f3b78b9dd2 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,31 @@ + + + "Afegeix fitxer adjunt" + "Activa/desactiva la llista amb punts" + "Cancel·la i tanca el format de text" + "Activa/desactiva bloc de codi" + "Afegeix llegenda" + "Missatge xifrat…" + "Missatge…" + "Missatge no xifrat…" + "Crea enllaç" + "Edita enllaç" + "%1$s, estat: %2$s" + "Aplica el format negreta" + "Aplica el format cursiva" + "desactivat" + "Aplica el format ratllat" + "Aplica el format subratllat" + "Activa/desactiva mode pantalla completa" + "Sagnia" + "Aplica format de codi" + "Estableix enllaç" + "Activa/desactiva llista numerada" + "Obre les opcions de redacció" + "Activa/desactiva cometes" + "Elimina enllaç" + "Treu sagnia" + "Enllaç" + "És possible que les llegendes no siguin visibles pels que utilitzin aplicacions antigues." + "Mantén premut per gravar." + diff --git a/libraries/troubleshoot/impl/src/main/res/values-ca/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..fe85dadb55 --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,11 @@ + + + "Executa tests" + "Torna a executar tests" + "Alguns tests han fallat. Comprova\'n els detalls." + "Executa els tests per detectar qualsevol problema a la configuració que pugui fer que les notificacions no es comportin com s\'espera." + "Intenta solucionar" + "Tots els tests s\'han superat amb èxit." + "Resolució de problemes de notificacions" + "Alguns tests necessiten la teva atenció. Comprova\'n els detalls." + diff --git a/libraries/ui-strings/src/main/res/values-ca/translations.xml b/libraries/ui-strings/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..d8abb7ff73 --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-ca/translations.xml @@ -0,0 +1,387 @@ + + + "Elimina" + + "%1$d dígit introduït" + "%1$d dígits introduïts" + + "Amaga contrasenya" + "Uneix-te a la trucada" + "Vés al final" + "Només mencions" + "Silenciat" + "Noves mencions" + "Pàgina %1$d" + "Pausa" + "Missatge de veu, durada: %1$s, posició actual: %2$s" + "Camp de PIN" + "Reprodueix" + "Votació" + "Votació finalitzada" + "Reacciona amb %1$s" + "Reacciona amb altres emoticones" + "Llegit per %1$s i %2$s" + + "Llegit per %1$s i %2$d més" + "Llegit per %1$s i %2$d més" + + "Llegit per %1$s" + "Toca per mostrar-los tots" + "Elimina la reacció: %1$s" + "Envia fitxers" + "Mostra contrasenya" + "Inicia trucada" + "Menú d\'usuari" + "Mostra els detalls" + "Missatge de veu, durada: %1$s" + "Grava un missatge de veu." + "Atura gravació" + "Accepta" + "Afegeix llegenda" + "Afegeix a la cronologia" + "Tornar" + "Truca" + "Cancel·la" + "Cancel·la per ara" + "Tria una foto" + "Esborra" + "Tanca" + "Completa la verificació" + "Confirma" + "Confirma la contrasenya" + "Continua" + "Copia" + "Copia llegenda" + "Copia l\'enllaç" + "Copia l\'enllaç al missatge" + "Copia text" + "Crea" + "Crea sala" + "Desactiva" + "Desactiva el compte" + "Declina" + "Rebutja i bloqueja" + "Elimina votació" + "Desactiva" + "Descarta" + "Omet" + "Fet" + "Edita" + "Edita llegenda" + "Edita votació" + "Activa" + "Finalitza votació" + "Introdueix PIN" + "Has oblidat la contrasenya?" + "Reenvia" + "Enrere" + "Ignora" + "Convida" + "Convida persones" + "Convida gent a %1$s" + "Convida a la gent a %1$s" + "Invitacions" + "Uneix-te" + "Més informació" + "Surt" + "Surt del xat" + "Surt de la sala" + "Carrega més" + "Gestiona compte" + "Gestiona dispositius" + "Envia missatge" + "Següent" + "No" + "Ara no" + "D\'acord" + "Configuració" + "Obre amb" + "Fixa" + "Resposta ràpida" + "Cita" + "Reacciona" + "Rebutja" + "Elimina" + "Elimina llegenda" + "Elimina missatge" + "Respon" + "Respon al fil" + "Denuncia" + "Informa d\'un error" + "Denuncia contingut" + "Denuncia la conversa" + "Denuncia sala" + "Restableix" + "Restableix identitat" + "Torna-ho a provar" + "Torna a intentar desxifrar" + "Desa" + "Cerca" + "Envia" + "Envia missatge" + "Comparteix" + "Comparteix enllaç" + "Mostra" + "Torna a iniciar sessió" + "Tanca sessió" + "Tanca sessió igualment" + "Omet" + "Comença" + "Inicia un xat" + "Torna a començar" + "Inicia verificació" + "Toca per carregar el mapa" + "Fes una foto" + "Toca per veure opcions" + "Torna-ho a intentar" + "No fixis" + "Mostra a la cronologia" + "Mostra font" + "Sí" + "Sí, torna-ho a intentar" + "El servidor utilizat admet un nou protocol més ràpid. Tanca la sessió i torna-la a iniciar per actualitzar-lo. Si ho fas ara, evitaràs un tancament de sessió forçat quan s\'elimini l\'antic protocol (més endavant)." + "Actualització disponible" + "Sobre l\'aplicació" + "Política d\'ús a acceptar" + "Afegint llegenda" + "Configuració avançada" + "Analítiques" + "Has sortit de la sala" + "Aspecte" + "Àudio" + "Usuaris bloquejats" + "Bombolles" + "Trucada iniciada" + "Còpia de seguretat de xat" + "Copiat al porta-retalls" + "Drets d\'autor" + "Creant sala…" + "Sol·licitud cancel·lada" + "Ha sortit de la sala" + "Invitació rebutjada" + "Error de desxifrat" + "Opcions per a desenvolupadors" + "ID de dispositiu" + "Xat directe" + "No ho tornis a mostrar" + "No s\'ha pogut baixar" + "Baixant" + "(editat)" + "Editant" + "Editant llegenda" + "* %1$s %2$s" + "Fitxer buit" + "Xifrat" + "Xifrat activat" + "Introdueix PIN" + "Error" + "S\'ha produït un error i és possible que no rebis notificacions dels missatges nous. Pots resoldre els problemes de notificacions des de la configuració. + +Motiu: %1$s." + "Tothom" + "Ha fallat" + "Preferit" + "Afegit a preferits" + "Fitxer" + "Fitxer eliminat" + "Fitxer desat" + "Fitxer desat a Descàrregues" + "Reenvia missatge" + "Utilitzats freqüentment" + "GIF" + "Imatge" + "En resposta a %1$s" + "Instal·la APK" + "No s\'ha trobat l\'ID de Matrix, és possible que la invitació no s\'hagi rebut." + "Sortint de la sala" + "Línia copiada al porta-retalls" + "Enllaç copiat al porta-retalls" + "S\'està carregant…" + "Carregant més…" + + "%d més" + "%d més" + + + "%1$d membre" + "%1$d membres" + + "Missatge" + "Accions de missatge" + "Estil dels missatges" + "Missatge eliminat" + "Modern" + "Silencia" + "%1$s (%2$s)" + "Sense resultats" + "Sala sense nom" + "Sense xifrar" + "Fora de línia" + "Llicències de codi obert" + "o" + "Contrasenya" + "Persones" + "Enllaç permanent" + "Permís" + "Fixat" + "Comprova la connexió a Internet" + "Si us plau, espera…" + "Segur que vols finalitzar aquesta votació?" + "Votació: %1$s" + "Vots totals: %1$s" + "Els resultats es mostraran quan hagi finalitzat la votació" + + "%d vot" + "%d vots" + + "Política de privadesa" + "Sala privada" + "Sala pública" + "Reacció" + "Reaccions" + "Motiu" + "Clau de recuperació" + "Actualitzant…" + + "%1$d resposta" + "%1$d respostes" + + "Responent a %1$s" + "Informa d\'un problema" + "S\'ha enviat" + "Editor de text enriquit" + "Sala" + "Nom de sala" + "p. ex. el nom d\'un projecte o grup" + "Canvis desats" + "Desant" + "Bloqueig de pantalla" + "Cerca persones" + "Resultats de la cerca" + "Seguretat" + "Vist per" + "Envia a" + "S\'està enviant…" + "Ha fallat l\'enviament" + "Enviat" + "Servidor no compatible" + "URL del servidor" + "Configuració" + "Ubicació compartida" + "Tancant sessió" + "Alguna cosa ha anat malament" + "S\'ha produït un problema. Torna-ho a intentar." + "Iniciant xat…" + "Adhesiu" + "Correcte" + "Suggeriments" + "Sincronitzant" + "Text" + "Avisos de tercers" + "Fil" + "Tema" + "De què tracta aquesta sala?" + "No s\'ha pogut desxifrar" + "Enviat des d\'un dispositiu insegur" + "No tens accés al missatge" + "La identitat verificada del remitent s\'ha restablert" + "No s\'han pogut enviar invitacions a un o més usuaris." + "No s\'han pogut enviar les invitacions" + "Desbloqueja" + "No silenciïs" + "Trucada no compatible" + "Esdeveniment no compatible" + "Nom d\'usuari" + "Verificació cancel·lada" + "Verificació completada" + "Error de verificació" + "Verificat" + "Verifica dispositiu" + "Verifica identitat" + "Verifica usuari" + "Vídeo" + "Missatge de veu" + "Esperant…" + "Esperant missatge" + "Tu" + "La identitat de %1$s s\'ha restablert. %2$s" + "La identitat de %1$s %2$s s\'ha restablert. %3$s" + "(%1$s)" + "%1$s ha restablert la identitat." + "Omet la verificació" + "L\'enllaç %1$s et portarà a un altre lloc %2$s + +Segur que vols continuar?" + "Revisa aquest enllaç" + "Sala denunciada" + "S\'ha denunciat i abandonat la sala." + "Confirmació" + "Error" + "Correcte" + "Avís" + "Hi ha canvis sense desar." + "Els canvis no s\'han desat. Segur que vols tornar enrere?" + "Desar canvis?" + "Cerca emoticones" + "El servidor utilitzat s\'ha d\'actualitzar per admetre el servei d\'autenticació de Matrix i la creació de comptes." + "No s\'ha pogut crear l\'enllaç permanent" + "%1$s no ha pogut carregar el mapa. Torna-ho a provar més tard." + "No s\'han pogut carregar els missatges" + "%1$s no ha pogut accedir a la teva ubicació. Torna-ho a provar més tard." + "No s\'ha pogut pujar el missatge de veu." + "Missatge no trobat" + "%1$s no té permís per accedir a la teva ubicació. Pots activar l\'accés a Configuració." + "%1$s no té permís per accedir a la teva ubicació. Activa l\'accés a sota." + "%1$s no té permís per accedir al micròfon. Activa\'n l\'accés per poder gravar missatges de veu." + "Això pot ser degut a problemes de xarxa o del servidor." + "Aquesta adreça de sala ja existeix. Prova d\'editar el camp d\'adreça o de canviar el nom de sala" + "Alguns caràcters no estan permesos. Només s\'admeten lletres, dígits i els símbols següents: ! $ & ‘ ( ) * + / ; = ? @ [ ] - . _" + "Alguns missatges no s\'han enviat" + "S\'ha produït un error" + "🔐️ Uneix-te a %1$s" + "Ei, xateja amb mi a %1$s: %2$s" + "%1$s Android" + "Sacseja per informar d\'errors" + "No s\'ha pogut seleccionar el contingut. Torna-ho a provar." + "Prem un missatge i selecciona “%1$s“ per incloure\'l aquí." + "Fixa els missatges importants perquè es puguin trobar fàcilment" + + "%1$d missatge fixat" + "%1$d missatges fixats" + + "Missatges fixats" + "No pots confirmar-la? Ves al teu compte per restablir la identitat." + "Omet la verificació i envia" + "Pots ometre la verificació i enviar el missatge igualment o pots cancel·lar i tornar-ho a intentar més tard, quan s\'hagi tornat a verificar %1$s." + "El teu missatge no s\'ha enviat perquè la identitat verificada de %1$s s\'ha reiniciat" + "Envia el missatge igualment" + "%1$s està utilitzant un o més dispositius no verificats. Pots enviar el missatge igualment o pots cancel·lar-lo i tornar-ho a provar més tard quan %2$s hagi verificat tots els seus dispositius." + "El teu missatge no s\'ha enviat perquè %1$s no ha verificat tots els dispositius" + "Un o més dels teus dispositius no estan verificats. Pots enviar el missatge igualment o cancel·lar-lo i tornar-ho a intentar més tard després d\'haver verificat tots els dispositius." + "El missatge no s\'ha enviat perquè no has verificat un o més dels teus dispositius." + "No s\'ha pogut processar el contingut que s\'havia de pujar. Torna-ho a provar." + "No s\'han pogut obtenir els detalls d\'usuari" + "Missatge a %1$s" + "%1$s de %2$s" + "%1$s missatges fixats" + "Crregant missatge…" + "Veure-ho tot" + "Xat" + "Comparteix ubicació" + "Comparteix la meva ubicació" + "Obre a Apple Maps" + "Obre a Google Maps" + "Obre a OpenStreetMap" + "Comparteix aquesta ubicació" + "Missatge no enviat perquè %1$s ha restablert la seva identitat verificada." + "Missatge no enviat perquè %1$s no ha verificat tots els dispositius." + "Missatge no enviat perquè no has verificat un o més dels teus dispositius." + "Ubicació" + "Versió: %1$s (%2$s)" + "en" + "L\'històric de missatges no està disponible en aquest dispositiu" + "Has de verificar aquest dispositiu per accedir a l\'històric de missatges" + "No tens accés al missatge" + "No s\'ha pogut desxifrar el missatge" + "Aquest missatge s\'ha bloquejat perquè no has verificat el teu dispositiu o perquè el remitent a de verificar la teva identitat." + 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 eef46172bd..f1c7d8d225 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -9,6 +9,7 @@ "%1$d number sisestatud" "%1$d numbrit sisestatud" + "Kestus: %1$s" "Muuda tunnuspilti" "Täisaadress saab olema %1$s" "Krüptimise üksikasjad" @@ -33,6 +34,7 @@ "Taasesituse kiirus" "Küsitlus" "Lõppenud küsitlus" + "Asukoht: %1$s" "QR-kood" "Reageeri emotikoniga %1$s" "Reageeri mõne muu emotikoniga" @@ -48,12 +50,15 @@ "Jututoa tunnuspilt" "Saada faile" "Saatja asukoht" + "%1$s saatis selle %2$s" "Palun tee see ajapiiranguga toiming, sul on aega üks minut" "Seaded, vajalik on tegevus" "Näita salasõna" "Helista" "Alusta videokõnet" "Helista" + "Jutulõng „%1$s“ jututoas" + "Jutulõngad „%1$s“ jututoas" "Lõpetatuks märgitud jututuba" "Kasutaja tunnuspilt" "Kasutajamenüü" 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 b3f0f32639..449fd0f352 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -9,13 +9,16 @@ "%1$d numero syötetty" "%1$d numeroa syötetty" + "Kesto: %1$s" "Muokkaa avataria" "Täysi osoite tulee olemaan %1$s" "Salauksen tiedot" "Laajenna viestin tekstikenttä" "Piilota salasana" + "Tiedot" "Liity puheluun" "Siirry loppuun" + "Siirry lukemattomiin" "Siirrä kartta sijaintiini" "Vain maininnat" "Mykistetty" @@ -32,6 +35,7 @@ "Toistonopeus" "Kysely" "Päättynyt kysely" + "Sijainti: %1$s" "QR-koodi" "Lisää reaktio: %1$s" "Reagoi muilla emojeilla" @@ -47,11 +51,15 @@ "Huoneen avatar" "Lähetä tiedostoja" "Lähettäjän sijainti" + "Lähettänyt %1$s aikaan %2$s" "Aikarajoitettu toimenpide vaaditaan, sinulla on yksi minuutti aikaa vahvistaa" + "Asetukset, toimenpide vaaditaan" "Näytä salasana" "Aloita puhelu" "Aloita videopuhelu" "Aloita äänipuhelu" + "Viestiketju huoneessa %1$s" + "Viestiketjut huoneessa %1$s" "Haudattu huone" "Käyttäjän avatar" "Käyttäjävalikko" @@ -69,6 +77,7 @@ "Soita" "Peruuta" "Peruuta toistaiseksi" + "Valitse tiedosto" "Valitse kuva" "Tyhjennä" "Sulje" @@ -88,12 +97,15 @@ "Deaktivoi tili" "Hylkää" "Hylkää ja estä" + "Poista" + "Poista tili" "Poista kysely" "Poista kaikki valinnat" "Poista käytöstä" "Hylkää" "Sulje" "Valmis" + "Lataa" "Muokkaa" "Muokkaa kuvatekstiä" "Muokkaa kyselyä" @@ -200,7 +212,9 @@ "Beeta" "Estetyt käyttäjät" "Kuplat" + "Puhelu hylätty" "Puhelu alkoi" + "Hylkäsit puhelun" "Keskustelujen varmuuskopiointi" "Kopioitu leikepöydälle" "Tekijänoikeudet" @@ -456,6 +470,9 @@ Haluatko varmasti jatkaa?" "Anteeksi, tapahtui virhe" "🔐️ Liity seuraani %1$s -sovelluksessa" "Hei, keskustele kanssani %1$s -sovelluksessa: %2$s" + "Reaaliaikaisen sijainnin jakaminen" + "Sijainnin jakaminen käynnissä" + "%1$s Reaaliaikainen sijainti" "%1$s Android" "Raivostunut ravistaminen ilmoittaa virheestä" "Näyttökuva" @@ -463,6 +480,10 @@ Haluatko varmasti jatkaa?" "Vaihtoehdot" "Poista %1$s" "Asetukset" + + "%1$d aste" + "%1$d astetta" + "Kukaan ei jaa sijaintiaan" "Jaetaan reaaliaikaista sijaintia" 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 545cf66c73..212b5eb79a 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -9,6 +9,7 @@ "%1$d chiffre saisi" "%1$d chiffres saisis" + "Durée: %1$s" "Modifier l’avatar" "L’adresse complète sera %1$s" "Détails du chiffrement" @@ -17,6 +18,7 @@ "Info" "Rejoindre l’appel" "Retourner à la fin de la conversation" + "Aller aux messages non lus" "Déplacer la carte vers ma position" "Mentions uniquement" "En sourdine" @@ -33,6 +35,7 @@ "Vitesse de lecture" "Sondage" "Sondage terminé" + "Position: %1$s" "Code QR" "Réagir avec %1$s" "Réagir avec d’autres émojis" @@ -48,12 +51,15 @@ "Avatar du salon" "Envoyer des fichiers" "Position de l’expéditeur" + "Envoyé par %1$s à %2$s" "Action limitée dans le temps requise, vous avez une minute pour effectuer la vérification" "Paramètres, action requise" "Afficher le mot de passe" "Démarrer un appel" "Passer un appel vidéo" "Lancer un appel vocal" + "Discussion dans %1$s" + "Discussions dans %1$s" "Salon clôturé" "Avatar de l’utilisateur" "Menu utilisateur" @@ -71,6 +77,7 @@ "Appel" "Annuler" "Annuler pour l’instant" + "Choisir un fichier" "Choisir une photo" "Effacer" "Fermer" @@ -463,6 +470,9 @@ Raison : %1$s." "Désolé, une erreur s’est produite" "🔐️ Rejoignez-moi sur %1$s" "Salut, parle-moi sur %1$s : %2$s" + "Partage de position en continu" + "Partage de position en cours" + "%1$s position en temps réel" "%1$s Android" "Rageshake pour signaler un problème" "Capture d’écran" @@ -470,6 +480,10 @@ Raison : %1$s." "Options" "Supprimer %1$s" "Paramètres" + + "%1$d degré" + "%1$d degrés" + "Personne ne partage sa position" "Partage de la position en direct" 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 7acfb90ef7..caca4b5014 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -9,6 +9,7 @@ "%1$d megadott számjegy" "%1$d megadott számjegy" + "Időtartam: %1$s" "Profilkép szerkesztése" "A teljes cím ez lesz: %1$s" "Titkosítás részletei" @@ -33,6 +34,7 @@ "Lejátszási sebesség" "Szavazás" "Befejezett szavazás" + "Pozíció: %1$s" "QR-kód" "Reagálás a következővel: %1$s" "Reagálás más emodzsikkal" @@ -48,12 +50,15 @@ "Szoba profilképe" "Fájlküldés" "Felhasználó tartózkodási helye" + "%1$s küldte ekkor: %2$s" "Időkorlátos művelet szükséges, egy perce van az ellenőrzésre" "Beállítások, beavatkozás szükséges" "Jelszó megjelenítése" "Hanghívás indítása" "Videohívás indítása" "Hanghívás indítása" + "Üzenetszál itt: %1$s" + "Üzenetszálak itt: %1$s" "Elévült szoba" "Felhasználói profilkép" "Felhasználói menü" 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 c62c579f32..c32cbca475 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -8,6 +8,7 @@ "%1$d 桁入力済" + "長さ: %1$s" "アバターを編集" "完全なアドレスは %1$s になります。" "暗号化の詳細" @@ -16,6 +17,7 @@ "情報" "通話に参加" "一番下へ" + "未読に移動" "現在地に移動" "メンションのみ" "ミュート有効" @@ -32,6 +34,7 @@ "再生速度" "投票" "投票終了" + "位置: %1$s" "QRコード" "リアクション: %1$s" "他の絵文字でリアクション" @@ -46,12 +49,15 @@ "ルームのアバター" "ファイルを送信" "送信者の位置情報" + "%2$s に %1$s が送信" "1分以内に検証を完了してください" "処置が必要な設定" "パスワードを表示" "通話を開始" "ビデオ通話を開始" "音声通話を開始" + "%1$s のスレッド" + "%1$s のスレッド" "埋没したルーム" "ユーザーのアバター" "ユーザーメニュー" @@ -272,7 +278,7 @@ "メッセージアクション" "メッセージの送信に失敗" "メッセージのレイアウト" - "メッセージは削除されました" + "メッセージが削除されました" "モダン" "ミュート" "名前" @@ -455,6 +461,9 @@ "申し訳ありません。エラーが発生しました。" "🔐️ %1$s に参加してください" "%1$s で話しましょう: %2$s" + "ライブ位置情報共有" + "位置情報を共有しています" + "%1$s ライブ位置情報" "%1$s Android" "開発者にバグを報告するには端末を振ってください。" "スクリーンショット" @@ -462,6 +471,11 @@ "選択肢" "%1$s を削除" "設定" + "画像を左に回転" + + "%1$d°" + + "写真を編集" "誰も位置情報を共有していません" "ライブ位置情報を共有しています" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index c654a66541..da3a5c2fea 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -10,6 +10,7 @@ "Wprowadzono %1$d cyfry" "Wprowadzono %1$d cyfr" + "Czas trwania: %1$s" "Edytuj awatar" "Podgląd pełnego adresu %1$s" "Szczegóły szyfrowania" @@ -18,6 +19,7 @@ "Informacje" "Dołącz do połączenia" "Przejdź na dół" + "Skocz do nieprzeczytanych" "Przesuń mapę do mojej lokalizacji" "Tylko wzmianki" "Wyciszone" @@ -34,6 +36,7 @@ "Prędkość odtwarzania" "Ankieta" "Zakończona ankieta" + "Pozycja: %1$s" "Kod QR" "Zareaguj z %1$s" "Zareaguj innym emoji" @@ -50,12 +53,15 @@ "Awatar pokoju" "Wyślij pliki" "Lokalizacja nadawcy" + "Wysłane przez %1$s o %2$s" "Wymagane jest działanie ograniczone czasowo, została jedna minuta" "Ustawienia, wymagane działanie" "Pokaż hasło" "Rozpocznij rozmowę" "Rozpocznij rozmowę wideo" "Rozpocznij połączenie głosowe" + "Wątek w %1$s" + "Wątki w %1$s" "Pokój nagrobkowy" "Awatar użytkownika" "Menu użytkownika" @@ -483,6 +489,13 @@ Czy na pewno chcesz kontynuować?" "Opcje" "Usuń %1$s" "Ustawienia" + "Obróć obraz w lewo" + + "%1$d stopień" + "%1$d stopnie" + "%1$d stopni" + + "Edytuj zdjęcie" "Nikt nie udostępnia swojej lokalizacji" "Udostępnianie lokalizacji na żywo" 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 26e1dcfe8d..3596bc04fe 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -15,6 +15,7 @@ "Сведения о шифровании" "Развернуть поле ввода" "Скрыть пароль" + "Информация" "Присоединиться к звонку" "Перейти вниз" "Переместить карту к моему местоположению" @@ -50,6 +51,7 @@ "Отправить файлы" "Местоположение отправителя" "Требуется действие, на которое есть ограничение по времени, у вас есть одна минута для проверки" + "Настройки, требуется действие" "Показать пароль" "Начать звонок" "Начать видеозвонок" @@ -71,6 +73,7 @@ "Позвонить" "Отмена" "Пока отменить" + "Выберите файл" "Выбрать фото" "Очистить" "Закрыть" @@ -90,12 +93,15 @@ "Отключить учётную запись" "Отклонить" "Отклонить и заблокировать" + "Удалить" + "Удалить аккаунт" "Удалить опрос" "Отменить выбор" "Отключить" "Отменить" "Закрыть" "Готово" + "Скачать" "Редактировать" "Изменить подпись" "Редактировать опрос" @@ -202,7 +208,9 @@ "Бета-версия" "Заблокированные пользователи" "Пузыри" + "Вызов отклонен" "Звонок начат" + "Ты отклонил звонок" "Резервная копия чатов" "Скопировано в буфер обмена" "Авторское право" @@ -465,6 +473,9 @@ "Произошла ошибка" "🔐️ Присоединяйтесь ко мне в %1$s" "Привет, давай поболтаем в %1$s: %2$s" + "Отправка местонахождения в реальном времени" + "Определение местоположения в процессе" + "Текущее местоположение %1$s" "%1$s Android" "Встряхните устройство, чтобы сообщить об ошибке" "Скриншот" 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 9cea16d2f0..1b50794182 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -8,6 +8,7 @@ "已输入 %1$d 个数字" + "持续时间:%1$s" "编辑头像" "完整地址为 %1$s" "加密详情" @@ -16,6 +17,7 @@ "信息" "加入通话" "跳转到底部" + "跳转到未读" "将地图移动到我的位置" "仅提及" "通知已关闭" @@ -32,6 +34,7 @@ "播放速度" "投票" "投票已结束" + "位置:%1$s" "二维码" "使用 %1$s 反应" "使用其它 Emoji 做出反应" @@ -46,11 +49,14 @@ "房间头像" "发送文件" "发送方位置" + "由 %1$s 发送于 %2$s" "请求的操作有时间限制,你有 1 分钟的时间来验证" "显示密码" "开始通话" "开始视频通话" "开始语音通话" + "位于 %1$s 中的消息列" + "位于 %1$s 中的消息列" "已封存的房间" "用户头像" "用户菜单" @@ -192,7 +198,7 @@ "可接受的使用政策" "添加账户" "添加账户" - "添加标题" + "正在添加标题" "高级设置" "一张图片" "分析" @@ -211,7 +217,7 @@ "版权" "正在创建房间…" "正在创建空间…" - "请求已取消" + "申请已取消" "离开房间" "离开空间" "邀请已拒绝" @@ -225,7 +231,7 @@ "正在下载" "(已编辑)" "正在编辑" - "编辑标题" + "正在编辑标题" "* %1$s %2$s" "空文件" "加密" @@ -407,10 +413,10 @@ "由于你当时不在房间内,%1$s 已将消息向你共享。" "此房间已配置为允许新成员阅读历史。%1$s" "%1$s 的数字身份已重置。%2$s" - "%1$s %2$s 的数字身份已重置。%3$s" + "%1$s(%2$s)的数字身份已重置。%3$s" "(%1$s)" "%1$s 的数字身份已重置。" - "%1$s %2$s 的数字身份已重置。%3$s" + "%1$s(%2$s)的数字身份已重置。%3$s" "撤回验证" "允许访问" "链接 %1$s 将跳转至外部网站 %2$s @@ -422,7 +428,7 @@ "允许的最大文件大小为:%1$s" "文件太大,无法上传" "已举报房间" - "举报并离开房间" + "已举报并离开房间" "确认" "错误" "成功" @@ -463,6 +469,11 @@ "选项" "移除 %1$s" "设置" + "向左旋转图像" + + "%1$d 度" + + "编辑照片" "目前无人分享其位置" "共享实时位置" @@ -517,7 +528,7 @@ "消息未能发送,因为 %1$s 尚未验证所有设备。" "消息未能发送,因为你有尚未验证的设备。" "位置" - "版本:%1$s (%2$s)" + "版本:%1$s(%2$s)" "zh-Hans" "历史消息在此设备上不可用" "你需要验证此设备才能访问历史消息" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index e5bc31396f..0b9490ae59 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -18,6 +18,7 @@ "Info" "Join call" "Jump to bottom" + "Jump to unread" "Move the map to my location" "Mentions only" "Muted" @@ -480,6 +481,12 @@ Are you sure you want to continue?" "Options" "Remove %1$s" "Settings" + "Rotate the image to the left" + + "%1$d degree" + "%1$d degrees" + + "Edit photo" "Nobody is sharing their location" "Sharing live location" diff --git a/plugins/src/main/kotlin/extension/locales.kt b/plugins/src/main/kotlin/extension/locales.kt index 650fbc4d72..2774b078b5 100644 --- a/plugins/src/main/kotlin/extension/locales.kt +++ b/plugins/src/main/kotlin/extension/locales.kt @@ -5,6 +5,7 @@ package extension val locales = setOf( "be", "bg", + "ca", "cs", "cy", "da", diff --git a/screenshots/de/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_de.png b/screenshots/de/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_de.png new file mode 100644 index 0000000000..f79c47c87a --- /dev/null +++ b/screenshots/de/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8dcfd0a6965522ddc3d1a0571176eb6889bbf15a390ea7d4348f002ec9696d5 +size 33189 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index c39909cf49..9dfcbcf1f6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10355aa4b00cbaa5ccded1d03d23db71907f9943ebd40dfec50545c046991b61 -size 49461 +oid sha256:ce3c8e771e43c186cadcf495a7d85d6ad36c089373782c209170282e0e5fb1fb +size 49709 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 7e18f43981..26411218a7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a2132a405f40d577a61420b4ad2d7bb9f55f67b5fe1b07b4ddb0daff10b8b89 -size 47704 +oid sha256:db7a53d858a08f1396a9c04b6a253623fa25160f90de62be9dc187f72fccedbd +size 48374 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index 4cd5290a7c..db935d5dc9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3003b423f3fa7504581ecf60cfbb82452eb17267bbc44f3b9439642da0ff096 -size 46416 +oid sha256:38e49c07c2f49bee8ba4d37f684be34ccb247bfecbfea5b1733e76246d160a45 +size 47086 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 0086307ec6..d0343f2f12 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bca6f953108331e512e3b0bca6086be207c1b1d2835d1dc220673098f5e3a9d -size 48263 +oid sha256:1f91bfd31c40b1cea5b4dd763dbc92eaaf7335d078ac496b51b05617c01f8b96 +size 48934 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index 0a99e31a52..12ccf2ffc3 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:494b1135a849734bce082b30aaeb491aebdb95cd67e6150be7334b55fe9fc0eb -size 48159 +oid sha256:d85a9aa1456dccaef8a7cb2c8b8c756e54c4fe03402d39d1240624d279449c28 +size 48821 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index 110a14531d..625ef06b29 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e147c903449a6c5ba6fa5041f73217c29965c2b4c2a165a96d36aebd2e2691e -size 49059 +oid sha256:1b65c937240f2a5bee4e4170a511fff5437c5bce47fb987674548487fcf72fd1 +size 49350 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 469a77a49a..0ab84d817e 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5590f66df4e26885e4b4776de840a9b1e4877a579f34769fe652172d01f5e374 -size 49554 +oid sha256:2f965ec5c45372e04fdcdc1c3c65633551f83e8dede75df8e8c329f849f487bf +size 49885 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index 7235a7a8e9..4798c4bc07 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbcc418cc648fe137d32a0455af4c0235c5c9269c49826c28dcdb22e7997638e -size 48441 +oid sha256:b68d23accbe81e6913d16ef6bb15712105422911905f274d66ef656f98d8a28f +size 49201 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index 6389db0432..11a68a7982 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8d7ee825e1e2cb28babc26bdd2de3747c99bff0b95f6c7e4d8a2b2dd9f9dd49 -size 47758 +oid sha256:3699ee438dbbd4aa0e5c5cd5a054304888421cb8c8a822dc52cb8369816f7feb +size 48429 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index 89c1174fd0..de0323860c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e6f13ca775952d7a06d82c41519a5f480f156eabd015a2020e0a5cf9d435765 -size 44694 +oid sha256:d3eada7d271b1f649d931e5077fc04e232046fd4171881c673bab8eaf990f92b +size 44452 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index 456f8db66c..65d67f1746 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c84a92f1c008dffb95cf4aa1337a35ba208d3702decf912e084937665079d947 -size 44674 +oid sha256:934be11ba08bc83461c1d859b3cf8b6f367feb89f6a779689ece209c30d8eaa8 +size 44441 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index 2f9e2bc268..637fe31e2f 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29f45a3272a173614152dd6e7b0d3dc08de6d3b1f86c9683b267e97db773fb19 -size 43163 +oid sha256:540a461ec0a84d22269abc644dd62444223818e337edbab2f79317f80cc24696 +size 44107 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index fb90141dde..bfa129700d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc70b1f6c6152f0f57b4f8586d781938c12af8bc61b517a232b779739eea6c72 -size 48521 +oid sha256:30918ebc116ebf2058aa619debfa9165d5ef95feb916a83e94e49d09377435e8 +size 49193 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index 10f31671ce..8a5276b209 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e5d32aea59c328b24d0a56bede3110e5b4a1d90a9b5eeb9bffffd30de5a41b6 -size 48437 +oid sha256:5cf3437703035eec0dd9623032bb62f1472b1a5fe996b7b85b9050385eb118ba +size 49109 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index 2a3f4a388a..a9e5ff3132 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddddf06d51977bcd997e3680d2fe3ff4f9d8102848980cf88b4d2ef08e37d5f9 -size 48004 +oid sha256:983d019c59d97d4bbe5b42562d6d028bb094a5b405fb2adc033232838952890d +size 48673 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index 28f7d63b1a..404ba5c5c1 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5ffb5c4bb36e659d6650acfc43c560d6c6cfc26f7b663e6de036c8d210c3c53 -size 42627 +oid sha256:1c79eb29314fbb2378034b03d368d5ca49ae49c6a53387784445a0b97e3cc56e +size 43324 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index b945a5f082..b492032c83 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd4f6d16dbb22cd3968e4fb3a1408ee6387bb3f7d81388b18e4b4d7cdc24a2b8 -size 45416 +oid sha256:d605c8379ff6844f7581231574cdfb50e5bce0b2e33c886fd43b520576f9149a +size 45963 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index 291e381783..09c0f584a7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19e656cf990a24bb08da6b7205a5fc1d39c76bbec967781cf0ea2a55bf7d11ab -size 46989 +oid sha256:355905f6a0fc25abe31db1359f24af1acb60bb3a013e697663c3ee9f87a9be52 +size 47386 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index 8ad5518a4c..0fd7d3e667 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df3eb3ec43a8219be6e5fb27ae316222bf049d73d897712e9e4981c7cd482f66 -size 44290 +oid sha256:a378c9b3a9bde80050444029ec6eaaaf76a5182c45babc898dbea24207466a32 +size 44054 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index 2524ad82a5..6392ad39ea 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:babe700b98176da34b30db8fcd367f13b26eb0b8216f8a486d0462dccdbe3068 -size 44782 +oid sha256:737de18454bbb78bd9ca789ba1ab821f203c54d55301a5851ae01e336cc42260 +size 45324 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index d3fe3eeec7..425e08b224 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e78510f867c14a8cc9e98d6bf36880136f36cdf08cf8940b9a5f54e327a1f115 -size 49064 +oid sha256:e2ce5bb8422a493541b30fe3eb95f756367358e039b759967e1f4d96f7cf337a +size 49729 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index ae3e083f08..6be8a7cc91 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:627f61625aadbd1801d38dec33a107c72d9c2bc10057ab85ed15207557fb8343 -size 48379 +oid sha256:a4fd1c7495908336646a05655f1c4c2d2ea0ece1e690f69164cc2946273a077c +size 49038 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index e52d7bbc87..8927152505 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3da232ee647be1a9722a00d4884f6f559cddc83f642aa07c3cbc4fb35746028 -size 47649 +oid sha256:12d25ae598f1a05aa86f0125b6acbaa4137becc2900a2ac649880c521ba2ef52 +size 48034 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index a825b90d21..86a072cb2b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b17db5e3de5f2a7cd8ab5adb998b9343993aeb4ca7e072287e0f60064638155 -size 50517 +oid sha256:7382605cb34650919a0b9f1d1e9460e28ce963dc4ff899fc6906dfcdd73dda50 +size 50783 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index 1e506d9628..b3d5dd204c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9165fa335486aa0463e9ee43b9e7c581a1c9bcd81f605a193d217fac58bff01 -size 48642 +oid sha256:c6f057a687620b49fde08e0c241aadca011d87154e73b7cbaf21a22896de07c9 +size 49348 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index 15456d858a..abf7a28899 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66d934f6d2fb764fd8d856e19671a47eb96bf79d1904222f12ba2c04ff815472 -size 47449 +oid sha256:a08b46085a213f7c6a93f24c2afc04cab4a0c30369d6eaf552cc6e58f50aea34 +size 48160 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index 759eda79f1..257169012b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6dfedba8b70af6389b88143e0c1c59dc9dbacba06b985fb791f9d5ef6b76d65 -size 49222 +oid sha256:e624adcc59354fc21c960547d0766929b95e1a2745b667eb57dd5e62d3ca8451 +size 49914 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index b50b33e08a..3804c84919 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:114059cd1d74d7e67039fdab4f4a37306badb38b2811b7cb494fd47a3de7dd52 -size 49118 +oid sha256:60cc99a113658fc4222b68b4801066c112d02dbd5c5b39e12471f77bb71ab348 +size 49807 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index 09a418c30b..080e2d2199 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:319b86e201bbcf3efb4ca2cceef15e7bba83800202c110439b5bab58d94aaa9d -size 50069 +oid sha256:fd16c5e9846823589ad5b22568c25b0cf3335cba8b467ceb3c9186e5b84e7fc7 +size 50318 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index 9bb6b27c92..f80834a2e0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ddeb573fd6c83a7b0d9e00947a1f1b87c27eda69796285c7b9a6cee487ccbb1 -size 50653 +oid sha256:6d3dbdcfe1dedaabb5d03dbdcc2a2f377fb6d1aafccd6b70cb147a97bf23b1c5 +size 50929 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index 8c769eb3c2..b43767563e 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a092056f5ae3f2bf40db0e1727afd191bf19b2bffea9bbeaa9cd5822b2235af -size 49426 +oid sha256:0761670005dd4463b662efb563a5270f89790470017d42001d00ce44e96f045c +size 50201 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index b7e8d5e7da..3c0a33e5fc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f300dbb1b0868fa619edef30e43231b5c2cb777bee2af56a8f3dfe42253db318 -size 48999 +oid sha256:6361321527d1bfa1ea84b361dec64c3746a85079a4048666e4016f52d3d34246 +size 49681 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index 602a4de377..c3b0b28c5d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b7f04ee27a8cdc0b9cde949d6167f013cbf2cbfcf591a54262ca697fd54ab57 -size 46011 +oid sha256:f5bbd36791567c89996dcd755b3ff4f956f69f1ff3f6f66595f16e1e733fe0a7 +size 45751 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 0bb73f7526..7dc11fb06d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d39a3067e1df646444276e13c1709e5c0ab0b27bb313531bdedde43fa056d6c -size 45947 +oid sha256:3bf0969b8a24c8d06fb3253646d6e2d0a94572cc346a8a9f9522ae48e5b4217a +size 45686 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 286ac63579..4fb1d5bebc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62ec3e5198b9d783cc7dcff94c39dec2ddd7edabbcbf1e272418e5446ec6d854 -size 44182 +oid sha256:3cfbd204c871feea36d0ac5ec740049488a9d3511156cf7a3e30d724d62fbdae +size 45187 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index 673cdd0c30..96b2a06800 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60c1951da07af010cd27d8622dcef6f953d369df9143a6c09e479bd26ea3aea9 -size 49487 +oid sha256:84af752733042d4d487a934144525bbcf31cf9c1cb1454a5561ea9b3bf794afd +size 50205 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index 49483a49d7..3576b6b30c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:951b4ed6186db857355229f9518aab6e72d0e6089e750eb58f1d21c23af54a58 -size 49415 +oid sha256:2a5c142c8539e0a7d40f4455e96d3d5fe1003f2cef84095709f15fd63b945a06 +size 50130 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index e49a2edf1b..6905512be4 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9036a65f211de57afb08e2a8a1edc679690286063855146616d1a9205f5e92ba -size 48963 +oid sha256:375274f827cb0b1a56461a95ebbbc12ab8dead23a41059b0909d87892b5b7f74 +size 49645 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index 037c1a51b9..23620c662b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c42fc0297235872ed4a405cbf73dbe68646b4ba2f2d8b4ab2a2c759372aedff5 -size 43575 +oid sha256:9737debc2f342c5ce2b20f48151597e164526297d2789b04bfda74e4cc70153c +size 44357 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index c7dd2f7b1a..aca9ef2193 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36df2a8757b8fea88e4d03150b7c9f1349e4112b1c7172224818cf394eb8755f -size 46360 +oid sha256:3d16e1a72ac9f47e0236b5ce3bf82c7e8d0d3ca0b245aba5fc751a0b9bed6cae +size 46946 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index 731d5599be..ab1ea77140 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73a5e4314e7d2cfffff54c1181aab1fb95227172758299c06754e97b59a58bba -size 47972 +oid sha256:e483482b88e7edc6724459da394f87a587ada9ddefea5d05d9bdcfe57e34ec47 +size 48423 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index fb6a42fde4..bd270b4ed0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9dec4b40543155b80a9d1db51a97f269d6188c0ea84384abf37e7c32a953a4c3 -size 45565 +oid sha256:7c8130c023137a1c3872202df289f364a3cc85217c7b0d7d36609d1fe896e96c +size 45304 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 6ce7d985b9..26e23487c0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d575f4e716de7fc5e1d376a8225f69bcf5375ea8a1555baa8d27d0481b45d4b -size 46038 +oid sha256:6c67de39146bb8c0049de90223d4a7293e3f42ab8f3780cc0980e62c97d10760 +size 46651 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index 28cb1f210b..2001c831b0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a4d42087d391ecc107d9f485e97499a9952f85c7555ac4428d36f4565c75dba -size 50112 +oid sha256:69695044a9afdc82d1a65e0911effcbb660dd550c31d5b8ae1f6a0f674dacd30 +size 50843 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index 8c515e1bfe..bbec3a797e 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5b97717f51c11b13b760cdb6922587db19d962f1f47c7c45bb39de2fc7880af -size 49374 +oid sha256:acbbccc700060f3511bdc2a44661ecd1442bb8db107c52d8a3ea93085e3cc370 +size 50181 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index 04877ee746..f1098ffed9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29a2b72b3ab467665c819763eee041fe349d26d9d2b6b724677a071dfcb84450 -size 48626 +oid sha256:891f50447359e8697ca26ac27179fb1687851c24156d36006764c874592c7584 +size 49072 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 08d02138ef..119bc1e013 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -2,99 +2,99 @@ export const screenshots = [ ["en","en-dark","de",], ["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",0,], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20588,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20595,], ["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",20588,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20588,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20588,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20588,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20588,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20588,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20588,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20588,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20588,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20588,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20588,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20595,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20595,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20595,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20595,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20595,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20595,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20595,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20595,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20595,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20595,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20595,], ["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",20588,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20588,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20595,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20595,], ["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",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20595,], ["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",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20588,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20588,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20588,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20588,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20588,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20588,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20588,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20588,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20588,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20588,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20595,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20595,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20595,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20595,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20595,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20595,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20595,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20595,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20595,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20588,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20588,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20588,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20588,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20588,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20595,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20595,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20595,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20595,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20595,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20588,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20588,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20588,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20588,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20595,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20595,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20595,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20595,], ["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",20588,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20595,], ["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",20588,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20595,], ["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",20588,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20595,], ["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",20588,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20595,], ["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,], @@ -104,19 +104,19 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20588,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20588,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20595,], ["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",20588,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20595,], ["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,], @@ -146,22 +146,22 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20588,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20595,], ["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",20588,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20588,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20588,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20588,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20588,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20588,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20588,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20595,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20588,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20588,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20588,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20588,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20588,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20595,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20595,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20595,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20595,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20595,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -172,141 +172,141 @@ export const screenshots = [ ["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20588,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20588,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20595,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20595,], ["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",20588,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20595,], ["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",20588,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20588,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20588,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20588,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20588,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20588,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20595,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20595,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20595,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20595,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20595,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20595,], ["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",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20588,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20588,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20588,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20595,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20595,], ["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",20588,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20588,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20588,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20588,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20588,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20595,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20595,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20595,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20595,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20595,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20588,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20595,], ["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",20588,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20588,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20588,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20588,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20588,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20588,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20588,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20588,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20595,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20595,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20595,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20595,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20595,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20595,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20595,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20595,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], -["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20588,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20595,], ["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",20588,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20588,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20588,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20588,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20588,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20588,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20588,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20595,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20595,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20595,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20595,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20595,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20595,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20595,], ["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","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20588,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20588,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20588,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20588,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20588,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20588,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20595,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20595,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20595,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20595,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20595,], ["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",20588,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20588,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20588,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20588,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20588,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20588,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20588,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20588,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20588,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20588,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20588,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20588,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20588,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20588,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20588,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20588,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20588,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20588,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20588,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20588,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20595,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20595,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20595,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20595,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20595,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20595,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20595,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20595,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20595,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20595,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20595,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20595,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20595,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20595,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20595,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20595,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20595,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20595,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20595,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20595,], ["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","",20588,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20588,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20588,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20588,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20588,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20588,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20588,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20595,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20595,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20595,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20595,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20595,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20595,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20595,], ["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",20588,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20588,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20588,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20595,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20595,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20595,], ["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",20588,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20595,], ["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",20588,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20588,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20588,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20588,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20588,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20588,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20588,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20588,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20588,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20595,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20595,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20595,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20595,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20595,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20595,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20595,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20595,], ["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,], @@ -319,20 +319,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",20588,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20588,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20588,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20588,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20588,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20588,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20588,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20588,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20588,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20588,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20588,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20588,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20588,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20588,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20595,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20595,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20595,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20595,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20595,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20595,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20595,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20595,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20595,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20595,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20595,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20595,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20595,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20595,], ["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,], @@ -340,29 +340,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20588,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20588,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20595,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20595,], ["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",20588,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20588,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20588,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20588,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20588,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20588,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20588,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20588,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20588,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20588,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20595,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20595,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20595,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20595,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20595,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20595,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20595,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20595,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20595,], ["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,], @@ -382,49 +382,49 @@ export const screenshots = [ ["features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en","features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20588,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20588,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20588,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20595,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20595,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20595,], ["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",20588,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20588,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20595,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20595,], ["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",20588,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20595,], ["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",20588,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20588,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20588,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20588,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20588,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20595,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20595,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20595,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20595,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20595,], ["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",20588,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20588,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20595,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20595,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20588,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20588,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20595,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20595,], ["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",20588,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20588,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20588,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20588,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20588,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20588,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20588,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20588,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20588,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20588,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20588,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20588,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20588,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20595,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20595,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20595,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20595,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20595,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20595,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20595,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20595,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20595,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20595,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20595,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20595,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20595,], ["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,], @@ -439,8 +439,8 @@ export const screenshots = [ ["appicon.enterprise_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",20588,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20588,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20595,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20595,], ["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,], @@ -448,119 +448,119 @@ export const screenshots = [ ["libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20588,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20595,], ["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",20588,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20595,], ["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",20588,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20588,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20595,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20595,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20588,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20588,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20595,], ["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",20588,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20588,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20588,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20595,], ["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",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20595,], ["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",20588,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20588,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20588,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20595,], ["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",20588,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20588,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20588,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20588,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20588,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20588,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20588,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20588,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20595,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20595,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20595,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20595,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20595,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20595,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20595,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20595,], ["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",20588,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20588,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20588,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20588,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20588,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20595,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20595,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20595,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20588,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20588,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20595,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20595,], ["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",20588,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20588,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20588,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20588,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20588,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20588,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20588,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20588,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20595,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20595,], ["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",20588,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20588,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20588,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20588,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20588,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20588,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20595,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20595,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20595,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20595,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20595,], ["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",20588,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20595,], ["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,], @@ -613,48 +613,48 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextNoPadding_List_supporting_text_-_no_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], -["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20591,], +["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20595,], ["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",20588,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20595,], ["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",20588,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20588,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20588,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20595,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20595,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20595,], ["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",20588,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20588,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20588,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20588,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20588,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20588,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20588,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20588,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20588,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20588,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20588,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20588,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20588,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20588,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20588,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20588,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20588,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20588,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20588,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20588,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20588,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20588,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20588,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20588,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20588,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20588,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20588,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20595,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20595,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20595,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20595,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20595,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20595,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20595,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20595,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20595,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20595,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20595,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20595,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20595,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20595,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20595,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20595,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20595,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20595,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20595,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20595,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20595,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20595,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20595,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20595,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20595,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20595,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20595,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20588,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20588,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20588,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20588,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20595,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20595,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20595,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20595,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -667,26 +667,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20588,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20588,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20588,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20588,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20588,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20588,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20595,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20595,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20595,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20595,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20595,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20595,], ["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",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20588,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20588,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20595,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -694,10 +694,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20588,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20595,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20595,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], @@ -707,7 +707,7 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20595,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -717,10 +717,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20588,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20595,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20595,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], @@ -730,7 +730,7 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerView_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20588,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20595,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -744,7 +744,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",20588,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20595,], ["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,], @@ -753,7 +753,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",20588,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20595,], ["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,], @@ -762,24 +762,24 @@ 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",20588,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20588,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20588,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20588,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20588,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20588,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20591,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20588,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20588,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20588,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20588,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20588,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20588,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20588,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20588,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20588,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20595,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20595,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20595,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20595,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20595,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20595,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20595,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20595,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20595,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20595,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20595,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20595,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20595,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20595,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20595,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20595,], ["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",20588,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20595,], ["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,], @@ -790,117 +790,117 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20588,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20588,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20588,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20595,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20595,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20595,], ["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",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20588,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20588,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20595,], ["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",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20588,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20595,], ["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",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20588,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20588,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20595,], ["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",20588,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20588,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20588,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20588,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20588,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20588,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20595,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20595,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20595,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20595,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20595,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20595,], ["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",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20588,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20588,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20595,], ["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",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20588,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20588,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20588,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20588,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20588,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20588,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20595,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20595,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20595,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20595,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20595,], ["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",20588,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20588,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20588,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20588,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20588,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20595,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20595,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20595,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20595,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20595,], ["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",20588,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20588,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20588,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20588,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20588,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20588,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20588,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20588,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20588,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20588,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20588,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20595,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20595,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20595,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20595,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20595,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20595,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20595,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20595,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20595,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20595,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20595,], ["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,], @@ -914,225 +914,225 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20588,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20588,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20595,], ["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","",20588,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20588,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20595,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20595,], ["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",20588,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20588,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20588,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20588,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20588,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20588,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20588,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20588,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20588,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20588,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20588,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20588,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20588,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20588,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20588,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20588,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20588,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20588,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20588,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20588,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20588,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20595,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20595,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20595,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20595,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20595,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20595,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20595,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20595,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20595,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20595,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20595,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20595,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20595,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20595,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20595,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20595,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20595,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20595,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20595,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20595,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20595,], ["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",20588,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20588,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20595,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20595,], ["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",20588,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20588,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20588,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20588,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20588,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20588,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20588,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20595,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20595,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20595,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20595,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20595,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20595,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20595,], ["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",20588,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20588,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20588,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20588,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20588,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20588,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20588,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20588,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20588,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20588,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20588,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20588,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20588,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20588,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20588,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20588,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20588,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20595,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20595,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20595,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20595,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20595,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20595,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20595,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20595,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20595,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20595,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20595,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20595,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20595,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20595,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20595,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20595,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20595,], ["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",20588,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20588,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20588,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20588,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20588,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20595,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20595,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20595,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20595,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20595,], ["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",20588,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20588,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20595,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20595,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20588,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20588,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20588,], -["features.roomdetails.impl_RoomDetails_0_en","",20588,], -["features.roomdetails.impl_RoomDetails_10_en","",20588,], -["features.roomdetails.impl_RoomDetails_11_en","",20588,], -["features.roomdetails.impl_RoomDetails_12_en","",20588,], -["features.roomdetails.impl_RoomDetails_13_en","",20588,], -["features.roomdetails.impl_RoomDetails_14_en","",20588,], -["features.roomdetails.impl_RoomDetails_15_en","",20588,], -["features.roomdetails.impl_RoomDetails_16_en","",20588,], -["features.roomdetails.impl_RoomDetails_17_en","",20588,], -["features.roomdetails.impl_RoomDetails_18_en","",20588,], -["features.roomdetails.impl_RoomDetails_19_en","",20588,], -["features.roomdetails.impl_RoomDetails_1_en","",20588,], -["features.roomdetails.impl_RoomDetails_20_en","",20588,], -["features.roomdetails.impl_RoomDetails_21_en","",20588,], -["features.roomdetails.impl_RoomDetails_22_en","",20588,], -["features.roomdetails.impl_RoomDetails_2_en","",20588,], -["features.roomdetails.impl_RoomDetails_3_en","",20588,], -["features.roomdetails.impl_RoomDetails_4_en","",20588,], -["features.roomdetails.impl_RoomDetails_5_en","",20588,], -["features.roomdetails.impl_RoomDetails_6_en","",20588,], -["features.roomdetails.impl_RoomDetails_7_en","",20588,], -["features.roomdetails.impl_RoomDetails_8_en","",20588,], -["features.roomdetails.impl_RoomDetails_9_en","",20588,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20588,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20588,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20588,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20588,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20588,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20588,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20588,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20588,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20588,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20595,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20595,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20595,], +["features.roomdetails.impl_RoomDetails_0_en","",20595,], +["features.roomdetails.impl_RoomDetails_10_en","",20595,], +["features.roomdetails.impl_RoomDetails_11_en","",20595,], +["features.roomdetails.impl_RoomDetails_12_en","",20595,], +["features.roomdetails.impl_RoomDetails_13_en","",20595,], +["features.roomdetails.impl_RoomDetails_14_en","",20595,], +["features.roomdetails.impl_RoomDetails_15_en","",20595,], +["features.roomdetails.impl_RoomDetails_16_en","",20595,], +["features.roomdetails.impl_RoomDetails_17_en","",20595,], +["features.roomdetails.impl_RoomDetails_18_en","",20595,], +["features.roomdetails.impl_RoomDetails_19_en","",20595,], +["features.roomdetails.impl_RoomDetails_1_en","",20595,], +["features.roomdetails.impl_RoomDetails_20_en","",20595,], +["features.roomdetails.impl_RoomDetails_21_en","",20595,], +["features.roomdetails.impl_RoomDetails_22_en","",20595,], +["features.roomdetails.impl_RoomDetails_2_en","",20595,], +["features.roomdetails.impl_RoomDetails_3_en","",20595,], +["features.roomdetails.impl_RoomDetails_4_en","",20595,], +["features.roomdetails.impl_RoomDetails_5_en","",20595,], +["features.roomdetails.impl_RoomDetails_6_en","",20595,], +["features.roomdetails.impl_RoomDetails_7_en","",20595,], +["features.roomdetails.impl_RoomDetails_8_en","",20595,], +["features.roomdetails.impl_RoomDetails_9_en","",20595,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20595,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20595,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20595,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20595,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20595,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20595,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20595,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20595,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20595,], ["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",20588,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20588,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20588,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20588,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20588,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20588,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20588,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20588,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20588,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20588,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20588,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20595,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20595,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20595,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20595,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20595,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20595,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20595,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20595,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20595,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20595,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20595,], ["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",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20588,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20588,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20588,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20595,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20595,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20595,], ["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",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20588,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20588,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20595,], ["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",20588,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20588,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20588,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20588,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20588,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20588,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20595,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20595,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20595,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20595,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20595,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20595,], ["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,], @@ -1155,16 +1155,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20588,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20588,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20595,], ["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",20588,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20595,], ["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,], @@ -1174,118 +1174,118 @@ export const screenshots = [ ["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,], ["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_0_en","appnav.root_RootView_Night_0_en",20588,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20588,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20588,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20595,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20595,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20595,], ["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",20588,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20588,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20588,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20588,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20588,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20588,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20588,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20588,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20595,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20595,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20595,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20595,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20595,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20595,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20595,], ["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","",20588,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20595,], ["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","",20588,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20588,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20588,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20588,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20588,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20588,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20588,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20588,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20588,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20588,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20588,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20588,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20588,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20588,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20588,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20595,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20595,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20595,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20595,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20595,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20595,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20595,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20595,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20595,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20595,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20595,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20595,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20595,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20595,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20595,], ["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,], @@ -1308,37 +1308,38 @@ 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",20588,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20588,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20588,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20588,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20588,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20588,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20588,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20588,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20588,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20588,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20588,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20588,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20588,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20588,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20588,], -["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20591,], -["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20591,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20595,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20595,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20595,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20595,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20595,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20595,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20595,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20595,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20595,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20595,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20595,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20595,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20595,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20595,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20595,], +["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20595,], +["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20595,], ["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",20588,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20588,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20588,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20588,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20588,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20588,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20588,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20588,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20588,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20588,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20588,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20595,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20595,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20595,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20595,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20595,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20595,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20595,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20595,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20595,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20598,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20595,], ["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,], @@ -1348,106 +1349,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",20588,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20595,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20588,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20588,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20588,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20588,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20588,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20595,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20595,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20595,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20595,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20595,], ["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",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20588,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20588,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20588,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20588,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20588,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20588,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20588,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20588,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20588,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20588,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20588,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20588,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20588,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20588,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20588,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20595,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20595,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20595,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20595,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20595,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20595,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20595,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20595,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20595,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20595,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20595,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20595,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20595,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20595,], ["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",20588,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20588,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20588,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20588,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20588,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20588,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20595,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20595,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20595,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20595,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20595,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20595,], ["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",20588,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20595,], ["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",20588,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20595,], ["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",20588,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20588,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20588,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20588,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20588,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20588,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20588,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20588,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20588,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20588,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20588,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20588,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20588,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20588,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20588,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20588,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20595,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20595,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20595,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20595,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20595,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20595,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20595,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20595,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20595,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20595,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20595,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20595,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20595,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20595,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20595,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20595,], ["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",20588,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20588,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20595,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20595,], ["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,], @@ -1460,17 +1461,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20588,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20588,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20595,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20595,], ["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","",20588,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20588,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20588,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20595,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20595,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20595,], ["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",20588,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20588,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20595,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20595,], ["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,], @@ -1480,18 +1481,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",20588,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20595,], ["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",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20595,], ["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,], @@ -1499,18 +1500,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",20588,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20595,], ["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",20588,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20588,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20595,], ["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",20588,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20595,], ["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,], @@ -1519,44 +1520,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20595,], ["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",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20595,], ["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",20588,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20595,], ["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","",20588,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20595,], ["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",20588,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20595,], ["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",20588,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20595,], ["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",20588,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20588,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20588,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20595,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20595,], ["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",20588,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20588,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20595,], ["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",20588,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20595,], ["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,], @@ -1565,8 +1566,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",20588,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20595,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20595,], ["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,], @@ -1581,8 +1582,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",20588,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20588,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20595,], ["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,], @@ -1605,84 +1606,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",20588,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20588,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20588,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20595,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20595,], ["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",20588,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20595,], ["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",20588,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20595,], ["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",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20588,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20588,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20595,], ["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",20588,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20588,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20588,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20588,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20588,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20588,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20595,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20595,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20595,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20595,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20595,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20595,], ["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","",20588,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20595,], ["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",20588,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20588,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20588,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20588,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20595,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20595,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20595,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20595,], ["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",20588,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20595,], ["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",20588,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20595,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20588,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20588,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20588,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20588,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20588,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20588,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20588,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20588,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20588,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20588,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20588,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20588,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20588,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20595,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20595,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20595,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20595,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20595,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20595,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20595,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20595,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20595,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20595,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20595,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20595,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20595,], ["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.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20588,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20588,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20595,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20595,], ["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",20588,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20595,], ["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,], From 0e2213a199a3981811712dc90b24ad7fedb23118 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 May 2026 10:10:42 +0200 Subject: [PATCH 0504/1083] Fix public read receipts being sent by mistake (#6838) When returning to the chat screen from the room details one or a member's profile, `TimelineEvent.OnScrollFinished` will be called immediately, and this would read the default value for `isSendPublicReadReceiptsEnabled`, which is `true`. If you had public read receipts disabled, this is a mistake, and would send a public read receipt. Instead, what we want to do is wait until the updated value is emitted and use it to decide whether we want to send a public or private read receipt. --- .../impl/timeline/TimelinePresenter.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) 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 0b99c45e06..0681a0ff38 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 @@ -66,6 +66,7 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -137,9 +138,6 @@ class TimelinePresenter( val messageShieldDialogData: MutableState = remember { mutableStateOf(null) } val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() - val isSendPublicReadReceiptsEnabled by remember { - sessionPreferencesStore.isSendPublicReadReceiptsEnabled() - }.collectAsState(initial = true) val renderReadReceipts by remember { sessionPreferencesStore.isRenderReadReceiptsEnabled() }.collectAsState(initial = true) @@ -171,12 +169,15 @@ class TimelinePresenter( newEventState.value = NewEventState.None } Timber.tag(tag).d("## sendReadReceiptIfNeeded firstVisibleIndex: ${event.firstIndex}") - sessionCoroutineScope.sendReadReceiptIfNeeded( - firstVisibleIndex = event.firstIndex, - timelineItems = timelineItems, - lastReadReceiptId = lastReadReceiptId, - readReceiptType = if (isSendPublicReadReceiptsEnabled) ReceiptType.READ else ReceiptType.READ_PRIVATE, - ) + sessionCoroutineScope.launch { + val sendPublicReadReceipts = sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first() + sendReadReceiptIfNeeded( + firstVisibleIndex = event.firstIndex, + timelineItems = timelineItems, + lastReadReceiptId = lastReadReceiptId, + readReceiptType = if (sendPublicReadReceipts) ReceiptType.READ else ReceiptType.READ_PRIVATE, + ) + } } else { newEventState.value = NewEventState.None } From 1e67c2f77bd3177a490528f8bc092c53bad806cc Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 May 2026 10:28:32 +0200 Subject: [PATCH 0505/1083] Move empty day separator filtering to a timeline post-processor (#6866) * Move empty day separator filtering to a timeline post-processor * Split `FilterPublicMembershipChangesPostProcessor` from `RoomBeginningPostProcessor` --- .../factories/TimelineItemsFactory.kt | 26 +-- .../factories/TimelineItemsFactoryTest.kt | 160 ------------------ .../matrix/impl/timeline/RustTimeline.kt | 20 ++- .../FilterEmptyDayPostProcessor.kt | 38 +++++ ...terPublicMembershipChangesPostProcessor.kt | 43 +++++ .../RoomBeginningPostProcessor.kt | 16 -- .../FilterEmptyDayPostProcessorTest.kt | 118 +++++++++++++ ...ublicMembershipChangesPostProcessorTest.kt | 75 ++++++++ .../RoomBeginningPostProcessorTest.kt | 89 ---------- 9 files changed, 292 insertions(+), 293 deletions(-) delete mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessor.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessorTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt index dc8bdddc92..7b369fe6b7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt @@ -16,7 +16,6 @@ import io.element.android.features.messages.impl.timeline.factories.event.Timeli import io.element.android.features.messages.impl.timeline.factories.virtual.TimelineItemVirtualFactory import io.element.android.features.messages.impl.timeline.groups.TimelineItemGrouper import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel import io.element.android.libraries.androidutils.diff.DiffCacheUpdater import io.element.android.libraries.androidutils.diff.MutableListDiffCache import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -97,8 +96,7 @@ class TimelineItemsFactory( } } val result = timelineItemGrouper.group(newTimelineItemStates).toImmutableList() - val filteredResult = filterEmptyDaySeparators(result) - this._timelineItems.emit(filteredResult) + this._timelineItems.emit(result) } private suspend fun buildAndCacheItem( @@ -116,25 +114,3 @@ class TimelineItemsFactory( return timelineItem } } - -// Remove day separators for days with no events after the client-side event filtering -internal fun filterEmptyDaySeparators(items: List): ImmutableList { - return buildList { - var hasEventBefore = false - for (item in items) { - when (item) { - is TimelineItem.Event, is TimelineItem.GroupedEvents -> { - hasEventBefore = true - add(item) - } - is TimelineItem.Virtual if item.model is TimelineItemDaySeparatorModel -> { - if (hasEventBefore) { - add(item) - } - hasEventBefore = false - } - else -> add(item) - } - } - }.toImmutableList() -} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt deleted file mode 100644 index 8df8d34f56..0000000000 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactoryTest.kt +++ /dev/null @@ -1,160 +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.features.messages.impl.timeline.factories - -import com.google.common.truth.Truth.assertThat -import io.element.android.features.messages.impl.fixtures.aMessageEvent -import io.element.android.features.messages.impl.timeline.aTimelineItemDebugInfo -import io.element.android.features.messages.impl.timeline.aTimelineItemReactions -import io.element.android.features.messages.impl.timeline.model.ReadReceiptData -import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts -import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel -import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel -import io.element.android.libraries.designsystem.components.avatar.anAvatarData -import io.element.android.libraries.matrix.api.core.UniqueId -import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails -import io.element.android.libraries.matrix.test.AN_EVENT_ID -import io.element.android.libraries.matrix.test.A_USER_ID -import io.element.android.libraries.matrix.test.core.FakeSendHandle -import kotlinx.collections.immutable.toImmutableList -import org.junit.Test - -class TimelineItemsFactoryTest { - private val anEvent = TimelineItem.Event( - id = UniqueId("event"), - eventId = AN_EVENT_ID, - senderId = A_USER_ID, - senderAvatar = anAvatarData(), - senderProfile = ProfileDetails.Ready(displayName = "User", displayNameAmbiguous = false, avatarUrl = null), - content = aMessageEvent().content, - reactionsState = aTimelineItemReactions(count = 0), - readReceiptState = TimelineItemReadReceipts(emptyList().toImmutableList()), - localSendState = LocalEventSendState.Sent(AN_EVENT_ID), - isEditable = false, - canBeRepliedTo = false, - inReplyTo = null, - threadInfo = null, - origin = null, - timelineItemDebugInfoProvider = { aTimelineItemDebugInfo() }, - messageShieldProvider = { null }, - sendHandleProvider = { FakeSendHandle() }, - forwarder = null, - forwarderProfile = null, - ) - - private fun aDaySeparator(date: String) = TimelineItem.Virtual( - id = UniqueId("day_$date"), - model = aTimelineItemDaySeparatorModel(date) - ) - - @Test - fun `filterEmptyDaySeparators keeps day separator with events after it`() { - val items = listOf( - anEvent, - aDaySeparator("Today"), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).hasSize(2) - assertThat(result[0]).isEqualTo(anEvent) - assertThat(result[1]).isEqualTo(aDaySeparator("Today")) - } - - @Test - fun `filterEmptyDaySeparators removes day separator with no events after it`() { - val items = listOf( - aDaySeparator("Today"), - aDaySeparator("Yesterday"), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).isEmpty() - } - - @Test - fun `filterEmptyDaySeparators removes first day separator and keeps second when only second has events`() { - val items = listOf( - aDaySeparator("Today"), - anEvent, - aDaySeparator("Yesterday"), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).hasSize(2) - assertThat(result[0]).isEqualTo(anEvent) - assertThat(result[1]).isEqualTo(aDaySeparator("Yesterday")) - } - - @Test - fun `filterEmptyDaySeparators handles multiple day separators in a row with no events`() { - val items = listOf( - aDaySeparator("Today"), - aDaySeparator("Yesterday"), - aDaySeparator("Last week"), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).isEmpty() - } - - @Test - fun `filterEmptyDaySeparators keeps all items when no day separators`() { - val items = listOf( - anEvent, - anEvent.copy(id = UniqueId("event2")), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).hasSize(2) - } - - @Test - fun `filterEmptyDaySeparators handles grouped events after day separator`() { - val groupedEvents = TimelineItem.GroupedEvents( - id = UniqueId("grouped"), - events = listOf(anEvent).toImmutableList(), - aggregatedReadReceipts = emptyList().toImmutableList(), - ) - val items = listOf( - groupedEvents, - aDaySeparator("Today"), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).hasSize(2) - assertThat(result[0]).isEqualTo(groupedEvents) - assertThat(result[1]).isEqualTo(aDaySeparator("Today")) - } - - @Test - fun `filterEmptyDaySeparators removes day separator followed by non-event virtual item`() { - val readMarker = TimelineItem.Virtual( - id = UniqueId("readMarker"), - model = TimelineItemReadMarkerModel - ) - val items = listOf( - aDaySeparator("Today"), - readMarker, - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).hasSize(1) - assertThat(result[0]).isEqualTo(readMarker) - } - - @Test - fun `filterEmptyDaySeparators keeps day separator when non-event virtual items are between separator and event`() { - val readMarker = TimelineItem.Virtual( - id = UniqueId("readMarker"), - model = TimelineItemReadMarkerModel - ) - val items = listOf( - anEvent, - readMarker, - aDaySeparator("Today"), - ) - val result = filterEmptyDaySeparators(items) - assertThat(result).hasSize(3) - assertThat(result[2]).isEqualTo(aDaySeparator("Today")) - } -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 016204e1b1..d44676d34a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -38,6 +38,8 @@ import io.element.android.libraries.matrix.impl.room.location.into import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper +import io.element.android.libraries.matrix.impl.timeline.postprocessor.FilterEmptyDayPostProcessor +import io.element.android.libraries.matrix.impl.timeline.postprocessor.FilterPublicMembershipChangesPostProcessor import io.element.android.libraries.matrix.impl.timeline.postprocessor.LastForwardIndicatorsPostProcessor import io.element.android.libraries.matrix.impl.timeline.postprocessor.LoadingIndicatorsPostProcessor import io.element.android.libraries.matrix.impl.timeline.postprocessor.RoomBeginningPostProcessor @@ -84,7 +86,7 @@ private const val PAGINATION_SIZE = 50 class RustTimeline( private val inner: InnerTimeline, override val mode: Timeline.Mode, - private val systemClock: SystemClock, + systemClock: SystemClock, private val joinedRoom: JoinedRoom, private val coroutineScope: CoroutineScope, private val dispatcher: CoroutineDispatcher, @@ -123,6 +125,8 @@ class RustTimeline( private val loadingIndicatorsPostProcessor = LoadingIndicatorsPostProcessor(systemClock) private val lastForwardIndicatorsPostProcessor = LastForwardIndicatorsPostProcessor(mode) private val typingNotificationPostProcessor = TypingNotificationPostProcessor(mode) + private val publicMembershipChangesPostProcessor = FilterPublicMembershipChangesPostProcessor() + private val emptyDayPostProcessor = FilterEmptyDayPostProcessor() private data class RoomTimelineInfo( val roomCreators: ImmutableList, @@ -245,11 +249,21 @@ class RustTimeline( items = items, isDm = isDm, roomCreator = roomCreators.firstOrNull(), - joinRule = joinRule, - isEncrypted = isEncrypted, hasMoreToLoadBackwards = backwardPaginationStatus.hasMoreToLoad, ) } + // This should be the first post processor after room beginning. + .let { items -> + publicMembershipChangesPostProcessor.process( + items = items, + joinRule = joinRule, + isEncrypted = isEncrypted, + ) + } + // After removing public membership changes, we might end up with empty days, so we need to filter them out. + .let { items -> + emptyDayPostProcessor.process(items) + } .let { items -> loadingIndicatorsPostProcessor.process( items = items, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt new file mode 100644 index 0000000000..b7dceafa25 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem + +/** + * Post-processor to filter out day separators for days that don't contain any events. + */ +class FilterEmptyDayPostProcessor { + /** + * Filters out day separators from [items] for days that don't contain any events. + */ + fun process(items: List): List = buildList { + // The timeline is ordered by descending timestamp, so events that happened during a day appear before the day separator for that day. + // We can use this to determine if a day separator should be kept or not. + var hasEvent = false + for (item in items) { + if (item is MatrixTimelineItem.Event) { + hasEvent = true + add(item) + } else if (item is MatrixTimelineItem.Virtual && item.virtual is VirtualTimelineItem.DayDivider) { + if (hasEvent) { + add(item) + hasEvent = false + } + } else { + add(item) + } + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessor.kt new file mode 100644 index 0000000000..806c9369bf --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessor.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import io.element.android.libraries.matrix.api.room.join.JoinRule +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent +import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent + +/** + * Post-processor to filter out public membership changes for non-encrypted, publicly joinable rooms. + */ +class FilterPublicMembershipChangesPostProcessor { + /** + * Filters out public membership changes from [items] if the room is publicly joinable and not encrypted. + */ + fun process( + items: List, + joinRule: JoinRule?, + isEncrypted: Boolean?, + ): List { + return if (joinRule !is JoinRule.Invite && isEncrypted == false) { + filterMembershipEvents(items) + } else { + items + } + } + + private fun filterMembershipEvents(items: List): List = items.filter { item -> + val eventContent = (item as? MatrixTimelineItem.Event)?.event?.content ?: return@filter true + when (eventContent) { + is RoomMembershipContent -> eventContent.change != null && eventContent.change !in listOf(MembershipChange.JOINED, MembershipChange.LEFT) + is ProfileChangeContent -> false + else -> true + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt index ec6a7a5380..8991d26f9c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt @@ -9,12 +9,10 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange import io.element.android.libraries.matrix.api.timeline.item.event.OtherState -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent import io.element.android.libraries.matrix.api.timeline.item.event.StateContent @@ -27,31 +25,17 @@ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) { items: List, isDm: Boolean, roomCreator: UserId?, - joinRule: JoinRule?, - isEncrypted: Boolean?, hasMoreToLoadBackwards: Boolean, ): List { return when { items.isEmpty() -> items mode == Timeline.Mode.PinnedEvents -> items - joinRule !is JoinRule.Invite && isEncrypted == false -> filterRoomMemberEvents(items) isDm -> processForDM(items, roomCreator) hasMoreToLoadBackwards -> items else -> processForRoom(items) } } - private fun filterRoomMemberEvents(items: List): List { - return items.filter { item -> - val eventContent = (item as? MatrixTimelineItem.Event)?.event?.content - when (eventContent) { - is RoomMembershipContent -> eventContent.change !in listOf(MembershipChange.JOINED, MembershipChange.LEFT) - is ProfileChangeContent -> false - else -> true - } - } - } - private fun processForRoom(items: List): List { // No changes needed, timeline start item is already added by the SDK return items diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt new file mode 100644 index 0000000000..7a3a091f4e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt @@ -0,0 +1,118 @@ +/* + * 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.timeline.postprocessor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem +import org.junit.Test + +private const val TODAY = 1_779_779_967_000 +private const val YESTERDAY = TODAY - 24 * 60 * 60 * 1000 +private const val DAY_BEFORE_YESTERDAY = YESTERDAY - 24 * 60 * 60 * 1000 + +class FilterEmptyDayPostProcessorTest { + private val anEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("event"), + event = anEventTimelineItem(), + ) + + private fun aDaySeparator(timestmap: Long) = MatrixTimelineItem.Virtual( + uniqueId = UniqueId("day_$timestmap"), + virtual = VirtualTimelineItem.DayDivider(timestmap) + ) + + @Test + fun `filterEmptyDaySeparators keeps day separator with events after it`() { + val items = listOf( + anEvent, + aDaySeparator(TODAY), + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).hasSize(2) + assertThat(result[0]).isEqualTo(anEvent) + assertThat(result[1]).isEqualTo(aDaySeparator(TODAY)) + } + + @Test + fun `filterEmptyDaySeparators removes day separator with no events after it`() { + val items = listOf( + aDaySeparator(TODAY), + aDaySeparator(YESTERDAY), + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).isEmpty() + } + + @Test + fun `filterEmptyDaySeparators removes first day separator and keeps second when only second has events`() { + val items = listOf( + aDaySeparator(TODAY), + anEvent, + aDaySeparator(YESTERDAY), + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).hasSize(2) + assertThat(result[0]).isEqualTo(anEvent) + assertThat(result[1]).isEqualTo(aDaySeparator(YESTERDAY)) + } + + @Test + fun `filterEmptyDaySeparators handles multiple day separators in a row with no events`() { + val items = listOf( + aDaySeparator(TODAY), + aDaySeparator(YESTERDAY), + aDaySeparator(DAY_BEFORE_YESTERDAY), + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).isEmpty() + } + + @Test + fun `filterEmptyDaySeparators keeps all items when no day separators`() { + val items = listOf( + anEvent, + anEvent.copy(uniqueId = UniqueId("event2")), + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).hasSize(2) + } + + @Test + fun `filterEmptyDaySeparators removes day separator followed by non-event virtual item`() { + val readMarker = MatrixTimelineItem.Virtual( + uniqueId = UniqueId("readMarker"), + virtual = VirtualTimelineItem.ReadMarker + ) + val items = listOf( + aDaySeparator(TODAY), + readMarker, + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).hasSize(1) + assertThat(result[0]).isEqualTo(readMarker) + } + + @Test + fun `filterEmptyDaySeparators keeps day separator when non-event virtual items are between separator and event`() { + val readMarker = MatrixTimelineItem.Virtual( + uniqueId = UniqueId("readMarker"), + virtual = VirtualTimelineItem.ReadMarker + ) + val items = listOf( + anEvent, + readMarker, + aDaySeparator(TODAY), + ) + val result = FilterEmptyDayPostProcessor().process(items) + assertThat(result).hasSize(3) + assertThat(result[2]).isEqualTo(aDaySeparator(TODAY)) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessorTest.kt new file mode 100644 index 0000000000..dd899baf5b --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterPublicMembershipChangesPostProcessorTest.kt @@ -0,0 +1,75 @@ +/* + * 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.timeline.postprocessor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.join.JoinRule +import org.junit.Test + +class FilterPublicMembershipChangesPostProcessorTest { + @Test + fun `processor removes join, leave, and profile events in unencrypted public rooms`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + otherMemberJoinEvent, + messageEvent, + otherMemberLeaveEvent, + profileChangeEvent, + ) + val expected = listOf( + roomCreateEvent, + messageEvent, + ) + val processor = FilterPublicMembershipChangesPostProcessor() + val processedItems = processor.process( + timelineItems, + joinRule = JoinRule.Public, + isEncrypted = false, + ) + assertThat(processedItems).isEqualTo(expected) + } + + @Test + fun `processor keeps all events in encrypted public rooms`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + otherMemberJoinEvent, + messageEvent, + otherMemberLeaveEvent, + profileChangeEvent, + ) + val processor = FilterPublicMembershipChangesPostProcessor() + val processedItems = processor.process( + timelineItems, + joinRule = JoinRule.Public, + isEncrypted = true, + ) + assertThat(processedItems).isEqualTo(timelineItems) + } + + @Test + fun `processor keeps membership events in invite-only rooms`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + otherMemberJoinEvent, + messageEvent, + otherMemberLeaveEvent, + profileChangeEvent, + ) + val processor = FilterPublicMembershipChangesPostProcessor() + val processedItems = processor.process( + timelineItems, + joinRule = JoinRule.Invite, + isEncrypted = null, + ) + assertThat(processedItems).isEqualTo(timelineItems) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index b562847d94..680422827c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test @@ -22,8 +21,6 @@ class RoomBeginningPostProcessorTest { items = emptyList(), isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEmpty() @@ -36,8 +33,6 @@ class RoomBeginningPostProcessorTest { items = listOf(messageEvent), isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEqualTo(listOf(messageEvent)) @@ -50,8 +45,6 @@ class RoomBeginningPostProcessorTest { items = listOf(messageEvent), isDm = true, roomCreator = null, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEqualTo(listOf(messageEvent)) @@ -69,8 +62,6 @@ class RoomBeginningPostProcessorTest { items = timelineItems, isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).containsExactly(timelineStartEvent) @@ -87,8 +78,6 @@ class RoomBeginningPostProcessorTest { items = timelineItems, isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = false, ) assertThat(processedItems).isEqualTo(timelineItems) @@ -111,8 +100,6 @@ class RoomBeginningPostProcessorTest { timelineItems, isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = false ) assertThat(processedItems).isEqualTo(expected) @@ -129,8 +116,6 @@ class RoomBeginningPostProcessorTest { timelineItems, isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = true ) assertThat(processedItems).isEmpty() @@ -146,8 +131,6 @@ class RoomBeginningPostProcessorTest { timelineItems, isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = true ) assertThat(processedItems).isEmpty() @@ -164,80 +147,8 @@ class RoomBeginningPostProcessorTest { timelineItems, isDm = true, roomCreator = A_USER_ID, - joinRule = null, - isEncrypted = null, hasMoreToLoadBackwards = true ) assertThat(processedItems).isEqualTo(listOf(otherMemberJoinEvent)) } - - @Test - fun `processor removes join, leave, and profile events in unencrypted public rooms`() { - val timelineItems = listOf( - roomCreateEvent, - roomCreatorJoinEvent, - otherMemberJoinEvent, - messageEvent, - otherMemberLeaveEvent, - profileChangeEvent, - ) - val expected = listOf( - roomCreateEvent, - messageEvent, - ) - val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process( - timelineItems, - isDm = false, - roomCreator = A_USER_ID, - joinRule = JoinRule.Public, - isEncrypted = false, - hasMoreToLoadBackwards = false - ) - assertThat(processedItems).isEqualTo(expected) - } - - @Test - fun `processor keeps all events in encrypted public rooms`() { - val timelineItems = listOf( - roomCreateEvent, - roomCreatorJoinEvent, - otherMemberJoinEvent, - messageEvent, - otherMemberLeaveEvent, - profileChangeEvent, - ) - val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process( - timelineItems, - isDm = false, - roomCreator = A_USER_ID, - joinRule = JoinRule.Public, - isEncrypted = true, - hasMoreToLoadBackwards = false - ) - assertThat(processedItems).isEqualTo(timelineItems) - } - - @Test - fun `processor keeps membership events in invite-only rooms`() { - val timelineItems = listOf( - roomCreateEvent, - roomCreatorJoinEvent, - otherMemberJoinEvent, - messageEvent, - otherMemberLeaveEvent, - profileChangeEvent, - ) - val processor = RoomBeginningPostProcessor(Timeline.Mode.Live) - val processedItems = processor.process( - timelineItems, - isDm = false, - roomCreator = A_USER_ID, - joinRule = JoinRule.Invite, - isEncrypted = null, - hasMoreToLoadBackwards = false - ) - assertThat(processedItems).isEqualTo(timelineItems) - } } From e1f968390a35e10f7eb45e28fd10698cb8b0b156 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Tue, 26 May 2026 11:56:45 +0300 Subject: [PATCH 0506/1083] fix unused import --- .../android/libraries/slashcommands/impl/CommandExecutorTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt index 800cdecfb3..c0f2ce89c2 100644 --- a/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt +++ b/libraries/slashcommands/impl/src/test/kotlin/io/element/android/libraries/slashcommands/impl/CommandExecutorTest.kt @@ -14,7 +14,6 @@ import io.element.android.libraries.matrix.api.timeline.MsgType import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.A_MESSAGE import io.element.android.libraries.matrix.test.A_USER_ID -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.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom From 87b3a5d2f0f3cffe1a19a882985dc1bf05492530 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 May 2026 12:19:26 +0200 Subject: [PATCH 0507/1083] Add better logs to track token update failures (#6859) 1. Make some logs use `info` log level instead of `debug`, so they appear in most user's bug reports. 2. Make the anonymized tokens even harder to reverse. 3. Detect when the tokens we should be saving match the current ones, as that's an error. --- .../matrix/impl/RustClientSessionDelegate.kt | 16 ++++++++++++++-- .../matrix/impl/RustMatrixClientFactory.kt | 2 +- .../android/libraries/matrix/impl/util/Token.kt | 3 ++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt index c776ca8522..a5c69bf831 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt @@ -65,10 +65,22 @@ class RustClientSessionDelegate( // This always runs on a background thread, so we *can* do blocking calls here, although we should avoid doing heavy work override fun saveSessionInKeychain(session: Session) { + Timber.tag(loggerTag.value).i("Saving new session info for user ${session.userId} after a token refresh") runCatchingExceptions { val existingData = runBlocking { sessionStore.getSession(session.userId) } ?: return + + if (existingData.accessToken == session.accessToken) { + Timber.tag(loggerTag.value).e("Access token is the same as the one already stored, this should not happen after a token refresh!") + return + } + + if (existingData.refreshToken == session.refreshToken) { + Timber.tag(loggerTag.value).e("Refresh token is the same as the one already stored, this should not happen after a token refresh!") + return + } + val (anonymizedAccessToken, anonymizedRefreshToken) = session.anonymizedTokens() - Timber.tag(loggerTag.value).d( + Timber.tag(loggerTag.value).i( "Saving new session data with token: access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'. " + "Was token valid: ${existingData.isTokenValid}" ) @@ -79,7 +91,7 @@ class RustClientSessionDelegate( sessionPaths = existingData.getSessionPaths(), ) runBlocking { sessionStore.updateData(newData) } - Timber.tag(loggerTag.value).d("Saved new session data with access token: '$anonymizedAccessToken'.") + Timber.tag(loggerTag.value).i("Saved new session data.") }.onFailure { Timber.tag(loggerTag.value).e(it, "Failed to save new session data.") } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 6757edf16c..c22a8b9454 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -131,7 +131,7 @@ class RustMatrixClientFactory( analyticsService = analyticsService, workManagerScheduler = workManagerScheduler, ).also { - Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") + Timber.tag("RustMatrixClient").i("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Token.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Token.kt index 815e134cf2..f5df21008b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Token.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Token.kt @@ -16,7 +16,8 @@ private val sha256 by lazy { MessageDigest.getInstance("SHA-256") } @OptIn(ExperimentalStdlibApi::class) private fun anonymizeToken(token: String): String { - return sha256.digest(token.toByteArray()).toHexString() + // Only keep the first 32 chars (16 bytes) of the hashed token to avoid displaying too much information. + return sha256.digest(token.toByteArray()).toHexString().take(32) } fun SessionData?.anonymizedTokens(): Pair { From 5aea8852407c2b8f49e630274135af9be2effff4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 10:21:34 +0000 Subject: [PATCH 0508/1083] Update dependency io.element.android:element-call-embedded to v0.20.0 --- 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 a328218d79..882d66f358 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -235,7 +235,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.19.4" +element_call_embedded = "io.element.android:element-call-embedded:0.20.0" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From b34473a88cc5682619e7cffddcaffd354dabc33e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 10:21:44 +0000 Subject: [PATCH 0509/1083] Update roborazzi to v1.62.0 --- 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 a328218d79..52cf4ca9ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ accompanist = "0.37.3" # Test test_core = "1.7.0" -roborazzi = "1.60.0" +roborazzi = "1.62.0" # Jetbrain datetime = "0.8.0" From 4a907688937c66049dab0e66de388fb4b33e2c41 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 26 May 2026 15:25:48 +0200 Subject: [PATCH 0510/1083] Read map tiler custom style from matrix .well-known file Closes #6844 --- .../MapTilerTileServerStyleUriBuilder.kt | 21 +++- .../api/internal/TileServerStyleUriBuilder.kt | 14 ++- .../MapTilerTileServerStyleUriBuilderTest.kt | 30 +++++- .../impl/common/ui/MapBottomSheetScaffold.kt | 28 ++++-- .../impl/share/ShareLocationPresenter.kt | 7 ++ .../location/impl/share/ShareLocationState.kt | 2 + .../impl/share/ShareLocationStateProvider.kt | 6 ++ .../location/impl/share/ShareLocationView.kt | 1 + .../impl/show/ShowLocationPresenter.kt | 9 ++ .../location/impl/show/ShowLocationState.kt | 2 + .../impl/show/ShowLocationStateProvider.kt | 6 ++ .../location/impl/show/ShowLocationView.kt | 1 + .../impl/share/ShareLocationPresenterTest.kt | 96 ++++++++++--------- .../show/DefaultShowLocationEntryPointTest.kt | 2 + .../impl/show/ShowLocationPresenterTest.kt | 29 +++++- gradle/libs.versions.toml | 2 +- .../libraries/matrix/api/MatrixClient.kt | 5 + .../libraries/matrix/impl/RustMatrixClient.kt | 6 ++ .../matrix/impl/pushers/RustPushersService.kt | 3 +- .../libraries/matrix/test/FakeMatrixClient.kt | 5 + 20 files changed, 211 insertions(+), 64 deletions(-) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt index d119dc7eb2..761adb25cf 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt @@ -25,8 +25,23 @@ internal class MapTilerTileServerStyleUriBuilder( darkMapId = BuildConfig.MAPTILER_DARK_MAP_ID, ) - override fun build(darkMode: Boolean): String { - val mapId = if (darkMode) darkMapId else lightMapId - return "$baseUrl/$mapId/style.json?key=$apiKey" + override fun build( + customMapStyleUrl: String?, + darkMode: Boolean, + ): String { + return buildString { + if (customMapStyleUrl.isNullOrBlank()) { + val mapId = if (darkMode) darkMapId else lightMapId + append(baseUrl) + append("/") + append(mapId) + append("/") + append("style.json") + } else { + append(customMapStyleUrl.removeSuffix("/")) + } + append("?key=") + append(apiKey) + } } } diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt index 17b620eec9..762d580f8e 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt @@ -19,21 +19,25 @@ import io.element.android.compound.theme.ElementTheme */ interface TileServerStyleUriBuilder { fun build( + customMapStyleUrl: String?, darkMode: Boolean, ): String } -fun TileServerStyleUriBuilder(): TileServerStyleUriBuilder = MapTilerTileServerStyleUriBuilder() - /** * Provides and remembers a style URI for a MapLibre compatible tile server. * * Used for rendering dynamic maps. */ @Composable -fun rememberTileStyleUrl(): String { +fun rememberTileStyleUrl( + customMapStyleUrl: String?, +): String { val darkMode = !ElementTheme.isLightTheme - return remember(darkMode) { - TileServerStyleUriBuilder().build(darkMode) + return remember(darkMode, customMapStyleUrl) { + MapTilerTileServerStyleUriBuilder().build( + customMapStyleUrl = customMapStyleUrl, + darkMode = darkMode, + ) } } diff --git a/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt index d5c6521258..2e07204594 100644 --- a/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt +++ b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt @@ -22,14 +22,40 @@ class MapTilerTileServerStyleUriBuilderTest { @Test fun `light map uri`() { assertThat( - builder.build(darkMode = false) + builder.build( + customMapStyleUrl = null, + darkMode = false, + ) ).isEqualTo("https://base.url/aLightMapId/style.json?key=anApiKey") } @Test fun `dark map uri`() { assertThat( - builder.build(darkMode = true) + builder.build( + customMapStyleUrl = null, + darkMode = true, + ) ).isEqualTo("https://base.url/aDarkMapId/style.json?key=anApiKey") } + + @Test + fun `custom map uri light`() { + assertThat( + builder.build( + customMapStyleUrl = "https://custom.url/style.json", + darkMode = false, + ) + ).isEqualTo("https://custom.url/style.json?key=anApiKey") + } + + @Test + fun `custom map uri dark`() { + assertThat( + builder.build( + customMapStyleUrl = "https://custom.url/style.json", + darkMode = true, + ) + ).isEqualTo("https://custom.url/style.json?key=anApiKey") + } } 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 13c30c28eb..5f09bcedb2 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 @@ -37,6 +37,7 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Dp @@ -44,9 +45,11 @@ import androidx.compose.ui.unit.dp 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.architecture.AsyncData 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 io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import org.maplibre.compose.camera.CameraState import org.maplibre.compose.camera.rememberCameraState import org.maplibre.compose.map.MapOptions @@ -63,6 +66,7 @@ import kotlin.math.roundToInt * - Updating camera position padding based on sheet height * - Rendering the MaplibreMap with proper ornament positioning * + * @param customMapStyleUrl Optional custom style URL for the map * @param modifier Modifier for the root layout * @param scaffoldState State for the bottom sheet scaffold * @param cameraState The camera state for the map @@ -79,6 +83,7 @@ import kotlin.math.roundToInt @OptIn(ExperimentalMaterial3Api::class) @Composable fun MapBottomSheetScaffold( + customMapStyleUrl: AsyncData, modifier: Modifier = Modifier, scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState( bottomSheetState = rememberStandardBottomSheetState(initialValue = SheetValue.PartiallyExpanded) @@ -130,13 +135,22 @@ fun MapBottomSheetScaffold( val ornamentOptions = mapOptions.ornamentOptions.copy(padding = sheetPadding) val mapOptions = mapOptions.copy(ornamentOptions = ornamentOptions) Box { - MaplibreMap( - options = mapOptions, - baseStyle = BaseStyle.Uri(rememberTileStyleUrl()), - modifier = Modifier.fillMaxSize(), - cameraState = cameraState, - content = mapContent, - ) + when (customMapStyleUrl) { + is AsyncData.Success -> { + MaplibreMap( + options = mapOptions, + baseStyle = BaseStyle.Uri(rememberTileStyleUrl(customMapStyleUrl.data)), + modifier = Modifier.fillMaxSize(), + cameraState = cameraState, + content = mapContent, + ) + } + else -> { + Box(modifier = Modifier.fillMaxSize()) { + CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) + } + } + } overlayContent(sheetPadding) } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index a1e45cfea2..9f4c8333b8 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -14,6 +14,7 @@ import androidx.compose.runtime.collectAsState 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.rememberCoroutineScope import androidx.compose.runtime.setValue @@ -35,6 +36,7 @@ import io.element.android.features.location.impl.common.toDialogState import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.messages.api.MessageComposerContext import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.extensions.flatMap @@ -86,6 +88,10 @@ class ShareLocationPresenter( } val startLiveLocationAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } val currentUser by client.userProfile.collectAsState() + val customMapStyleUrl by produceState(AsyncData.Loading()) { + // Ignore errors + value = AsyncData.Success(client.getMapStyleUrl().getOrNull()) + } val sendLiveLocationPermissions by room.permissionsAsState(SendLiveLocationPermissions.DEFAULT) { perms -> perms.sendLiveLocationPermissions() } @@ -161,6 +167,7 @@ class ShareLocationPresenter( } return ShareLocationState( + customMapStyleUrl = customMapStyleUrl, currentUser = currentUser, dialogState = dialogState, trackUserLocation = trackUserPosition, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt index 68598cba04..9e78345bab 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt @@ -10,10 +10,12 @@ package io.element.android.features.location.impl.share import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList data class ShareLocationState( + val customMapStyleUrl: AsyncData, val currentUser: MatrixUser, val dialogState: Dialog, val trackUserLocation: Boolean, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt index ae1b765b6b..e7942b12df 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt @@ -11,6 +11,7 @@ package io.element.android.features.location.impl.share import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.persistentListOf @@ -76,10 +77,14 @@ class ShareLocationStateProvider : PreviewParameterProvider hasLocationPermission = true, canShareLiveLocation = true, ), + aShareLocationState( + customMapStyleUrl = AsyncData.Loading(), + ), ) } fun aShareLocationState( + customMapStyleUrl: AsyncData = AsyncData.Success(null), currentUser: MatrixUser = MatrixUser(UserId("@user:matrix.org")), dialogState: ShareLocationState.Dialog = ShareLocationState.Dialog.None, trackUserPosition: Boolean = false, @@ -90,6 +95,7 @@ fun aShareLocationState( eventSink: (ShareLocationEvent) -> Unit = {}, ): ShareLocationState { return ShareLocationState( + customMapStyleUrl = customMapStyleUrl, currentUser = currentUser, dialogState = dialogState, trackUserLocation = trackUserPosition, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index e20ee3a7a5..985c6c8bdc 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -117,6 +117,7 @@ fun ShareLocationView( } MapBottomSheetScaffold( + customMapStyleUrl = state.customMapStyleUrl, cameraState = cameraState, modifier = modifier, scaffoldState = scaffoldState, 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 207b4b01dd..bdb6dd26b8 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 @@ -33,6 +33,7 @@ import io.element.android.features.location.impl.common.permissions.PermissionsP import io.element.android.features.location.impl.common.permissions.PermissionsState 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.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.core.meta.BuildMeta @@ -40,6 +41,7 @@ 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.MatrixClient 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 @@ -58,6 +60,7 @@ class ShowLocationPresenter( private val buildMeta: BuildMeta, private val dateFormatter: DateFormatter, private val stringProvider: StringProvider, + private val client: MatrixClient, private val joinedRoom: JoinedRoom, private val liveLocationShareManager: ActiveLiveLocationShareManager, ) : Presenter { @@ -78,6 +81,11 @@ class ShowLocationPresenter( mutableStateOf(LocationConstraintsDialogState.None) } + val customMapStyleUrl by produceState(AsyncData.Loading()) { + // Ignore errors + value = AsyncData.Success(client.getMapStyleUrl().getOrNull()) + } + LaunchedEffect(permissionsState.permissions) { if (permissionsState.isAnyGranted) { dialogState = LocationConstraintsDialogState.None @@ -188,6 +196,7 @@ class ShowLocationPresenter( } return ShowLocationState( + customMapStyleUrl = customMapStyleUrl, dialogState = dialogState, locationShares = locationShares, focusedLocation = focusedLocation, 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 720697cbf7..478a3bd730 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 @@ -11,6 +11,7 @@ package io.element.android.features.location.impl.show import io.element.android.features.location.api.Location 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.architecture.AsyncData import io.element.android.libraries.designsystem.components.PinVariant import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.api.core.UserId @@ -18,6 +19,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType import kotlinx.collections.immutable.ImmutableList data class ShowLocationState( + val customMapStyleUrl: AsyncData, val isLive: Boolean, val dialogState: LocationConstraintsDialogState, val locationShares: ImmutableList, 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 1c7b9a3160..85eacd3ce4 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 @@ -11,6 +11,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.impl.common.ui.LocationConstraintsDialogState +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE @@ -41,12 +42,16 @@ class ShowLocationStateProvider : PreviewParameterProvider { hasLocationPermission = true, isTrackMyLocation = true, ), + aShowLocationState( + customMapStyleUrl = AsyncData.Loading(), + ), ) } private const val APP_NAME = "ApplicationName" fun aShowLocationState( + customMapStyleUrl: AsyncData = AsyncData.Success(null), isLive: Boolean = false, constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None, locationShares: List = listOf(aLocationShareItem(isLive = isLive)), @@ -57,6 +62,7 @@ fun aShowLocationState( eventSink: (ShowLocationEvent) -> Unit = {}, ): ShowLocationState { return ShowLocationState( + customMapStyleUrl = customMapStyleUrl, dialogState = constraintsDialogState, locationShares = locationShares.toImmutableList(), focusedLocation = focusedLocation, 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 6766fa6424..80ffaabedd 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 @@ -100,6 +100,7 @@ fun ShowLocationView( } } MapBottomSheetScaffold( + customMapStyleUrl = state.customMapStyleUrl, sheetDragHandle = if (state.isSheetDraggable) { { BottomSheetDefaults.DragHandle() } } else { diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index 1bc4fce586..5be96a50c5 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -15,6 +15,7 @@ import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.emptyPreferences import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow +import app.cash.turbine.ReceiveTurbine import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.Composer @@ -75,7 +76,10 @@ class ShareLocationPresenterTest { private val fakeMessageComposerContext = FakeMessageComposerContext() private val fakeLocationActions = FakeLocationActions() private val fakeBuildMeta = aBuildMeta(applicationName = "app name") - private val fakeMatrixClient = FakeMatrixClient(sessionId = A_USER_ID) + private val fakeMatrixClient = FakeMatrixClient( + sessionId = A_USER_ID, + getMapStyleUrlResult = { Result.success(null) }, + ) private val durationFormatter = FakeDurationFormatter() @@ -85,6 +89,7 @@ class ShareLocationPresenterTest { locationActions: FakeLocationActions = fakeLocationActions, liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), liveLocationStore: LiveLocationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId), + client: FakeMatrixClient = fakeMatrixClient, ): ShareLocationPresenter = ShareLocationPresenter( permissionsPresenterFactory = { fakePermissionsPresenter }, room = joinedRoom, @@ -93,7 +98,7 @@ class ShareLocationPresenterTest { messageComposerContext = fakeMessageComposerContext, locationActions = locationActions, buildMeta = fakeBuildMeta, - client = fakeMatrixClient, + client = client, durationFormatter = durationFormatter, liveLocationShareManager = liveLocationShareManager, liveLocationStore = liveLocationStore, @@ -110,14 +115,31 @@ class ShareLocationPresenterTest { val shareLocationPresenter = createShareLocationPresenter() shareLocationPresenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() + assertThat(state.customMapStyleUrl.isLoading()).isFalse() assertThat(state.trackUserLocation).isTrue() assertThat(state.hasLocationPermission).isTrue() assertThat(state.dialogState).isEqualTo(ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.None)) } } + @Test + fun `present - non-null customMapStyleUrl`() = runTest { + val shareLocationPresenter = createShareLocationPresenter( + client = FakeMatrixClient( + sessionId = A_USER_ID, + getMapStyleUrlResult = { Result.success("aUrl") }, + ) + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.customMapStyleUrl.isLoading()).isTrue() + val finalState = awaitItem() + assertThat(finalState.customMapStyleUrl.dataOrNull()).isEqualTo("aUrl") + } + } + @Test fun `initial state with permissions partially granted and location enabled`() = runTest { val shareLocationPresenter = createShareLocationPresenter() @@ -131,8 +153,7 @@ class ShareLocationPresenterTest { moleculeFlow(RecompositionMode.Immediate) { shareLocationPresenter.present() }.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isTrue() assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.dialogState).isEqualTo(ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.None)) @@ -152,8 +173,7 @@ class ShareLocationPresenterTest { moleculeFlow(RecompositionMode.Immediate) { shareLocationPresenter.present() }.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isFalse() assertThat(initialState.hasLocationPermission).isFalse() assertThat(initialState.dialogState).isEqualTo( @@ -173,8 +193,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isFalse() assertThat(initialState.hasLocationPermission).isFalse() assertThat(initialState.dialogState).isEqualTo( @@ -195,8 +214,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isFalse() assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.dialogState).isEqualTo( @@ -216,8 +234,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isTrue() initialState.eventSink(ShareLocationEvent.StopTrackingUserLocation) @@ -237,8 +254,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.dialogState).isEqualTo( ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionRationale) ) @@ -260,7 +276,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - val initialState = awaitItem() + val initialState = awaitFirstItem() initialState.eventSink(ShareLocationEvent.RequestPermissions) // Wait for dialog to be dismissed @@ -282,8 +298,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() initialState.eventSink(ShareLocationEvent.OpenAppSettings) val settingsOpenedState = awaitItem() @@ -304,8 +319,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() assertThat(initialState.dialogState).isEqualTo( ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled) ) @@ -337,8 +351,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() initialState.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val durationDialogState = awaitItem() @@ -358,8 +371,7 @@ class ShareLocationPresenterTest { ) presenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val dialogState = awaitItem() @@ -385,8 +397,7 @@ class ShareLocationPresenterTest { ) presenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) awaitItem() @@ -413,8 +424,7 @@ class ShareLocationPresenterTest { ) presenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val disclaimerState = awaitItem() @@ -444,8 +454,7 @@ class ShareLocationPresenterTest { ) presenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val durationState = awaitItem() @@ -472,8 +481,7 @@ class ShareLocationPresenterTest { ) presenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val dialogState = awaitItem() @@ -504,8 +512,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() // Dismiss initial dialog initialState.eventSink(ShareLocationEvent.DismissDialog) val dismissedState = awaitItem() @@ -539,8 +546,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val initialState = awaitItem() + val initialState = awaitFirstItem() initialState.eventSink( ShareLocationEvent.ShareStaticLocation( @@ -593,7 +599,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - val initialState = awaitItem() + val initialState = awaitFirstItem() initialState.eventSink( ShareLocationEvent.ShareStaticLocation( @@ -641,8 +647,7 @@ class ShareLocationPresenterTest { ) shareLocationPresenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration = 1.hours)) advanceUntilIdle() assert(startShareLambda).isCalledOnce().with( @@ -659,8 +664,7 @@ class ShareLocationPresenterTest { timelineMode = Timeline.Mode.Live, ) shareLocationPresenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() assertThat(state.canShareLiveLocation).isTrue() } } @@ -671,11 +675,15 @@ class ShareLocationPresenterTest { timelineMode = Timeline.Mode.Thread(A_THREAD_ID), ) shareLocationPresenter.test { - skipItems(1) - val state = awaitItem() + val state = awaitFirstItem() assertThat(state.canShareLiveLocation).isFalse() } } + + private suspend fun ReceiveTurbine.awaitFirstItem(): T { + skipItems(2) + return awaitItem() + } } private fun createLiveLocationStore( 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 985dcc1f9c..8f55510128 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.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.FakeMatrixClient 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 @@ -48,6 +49,7 @@ class DefaultShowLocationEntryPointTest { dateFormatter = FakeDateFormatter(), stringProvider = FakeStringProvider(), joinedRoom = joinedRoom, + client = FakeMatrixClient(), liveLocationShareManager = FakeActiveLiveLocationShareManager(), ) }, 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 c1f9f6487e..da3cea88f6 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,10 +22,13 @@ import io.element.android.features.location.impl.common.permissions.PermissionsS import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.libraries.dateformatter.test.FakeDateFormatter +import io.element.android.libraries.matrix.api.MatrixClient 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.A_USER_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare @@ -61,6 +64,7 @@ class ShowLocationPresenterTest { ), locationActions: FakeLocationActions = fakeLocationActions, joinedRoom: JoinedRoom = FakeJoinedRoom(), + client: MatrixClient = FakeMatrixClient(), liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ) = ShowLocationPresenter( mode = mode, @@ -70,6 +74,7 @@ class ShowLocationPresenterTest { dateFormatter = fakeDateFormatter, stringProvider = FakeStringProvider(), joinedRoom = joinedRoom, + client = client, liveLocationShareManager = liveLocationShareManager, ) @@ -85,11 +90,28 @@ class ShowLocationPresenterTest { val presenter = createShowLocationPresenter() presenter.test { val initialState = awaitItem() + assertThat(initialState.customMapStyleUrl.isLoading()).isTrue() assertThat(initialState.hasLocationPermission).isFalse() assertThat(initialState.isTrackMyLocation).isFalse() } } + @Test + fun `present - non-null customMapStyleUrl`() = runTest { + val shareLocationPresenter = createShowLocationPresenter( + client = FakeMatrixClient( + sessionId = A_USER_ID, + getMapStyleUrlResult = { Result.success("aUrl") }, + ) + ) + shareLocationPresenter.test { + val state = awaitItem() + assertThat(state.customMapStyleUrl.isLoading()).isTrue() + val finalState = awaitItem() + assertThat(finalState.customMapStyleUrl.dataOrNull()).isEqualTo("aUrl") + } + } + @Test fun `emits initial state location permission denied once`() = runTest { fakePermissionsPresenter.givenState( @@ -146,8 +168,13 @@ class ShowLocationPresenterTest { fun `centers on user location`() = runTest { fakePermissionsPresenter.givenState(aPermissionsState(permissions = PermissionsState.Permissions.AllGranted)) - val presenter = createShowLocationPresenter() + val presenter = createShowLocationPresenter( + client = FakeMatrixClient( + getMapStyleUrlResult = { Result.success(null) } + ) + ) presenter.test { + skipItems(1) val initialState = awaitItem() assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.isTrackMyLocation).isFalse() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a328218d79..170504f0fe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -179,7 +179,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.20" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.26" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index bd7b1399e1..836459f8c7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -221,6 +221,11 @@ interface MatrixClient { */ suspend fun performDatabaseVacuum(): Result + /** + * Returns the URL of the map style configured on the server, if any. + */ + suspend fun getMapStyleUrl(): Result + /** * Resets the cached client `well-known` config by the SDK. */ diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 05e52605dc..bec20aedf2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -808,6 +808,12 @@ class RustMatrixClient( } } + override suspend fun getMapStyleUrl(): Result = withContext(sessionDispatcher) { + runCatchingExceptions { + innerClient.tileServer()?.mapStyleUrl + } + } + override suspend fun resetWellKnownConfig(): Result { return runCatchingExceptions { Timber.d("Resetting well-known config for session $sessionId") diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt index 860993d4bc..03a4ca3281 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt @@ -44,7 +44,8 @@ class RustPushersService( appDisplayName = setHttpPusherData.appDisplayName, deviceDisplayName = setHttpPusherData.deviceDisplayName, profileTag = setHttpPusherData.profileTag, - lang = setHttpPusherData.lang + lang = setHttpPusherData.lang, + append = false, ) } .mapFailure { it.mapClientException() } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index af28dc37e4..3278eae855 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -115,6 +115,7 @@ class FakeMatrixClient( private val addRecentEmojiLambda: (String) -> Result = { Result.success(Unit) }, private val markRoomAsFullyReadResult: (RoomId, EventId) -> Result = { _, _ -> lambdaError() }, private val performDatabaseVacuumLambda: () -> Result = { lambdaError() }, + private val getMapStyleUrlResult: () -> Result = { lambdaError() }, private val getDatabaseSizesLambda: () -> Result = { lambdaError() }, private val resetWellKnownConfigLambda: () -> Result = { lambdaError() }, ) : MatrixClient { @@ -373,6 +374,10 @@ class FakeMatrixClient( return performDatabaseVacuumLambda() } + override suspend fun getMapStyleUrl(): Result = simulateLongTask { + getMapStyleUrlResult() + } + override suspend fun canLinkNewDevice(): Result = simulateLongTask { return canLinkNewDeviceResult() } From f6bdf51f6d360f81ba32490e9bded21b8eaab6b3 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 26 May 2026 14:33:42 +0000 Subject: [PATCH 0511/1083] Update screenshots --- ...features.location.impl.share_ShareLocationView_Day_9_en.png | 3 +++ ...atures.location.impl.share_ShareLocationView_Night_9_en.png | 3 +++ .../features.location.impl.show_ShowLocationView_Day_8_en.png | 3 +++ ...features.location.impl.show_ShowLocationView_Night_8_en.png | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_9_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_9_en.png new file mode 100644 index 0000000000..f4ff1a611e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc36d1f05a6035dd4775dda0592d5557d45314c24d638738401eb910b6ba719c +size 21719 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_9_en.png new file mode 100644 index 0000000000..213a75dce9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5198742a388a2bd04985fe6b9f035de3878125607fe3b554209b0eb5c4590db3 +size 19935 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png new file mode 100644 index 0000000000..e01e90f7d0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dea2fa898a6f9b921eca0931d7380814b31ba858b88c90ba1fbab6332b4c8ebb +size 20722 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png new file mode 100644 index 0000000000..547e7ba364 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9f64bc6bb5956459f8943c05bbf0aa6ee9e97e3103713f34d49c013f86376a9 +size 18878 From dd48582313563aee3ad8a11e0178084a65dfb291 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 May 2026 19:27:35 +0200 Subject: [PATCH 0512/1083] Remove DI-generated code from Kover reports (#6834) * Remove DI-generated code from Kover reports * Add more regexes for DI-generated code to exclude --- plugins/src/main/kotlin/extension/KoverExtension.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/src/main/kotlin/extension/KoverExtension.kt b/plugins/src/main/kotlin/extension/KoverExtension.kt index 5d6b1ddabb..c851a25ab9 100644 --- a/plugins/src/main/kotlin/extension/KoverExtension.kt +++ b/plugins/src/main/kotlin/extension/KoverExtension.kt @@ -126,6 +126,14 @@ fun Project.setupKover() { "io.element.android.tests.konsist.failures", // Copied from Appyx "io.element.android.libraries.architecture.appyx.SafeChildrenTransitionScope", + // DI-generated classes + "io.element.android.x.di.*Impl", + "io.element.android.x.di.*Impls", + "io.element.android.x.di.*Mirror", + "io.element.android.x.di.*Factory", + $$"io.element.android.*$Metro*", + $$"io.element.android.*$Factory*", + $$"io.element.android.*$Impl*", ) annotatedBy( "androidx.compose.ui.tooling.preview.Preview", From d7af6c0d0ad01dc3cb93d149cea3e673bbae5812 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 May 2026 19:28:23 +0200 Subject: [PATCH 0513/1083] Use a raw key for the SDK stores for new sessions (#6835) * Use a raw key for the SDK stores for new sessions - Add `ClientSecret` to tell apart the legacy passphrases from the raw keys and centralise parsing/formatting. - Use the `ClientSecret` to set the passphrase/key in the `SqliteStoreBuilder`. --- .../libraries/matrix/impl/ClientSecret.kt | 66 +++++++++++++++++++ .../matrix/impl/RustMatrixClientFactory.kt | 8 ++- .../auth/RustMatrixAuthenticationService.kt | 28 ++++---- ...Generator.kt => DefaultSecretGenerator.kt} | 17 +++-- .../matrix/impl/keys/PassphraseGenerator.kt | 17 ----- .../matrix/impl/keys/SecretGenerator.kt | 30 +++++++++ .../matrix/impl/storage/SqliteStoreBuilder.kt | 36 +++++++++- .../impl/auth/FakePassphraseGenerator.kt | 18 ----- .../matrix/impl/auth/FakeSecretGenerator.kt | 21 ++++++ .../RustMatrixAuthenticationServiceTest.kt | 2 +- .../keys/DefaultPassphraseGeneratorTest.kt | 24 ------- .../impl/keys/DefaultSecretGeneratorTest.kt | 35 ++++++++++ .../impl/storage/FakeSqliteStoreBuilder.kt | 3 +- .../DefaultAnalyticsColdStartWatcher.kt | 5 +- 14 files changed, 220 insertions(+), 90 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt rename libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/{DefaultPassphraseGenerator.kt => DefaultSecretGenerator.kt} (50%) delete mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/PassphraseGenerator.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt delete mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt delete mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt new file mode 100644 index 0000000000..25d040e15b --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt @@ -0,0 +1,66 @@ +/* + * 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 + +import okio.ByteString.Companion.decodeHex + +/** + * Represents a client secret used to encrypt/decrypt data from databases, which can be either a passphrase or a raw key. + */ +sealed interface ClientSecret { + /** + * A passphrase that can be used to derive a key for encryption/decryption. + */ + data class Passphrase(val value: String) : ClientSecret { + override fun formattedAsString(): String = toString() + } + + /** + * A raw key that can be directly used for encryption/decryption. The key is represented as a byte array, and is formatted as a string in the form of + * `x'...'` where the bytes are encoded as hex characters. + */ + data class RawKey(val bytes: ByteArray) : ClientSecret { + override fun formattedAsString() = "x'${bytes.toHexString()}'" + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + return bytes.contentEquals((other as RawKey).bytes) + } + + override fun hashCode(): Int { + return bytes.contentHashCode() + } + + override fun toString(): String { + return formattedAsString() + } + } + + /** + * Format the client secret as a string that can be parsed back with [fromString]. + * For a passphrase, this is just the passphrase value. For a raw key, this is the hex-encoded representation of the key formatted as `x'...'`. + */ + fun formattedAsString(): String + + companion object { + /** + * Parse a string representation of a client secret, which can be either a passphrase or a raw key formatted as `x'...'`. + */ + fun fromString(secret: String): ClientSecret { + val regex = Regex("^x'([0-9a-fA-F]+)'$") + val rawKeyMatch = regex.matchEntire(secret) + return if (rawKeyMatch != null) { + RawKey(rawKeyMatch.groupValues[1].decodeHex().toByteArray()) + } else { + Passphrase(secret) + } + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index c22a8b9454..9a7452aa5f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -75,9 +75,11 @@ class RustMatrixClientFactory( ) suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { + // This secret is called 'passphrase' for historical reasons, but it can be a raw key or an actual passphrase + val clientSecret = sessionData.passphrase?.let(ClientSecret::fromString) val client = getBaseClientBuilder( sessionPaths = sessionData.getSessionPaths(), - passphrase = sessionData.passphrase, + clientSecret = clientSecret, slidingSyncType = ClientBuilderSlidingSync.Restored, ) .homeserverUrl(sessionData.homeserverUrl) @@ -137,13 +139,13 @@ class RustMatrixClientFactory( internal suspend fun getBaseClientBuilder( sessionPaths: SessionPaths, - passphrase: String?, + clientSecret: ClientSecret?, slidingSyncType: ClientBuilderSlidingSync, ): ClientBuilder { return clientBuilderProvider.provide() .run { sqliteStoreBuilderProvider.provide(sessionPaths) - .passphrase(passphrase) + .secret(clientSecret) .setupClientBuilder(this) } .setSessionDelegate(sessionDelegate) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 692edf79ae..812a0dd6fe 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -30,12 +30,13 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.impl.ClientBuilderSlidingSync +import io.element.android.libraries.matrix.impl.ClientSecret import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.auth.qrlogin.QrErrorMapper import io.element.android.libraries.matrix.impl.auth.qrlogin.SdkQrCodeLoginData import io.element.android.libraries.matrix.impl.auth.qrlogin.toStep import io.element.android.libraries.matrix.impl.exception.mapClientException -import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator +import io.element.android.libraries.matrix.impl.keys.SecretGenerator import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory @@ -65,7 +66,7 @@ class RustMatrixAuthenticationService( private val coroutineDispatchers: CoroutineDispatchers, private val sessionStore: SessionStore, private val rustMatrixClientFactory: RustMatrixClientFactory, - private val passphraseGenerator: PassphraseGenerator, + private val secretGenerator: SecretGenerator, private val oAuthConfigurationProvider: OAuthConfigurationProvider, private val enterpriseService: EnterpriseService, ) : MatrixAuthenticationService { @@ -74,7 +75,7 @@ class RustMatrixAuthenticationService( // Passphrase which will be used for new sessions. Existing sessions will use the passphrase // stored in the SessionData. - private val pendingPassphrase = getDatabasePassphrase() + private val pendingKey by lazy { getDatabaseKey() } // Need to keep a copy of the current session path to eventually delete it. // Ideally it would be possible to get the sessionPath from the Client to avoid doing this. @@ -115,12 +116,9 @@ class RustMatrixAuthenticationService( } } - private fun getDatabasePassphrase(): String? { - val passphrase = passphraseGenerator.generatePassphrase() - if (passphrase != null) { - Timber.w("New sessions will be encrypted with a passphrase") - } - return passphrase + private fun getDatabaseKey(): ClientSecret { + Timber.d("New sessions will be encrypted with a raw key") + return secretGenerator.generateKey() } override suspend fun setHomeserver(homeserver: String): Result = @@ -159,7 +157,7 @@ class RustMatrixAuthenticationService( .toSessionData( isTokenValid = true, loginType = LoginType.PASSWORD, - passphrase = pendingPassphrase, + passphrase = pendingKey.formattedAsString(), sessionPaths = currentSessionPaths, ) val matrixClient = rustMatrixClientFactory.create(client) @@ -231,7 +229,7 @@ class RustMatrixAuthenticationService( val sessionData = externalSession.toSessionData( isTokenValid = true, loginType = LoginType.PASSWORD, - passphrase = pendingPassphrase, + passphrase = pendingKey.formattedAsString(), sessionPaths = currentSessionPaths, ) @@ -324,7 +322,7 @@ class RustMatrixAuthenticationService( val sessionData = client.session().toSessionData( isTokenValid = true, loginType = LoginType.OIDC, - passphrase = pendingPassphrase, + passphrase = pendingKey.formattedAsString(), sessionPaths = currentSessionPaths, ) val matrixClient = rustMatrixClientFactory.create(client) @@ -389,7 +387,7 @@ class RustMatrixAuthenticationService( .toSessionData( isTokenValid = true, loginType = LoginType.QR, - passphrase = pendingPassphrase, + passphrase = pendingKey.formattedAsString(), sessionPaths = emptySessionPaths, ) val matrixClient = rustMatrixClientFactory.create(client) @@ -422,7 +420,7 @@ class RustMatrixAuthenticationService( return rustMatrixClientFactory .getBaseClientBuilder( sessionPaths = sessionPaths, - passphrase = pendingPassphrase, + clientSecret = pendingKey, slidingSyncType = ClientBuilderSlidingSync.Discovered, ) .config() @@ -454,7 +452,7 @@ class RustMatrixAuthenticationService( return rustMatrixClientFactory .getBaseClientBuilder( sessionPaths = sessionPaths, - passphrase = pendingPassphrase, + clientSecret = pendingKey, slidingSyncType = ClientBuilderSlidingSync.Discovered, ) .serverNameOrHomeserverUrl(baseUrlOrServerName) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGenerator.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt similarity index 50% rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGenerator.kt rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt index d13ff7779e..042dae36d9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGenerator.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt @@ -11,15 +11,20 @@ package io.element.android.libraries.matrix.impl.keys import android.util.Base64 import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.matrix.impl.ClientSecret import java.security.SecureRandom -private const val SECRET_SIZE = 256 - @ContributesBinding(AppScope::class) -class DefaultPassphraseGenerator : PassphraseGenerator { - override fun generatePassphrase(): String? { - val key = ByteArray(size = SECRET_SIZE) +class DefaultSecretGenerator : SecretGenerator { + override fun generatePassphrase(size: Int): ClientSecret.Passphrase? { + val key = ByteArray(size = size) SecureRandom().nextBytes(key) - return Base64.encodeToString(key, Base64.NO_PADDING or Base64.NO_WRAP) + return ClientSecret.Passphrase(Base64.encodeToString(key, Base64.NO_PADDING or Base64.NO_WRAP)) + } + + override fun generateKey(size: Int): ClientSecret.RawKey { + val key = ByteArray(size = size) + SecureRandom().nextBytes(key) + return ClientSecret.RawKey(key) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/PassphraseGenerator.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/PassphraseGenerator.kt deleted file mode 100644 index e0f925fa28..0000000000 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/PassphraseGenerator.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.impl.keys - -interface PassphraseGenerator { - /** - * Generate a passphrase to encrypt the databases of a session. - * Return null to not encrypt the databases. - */ - fun generatePassphrase(): String? -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt new file mode 100644 index 0000000000..4699f2a720 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 2024, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.keys + +import io.element.android.libraries.matrix.impl.ClientSecret + +private const val PASSPHRASE_SIZE = 256 +private const val KEY_SIZE = 32 + +interface SecretGenerator { + /** + * Generate a passphrase to encrypt the databases. + * @param size the size of the passphrase in bytes, before encoding. The default value is 256 bytes. + * @return either a random passphrase or `null` to not encrypt the databases. + */ + fun generatePassphrase(size: Int = PASSPHRASE_SIZE): ClientSecret.Passphrase? + + /** + * Generate a key to encrypt the databases. + * @param size the size of the key in bytes. The default value is 32 bytes. + * @return a random key. + */ + fun generateKey(size: Int = KEY_SIZE): ClientSecret.RawKey +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt index 84f124868e..1e5b8e037c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt @@ -9,12 +9,23 @@ package io.element.android.libraries.matrix.impl.storage import io.element.android.libraries.core.data.ByteUnit import io.element.android.libraries.core.data.megaBytes +import io.element.android.libraries.matrix.impl.ClientSecret import io.element.android.libraries.matrix.impl.paths.SessionPaths import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.SqliteStoreBuilder as SdkSqliteStoreBuilder +/** + * Abstraction over the SDK's [SdkSqliteStoreBuilder] to allow configuring it with a ClientSecret and to hide the SDK from the rest of the codebase. + */ interface SqliteStoreBuilder { - fun passphrase(passphrase: String?): SqliteStoreBuilder + /** + * Configure the builder with a [ClientSecret], if provided. If the [clientSecret] is null, the databases will not be encrypted. + */ + fun secret(clientSecret: ClientSecret?): SqliteStoreBuilder + + /** + * Configure the provided [clientBuilder] with the configured [SdkSqliteStoreBuilder] and return it. + */ fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder } @@ -26,8 +37,15 @@ class RustSqliteStoreBuilder( cachePath = sessionPaths.cacheDirectory.absolutePath, ).journalSizeLimit(25.megaBytes.into(ByteUnit.BYTES).toUInt()) - override fun passphrase(passphrase: String?): SqliteStoreBuilder { - inner = inner.passphrase(passphrase) + override fun secret(clientSecret: ClientSecret?): SqliteStoreBuilder { + when (clientSecret) { + null -> Unit + is ClientSecret.Passphrase -> inner = inner.passphrase(clientSecret.value) + is ClientSecret.RawKey -> { + // Ensure the key is 32 bytes long, as required by the SDK + inner = inner.key(clientSecret.keyOfSize(32)) + } + } return this } @@ -35,3 +53,15 @@ class RustSqliteStoreBuilder( return clientBuilder.sqliteStore(this.inner) } } + +private fun ClientSecret.RawKey.keyOfSize(size: Int): ByteArray { + return if (bytes.size == 32) { + bytes + } else if (bytes.size < 32) { + // If the key is shorter than 32 bytes, pad it with zeros + bytes + ByteArray(32 - bytes.size) + } else { + // Otherwise, take the first 32 bytes of the key + bytes.copyOfRange(0, 32) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt deleted file mode 100644 index a089920422..0000000000 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.impl.auth - -import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator -import io.element.android.libraries.matrix.test.A_PASSPHRASE - -class FakePassphraseGenerator( - private val passphrase: () -> String? = { A_PASSPHRASE } -) : PassphraseGenerator { - override fun generatePassphrase(): String? = passphrase() -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt new file mode 100644 index 0000000000..6bd995348a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 2024, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.auth + +import io.element.android.libraries.matrix.impl.ClientSecret +import io.element.android.libraries.matrix.impl.keys.SecretGenerator +import io.element.android.libraries.matrix.test.A_PASSPHRASE + +class FakeSecretGenerator( + private val passphrase: (Int) -> String? = { A_PASSPHRASE }, + private val key: (Int) -> ByteArray = { ByteArray(it) { 0 } }, +) : SecretGenerator { + override fun generatePassphrase(size: Int): ClientSecret.Passphrase? = passphrase(size)?.let { ClientSecret.Passphrase(it) } + override fun generateKey(size: Int): ClientSecret.RawKey = ClientSecret.RawKey(key(size)) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index 7f422acfcf..2b9080195f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -66,7 +66,7 @@ class RustMatrixAuthenticationServiceTest { coroutineDispatchers = testCoroutineDispatchers(), sessionStore = sessionStore, rustMatrixClientFactory = rustMatrixClientFactory, - passphraseGenerator = FakePassphraseGenerator(), + secretGenerator = FakeSecretGenerator(), oAuthConfigurationProvider = OAuthConfigurationProvider( buildMeta = aBuildMeta(), oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt deleted file mode 100644 index 465d920074..0000000000 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.impl.keys - -import com.google.common.truth.Truth.assertThat -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner - -@RunWith(RobolectricTestRunner::class) -class DefaultPassphraseGeneratorTest { - @Test - fun `check that generated passphrase has the expected length`() { - val passphraseGenerator = DefaultPassphraseGenerator() - val passphrase = passphraseGenerator.generatePassphrase() - assertThat(passphrase!!.length).isEqualTo(342) - } -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt new file mode 100644 index 0000000000..5fa2b263a1 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 2024, 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.keys + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.ClientSecret +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class DefaultSecretGeneratorTest { + @Test + fun `check that generated passphrase has the expected length`() { + val secretGenerator = DefaultSecretGenerator() + val passphrase = secretGenerator.generatePassphrase(256) + assertThat(passphrase).isInstanceOf(ClientSecret.Passphrase::class.java) + // Size after Base64 encoding should be 4/3 of the original size, without padding + assertThat(passphrase!!.value).hasLength(342) + } + + @Test + fun `check that generated key has the expected length`() { + val secretGenerator = DefaultSecretGenerator() + val key = secretGenerator.generateKey(123) + assertThat(key).isInstanceOf(ClientSecret.RawKey::class.java) + assertThat(key.bytes).hasLength(123) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt index 2f12587f5a..c33a67790b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt @@ -7,10 +7,11 @@ package io.element.android.libraries.matrix.impl.storage +import io.element.android.libraries.matrix.impl.ClientSecret import org.matrix.rustcomponents.sdk.ClientBuilder class FakeSqliteStoreBuilder : SqliteStoreBuilder { - override fun passphrase(passphrase: String?): SqliteStoreBuilder = this + override fun secret(clientSecret: ClientSecret?): SqliteStoreBuilder = this override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder { return clientBuilder diff --git a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt index e596bc35a5..a9647ba3a1 100644 --- a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt +++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt @@ -56,8 +56,9 @@ class DefaultAnalyticsColdStartWatcher( override fun onRoomListVisible() { if (isColdStart.getAndSet(false)) { - Timber.d("Room list is visible, finishing cold start check") - analyticsService.finishLongRunningTransaction(AnalyticsLongRunningTransaction.ColdStart) + analyticsService.finishLongRunningTransaction(AnalyticsLongRunningTransaction.ColdStart) { + Timber.d("Room list is visible, finishing cold start check. Elapsed: ${it.duration}") + } } } } From 8fd5072ba55f4a92a681b94ba9e13ebc21a4bb08 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 00:46:10 +0000 Subject: [PATCH 0514/1083] Update dependency org.maplibre.compose:maplibre-compose to v0.13.0 --- 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 d2abf57b90..391a97bfc9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -210,7 +210,7 @@ telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = " statemachine = "com.freeletics.flowredux:compose:1.2.2" maplibre = "org.maplibre.gl:android-sdk:13.1.0" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" -maplibre_compose = "org.maplibre.compose:maplibre-compose:0.12.1" +maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.0" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" opusencoder = "io.element.android:opusencoder:1.2.0" zxing_cpp = "io.github.zxing-cpp:android:3.0.2" From ecfeb52424578591e69ff49983bf73c39f831276 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 09:22:28 +0200 Subject: [PATCH 0515/1083] Update dependency androidx.compose:compose-bom to v2026.05.01 (#6888) 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 d2abf57b90..514dbd19d4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ camera = "1.6.1" work = "2.11.2" # Compose -compose_bom = "2026.05.00" +compose_bom = "2026.05.01" # Coroutines coroutines = "1.11.0" From 6984ab03933a8c294d2255a3e9637f20211c705b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 27 May 2026 09:54:27 +0200 Subject: [PATCH 0516/1083] Use string template instead of multiple append invocations. --- .../api/internal/MapTilerTileServerStyleUriBuilder.kt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt index 761adb25cf..b580ea4824 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt @@ -32,16 +32,11 @@ internal class MapTilerTileServerStyleUriBuilder( return buildString { if (customMapStyleUrl.isNullOrBlank()) { val mapId = if (darkMode) darkMapId else lightMapId - append(baseUrl) - append("/") - append(mapId) - append("/") - append("style.json") + append("$baseUrl/$mapId/style.json") } else { append(customMapStyleUrl.removeSuffix("/")) } - append("?key=") - append(apiKey) + append("?key=$apiKey") } } } From c846f4eee29fae2bdd4af13c8a9053a6e1da0d8a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 27 May 2026 09:59:32 +0200 Subject: [PATCH 0517/1083] `customMapStyleUrl` should end with `style.json` and should not have any trailing slash. --- .../location/api/internal/MapTilerTileServerStyleUriBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt index b580ea4824..054805d1ab 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt @@ -34,7 +34,7 @@ internal class MapTilerTileServerStyleUriBuilder( val mapId = if (darkMode) darkMapId else lightMapId append("$baseUrl/$mapId/style.json") } else { - append(customMapStyleUrl.removeSuffix("/")) + append(customMapStyleUrl) } append("?key=$apiKey") } From f37222e2d8e4ac464312fefe55e3f94cd136ef6e Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 26 May 2026 23:17:32 +0200 Subject: [PATCH 0518/1083] change(permissions) : allow to change ShareLiveLocation permission --- .../impl/permissions/ChangeRoomPermissionsPresenter.kt | 2 ++ .../impl/permissions/ChangeRoomPermissionsState.kt | 2 ++ .../impl/permissions/ChangeRoomPermissionsView.kt | 1 + .../impl/permissions/ChangeRoomPermissionsPresenterTest.kt | 1 + .../android/libraries/matrix/impl/room/JoinedRustRoom.kt | 2 ++ 5 files changed, 8 insertions(+) diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenter.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenter.kt index 552f1d0ec6..3023124e9e 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenter.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenter.kt @@ -47,6 +47,7 @@ class ChangeRoomPermissionsPresenter( RoomPermissionsSection.MessagesAndContent -> persistentListOf( RoomPermissionType.SEND_EVENTS, RoomPermissionType.REDACT_EVENTS, + RoomPermissionType.SHARE_LIVE_LOCATION, ) RoomPermissionsSection.ManageMembers -> persistentListOf( RoomPermissionType.INVITE, @@ -114,6 +115,7 @@ class ChangeRoomPermissionsPresenter( RoomPermissionType.ROOM_AVATAR -> currentPermissions?.copy(roomAvatar = powerLevel) RoomPermissionType.ROOM_TOPIC -> currentPermissions?.copy(roomTopic = powerLevel) RoomPermissionType.SPACE_MANAGE_ROOMS -> currentPermissions?.copy(spaceChild = powerLevel) + RoomPermissionType.SHARE_LIVE_LOCATION -> currentPermissions?.copy(beaconInfo = powerLevel, beacon = powerLevel) } } is ChangeRoomPermissionsEvent.Save -> coroutineScope.save() diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsState.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsState.kt index 535f2b4a71..b6b2ca0bda 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsState.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsState.kt @@ -65,6 +65,7 @@ data class ChangeRoomPermissionsState( RoomPermissionType.ROOM_AVATAR -> currentPermissions.roomAvatar RoomPermissionType.ROOM_TOPIC -> currentPermissions.roomTopic RoomPermissionType.SPACE_MANAGE_ROOMS -> currentPermissions.spaceChild + RoomPermissionType.SHARE_LIVE_LOCATION -> maxOf(currentPermissions.beacon, currentPermissions.beaconInfo) } } } @@ -104,4 +105,5 @@ enum class RoomPermissionType { ROOM_AVATAR, ROOM_TOPIC, SPACE_MANAGE_ROOMS, + SHARE_LIVE_LOCATION, } diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsView.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsView.kt index 529df0d50d..bb702ed90a 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsView.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsView.kt @@ -127,6 +127,7 @@ private fun titleForType(type: RoomPermissionType): String = when (type) { RoomPermissionType.ROOM_AVATAR -> stringResource(R.string.screen_room_change_permissions_room_avatar) RoomPermissionType.ROOM_TOPIC -> stringResource(R.string.screen_room_change_permissions_room_topic) RoomPermissionType.SPACE_MANAGE_ROOMS -> stringResource(R.string.screen_room_change_permissions_manage_space_rooms) + RoomPermissionType.SHARE_LIVE_LOCATION -> stringResource(R.string.screen_room_change_permissions_live_location) } @PreviewsDayNight diff --git a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt index 72b2b8b5e7..c143b7c969 100644 --- a/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt +++ b/features/rolesandpermissions/impl/src/test/kotlin/io/element/android/features/rolesandpermissions/impl/permissions/ChangeRoomPermissionsPresenterTest.kt @@ -66,6 +66,7 @@ class ChangeRoomPermissionsPresenterTest { assertThat(itemsBySection[RoomPermissionsSection.MessagesAndContent]).containsExactly( RoomPermissionType.SEND_EVENTS, RoomPermissionType.REDACT_EVENTS, + RoomPermissionType.SHARE_LIVE_LOCATION, ) assertThat(itemsBySection[RoomPermissionsSection.ManageMembers]).containsExactly( RoomPermissionType.INVITE, 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 e75091eadc..1b02c03e30 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 @@ -421,6 +421,8 @@ class JoinedRustRoom( roomAvatar = roomPowerLevelsValues.roomAvatar, roomTopic = roomPowerLevelsValues.roomTopic, spaceChild = roomPowerLevelsValues.spaceChild, + beacon = roomPowerLevelsValues.beacon, + beaconInfo = roomPowerLevelsValues.beaconInfo, ) innerRoom.applyPowerLevelChanges(changes) } From f36916e5e7c0e4fe317a285103dfb4fc46a22660 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 27 May 2026 11:03:45 +0200 Subject: [PATCH 0519/1083] Fix test compilation --- .../libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt index 57ffcddb37..43c36f7bfb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt @@ -73,6 +73,7 @@ class FakeFfiClient( deviceDisplayName: String, profileTag: String?, lang: String, + append: Boolean, ) = Unit override suspend fun deletePusher(identifiers: PusherIdentifiers) = Unit From 22054875717cc3aab92419e7aae90a36aa5b7564 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 11:38:49 +0200 Subject: [PATCH 0520/1083] Merge pull request #6893 from element-hq/renovate/roborazzi Update roborazzi to v1.63.0 --- 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 514dbd19d4..d3b2314b33 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ accompanist = "0.37.3" # Test test_core = "1.7.0" -roborazzi = "1.62.0" +roborazzi = "1.63.0" # Jetbrain datetime = "0.8.0" From 2e42e78307998d69f15f9cf4b6334974f231e29c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 12:16:17 +0200 Subject: [PATCH 0521/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.05.26 (#6885) * Update dependency org.matrix.rustcomponents:sdk-android to v26.05.26 * Fix API break * Fix test compilation --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Benoit Marty --- gradle/libs.versions.toml | 2 +- .../android/libraries/matrix/api/pusher/SetHttpPusherData.kt | 1 + .../libraries/matrix/impl/pushers/RustPushersService.kt | 3 ++- .../libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt | 1 + .../libraries/matrix/impl/pushers/RustPushersServiceTest.kt | 4 +++- .../android/libraries/push/impl/DefaultPusherSubscriber.kt | 3 ++- .../libraries/push/impl/DefaultPusherSubscriberTest.kt | 1 + 7 files changed, 11 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d3b2314b33..b526c0ab69 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -179,7 +179,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.20" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.26" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt index 8a557f4b70..97a3cabd20 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/pusher/SetHttpPusherData.kt @@ -17,4 +17,5 @@ data class SetHttpPusherData( val profileTag: String?, val lang: String, val defaultPayload: String, + val append: Boolean, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt index 860993d4bc..2e2a36c449 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersService.kt @@ -44,7 +44,8 @@ class RustPushersService( appDisplayName = setHttpPusherData.appDisplayName, deviceDisplayName = setHttpPusherData.deviceDisplayName, profileTag = setHttpPusherData.profileTag, - lang = setHttpPusherData.lang + lang = setHttpPusherData.lang, + append = setHttpPusherData.append, ) } .mapFailure { it.mapClientException() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt index 57ffcddb37..43c36f7bfb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt @@ -73,6 +73,7 @@ class FakeFfiClient( deviceDisplayName: String, profileTag: String?, lang: String, + append: Boolean, ) = Unit override suspend fun deletePusher(identifiers: PusherIdentifiers) = Unit diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt index 61b2965cdd..b58c2985ff 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt @@ -48,6 +48,7 @@ private fun aSetHttpPusherData( deviceDisplayName: String = "deviceDisplayName", profileTag: String = "profileTag", lang: String = "lang", + append: Boolean = false, ) = SetHttpPusherData( pushKey = pushKey, appId = appId, @@ -56,7 +57,8 @@ private fun aSetHttpPusherData( appDisplayName = appDisplayName, deviceDisplayName = deviceDisplayName, profileTag = profileTag, - lang = lang + lang = lang, + append = append, ) private fun aUnsetHttpPusherData( diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriber.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriber.kt index 39f9d3acd6..35482aa164 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriber.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriber.kt @@ -83,7 +83,8 @@ class DefaultPusherSubscriber( // TODO getDeviceInfoUseCase.execute().displayName().orEmpty() deviceDisplayName = "MyDevice", url = gateway, - defaultPayload = createDefaultPayload(pushClientSecret.getSecretForUser(userId)) + defaultPayload = createDefaultPayload(pushClientSecret.getSecretForUser(userId)), + append = false, ) /** diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriberTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriberTest.kt index dd2cb24841..8cb1e2a7f6 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriberTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/DefaultPusherSubscriberTest.kt @@ -103,6 +103,7 @@ class DefaultPusherSubscriberTest { profileTag = DEFAULT_PUSHER_FILE_TAG + "_", lang = "en", defaultPayload = "{\"cs\":\"$A_SECRET\"}", + append = false, ), ) ) From e115d620cae5bf3ef9a9e5172bf4a83ac75211df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 27 May 2026 13:19:41 +0200 Subject: [PATCH 0522/1083] Fix API breaks and an issue with the location changing not moving the camera --- .../impl/common/ui/UserLocationPuck.kt | 37 ++++++++++++------- .../service/LiveLocationSharingService.kt | 10 +++-- .../impl/share/ShareLocationPresenter.kt | 2 +- .../location/impl/share/ShareLocationView.kt | 4 +- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt index 589ed87c6f..6f47903c9c 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.impl.common.MapDefaults +import kotlinx.coroutines.flow.SharingStarted import org.maplibre.compose.camera.CameraState import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.compose.location.LocationPuck @@ -23,6 +24,9 @@ import org.maplibre.compose.location.UserLocationState import org.maplibre.compose.location.rememberAndroidLocationProvider import org.maplibre.compose.location.rememberNullLocationProvider import org.maplibre.compose.location.rememberUserLocationState +import org.maplibre.spatialk.units.Bearing +import org.maplibre.spatialk.units.extensions.inDegrees +import org.maplibre.spatialk.units.extensions.meters import kotlin.time.Duration.Companion.seconds @Composable @@ -31,22 +35,28 @@ fun UserLocationPuck( locationState: UserLocationState, trackUserLocation: Boolean, ) { - LocationTrackingEffect( - locationState = locationState, - enabled = trackUserLocation, - ) { - val finalPosition = cameraState.position.copy( - target = currentLocation.position, - bearing = currentLocation.bearing ?: cameraState.position.bearing, - zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM) - ) - cameraState.animateTo(finalPosition) - } val location = locationState.location if (location != null) { + // Moved inside this block so it correctly tracks the updated locationState value + LocationTrackingEffect( + locationState = locationState, + enabled = trackUserLocation, + ) { + val newTarget = currentLocation.location?.position?.value + val newBearing = currentLocation.orientation?.orientation?.value?.clockwiseRotationTo(Bearing.North)?.inDegrees + if (newTarget != null || newBearing != null) { + val finalPosition = cameraState.position.copy( + target = newTarget ?: cameraState.position.target, + bearing = newBearing ?: cameraState.position.bearing, + zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM) + ) + cameraState.animateTo(finalPosition) + } + } + LocationPuck( idPrefix = "user-location", - locationState = locationState, + location = locationState.location, cameraState = cameraState, accuracyThreshold = Float.POSITIVE_INFINITY, showBearingAccuracy = false, @@ -74,7 +84,8 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState rememberAndroidLocationProvider( updateInterval = 5.seconds, desiredAccuracy = DesiredAccuracy.High, - minDistanceMeters = 5f, + minDistance = 5.meters, + sharingStarted = SharingStarted.Eagerly, ) } return rememberUserLocationState(locationProvider) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt index 4451febb19..aba45f30c1 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -36,6 +36,8 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import org.maplibre.compose.location.AndroidLocationProvider import org.maplibre.compose.location.DesiredAccuracy +import org.maplibre.spatialk.units.extensions.inMeters +import org.maplibre.spatialk.units.extensions.meters import timber.log.Timber import kotlin.time.Duration.Companion.seconds import io.element.android.features.location.api.Location as ApiLocation @@ -91,7 +93,7 @@ class LiveLocationSharingService : Service() { val locationProvider = AndroidLocationProvider( context = applicationContext, updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, - minDistanceMeters = minDistanceMeters.toFloat(), + minDistance = minDistanceMeters.meters, desiredAccuracy = DesiredAccuracy.Balanced, coroutineScope = coroutineScope ) @@ -100,9 +102,9 @@ class LiveLocationSharingService : Service() { .filterNotNull() .map { location -> ApiLocation( - lat = location.position.latitude, - lon = location.position.longitude, - accuracy = location.accuracy.toFloat(), + lat = location.position.value.latitude, + lon = location.position.value.longitude, + accuracy = location.position.accuracy?.inMeters?.toFloat() ?: 0f, ) } .onEach(coordinator::dispatch) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index a1e45cfea2..bb2ed77131 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -94,8 +94,8 @@ class ShareLocationPresenter( fun checkLocationConstraints() { // No need to check SendLiveLocationPermissions here val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) - dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState()) trackUserPosition = locationConstraints is LocationConstraintsCheck.Success + dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState()) } suspend fun computeLiveLocationDialogState(): ShareLocationState.Dialog { diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index e20ee3a7a5..7320911990 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -222,8 +222,8 @@ private fun BottomSheetContent( state.eventSink( ShareLocationEvent.ShareStaticLocation( location = Location( - lat = userLocation.position.latitude, - lon = userLocation.position.longitude + lat = userLocation.position.value.latitude, + lon = userLocation.position.value.longitude ), isPinned = false ) From 1e00353f297e50d41b81ab0bec3d7bb0ab844ed4 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 27 May 2026 17:25:51 +0200 Subject: [PATCH 0523/1083] Avoid SQLCipher key derivation (#6774) * Avoid SQLCipher key derivation by manually providing the generated as a raw key: this needs a series of DB re-key operations, performed as part of a 'dummy' DB migration * Set key generation length to 32 bytes in `RandomSecretPassphraseProvider`. * Use `ClientSecret` for handling the keys for SQLCipher. Move `ClientSecret` to `:libraries:androidutils` so it's shared. --- .../androidutils/crypto}/ClientSecret.kt | 16 ++++--- .../cachestore/impl/di/CacheStoreModule.kt | 19 ++++++-- .../impl/src/main/sqldelight/migrations/1.sqm | 8 ++++ .../impl/src/main/sqldelight/migrations/2.sqm | 2 + .../encrypteddb/SqlCipherDriverFactory.kt | 40 +++++++++++++---- ...eProvider.kt => DatabaseSecretProvider.kt} | 13 ++++-- ...der.kt => RandomDatabaseSecretProvider.kt} | 26 ++++++----- .../encrypteddb/utils/ReplaceDatabaseKey.kt | 45 +++++++++++++++++++ .../matrix/impl/RustMatrixClientFactory.kt | 1 + .../auth/RustMatrixAuthenticationService.kt | 2 +- .../impl/keys/DefaultSecretGenerator.kt | 2 +- .../matrix/impl/keys/SecretGenerator.kt | 2 +- .../matrix/impl/storage/SqliteStoreBuilder.kt | 2 +- .../matrix/impl/auth/FakeSecretGenerator.kt | 2 +- .../impl/keys/DefaultSecretGeneratorTest.kt | 2 +- .../impl/storage/FakeSqliteStoreBuilder.kt | 2 +- .../push/impl/history/di/PushHistoryModule.kt | 19 ++++++-- .../impl/src/main/sqldelight/migrations/2.sqm | 2 + .../impl/di/SessionStorageModule.kt | 19 ++++++-- .../src/main/sqldelight/migrations/11.sqm | 2 + .../DefaultAnalyticsColdStartWatcher.kt | 2 +- 21 files changed, 185 insertions(+), 43 deletions(-) rename libraries/{matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl => androidutils/src/main/kotlin/io/element/android/libraries/androidutils/crypto}/ClientSecret.kt (81%) create mode 100644 libraries/cachestore/impl/src/main/sqldelight/migrations/1.sqm create mode 100644 libraries/cachestore/impl/src/main/sqldelight/migrations/2.sqm rename libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/{PassphraseProvider.kt => DatabaseSecretProvider.kt} (51%) rename libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/{RandomSecretPassphraseProvider.kt => RandomDatabaseSecretProvider.kt} (56%) create mode 100644 libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/utils/ReplaceDatabaseKey.kt create mode 100644 libraries/push/impl/src/main/sqldelight/migrations/2.sqm create mode 100644 libraries/session-storage/impl/src/main/sqldelight/migrations/11.sqm diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/crypto/ClientSecret.kt similarity index 81% rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt rename to libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/crypto/ClientSecret.kt index 25d040e15b..d07d302f39 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientSecret.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/crypto/ClientSecret.kt @@ -5,9 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.matrix.impl - -import okio.ByteString.Companion.decodeHex +package io.element.android.libraries.androidutils.crypto /** * Represents a client secret used to encrypt/decrypt data from databases, which can be either a passphrase or a raw key. @@ -17,7 +15,7 @@ sealed interface ClientSecret { * A passphrase that can be used to derive a key for encryption/decryption. */ data class Passphrase(val value: String) : ClientSecret { - override fun formattedAsString(): String = toString() + override fun formattedAsString(): String = value } /** @@ -57,10 +55,18 @@ sealed interface ClientSecret { val regex = Regex("^x'([0-9a-fA-F]+)'$") val rawKeyMatch = regex.matchEntire(secret) return if (rawKeyMatch != null) { - RawKey(rawKeyMatch.groupValues[1].decodeHex().toByteArray()) + RawKey(rawKeyMatch.groupValues[1].hexToByteArray()) } else { Passphrase(secret) } } + + /** + * Create a [ClientSecret] from raw bytes, which will be treated as a raw key. + */ + fun fromRawBytes(bytes: ByteArray): ClientSecret = when (bytes.size) { + 32 -> RawKey(bytes) + else -> Passphrase(bytes.toHexString()) + } } } diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt index 05fa3d9d97..89de82a08f 100644 --- a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/di/CacheStoreModule.kt @@ -16,7 +16,9 @@ import dev.zacsweers.metro.SingleIn import io.element.android.libraries.cachestore.impl.CacheDatabase import io.element.android.libraries.di.annotations.ApplicationContext import io.element.encrypteddb.SqlCipherDriverFactory -import io.element.encrypteddb.passphrase.RandomSecretPassphraseProvider +import io.element.encrypteddb.passphrase.RandomDatabaseSecretProvider +import io.element.encrypteddb.utils.ReplaceDatabaseKey +import timber.log.Timber @BindingContainer @ContributesTo(AppScope::class) @@ -35,9 +37,20 @@ object CacheStoreModule { parentDir.mkdirs() } - val passphraseProvider = RandomSecretPassphraseProvider(context, secretFile) + val rekeyMigrationVersion = 2L + val passphraseProvider = RandomDatabaseSecretProvider(context, secretFile) val driver = SqlCipherDriverFactory(passphraseProvider) - .create(CacheDatabase.Schema, "$name.db", context) + .create( + schema = CacheDatabase.Schema, + name = "$name.db", + context = context + ) { db, oldVersion, newVersion -> + Timber.d("Migrating $name database from version $oldVersion to $newVersion") + if (rekeyMigrationVersion in oldVersion..newVersion) { + ReplaceDatabaseKey(passphraseProvider).replaceKey(name, db) + } + } + return CacheDatabase(driver) } } diff --git a/libraries/cachestore/impl/src/main/sqldelight/migrations/1.sqm b/libraries/cachestore/impl/src/main/sqldelight/migrations/1.sqm new file mode 100644 index 0000000000..f038b85649 --- /dev/null +++ b/libraries/cachestore/impl/src/main/sqldelight/migrations/1.sqm @@ -0,0 +1,8 @@ +-- Migrate DB from version 1 +-- Initial schema for CacheData table + +CREATE TABLE IF NOT EXISTS CacheData ( + key TEXT NOT NULL PRIMARY KEY, + value TEXT NOT NULL, + updatedAt INTEGER NOT NULL +); diff --git a/libraries/cachestore/impl/src/main/sqldelight/migrations/2.sqm b/libraries/cachestore/impl/src/main/sqldelight/migrations/2.sqm new file mode 100644 index 0000000000..e7adfb091a --- /dev/null +++ b/libraries/cachestore/impl/src/main/sqldelight/migrations/2.sqm @@ -0,0 +1,2 @@ +-- Migrate DB from version 2 +-- Dummy migration to trigger a re-key diff --git a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/SqlCipherDriverFactory.kt b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/SqlCipherDriverFactory.kt index e4ac1a949f..84ab2d2a18 100644 --- a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/SqlCipherDriverFactory.kt +++ b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/SqlCipherDriverFactory.kt @@ -9,30 +9,54 @@ package io.element.encrypteddb import android.content.Context +import androidx.sqlite.db.SupportSQLiteDatabase import app.cash.sqldelight.db.QueryResult import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.db.SqlSchema import app.cash.sqldelight.driver.android.AndroidSqliteDriver -import io.element.encrypteddb.passphrase.PassphraseProvider +import io.element.android.libraries.androidutils.crypto.ClientSecret +import io.element.encrypteddb.passphrase.DatabaseSecretProvider import net.zetetic.database.sqlcipher.SupportOpenHelperFactory /** * Creates an encrypted version of the [SqlDriver] using SQLCipher's [SupportOpenHelperFactory]. - * @param passphraseProvider Provides the passphrase needed to use the SQLite database with SQLCipher. + * @param databaseSecretProvider Provides the passphrase needed to use the SQLite database with SQLCipher. */ class SqlCipherDriverFactory( - private val passphraseProvider: PassphraseProvider, + private val databaseSecretProvider: DatabaseSecretProvider, ) { + companion object { + init { + System.loadLibrary("sqlcipher") + } + } + /** * Returns a valid [SqlDriver] with SQLCipher support. * @param schema The SQLite DB schema. * @param name The name of the database to create. * @param context Android [Context], used to instantiate the driver. + * @param onUpgradeCallback Optional callback to handle database upgrades, which will be called in the [AndroidSqliteDriver.Callback.onUpgrade] method. */ - fun create(schema: SqlSchema>, name: String, context: Context): SqlDriver { - System.loadLibrary("sqlcipher") - val passphrase = passphraseProvider.getPassphrase() - val factory = SupportOpenHelperFactory(passphrase) - return AndroidSqliteDriver(schema = schema, context = context, name = name, factory = factory) + fun create( + schema: SqlSchema>, + name: String, + context: Context, + onUpgradeCallback: ((driver: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) -> Unit)? = null, + ): SqlDriver { + val key = when (val secret = databaseSecretProvider.getSecret()) { + // For a raw key, we need the blob representation (`x'...'`) as bytes + is ClientSecret.RawKey -> secret.formattedAsString().toByteArray() + // For a passphrase, we need the bytes for the hex string representation + is ClientSecret.Passphrase -> secret.formattedAsString().hexToByteArray() + } + val factory = SupportOpenHelperFactory(key) + return AndroidSqliteDriver(schema = schema, context = context, name = name, factory = factory, callback = object : AndroidSqliteDriver.Callback( + schema + ) { + override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) { + onUpgradeCallback?.invoke(db, oldVersion, newVersion) + } + }) } } diff --git a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/PassphraseProvider.kt b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/DatabaseSecretProvider.kt similarity index 51% rename from libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/PassphraseProvider.kt rename to libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/DatabaseSecretProvider.kt index a72dc73596..140a5d8de2 100644 --- a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/PassphraseProvider.kt +++ b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/DatabaseSecretProvider.kt @@ -8,12 +8,19 @@ package io.element.encrypteddb.passphrase +import io.element.android.libraries.androidutils.crypto.ClientSecret + /** * An abstraction to implement secure providers for SQLCipher passphrases. */ -interface PassphraseProvider { +interface DatabaseSecretProvider { /** - * Returns a passphrase for SQLCipher in [ByteArray] format. + * Returns a secret for SQLCipher. */ - fun getPassphrase(): ByteArray + fun getSecret(): ClientSecret + + /** + * Resets the passphrase, for example by deleting the persisted secret. Returns `true` if the reset was successful, `false` otherwise. + */ + fun reset(): Boolean } diff --git a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/RandomSecretPassphraseProvider.kt b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/RandomDatabaseSecretProvider.kt similarity index 56% rename from libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/RandomSecretPassphraseProvider.kt rename to libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/RandomDatabaseSecretProvider.kt index fe78a4a8da..246a65da07 100644 --- a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/RandomSecretPassphraseProvider.kt +++ b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/passphrase/RandomDatabaseSecretProvider.kt @@ -9,35 +9,41 @@ package io.element.encrypteddb.passphrase import android.content.Context +import io.element.android.libraries.androidutils.crypto.ClientSecret import io.element.encrypteddb.crypto.EncryptedFile import java.io.File import java.security.SecureRandom /** - * Provides a secure passphrase for SQLCipher by generating a random secret and storing it into an [EncryptedFile]. + * Provides a secure secret for SQLCipher by generating a random secret and storing it into an [EncryptedFile]. * @param context Android [Context], used by [EncryptedFile] for cryptographic operations. * @param file Destination file where the key will be stored. - * @param secretSize Length of the generated secret. + * @param secretSizeBytes Length of the generated secret. */ -class RandomSecretPassphraseProvider( +class RandomDatabaseSecretProvider( private val context: Context, private val file: File, - private val secretSize: Int = 256, -) : PassphraseProvider { - override fun getPassphrase(): ByteArray { + private val secretSizeBytes: Int = 32, +) : DatabaseSecretProvider { + override fun getSecret(): ClientSecret { val encryptedFile = EncryptedFile(context, file) - return if (!file.exists()) { + val bytes = if (!file.exists()) { val secret = generateSecret() encryptedFile.openFileOutput().use { it.write(secret) } secret } else { encryptedFile.openFileInput().use { it.readBytes() } } + return ClientSecret.fromRawBytes(bytes) + } + + override fun reset(): Boolean { + return file.delete() } private fun generateSecret(): ByteArray { - val buffer = ByteArray(size = secretSize) - SecureRandom().nextBytes(buffer) - return buffer + // Generate a random secret of the specified size using a secure random generator. + return ByteArray(size = secretSizeBytes) + .also { SecureRandom().nextBytes(it) } } } diff --git a/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/utils/ReplaceDatabaseKey.kt b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/utils/ReplaceDatabaseKey.kt new file mode 100644 index 0000000000..fafb18794b --- /dev/null +++ b/libraries/encrypted-db/src/main/kotlin/io/element/encrypteddb/utils/ReplaceDatabaseKey.kt @@ -0,0 +1,45 @@ +/* + * 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.encrypteddb.utils + +import androidx.sqlite.db.SupportSQLiteDatabase +import io.element.encrypteddb.passphrase.RandomDatabaseSecretProvider +import timber.log.Timber + +/** + * A utility class to replace the encryption key of an existing SQLCipher database. + * This is used during database migrations when we want to change the encryption key. + * + * @param databaseSecretProvider The provider for generating new secrets. + */ +class ReplaceDatabaseKey( + private val databaseSecretProvider: RandomDatabaseSecretProvider +) { + fun replaceKey(name: String, database: SupportSQLiteDatabase) { + Timber.d("Re-keying database $name") + // Reset the passphrase provider to generate a new passphrase + databaseSecretProvider.reset() + + // Get the new secret and convert it to the format expected by SQLCipher + val newSecret = databaseSecretProvider.getSecret() + val key = newSecret.formattedAsString() + + // Use the PRAGMA rekey command to change the encryption key of the database + database.query("PRAGMA rekey = \"$key\";").close() + + // Verify that the database can be accessed with the new key by running a simple query + val result = database.query("select count(*) from sqlite_master").use { cursor -> + if (cursor.moveToNext()) cursor.getLong(0) else -1L + } + if (result >= 0) { + Timber.d("Re-keying database $name completed") + } else { + Timber.e("Re-keying database $name didn't work as expected.") + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 9a7452aa5f..4a91462399 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl import dev.zacsweers.metro.Inject +import io.element.android.libraries.androidutils.crypto.ClientSecret import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.data.ByteUnit import io.element.android.libraries.core.data.megaBytes diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 812a0dd6fe..c44f7ffae7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -12,6 +12,7 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.libraries.androidutils.crypto.ClientSecret import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions @@ -30,7 +31,6 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.impl.ClientBuilderSlidingSync -import io.element.android.libraries.matrix.impl.ClientSecret import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.auth.qrlogin.QrErrorMapper import io.element.android.libraries.matrix.impl.auth.qrlogin.SdkQrCodeLoginData diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt index 042dae36d9..bad4ecb169 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGenerator.kt @@ -11,7 +11,7 @@ package io.element.android.libraries.matrix.impl.keys import android.util.Base64 import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.matrix.impl.ClientSecret +import io.element.android.libraries.androidutils.crypto.ClientSecret import java.security.SecureRandom @ContributesBinding(AppScope::class) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt index 4699f2a720..6dfade9b7c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/keys/SecretGenerator.kt @@ -8,7 +8,7 @@ package io.element.android.libraries.matrix.impl.keys -import io.element.android.libraries.matrix.impl.ClientSecret +import io.element.android.libraries.androidutils.crypto.ClientSecret private const val PASSPHRASE_SIZE = 256 private const val KEY_SIZE = 32 diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt index 1e5b8e037c..3fdfb7a179 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/storage/SqliteStoreBuilder.kt @@ -7,9 +7,9 @@ package io.element.android.libraries.matrix.impl.storage +import io.element.android.libraries.androidutils.crypto.ClientSecret import io.element.android.libraries.core.data.ByteUnit import io.element.android.libraries.core.data.megaBytes -import io.element.android.libraries.matrix.impl.ClientSecret import io.element.android.libraries.matrix.impl.paths.SessionPaths import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.SqliteStoreBuilder as SdkSqliteStoreBuilder diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt index 6bd995348a..12c227946a 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeSecretGenerator.kt @@ -8,7 +8,7 @@ package io.element.android.libraries.matrix.impl.auth -import io.element.android.libraries.matrix.impl.ClientSecret +import io.element.android.libraries.androidutils.crypto.ClientSecret import io.element.android.libraries.matrix.impl.keys.SecretGenerator import io.element.android.libraries.matrix.test.A_PASSPHRASE diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt index 5fa2b263a1..4bda511d42 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultSecretGeneratorTest.kt @@ -9,7 +9,7 @@ package io.element.android.libraries.matrix.impl.keys import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.impl.ClientSecret +import io.element.android.libraries.androidutils.crypto.ClientSecret import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt index c33a67790b..7eeff7db33 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/storage/FakeSqliteStoreBuilder.kt @@ -7,7 +7,7 @@ package io.element.android.libraries.matrix.impl.storage -import io.element.android.libraries.matrix.impl.ClientSecret +import io.element.android.libraries.androidutils.crypto.ClientSecret import org.matrix.rustcomponents.sdk.ClientBuilder class FakeSqliteStoreBuilder : SqliteStoreBuilder { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/history/di/PushHistoryModule.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/history/di/PushHistoryModule.kt index 6472883d4d..93194b2738 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/history/di/PushHistoryModule.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/history/di/PushHistoryModule.kt @@ -17,7 +17,9 @@ import dev.zacsweers.metro.SingleIn import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.push.impl.PushDatabase import io.element.encrypteddb.SqlCipherDriverFactory -import io.element.encrypteddb.passphrase.RandomSecretPassphraseProvider +import io.element.encrypteddb.passphrase.RandomDatabaseSecretProvider +import io.element.encrypteddb.utils.ReplaceDatabaseKey +import timber.log.Timber @BindingContainer @ContributesTo(AppScope::class) @@ -36,9 +38,20 @@ object PushHistoryModule { parentDir.mkdirs() } - val passphraseProvider = RandomSecretPassphraseProvider(context, secretFile) + val rekeyMigrationVersion = 2L + val passphraseProvider = RandomDatabaseSecretProvider(context, secretFile) val driver = SqlCipherDriverFactory(passphraseProvider) - .create(PushDatabase.Schema, "$name.db", context) + .create( + schema = PushDatabase.Schema, + name = "$name.db", + context = context + ) { db, oldVersion, newVersion -> + Timber.d("Migrating $name database from version $oldVersion to $newVersion") + if (rekeyMigrationVersion in oldVersion..newVersion) { + ReplaceDatabaseKey(passphraseProvider).replaceKey(name, db) + } + } + return PushDatabase(driver) } } diff --git a/libraries/push/impl/src/main/sqldelight/migrations/2.sqm b/libraries/push/impl/src/main/sqldelight/migrations/2.sqm new file mode 100644 index 0000000000..e7adfb091a --- /dev/null +++ b/libraries/push/impl/src/main/sqldelight/migrations/2.sqm @@ -0,0 +1,2 @@ +-- Migrate DB from version 2 +-- Dummy migration to trigger a re-key diff --git a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/di/SessionStorageModule.kt b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/di/SessionStorageModule.kt index fb2c9a2c78..8955aa4a27 100644 --- a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/di/SessionStorageModule.kt +++ b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/di/SessionStorageModule.kt @@ -17,7 +17,9 @@ import dev.zacsweers.metro.SingleIn import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.sessionstorage.impl.SessionDatabase import io.element.encrypteddb.SqlCipherDriverFactory -import io.element.encrypteddb.passphrase.RandomSecretPassphraseProvider +import io.element.encrypteddb.passphrase.RandomDatabaseSecretProvider +import io.element.encrypteddb.utils.ReplaceDatabaseKey +import timber.log.Timber @BindingContainer @ContributesTo(AppScope::class) @@ -36,9 +38,20 @@ object SessionStorageModule { parentDir.mkdirs() } - val passphraseProvider = RandomSecretPassphraseProvider(context, secretFile) + val rekeyMigrationVersion = 11L + val passphraseProvider = RandomDatabaseSecretProvider(context, secretFile) val driver = SqlCipherDriverFactory(passphraseProvider) - .create(SessionDatabase.Schema, "$name.db", context) + .create( + schema = SessionDatabase.Schema, + name = "$name.db", + context = context, + ) { db, oldVersion, newVersion -> + Timber.d("Migrating $name database from version $oldVersion to $newVersion") + if (rekeyMigrationVersion in oldVersion..newVersion) { + ReplaceDatabaseKey(passphraseProvider).replaceKey(name, db) + } + } + return SessionDatabase(driver) } } diff --git a/libraries/session-storage/impl/src/main/sqldelight/migrations/11.sqm b/libraries/session-storage/impl/src/main/sqldelight/migrations/11.sqm new file mode 100644 index 0000000000..3d61c92c07 --- /dev/null +++ b/libraries/session-storage/impl/src/main/sqldelight/migrations/11.sqm @@ -0,0 +1,2 @@ +-- Migrate DB from version 11 +-- Dummy migration to trigger a re-key diff --git a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt index a9647ba3a1..8659fc9634 100644 --- a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt +++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/watchers/DefaultAnalyticsColdStartWatcher.kt @@ -57,7 +57,7 @@ class DefaultAnalyticsColdStartWatcher( override fun onRoomListVisible() { if (isColdStart.getAndSet(false)) { analyticsService.finishLongRunningTransaction(AnalyticsLongRunningTransaction.ColdStart) { - Timber.d("Room list is visible, finishing cold start check. Elapsed: ${it.duration}") + Timber.d("Room list is visible, finishing cold start check after ${it.duration}") } } } From ab4b11b9f06092848e496e075232b4205a6fdaf8 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 27 May 2026 17:26:14 +0200 Subject: [PATCH 0524/1083] Disable cron jobs and private SSH key jobs in forks (#6821) * Try disabling cron jobs in forks * Try fixing quality checks * Try fixing tests and enterprise builds * Stop using the ssh private key in more quality checks * Try disabling codecov if there is no token --- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/nightlyReports.yml | 3 ++- .github/workflows/quality.yml | 28 ++++++++++----------- .github/workflows/stale-issues.yml | 1 + .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- .github/workflows/tests.yml | 7 ++++-- 9 files changed, 27 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 956655b262..92cfe6ded5 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -19,7 +19,7 @@ jobs: name: Build Enterprise APKs runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} strategy: matrix: variant: [debug, release, nightly] diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 8de21b3ef1..6b4d08fd39 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -11,7 +11,7 @@ jobs: generate-github-pages: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event_name != 'pull_request' || github.event.repository.fork != true }} permissions: contents: write steps: diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index 66078b7b4b..a8986b6005 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -11,7 +11,7 @@ jobs: update-gradle-wrapper: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event_name != 'pull_request' && github.event.repository.fork != true }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 371c11b3ff..7c83d63ebd 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -17,7 +17,7 @@ jobs: nightlyReports: name: Create kover report artifact and upload sonar result. runs-on: ubuntu-latest - if: ${{ github.repository == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be @@ -75,6 +75,7 @@ jobs: dependency-analysis: name: Dependency analysis runs-on: ubuntu-latest + if: ${{ github.event.repository.fork != true }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index ceaa86016a..a9180f6276 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -38,11 +38,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Run code quality check suite run: ./tools/check/check_code_quality.sh @@ -101,11 +101,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -142,11 +142,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -176,11 +176,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -221,11 +221,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -262,11 +262,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -303,11 +303,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: Run docs check # This is equivalent to `./gradlew checkDocs`, but we avoid having to install java and gradle diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml index 1958e80083..f5d2fe911c 100644 --- a/.github/workflows/stale-issues.yml +++ b/.github/workflows/stale-issues.yml @@ -9,6 +9,7 @@ permissions: {} jobs: stale: runs-on: ubuntu-latest + if: ${{ github.event.repository.fork != true }} permissions: issues: write steps: diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 6de0f3b0df..131a2f3073 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -11,7 +11,7 @@ jobs: sync-localazy: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event_name != 'pull_request' || github.event.repository.fork != true }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index 9f7a67cc22..832ef4a71c 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -11,7 +11,7 @@ jobs: sync-sas-strings: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event_name != 'pull_request' || github.event.repository.fork != true }} # No concurrency required, runs every time on a schedule. steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 842c8113f4..dc8b2852d2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,11 +56,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} + if: ${{ github.event.repository.fork != true }} run: git submodule update --init --recursive - name: ☕️ Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -109,6 +109,9 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + env: + HAS_TOKEN: ${{ secrets.CODECOV_TOKEN != ''}} + if: ${{ env.HAS_TOKEN == 'true' }} with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From bf1462f9b1f17583ed4ef1849a99568705c8b755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 15 May 2026 14:57:39 +0200 Subject: [PATCH 0525/1083] WIP --- build.gradle.kts | 5 +++-- .../home/impl/components/HomeTopBar.kt | 3 ++- .../impl/spacefilters/SpaceFiltersView.kt | 9 +++++---- .../impl/screens/error/ErrorView.kt | 2 +- .../impl/common/ui/LocationPinMarkers.kt | 3 ++- .../location/impl/share/ShareLocationView.kt | 4 +++- .../location/impl/show/ShowLocationView.kt | 3 ++- .../screens/qrcode/error/QrCodeErrorView.kt | 2 +- .../features/messages/impl/MessagesView.kt | 3 ++- .../impl/threads/list/ThreadsListView.kt | 4 +++- .../event/TimelineItemLocationContent.kt | 7 +++++-- .../impl/advanced/AdvancedSettingsView.kt | 4 +++- gradle/libs.versions.toml | 1 + .../appyx/SafeChildrenTransitionScope.kt | 1 + .../theme/components/ModalBottomSheet.kt | 7 +++++-- .../matrix/ui/components/AvatarPickerView.kt | 1 + .../libraries/qrcode/QrCodeCameraView.kt | 2 +- tools/detekt/detekt.yml | 19 ++++++++++++++++++- 18 files changed, 59 insertions(+), 21 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 474b868eda..1aaccbe2f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,7 +30,8 @@ tasks.register("clean").configure { delete(rootProject.layout.buildDirectory) } -private val ktLintVersion = the().versions.ktlint.get() +private val catalog = the() +private val ktLintVersion = catalog.versions.ktlint.get() allprojects { // Detekt @@ -46,7 +47,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.5.8") + detektPlugins(catalog.detekt.compose.rules) detektPlugins(project(":tests:detekt-rules")) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt index 5f55beaf60..a563520e09 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/HomeTopBar.kt @@ -10,6 +10,7 @@ package io.element.android.features.home.impl.components import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -160,7 +161,7 @@ fun HomeTopBar( } @Composable -private fun RoomListMenuItems( +private fun RowScope.RoomListMenuItems( onToggleSearch: () -> Unit, onMenuActionClick: (RoomListMenuAction) -> Unit, canReportBug: Boolean, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt index 1f0d6ff7d9..8a270f1b85 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt @@ -48,6 +48,7 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.ImmutableList @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -93,7 +94,7 @@ fun SpaceFiltersView( SpaceFiltersBottomSheetContent( filters = state.visibleFilters, searchQuery = state.searchQuery, - onFilterSelected = { filter -> + onSelectFilter = { filter -> state.eventSink(SpaceFiltersEvent.Selecting.SelectFilter(filter)) } ) @@ -105,9 +106,9 @@ fun SpaceFiltersView( @Composable private fun SpaceFiltersBottomSheetContent( - filters: List, + filters: ImmutableList, searchQuery: TextFieldState, - onFilterSelected: (SpaceServiceFilter) -> Unit, + onSelectFilter: (SpaceServiceFilter) -> Unit, modifier: Modifier = Modifier ) { Column( @@ -133,7 +134,7 @@ private fun SpaceFiltersBottomSheetContent( items(filters) { filter -> SpaceFilterItem( filter = filter, - onClick = { onFilterSelected(filter) } + onClick = { onSelectFilter(filter) } ) } } diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt index 4db2aa9ad5..cc94951dbd 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt @@ -147,7 +147,7 @@ private fun DoneButton( } @Composable -private fun Buttons( +private fun ColumnScope.Buttons( onRetry: () -> Unit, onCancel: () -> Unit, ) { diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationPinMarkers.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationPinMarkers.kt index 762a719cf4..e30dfd53de 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationPinMarkers.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationPinMarkers.kt @@ -14,6 +14,7 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.api.Location import io.element.android.libraries.designsystem.components.PinVariant import io.element.android.libraries.designsystem.components.rememberLocationPinBitmap +import kotlinx.collections.immutable.ImmutableList import kotlinx.serialization.json.JsonPrimitive import org.maplibre.compose.expressions.dsl.and import org.maplibre.compose.expressions.dsl.asString @@ -66,7 +67,7 @@ data class LocationMarkerData( */ @Composable fun LocationPinMarkers( - markers: List, + markers: ImmutableList, onMarkerClick: ((LocationMarkerData) -> Unit)? = null, onClusterClick: ((Position) -> Unit)? = null, ) { diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index 985c6c8bdc..52400cd49d 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -26,6 +26,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -180,6 +181,7 @@ private fun StartLiveLocationActionView( onActionSuccess: () -> Unit, modifier: Modifier = Modifier, ) { + val updatedOnActionSuccess by rememberUpdatedState(onActionSuccess) Box(modifier = modifier) { val asyncIndicatorState = rememberAsyncIndicatorState() AsyncIndicatorHost(state = asyncIndicatorState) @@ -202,7 +204,7 @@ private fun StartLiveLocationActionView( } } is AsyncAction.Success -> { - LaunchedEffect(action) { onActionSuccess() } + LaunchedEffect(action) { updatedOnActionSuccess() } } else -> Unit } 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 80ffaabedd..231bc01b12 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 @@ -50,6 +50,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch import org.maplibre.compose.camera.CameraMoveReason import org.maplibre.compose.camera.CameraPosition @@ -172,7 +173,7 @@ fun ShowLocationView( trackUserLocation = state.isTrackMyLocation ) val markers = remember(state.locationShares) { - state.locationShares.map { it.toMarkerData() } + state.locationShares.map { it.toMarkerData() }.toImmutableList() } LocationPinMarkers(markers) }, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorView.kt index a6d9da3de2..6b5da8f300 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/error/QrCodeErrorView.kt @@ -125,7 +125,7 @@ private fun Content(errorScreenType: QrCodeErrorScreenType) { } @Composable -private fun Buttons( +private fun ColumnScope.Buttons( onRetry: () -> Unit, onCancel: () -> Unit, ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 3e6f14e805..b299ea42a9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets @@ -412,7 +413,7 @@ fun MessagesView( } @Composable -internal fun MessagesMenuActions( +internal fun RowScope.MessagesMenuActions( displayThreads: Boolean, roomCallState: RoomCallState, onJoinCallClick: (isAudioCall: Boolean) -> Unit, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt index 5e26d849a5..7d741eb3ea 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListView.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -157,6 +158,7 @@ private fun ScrollHelper( listState: LazyListState, onPaginate: () -> Unit, ) { + val updatedOnPaginate by rememberUpdatedState(onPaginate) val lastVisibleItemIndex by remember { derivedStateOf { listState.firstVisibleItemIndex + listState.layoutInfo.visibleItemsInfo.size - 1 } } @@ -168,7 +170,7 @@ private fun ScrollHelper( } LaunchedEffect(needsPagination, lastVisibleItemIndex) { if (needsPagination) { - onPaginate() + updatedOnPaginate() delay(400L) } } 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 1003d03b4b..12368530a3 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 @@ -9,7 +9,9 @@ package io.element.android.features.messages.impl.timeline.model.event import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState +import androidx.compose.runtime.rememberUpdatedState import io.element.android.features.location.api.Location import io.element.android.libraries.designsystem.components.PinVariant import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -103,8 +105,9 @@ private fun rememberIsLiveLocationActive( mode: TimelineItemLocationContent.Mode.Live, currentTimeMillis: () -> Long, ): Boolean { + val updatedCurrentTimeMillis by rememberUpdatedState(currentTimeMillis) fun TimelineItemLocationContent.Mode.Live.isActive(): Boolean { - return isActive && endTimestamp > currentTimeMillis() + return isActive && endTimestamp > updatedCurrentTimeMillis() } return produceState( initialValue = mode.isActive(), @@ -112,7 +115,7 @@ private fun rememberIsLiveLocationActive( key2 = mode.isActive, ) { if (mode.isActive) { - val remainingMillis = mode.endTimestamp - currentTimeMillis() + val remainingMillis = mode.endTimestamp - updatedCurrentTimeMillis() delay(remainingMillis) } value = false 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 af28e3443f..7b5d0c5a9a 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 @@ -19,6 +19,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -343,6 +344,7 @@ private fun LiveLocationUpdatesSection( onOpenAppPermissionsClick: () -> Unit, modifier: Modifier = Modifier, ) { + val updatedOnValueSaved by rememberUpdatedState(onValueSaved) PreferenceCategory( modifier = modifier, showTopDivider = true, @@ -382,7 +384,7 @@ private fun LiveLocationUpdatesSection( value = sliderValue.toFloat(), onValueChange = { sliderValue = it.roundToInt() }, onValueChangeFinish = { - onValueSaved(sliderValue) + updatedOnValueSaved(sliderValue) }, valueRange = valueRange, colors = SliderDefaults.colors( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b526c0ab69..524ec54c73 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -72,6 +72,7 @@ android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref compose_compiler_plugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } # https://developer.android.com/studio/write/java8-support#library-desugaring-versions android_desugar = "com.android.tools:desugar_jdk_libs:2.1.5" +detekt_compose_rules = "io.nlopez.compose.rules:detekt:0.4.28" kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } metro_gradle_plugin = { module = "dev.zacsweers.metro:gradle-plugin", version.ref = "metro" } kotlin_compiler = { module = "org.jetbrains.kotlin:kotlin-compiler", version.ref = "kotlin" } diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/SafeChildrenTransitionScope.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/SafeChildrenTransitionScope.kt index 00e49d7bee..b90e95beca 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/SafeChildrenTransitionScope.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/appyx/SafeChildrenTransitionScope.kt @@ -186,6 +186,7 @@ class SafeChildrenTransitionScope( } @OptIn(ExperimentalSharedTransitionApi::class) +@Suppress("ContentSlotReused") @Composable inline fun ParentNode.SafeChildren( navModel: NavModel, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt index 689cba727f..ec5f7ce456 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt @@ -24,6 +24,8 @@ import androidx.compose.material3.SheetState import androidx.compose.material3.contentColorFor import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable +import androidx.compose.runtime.movableContentOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape @@ -88,14 +90,15 @@ fun ModalBottomSheet( dragHandle = dragHandle, contentWindowInsets = contentWindowInsets, ) { + val movableContent = remember { movableContentOf { content() } } if (scrollable) { Column( modifier = Modifier.verticalScroll(rememberScrollState()), ) { - content() + movableContent() } } else { - content() + movableContent() } } } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt index 4d3ba4dc6b..81822a04cc 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarPickerView.kt @@ -184,6 +184,7 @@ private fun PickButton( } } +@Suppress("ModifierClickableOrder") @Composable private fun BoxScope.OverlayEditButton( onClick: () -> Unit, diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt index 18bd1cff10..77648c0f0b 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt @@ -114,7 +114,7 @@ fun QrCodeCameraView( Box(modifier.clipToBounds()) { if (LocalInspectionMode.current) { Box( - modifier = modifier + modifier = Modifier .background(color = ElementTheme.colors.bgSubtlePrimary), contentAlignment = Alignment.Center, ) { diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml index 552b46755e..cc99ecab5a 100644 --- a/tools/detekt/detekt.yml +++ b/tools/detekt/detekt.yml @@ -150,7 +150,7 @@ exceptions: TooGenericExceptionCaught: active: false SwallowedException: - active: true + active: false ThrowingExceptionsWithoutMessageOrCause: active: true TooGenericExceptionThrown: @@ -224,12 +224,27 @@ comments: Compose: CompositionLocalAllowlist: active: true + # You can optionally define a list of CompositionLocals that are allowed here + allowedCompositionLocals: + - LocalCompoundColors + - LocalSnackbarDispatcher + - LocalCameraPositionState + - LocalMediaItemPresenterFactories + - LocalTimelineItemPresenterFactories + - LocalRoomMemberProfilesCache + - LocalMentionSpanUpdater + - LocalAnalyticsService + - LocalBuildMeta + - LocalUiTestMode + - LocalSdkIntVersionProvider CompositionLocalNaming: active: true ContentEmitterReturningValues: active: true # You can optionally add your own composables here # contentEmitters: MyComposable,MyOtherComposable + ModifierComposable: + active: true ModifierMissing: active: true ModifierReused: @@ -252,6 +267,8 @@ Compose: active: true PreviewPublic: active: true + # You can optionally disable that only previews with @PreviewParameter are flagged + previewPublicOnlyIfParams: false RememberMissing: active: true UnstableCollections: From 97de57fd79658a0ebfefae4598350fa46ad5f536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 15 May 2026 15:04:08 +0200 Subject: [PATCH 0526/1083] More fixes --- .../preferences/impl/advanced/AdvancedSettingsView.kt | 8 ++++---- .../features/space/impl/addroom/AddRoomToSpaceNode.kt | 2 +- .../features/space/impl/addroom/AddRoomToSpaceView.kt | 9 ++++++--- .../space/impl/addroom/AddRoomToSpaceViewTest.kt | 2 +- .../android/libraries/textcomposer/TextComposer.kt | 8 +++++--- 5 files changed, 17 insertions(+), 12 deletions(-) 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 7b5d0c5a9a..2f983d30df 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 @@ -207,7 +207,7 @@ fun AdvancedSettingsView( if (state.liveLocationMinimumDistanceUpdate != null) { LiveLocationUpdatesSection( value = state.liveLocationMinimumDistanceUpdate, - onValueSaved = { value -> + onSaveValue = { value -> state.eventSink(AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate(value)) }, onOpenAppPermissionsClick = onOpenAppSettingsClick, @@ -340,11 +340,11 @@ private fun ModerationAndSafety( @Composable private fun LiveLocationUpdatesSection( value: Int, - onValueSaved: (Int) -> Unit, + onSaveValue: (Int) -> Unit, onOpenAppPermissionsClick: () -> Unit, modifier: Modifier = Modifier, ) { - val updatedOnValueSaved by rememberUpdatedState(onValueSaved) + val updatedOnSaveValue by rememberUpdatedState(onSaveValue) PreferenceCategory( modifier = modifier, showTopDivider = true, @@ -384,7 +384,7 @@ private fun LiveLocationUpdatesSection( value = sliderValue.toFloat(), onValueChange = { sliderValue = it.roundToInt() }, onValueChangeFinish = { - updatedOnValueSaved(sliderValue) + updatedOnSaveValue(sliderValue) }, valueRange = valueRange, colors = SliderDefaults.colors( diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceNode.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceNode.kt index dadd54cf6f..c7aea55488 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceNode.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceNode.kt @@ -41,7 +41,7 @@ class AddRoomToSpaceNode( AddRoomToSpaceView( state = state, onBackClick = callback::onFinish, - onRoomsAdded = callback::onFinish, + onAddRoom = callback::onFinish, modifier = modifier ) } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceView.kt index c64efa8074..47c78e6fb8 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceView.kt @@ -23,6 +23,8 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter @@ -57,9 +59,10 @@ import kotlinx.collections.immutable.toImmutableList fun AddRoomToSpaceView( state: AddRoomToSpaceState, onBackClick: () -> Unit, - onRoomsAdded: () -> Unit, + onAddRoom: () -> Unit, modifier: Modifier = Modifier, ) { + val updatedOnAddRoom by rememberUpdatedState(onAddRoom) fun onRoomToggled(room: SelectRoomInfo) { state.eventSink(AddRoomToSpaceEvent.ToggleRoom(room)) } @@ -78,7 +81,7 @@ fun AddRoomToSpaceView( // Navigate back on success LaunchedEffect(state.saveAction) { if (state.saveAction is AsyncAction.Success) { - onRoomsAdded() + updatedOnAddRoom() } } @@ -247,6 +250,6 @@ internal fun AddRoomToSpaceViewPreview( AddRoomToSpaceView( state = state, onBackClick = {}, - onRoomsAdded = {}, + onAddRoom = {}, ) } diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt index 6fc10f1e82..fa47ce63bb 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceViewTest.kt @@ -125,7 +125,7 @@ private fun AndroidComposeUiTest.setAddRoomToSpaceView( AddRoomToSpaceView( state = state, onBackClick = onBackClick, - onRoomsAdded = onRoomsAdded, + onAddRoom = onRoomsAdded, ) } } 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 3993b3d64c..0f62eb5234 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 @@ -32,6 +32,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -419,7 +420,7 @@ fun TextComposer( // Re-focus the text input when voice recording ends so the user can continue typing var previousVoiceMessageState by remember { mutableStateOf(voiceMessageState) } - LaunchedEffect(voiceMessageState) { + LaunchedEffect(voiceMessageState, onRequestFocus) { if (voiceMessageState is VoiceMessageState.Idle && previousVoiceMessageState !is VoiceMessageState.Idle) { onRequestFocus() } @@ -522,6 +523,7 @@ private fun StandardLayout( .padding(bottom = 8.dp, top = 8.dp) .weight(1f) ) { + val movableVoiceRecording = remember { movableContentOf { voiceRecording() } } if (voiceMessageState is VoiceMessageState.Idle) { textInput() } else if (composerMode is MessageComposerMode.Special) { @@ -530,10 +532,10 @@ private fun StandardLayout( onResetComposerMode = onResetComposerMode, isTextEmpty = true, ) { - voiceRecording() + movableVoiceRecording() } } else { - voiceRecording() + movableVoiceRecording() } } // To avoid loosing keyboard focus, the IconButton has to be defined here and has to be always enabled. From 5b138e7ad70cb99df7cb2ce65388baefd848955a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 22 May 2026 14:38:35 +0200 Subject: [PATCH 0527/1083] Small cleanup and comment --- build.gradle.kts | 3 +-- gradle/libs.versions.toml | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1aaccbe2f2..661fc9d30a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,7 +31,6 @@ tasks.register("clean").configure { } private val catalog = the() -private val ktLintVersion = catalog.versions.ktlint.get() allprojects { // Detekt @@ -65,7 +64,7 @@ allprojects { // See https://github.com/JLLeitschuh/ktlint-gradle#configuration configure { - version = ktLintVersion + version = catalog.versions.ktlint.get() android = true ignoreFailures = false enableExperimentalRules = true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 524ec54c73..f3e79e3c45 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -61,6 +61,8 @@ autoservice = "1.1.1" # quality detekt = "1.23.8" +# Stick to version < 0.5 since error detection is broken. See https://mrmans0n.github.io/compose-rules/detekt/#supported-versions-matrix +detekt_compose_rules = "0.4.28" # See https://github.com/pinterest/ktlint/releases/ ktlint = "1.8.0" androidx-test-ext-junit = "1.3.0" @@ -72,7 +74,8 @@ android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref compose_compiler_plugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } # https://developer.android.com/studio/write/java8-support#library-desugaring-versions android_desugar = "com.android.tools:desugar_jdk_libs:2.1.5" -detekt_compose_rules = "io.nlopez.compose.rules:detekt:0.4.28" +# Used in build.gradle.kts +detekt_compose_rules = { module = "io.nlopez.compose.rules:detekt", version.ref = "detekt_compose_rules" } kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } metro_gradle_plugin = { module = "dev.zacsweers.metro:gradle-plugin", version.ref = "metro" } kotlin_compiler = { module = "org.jetbrains.kotlin:kotlin-compiler", version.ref = "kotlin" } From c409fc2c838b5b8f3c958f302f24bfa7fc085f3c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 22 May 2026 14:48:08 +0200 Subject: [PATCH 0528/1083] Fix other issues detekted. --- .../android/features/roomdetails/impl/RoomDetailsView.kt | 2 +- .../mediaviewer/impl/viewer/MediaViewerDataSource.kt | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index b30c73b9c8..40210279fa 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -206,7 +206,7 @@ fun RoomDetailsView( ), trailingContent = ListItemContent.Custom { Box( - modifier = modifier + modifier = Modifier .size(8.dp) .clip(CircleShape) .background(ElementTheme.colors.iconAccentPrimary) 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 b0b81bbde0..6feb3c7d53 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 @@ -13,8 +13,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.ProduceStateScope import androidx.compose.runtime.State +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState +import androidx.compose.runtime.rememberUpdatedState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.extensions.mapCatchingExceptions import io.element.android.libraries.matrix.api.core.EventId @@ -87,8 +89,9 @@ class MediaViewerDataSource( fun produceState( producer: suspend ProduceStateScope>.(StateFlow>) -> Unit ): State> { + val latestProducer by rememberUpdatedState(producer) return produceState(initialValue = initialData()) { - producer(dataFlow) + latestProducer(dataFlow) } } From 7003bf570232655b2be1ceecf9dd2e6adf0648d4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 26 May 2026 10:29:50 +0200 Subject: [PATCH 0529/1083] Fix broken preview --- .../io/element/android/libraries/qrcode/QrCodeCameraView.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt index 77648c0f0b..cae7452cd8 100644 --- a/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt +++ b/libraries/qrcode/src/main/kotlin/io/element/android/libraries/qrcode/QrCodeCameraView.kt @@ -18,6 +18,7 @@ import androidx.camera.view.PreviewView import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -115,6 +116,7 @@ fun QrCodeCameraView( if (LocalInspectionMode.current) { Box( modifier = Modifier + .fillMaxSize() .background(color = ElementTheme.colors.bgSubtlePrimary), contentAlignment = Alignment.Center, ) { From 5ebeddfe2e4ddfe9b946e983907c722dcb42d938 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 26 May 2026 16:16:27 +0200 Subject: [PATCH 0530/1083] Revert change --- .../features/preferences/impl/advanced/AdvancedSettingsView.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 2f983d30df..41e6ba2d83 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 @@ -344,7 +344,6 @@ private fun LiveLocationUpdatesSection( onOpenAppPermissionsClick: () -> Unit, modifier: Modifier = Modifier, ) { - val updatedOnSaveValue by rememberUpdatedState(onSaveValue) PreferenceCategory( modifier = modifier, showTopDivider = true, @@ -384,7 +383,7 @@ private fun LiveLocationUpdatesSection( value = sliderValue.toFloat(), onValueChange = { sliderValue = it.roundToInt() }, onValueChangeFinish = { - updatedOnSaveValue(sliderValue) + onSaveValue(sliderValue) }, valueRange = valueRange, colors = SliderDefaults.colors( From 27982449755f1605b8ba44956291381f2c68ae13 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 27 May 2026 14:34:19 +0200 Subject: [PATCH 0531/1083] Remove unused import --- .../features/preferences/impl/advanced/AdvancedSettingsView.kt | 1 - 1 file changed, 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 41e6ba2d83..c108c45d3b 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 @@ -19,7 +19,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier From f8712525739fccaf865260586842fbeb811dd1b7 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 28 May 2026 09:56:07 +0200 Subject: [PATCH 0532/1083] Revert "Disable cron jobs and private SSH key jobs in forks" (#6905) This reverts commit ab4b11b9f06092848e496e075232b4205a6fdaf8. --- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/nightlyReports.yml | 3 +-- .github/workflows/quality.yml | 28 ++++++++++----------- .github/workflows/stale-issues.yml | 1 - .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- .github/workflows/tests.yml | 7 ++---- 9 files changed, 22 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 92cfe6ded5..956655b262 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -19,7 +19,7 @@ jobs: name: Build Enterprise APKs runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} strategy: matrix: variant: [debug, release, nightly] diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 6b4d08fd39..8de21b3ef1 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -11,7 +11,7 @@ jobs: generate-github-pages: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} permissions: contents: write steps: diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index a8986b6005..66078b7b4b 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -11,7 +11,7 @@ jobs: update-gradle-wrapper: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' && github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 7c83d63ebd..371c11b3ff 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -17,7 +17,7 @@ jobs: nightlyReports: name: Create kover report artifact and upload sonar result. runs-on: ubuntu-latest - if: ${{ github.event.repository.fork != true }} + if: ${{ github.repository == 'element-hq/element-x-android' }} steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be @@ -75,7 +75,6 @@ jobs: dependency-analysis: name: Dependency analysis runs-on: ubuntu-latest - if: ${{ github.event.repository.fork != true }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index a9180f6276..ceaa86016a 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -38,11 +38,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Run code quality check suite run: ./tools/check/check_code_quality.sh @@ -101,11 +101,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -142,11 +142,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -176,11 +176,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -221,11 +221,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -262,11 +262,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -303,11 +303,11 @@ jobs: persist-credentials: false - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Run docs check # This is equivalent to `./gradlew checkDocs`, but we avoid having to install java and gradle diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml index f5d2fe911c..1958e80083 100644 --- a/.github/workflows/stale-issues.yml +++ b/.github/workflows/stale-issues.yml @@ -9,7 +9,6 @@ permissions: {} jobs: stale: runs-on: ubuntu-latest - if: ${{ github.event.repository.fork != true }} permissions: issues: write steps: diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 131a2f3073..6de0f3b0df 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -11,7 +11,7 @@ jobs: sync-localazy: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index 832ef4a71c..9f7a67cc22 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -11,7 +11,7 @@ jobs: sync-sas-strings: runs-on: ubuntu-latest # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} # No concurrency required, runs every time on a schedule. steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dc8b2852d2..842c8113f4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,11 +56,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: ${{ github.event.repository.fork != true }} + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: ☕️ Use JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -109,9 +109,6 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 - env: - HAS_TOKEN: ${{ secrets.CODECOV_TOKEN != ''}} - if: ${{ env.HAS_TOKEN == 'true' }} with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From bdedf41f99bb44791d216e1eee251d1a1f046355 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Thu, 28 May 2026 17:52:59 +0300 Subject: [PATCH 0533/1083] Fix `FLAG_SECURE` splash screen having a pink top bar (#6903) --- app/src/main/res/values-night/themes.xml | 9 ++++++++- app/src/main/res/values/themes.xml | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index af159a0b11..2e610fc0c7 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -11,7 +11,14 @@ @color/splashscreen_bg_dark @drawable/transparent @style/Theme.ElementX + @color/splashscreen_bg_dark + @color/splashscreen_bg_dark + @color/splashscreen_bg_dark - diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 4190fd84f2..26cb0a56bd 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -10,8 +10,14 @@ @color/splashscreen_bg_light @drawable/transparent @style/Theme.ElementX + @color/splashscreen_bg_light + @color/splashscreen_bg_light + @color/splashscreen_bg_light From c88edc9621d342152795b4fcff70545363f91417 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 28 May 2026 16:54:12 +0200 Subject: [PATCH 0534/1083] Notification settings: pick custom sounds for messages and call ringtones (#6897) * Notification settings: pick custom sounds for messages and call ringtones (#6702) * Feature: add notification sound settings for messages and calls * Add sound not available banner, accessibility checks * Fix build and Konsist convention violations - libraries:preferences:api now uses io.element.android-compose-library so NotificationSound's @Immutable annotation can resolve, matching the pattern in libraries:matrix:api. - Rename SoundUnavailableBannerStateProvider to NotificationSoundUnavailableStateProvider so the class name contains the parameter type as required by KonsistClassNameTest. * Suppress LargeClass on RoomListPresenterTest The three new sound-unavailable tests pushed the class past Detekt's default LargeClass threshold. Matches the suppression pattern already used on five presenter test classes under features/messages/impl/test. * NotificationSettingsView: guard ringtone-picker launchers in inspection mode rememberLauncherForActivityResult requires a LocalActivityResultRegistryOwner, which Paparazzi-driven preview snapshot tests don't provide, causing NotificationSettingsViewPreview to throw IllegalStateException for every preview parameter. Extract the click handlers into a helper that returns a no-op when LocalInspectionMode.current is true; the runtime path is unchanged. * Handle unresolved notification sounds mid session * Quality checks, refactor mid session error ui * Suppress detekt LargeClass on NotificationSettingsPresenterTest * Remove notification sound resilience layer, replace with file copy * Reselect element sound option, code cleanup * Add element fade notification sound option * Fix new file headers * Revert to flowOf(Unit) for announcement service * Add ringtone picker dialog to match message selector * Update strings in conjunction with ios * Update test to reflect new string * Sync strings. * Update screenshots * Fix test * Remove not properly located translations. This will be fixed in the next String sync. * Fix test on CI --------- Co-authored-by: Jenna Vassar Co-authored-by: ElementBot --- app/src/main/res/xml/file_providers.xml | 1 + .../impl/store/DefaultAnnouncementStore.kt | 5 +- .../impl/components/RoomListContentView.kt | 28 +- .../impl/roomlist/RoomListPresenterTest.kt | 1 + .../NotificationSettingsEvents.kt | 14 + .../NotificationSettingsPresenter.kt | 249 ++++++ .../NotificationSettingsState.kt | 29 + .../NotificationSettingsStateProvider.kt | 67 ++ .../notifications/NotificationSettingsView.kt | 201 +++++ .../notifications/NotificationSoundPicker.kt | 55 ++ .../impl/src/main/res/values/localazy.xml | 9 + .../NotificationSettingsPresenterTest.kt | 765 ++++++++++++++++++ .../NotificationSettingsViewTest.kt | 42 +- .../NotificationSoundPickerTest.kt | 90 +++ .../NotificationSoundStorageTest.kt | 80 ++ libraries/preferences/api/build.gradle.kts | 2 +- .../api/store/AppPreferencesStore.kt | 22 + .../api/store/NotificationSound.kt | 77 ++ .../impl/store/DefaultAppPreferencesStore.kt | 79 ++ .../test/InMemoryAppPreferencesStore.kt | 58 +- libraries/push/api/build.gradle.kts | 1 + .../notifications/NotificationSoundUpdater.kt | 26 + .../notifications/SoundDisplayNameResolver.kt | 18 + .../sound/NotificationSoundCopier.kt | 47 ++ libraries/push/impl/build.gradle.kts | 2 + .../DefaultSoundDisplayNameResolver.kt | 35 + .../NotificationSoundFileProviderAuthority.kt | 18 + .../channels/NotificationChannels.kt | 293 +++++-- .../sound/DefaultNotificationSoundCopier.kt | 208 +++++ .../impl/src/main/res/raw/element_fade.mp3 | Bin 0 -> 33645 bytes .../channels/FakeNotificationChannels.kt | 22 +- .../channels/NotificationChannelsTest.kt | 415 +++++++++- .../DefaultNotificationCreatorTest.kt | 4 +- .../DefaultNotificationSoundCopierTest.kt | 82 ++ libraries/push/test/build.gradle.kts | 1 + .../FakeNotificationSoundUpdater.kt | 31 + .../FakeSoundDisplayNameResolver.kt | 19 + .../sound/FakeNotificationSoundCopier.kt | 24 + .../src/main/res/values-fi/translations.xml | 4 - .../src/main/res/values-fr/translations.xml | 4 - .../src/main/res/values-ja/translations.xml | 5 - .../src/main/res/values-pl/translations.xml | 7 - .../src/main/res/values-zh/translations.xml | 5 - .../src/main/res/values/localazy.xml | 6 - ...ions_NotificationSettingsView_Day_0_en.png | 4 +- ...ons_NotificationSettingsView_Day_14_en.png | 3 + ...ons_NotificationSettingsView_Day_15_en.png | 3 + ...ons_NotificationSettingsView_Day_16_en.png | 3 + ...ons_NotificationSettingsView_Day_17_en.png | 3 + ...ons_NotificationSettingsView_Day_18_en.png | 3 + ...ons_NotificationSettingsView_Day_19_en.png | 3 + ...ions_NotificationSettingsView_Day_1_en.png | 4 +- ...ons_NotificationSettingsView_Day_20_en.png | 3 + ...ions_NotificationSettingsView_Day_2_en.png | 4 +- ...ions_NotificationSettingsView_Day_3_en.png | 4 +- ...ions_NotificationSettingsView_Day_4_en.png | 4 +- ...ions_NotificationSettingsView_Day_5_en.png | 4 +- ...ions_NotificationSettingsView_Day_6_en.png | 4 +- ...ions_NotificationSettingsView_Day_7_en.png | 4 +- ...ions_NotificationSettingsView_Day_8_en.png | 4 +- ...ions_NotificationSettingsView_Day_9_en.png | 4 +- ...ns_NotificationSettingsView_Night_0_en.png | 4 +- ...s_NotificationSettingsView_Night_14_en.png | 3 + ...s_NotificationSettingsView_Night_15_en.png | 3 + ...s_NotificationSettingsView_Night_16_en.png | 3 + ...s_NotificationSettingsView_Night_17_en.png | 3 + ...s_NotificationSettingsView_Night_18_en.png | 3 + ...s_NotificationSettingsView_Night_19_en.png | 3 + ...ns_NotificationSettingsView_Night_1_en.png | 4 +- ...s_NotificationSettingsView_Night_20_en.png | 3 + ...ns_NotificationSettingsView_Night_2_en.png | 4 +- ...ns_NotificationSettingsView_Night_3_en.png | 4 +- ...ns_NotificationSettingsView_Night_4_en.png | 4 +- ...ns_NotificationSettingsView_Night_5_en.png | 4 +- ...ns_NotificationSettingsView_Night_6_en.png | 4 +- ...ns_NotificationSettingsView_Night_7_en.png | 4 +- ...ns_NotificationSettingsView_Night_8_en.png | 4 +- ...ns_NotificationSettingsView_Night_9_en.png | 4 +- tools/localazy/config.json | 1 + 79 files changed, 3135 insertions(+), 139 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPicker.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPickerTest.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundStorageTest.kt create mode 100644 libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/NotificationSound.kt create mode 100644 libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationSoundUpdater.kt create mode 100644 libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/SoundDisplayNameResolver.kt create mode 100644 libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/sound/NotificationSoundCopier.kt create mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultSoundDisplayNameResolver.kt create mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationSoundFileProviderAuthority.kt create mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopier.kt create mode 100644 libraries/push/impl/src/main/res/raw/element_fade.mp3 create mode 100644 libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopierTest.kt create mode 100644 libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationSoundUpdater.kt create mode 100644 libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeSoundDisplayNameResolver.kt create mode 100644 libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/sound/FakeNotificationSoundCopier.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_14_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_15_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_16_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_17_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_18_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_19_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_20_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_14_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_15_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_16_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_17_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_18_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_19_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_20_en.png diff --git a/app/src/main/res/xml/file_providers.xml b/app/src/main/res/xml/file_providers.xml index ac74590cba..330a2e0c3f 100644 --- a/app/src/main/res/xml/file_providers.xml +++ b/app/src/main/res/xml/file_providers.xml @@ -7,4 +7,5 @@ --> + diff --git a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt index 5a6c135247..2093baa8b3 100644 --- a/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt +++ b/features/announcement/impl/src/main/kotlin/io/element/android/features/announcement/impl/store/DefaultAnnouncementStore.kt @@ -35,8 +35,9 @@ class DefaultAnnouncementStore( override fun announcementStatusFlow(announcement: Announcement): Flow { val key = announcement.toKey() - // Announcement.Fullscreen.Space is disabled, consider it's shown - // For NewNotificationSound, a migration will set it to Show on application upgrade (see AppMigration08) + // Default-status convention: Shown for one-shot intro/feature announcements that should + // NOT replay on first launch (Fullscreen.Space is disabled; NewNotificationSound is opted + // in by AppMigration08). val defaultStatus = when (announcement) { Announcement.Fullscreen.Space -> AnnouncementStatus.Shown Announcement.NewNotificationSound -> AnnouncementStatus.Shown diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt index a03399baf7..dee175a7b1 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt @@ -245,19 +245,25 @@ private fun RoomsViewList( ) } } - SecurityBannerState.None -> if (state.fullScreenIntentPermissionsState.shouldDisplayBanner) { - item { - FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState) + // Banner precedence (top-to-bottom): full-screen-intent > battery-optimization > + // new-notification-sound > sound-unavailable. At most one renders at a time. + SecurityBannerState.None -> when { + state.fullScreenIntentPermissionsState.shouldDisplayBanner -> { + item { + FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState) + } } - } else if (state.batteryOptimizationState.shouldDisplayBanner) { - item { - BatteryOptimizationBanner(state = state.batteryOptimizationState) + state.batteryOptimizationState.shouldDisplayBanner -> { + item { + BatteryOptimizationBanner(state = state.batteryOptimizationState) + } } - } else if (state.showNewNotificationSoundBanner) { - item { - NewNotificationSoundBanner( - onDismissClick = { eventSink(RoomListEvent.DismissNewNotificationSoundBanner) }, - ) + state.showNewNotificationSoundBanner -> { + item { + NewNotificationSoundBanner( + onDismissClick = { eventSink(RoomListEvent.DismissNewNotificationSoundBanner) }, + ) + } } } } diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt index 99a5550a08..5c2c3e294b 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt @@ -89,6 +89,7 @@ import org.junit.Rule import org.junit.Test import kotlin.time.Duration.Companion.seconds +@Suppress("LargeClass") class RoomListPresenterTest { @get:Rule val warmUpRule = WarmUpRule() diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt index 8f1b332c8c..5ca7fc9fdf 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt @@ -8,6 +8,8 @@ package io.element.android.features.preferences.impl.notifications +import io.element.android.libraries.preferences.api.store.NotificationSound + sealed interface NotificationSettingsEvents { data object RefreshSystemNotificationsEnabled : NotificationSettingsEvents data class SetNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents @@ -20,4 +22,16 @@ sealed interface NotificationSettingsEvents { data object ChangePushProvider : NotificationSettingsEvents data object CancelChangePushProvider : NotificationSettingsEvents data class SetPushProvider(val index: Int) : NotificationSettingsEvents + data class SetMessageSound(val sound: NotificationSound) : NotificationSettingsEvents + data class SetCallRingtone(val sound: NotificationSound) : NotificationSettingsEvents + data object DismissMessageSoundCopyError : NotificationSettingsEvents + data object DismissCallRingtoneCopyError : NotificationSettingsEvents + data object ShowMessageSoundDialog : NotificationSettingsEvents + data object DismissMessageSoundDialog : NotificationSettingsEvents + data class SelectMessageSoundPreset(val sound: NotificationSound) : NotificationSettingsEvents + data object LaunchMessageSoundPicker : NotificationSettingsEvents + data object ShowCallRingtoneDialog : NotificationSettingsEvents + data object DismissCallRingtoneDialog : NotificationSettingsEvents + data class SelectCallRingtonePreset(val sound: NotificationSound) : NotificationSettingsEvents + data object LaunchCallRingtonePicker : NotificationSettingsEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index 12f13e734b..03fe2cf31b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -16,10 +16,12 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.key import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject +import io.element.android.features.preferences.impl.R import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter @@ -30,18 +32,30 @@ import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermiss import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.NotificationSound import io.element.android.libraries.push.api.PushService +import io.element.android.libraries.push.api.notifications.NotificationSoundUpdater +import io.element.android.libraries.push.api.notifications.SoundDisplayNameResolver +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.CopyResult +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.SoundSlot import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.api.PushProvider import io.element.android.libraries.pushstore.api.UserPushStore import io.element.android.libraries.pushstore.api.UserPushStoreFactory +import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import timber.log.Timber import kotlin.time.Duration.Companion.seconds @Inject @@ -52,9 +66,22 @@ class NotificationSettingsPresenter( private val pushService: PushService, private val systemNotificationsEnabledProvider: SystemNotificationsEnabledProvider, private val fullScreenIntentPermissionsPresenter: Presenter, + private val appPreferencesStore: AppPreferencesStore, + private val notificationSoundUpdater: NotificationSoundUpdater, + private val notificationSoundCopier: NotificationSoundCopier, + private val soundDisplayNameResolver: SoundDisplayNameResolver, + private val stringProvider: StringProvider, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, ) : Presenter { + // Serializes the pick → copy → persist → recreate pipeline per slot. The copier already locks + // its `.tmp` file, but the persist+recreate window outside the copier is unprotected; + // without this, two rapid picks (e.g. an automation or accessibility service firing back-to- + // back events) could interleave and leave the channel id pointing at the older version while + // DataStore reflects the newer one. + private val messageSoundLock = Mutex() + private val callRingtoneLock = Mutex() + @Composable override fun present(): NotificationSettingsState { val userPushStore = remember { userPushStoreFactory.getOrCreate(matrixClient.sessionId) } @@ -109,6 +136,42 @@ class NotificationSettingsPresenter( var showChangePushProviderDialog by remember { mutableStateOf(false) } + val messageSound by remember { appPreferencesStore.getMessageSoundFlow() }.collectAsState(initial = NotificationSound.SystemDefault) + val callRingtone by remember { appPreferencesStore.getCallRingtoneFlow() }.collectAsState(initial = NotificationSound.SystemDefault) + val persistedMessageSoundTitle by remember { appPreferencesStore.getMessageSoundDisplayNameFlow() }.collectAsState(initial = null) + val persistedCallRingtoneTitle by remember { appPreferencesStore.getCallRingtoneDisplayNameFlow() }.collectAsState(initial = null) + val defaultLabel = stringProvider.getString(R.string.screen_notification_settings_sound_system_default) + + // One-shot classification for the call-ringtone slot only: users who customised the + // channel via Android system settings before the in-app picker existed (channel version 0, + // persisted SystemDefault) get reflected here. The message-sound equivalent is handled by + // the eager migration in DefaultNotificationChannels.createNotificationChannels(). Cleared + // on any in-app pick so a stale read can't bleed into the row after the recreate. + var legacyCallRingtone by remember { mutableStateOf(null) } + LaunchedEffect(Unit) { + val config = appPreferencesStore.getNotificationSoundChannelConfig() + if (config.callRingtone == NotificationSound.SystemDefault && config.callRingtoneVersion == 0) { + legacyCallRingtone = notificationSoundUpdater.readRingingCallChannelSound() + } + } + + val effectiveMessageSound = messageSound + val effectiveCallRingtone = if (callRingtone == NotificationSound.SystemDefault) { + legacyCallRingtone ?: callRingtone + } else { + callRingtone + } + + val messageSoundDisplayName = probeSoundDisplayName(effectiveMessageSound, persistedMessageSoundTitle, defaultLabel) + val callRingtoneDisplayName = probeSoundDisplayName(effectiveCallRingtone, persistedCallRingtoneTitle, defaultLabel) + + var messageSoundCopyError by remember { mutableStateOf(false) } + var callRingtoneCopyError by remember { mutableStateOf(false) } + var showMessageSoundDialog by remember { mutableStateOf(false) } + var pendingMessageSoundPickerLaunch by remember { mutableIntStateOf(0) } + var showCallRingtoneDialog by remember { mutableStateOf(false) } + var pendingCallRingtonePickerLaunch by remember { mutableIntStateOf(0) } + fun CoroutineScope.changePushProvider( data: Pair? ) = launch { @@ -157,6 +220,62 @@ class NotificationSettingsPresenter( NotificationSettingsEvents.ChangePushProvider -> showChangePushProviderDialog = true NotificationSettingsEvents.CancelChangePushProvider -> showChangePushProviderDialog = false is NotificationSettingsEvents.SetPushProvider -> localCoroutineScope.changePushProvider(distributors.getOrNull(event.index)) + is NotificationSettingsEvents.SetMessageSound -> applyMessageSound( + sound = event.sound, + sessionCoroutineScope = sessionCoroutineScope, + onCopyError = { messageSoundCopyError = true }, + onCopySuccess = { messageSoundCopyError = false }, + onChannelFailure = { failure -> changeNotificationSettingAction.value = AsyncAction.Failure(failure) }, + ) + is NotificationSettingsEvents.SelectMessageSoundPreset -> { + showMessageSoundDialog = false + applyMessageSound( + sound = event.sound, + sessionCoroutineScope = sessionCoroutineScope, + onCopyError = { messageSoundCopyError = true }, + onCopySuccess = { messageSoundCopyError = false }, + onChannelFailure = { failure -> changeNotificationSettingAction.value = AsyncAction.Failure(failure) }, + ) + } + NotificationSettingsEvents.ShowMessageSoundDialog -> showMessageSoundDialog = true + NotificationSettingsEvents.DismissMessageSoundDialog -> showMessageSoundDialog = false + NotificationSettingsEvents.LaunchMessageSoundPicker -> { + showMessageSoundDialog = false + pendingMessageSoundPickerLaunch++ + } + is NotificationSettingsEvents.SetCallRingtone -> { + legacyCallRingtone = null + applyCallRingtone( + sound = event.sound, + sessionCoroutineScope = sessionCoroutineScope, + onCopyError = { callRingtoneCopyError = true }, + onCopySuccess = { callRingtoneCopyError = false }, + onChannelFailure = { failure -> changeNotificationSettingAction.value = AsyncAction.Failure(failure) }, + ) + } + is NotificationSettingsEvents.SelectCallRingtonePreset -> { + showCallRingtoneDialog = false + legacyCallRingtone = null + applyCallRingtone( + sound = event.sound, + sessionCoroutineScope = sessionCoroutineScope, + onCopyError = { callRingtoneCopyError = true }, + onCopySuccess = { callRingtoneCopyError = false }, + onChannelFailure = { failure -> changeNotificationSettingAction.value = AsyncAction.Failure(failure) }, + ) + } + NotificationSettingsEvents.ShowCallRingtoneDialog -> showCallRingtoneDialog = true + NotificationSettingsEvents.DismissCallRingtoneDialog -> showCallRingtoneDialog = false + NotificationSettingsEvents.LaunchCallRingtonePicker -> { + showCallRingtoneDialog = false + pendingCallRingtonePickerLaunch++ + } + NotificationSettingsEvents.DismissMessageSoundCopyError -> { + messageSoundCopyError = false + } + NotificationSettingsEvents.DismissCallRingtoneCopyError -> { + callRingtoneCopyError = false + } } } @@ -171,10 +290,140 @@ class NotificationSettingsPresenter( availablePushDistributors = availableDistributors, showChangePushProviderDialog = showChangePushProviderDialog, fullScreenIntentPermissionsState = key(refreshFullScreenIntentSettings) { fullScreenIntentPermissionsPresenter.present() }, + messageSound = NotificationSettingsState.SoundChannelUiState( + sound = effectiveMessageSound, + displayName = messageSoundDisplayName, + copyError = messageSoundCopyError, + ), + callRingtone = NotificationSettingsState.SoundChannelUiState( + sound = effectiveCallRingtone, + displayName = callRingtoneDisplayName, + copyError = callRingtoneCopyError, + ), + showMessageSoundDialog = showMessageSoundDialog, + showCallRingtoneDialog = showCallRingtoneDialog, + pendingMessageSoundPickerLaunch = pendingMessageSoundPickerLaunch, + pendingCallRingtonePickerLaunch = pendingCallRingtonePickerLaunch, eventSink = ::handleEvent, ) } + private fun applyMessageSound( + sound: NotificationSound, + sessionCoroutineScope: CoroutineScope, + onCopyError: () -> Unit, + onCopySuccess: () -> Unit, + onChannelFailure: (Throwable) -> Unit, + ) { + sessionCoroutineScope.launch { + messageSoundLock.withLock { + // Re-selecting the current non-Custom sound is a no-op: skip the channel churn + // (delete + create round-trips through system_server) and the version bump. Custom + // still falls through so the copier refreshes the file from the (possibly updated) + // source URI. + if (sound !is NotificationSound.Custom && appPreferencesStore.getMessageSoundFlow().first() == sound) { + onCopySuccess() + return@withLock + } + val resolved = resolvePickedSound(sound, SoundSlot.Message, onCopyError) ?: return@withLock + runCatchingExceptions { + onCopySuccess() + val newVersion = appPreferencesStore.setMessageSoundAndIncrementVersion(resolved.first, resolved.second) + notificationSoundUpdater.recreateNoisyChannel(resolved.first, newVersion) + // Non-Custom picks bypass the copier, so they don't sweep the prior Custom file + // inline. Drop it now that the new channel no longer references it. + if (resolved.first !is NotificationSound.Custom) { + notificationSoundCopier.deleteStoredSoundFor(SoundSlot.Message) + } + }.onFailure(onChannelFailure) + } + } + } + + private fun applyCallRingtone( + sound: NotificationSound, + sessionCoroutineScope: CoroutineScope, + onCopyError: () -> Unit, + onCopySuccess: () -> Unit, + onChannelFailure: (Throwable) -> Unit, + ) { + sessionCoroutineScope.launch { + callRingtoneLock.withLock { + if (sound !is NotificationSound.Custom && appPreferencesStore.getCallRingtoneFlow().first() == sound) { + onCopySuccess() + return@withLock + } + val resolved = resolvePickedSound(sound, SoundSlot.Call, onCopyError) ?: return@withLock + runCatchingExceptions { + onCopySuccess() + val newVersion = appPreferencesStore.setCallRingtoneAndIncrementVersion(resolved.first, resolved.second) + notificationSoundUpdater.recreateRingingCallChannel(resolved.first, newVersion) + if (resolved.first !is NotificationSound.Custom) { + notificationSoundCopier.deleteStoredSoundFor(SoundSlot.Call) + } + }.onFailure(onChannelFailure) + } + } + } + + /** + * Custom rows prefer [persistedTitle] (captured at copy time), fall back to a live resolver + * probe for legacy data, then to a localised "Custom" — never to [defaultLabel], so an + * unresolvable Custom isn't mislabelled as Default. + */ + @Composable + private fun probeSoundDisplayName( + sound: NotificationSound, + persistedTitle: String?, + defaultLabel: String, + ): String = when (sound) { + NotificationSound.SystemDefault -> defaultLabel + NotificationSound.ElementDefault -> stringProvider.getString(R.string.screen_notification_settings_sound_element_default) + NotificationSound.ElementFade -> stringProvider.getString(R.string.screen_notification_settings_sound_element_fade) + NotificationSound.Silent -> stringProvider.getString(R.string.screen_notification_settings_sound_silent) + is NotificationSound.Custom -> { + val nonBlankPersisted = persistedTitle?.takeUnless { it.isBlank() } + if (nonBlankPersisted != null) { + nonBlankPersisted + } else { + val customFallback = stringProvider.getString(R.string.screen_notification_settings_sound_custom_fallback) + val resolved by produceState(initialValue = "", sound.uri) { + val title = soundDisplayNameResolver.resolveCustomSoundTitle(sound.uri) + value = title?.takeUnless { it.isBlank() } ?: customFallback + } + resolved + } + } + } + + /** + * For a Custom pick, copies into app-private storage and returns (FileProvider URI, title). + * Returns null on copy failure after invoking [onCopyError]. Pass-through for SystemDefault / + * Silent. + */ + private suspend fun resolvePickedSound( + requested: NotificationSound, + slot: SoundSlot, + onCopyError: () -> Unit, + ): Pair? { + if (requested !is NotificationSound.Custom) return requested to null + return when (val result = notificationSoundCopier.copyToAppFiles(requested.uri, slot)) { + is CopyResult.Success -> NotificationSound.Custom(result.fileProviderUriString) to result.displayName + is CopyResult.Failure -> { + Timber.w(result.cause, "Notification sound copy failed for slot=%s", slot) + onCopyError() + null + } + CopyResult.UnplayableSource, + CopyResult.UnplayableCopy, + CopyResult.FileTooLarge -> { + Timber.w("Notification sound rejected: result=%s slot=%s", result::class.simpleName, slot) + onCopyError() + null + } + } + } + @OptIn(FlowPreview::class) private fun CoroutineScope.observeNotificationSettings( target: MutableState, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt index 0a55909e2c..3c59f6c355 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt @@ -12,6 +12,7 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.preferences.api.store.NotificationSound import io.element.android.libraries.pushproviders.api.Distributor import kotlinx.collections.immutable.ImmutableList @@ -23,6 +24,24 @@ data class NotificationSettingsState( val availablePushDistributors: ImmutableList, val showChangePushProviderDialog: Boolean, val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState, + val messageSound: SoundChannelUiState, + val callRingtone: SoundChannelUiState, + val showMessageSoundDialog: Boolean, + val showCallRingtoneDialog: Boolean, + /** + * One-shot trigger for launching the system ringtone picker. Each + * [NotificationSettingsEvents.LaunchMessageSoundPicker] increments the value; + * the view watches this in `LaunchedEffect` and calls the launcher whenever it goes above 0. + * **Always start at 0** in initial state, providers, and previews — a non-zero seed will + * auto-open the picker on screen entry. + */ + val pendingMessageSoundPickerLaunch: Int, + /** + * One-shot trigger for launching the system ringtone picker from the call ringtone dialog. + * Same contract as [pendingMessageSoundPickerLaunch]: **always start at 0**, or the picker + * auto-opens on screen entry. + */ + val pendingCallRingtonePickerLaunch: Int, val eventSink: (NotificationSettingsEvents) -> Unit, ) { sealed interface MatrixSettings { @@ -45,6 +64,16 @@ data class NotificationSettingsState( val appNotificationsEnabled: Boolean, ) + /** + * UI state for one of the two sound rows (message sound, call ringtone). [copyError] is set + * when the last pick failed to copy into app-private storage; the persisted choice stays put. + */ + data class SoundChannelUiState( + val sound: NotificationSound, + val displayName: String, + val copyError: Boolean, + ) + /** * Whether the advanced settings should be shown. * This is true if the current push distributor is in a failure state or if there are multiple push distributors available. diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt index fb396443c3..905f869dbe 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.preferences.api.store.NotificationSound import io.element.android.libraries.pushproviders.api.Distributor import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -45,6 +46,34 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider Unit = {}, ) = NotificationSettingsState( matrixSettings = NotificationSettingsState.MatrixSettings.Valid( @@ -80,6 +119,20 @@ fun aValidNotificationSettingsState( availablePushDistributors = availablePushDistributors.toImmutableList(), showChangePushProviderDialog = showChangePushProviderDialog, fullScreenIntentPermissionsState = fullScreenIntentPermissionsState, + messageSound = NotificationSettingsState.SoundChannelUiState( + sound = messageSound, + displayName = messageSoundDisplayName, + copyError = messageSoundCopyError, + ), + callRingtone = NotificationSettingsState.SoundChannelUiState( + sound = callRingtone, + displayName = callRingtoneDisplayName, + copyError = callRingtoneCopyError, + ), + showMessageSoundDialog = showMessageSoundDialog, + showCallRingtoneDialog = showCallRingtoneDialog, + pendingMessageSoundPickerLaunch = pendingMessageSoundPickerLaunch, + pendingCallRingtonePickerLaunch = pendingCallRingtonePickerLaunch, eventSink = eventSink, ) @@ -99,6 +152,20 @@ fun aInvalidNotificationSettingsState( availablePushDistributors = persistentListOf(), showChangePushProviderDialog = false, fullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(), + messageSound = NotificationSettingsState.SoundChannelUiState( + sound = NotificationSound.SystemDefault, + displayName = "System default", + copyError = false, + ), + callRingtone = NotificationSettingsState.SoundChannelUiState( + sound = NotificationSound.SystemDefault, + displayName = "System default", + copyError = false, + ), + showMessageSoundDialog = false, + showCallRingtoneDialog = false, + pendingMessageSoundPickerLaunch = 0, + pendingCallRingtonePickerLaunch = 0, eventSink = eventSink, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 09f54b7027..5652276c23 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -8,16 +8,29 @@ package io.element.android.features.preferences.impl.notifications +import android.app.Activity +import android.media.RingtoneManager +import android.net.Uri +import android.provider.Settings +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.progressSemantics import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.LiveRegionMode +import androidx.compose.ui.semantics.liveRegion +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.lifecycle.Lifecycle +import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.preferences.impl.R import io.element.android.libraries.androidutils.system.startNotificationSettingsIntent @@ -35,13 +48,17 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen 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.IconSource import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.preferences.api.store.NotificationSound import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList /** @@ -182,6 +199,7 @@ private fun NotificationSettingsContentView( onCheckedChange = onMentionNotificationsChange ) } + SoundsPreferenceCategory(state = state) PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_additional_settings_section_title)) { // TODO We are removing the call notification toggle until support for call notifications has been added // PreferenceSwitch( @@ -261,6 +279,189 @@ private fun NotificationSettingsContentView( } } +@Composable +private fun SoundsPreferenceCategory(state: NotificationSettingsState) { + PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_sound_section_title)) { + val launchMessageSoundPicker = rememberSoundPickerOnClick( + type = RingtoneManager.TYPE_NOTIFICATION, + current = state.messageSound.sound, + defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI, + onSoundPicked = { sound -> state.eventSink(NotificationSettingsEvents.SetMessageSound(sound)) }, + ) + // Skip the initial 0 emission so the picker doesn't auto-open on screen entry; only + // increments fired by LaunchMessageSoundPicker should launch it. + LaunchedEffect(state.pendingMessageSoundPickerLaunch) { + if (state.pendingMessageSoundPickerLaunch > 0) { + launchMessageSoundPicker() + } + } + ListItem( + headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_message_sound_label)) }, + supportingContent = { Text(state.messageSound.displayName) }, + onClick = { state.eventSink(NotificationSettingsEvents.ShowMessageSoundDialog) }, + ) + if (state.messageSound.copyError) { + SoundCopyErrorRow( + onDismissClick = { state.eventSink(NotificationSettingsEvents.DismissMessageSoundCopyError) }, + ) + } + if (state.showMessageSoundDialog) { + MessageSoundDialog(state) + } + + val launchCallRingtonePicker = rememberSoundPickerOnClick( + type = RingtoneManager.TYPE_RINGTONE, + current = state.callRingtone.sound, + defaultUri = Settings.System.DEFAULT_RINGTONE_URI, + onSoundPicked = { sound -> state.eventSink(NotificationSettingsEvents.SetCallRingtone(sound)) }, + ) + // Skip the initial 0 emission so the picker doesn't auto-open on screen entry; only + // increments fired by LaunchCallRingtonePicker should launch it. + LaunchedEffect(state.pendingCallRingtonePickerLaunch) { + if (state.pendingCallRingtonePickerLaunch > 0) { + launchCallRingtonePicker() + } + } + ListItem( + headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_call_ringtone_label)) }, + supportingContent = { Text(state.callRingtone.displayName) }, + onClick = { state.eventSink(NotificationSettingsEvents.ShowCallRingtoneDialog) }, + ) + if (state.callRingtone.copyError) { + SoundCopyErrorRow( + onDismissClick = { state.eventSink(NotificationSettingsEvents.DismissCallRingtoneCopyError) }, + ) + } + if (state.showCallRingtoneDialog) { + CallRingtoneDialog(state) + } + } +} + +@Composable +private fun MessageSoundDialog(state: NotificationSettingsState) { + val initialSelection = when (state.messageSound.sound) { + NotificationSound.ElementDefault -> 0 + NotificationSound.ElementFade -> 1 + NotificationSound.SystemDefault -> 2 + else -> null + } + // When the user is on Custom or Silent, no preset row is selected — surface the current + // sound as a subtitle so screen readers (and sighted users) still have state context. + val subtitle = if (initialSelection == null) { + stringResource( + id = R.string.screen_notification_settings_message_sound_dialog_current_subtitle, + state.messageSound.displayName, + ) + } else { + null + } + SingleSelectionDialog( + title = stringResource(id = R.string.screen_notification_settings_message_sound_dialog_title), + subtitle = subtitle, + options = persistentListOf( + ListOption(title = stringResource(id = R.string.screen_notification_settings_sound_element_default)), + ListOption(title = stringResource(id = R.string.screen_notification_settings_sound_element_fade)), + ListOption(title = stringResource(id = R.string.screen_notification_settings_sound_system_default)), + ListOption(title = stringResource(id = R.string.screen_notification_settings_message_sound_dialog_choose_other)), + ), + initialSelection = initialSelection, + onSelectOption = { index -> + when (index) { + 0 -> state.eventSink(NotificationSettingsEvents.SelectMessageSoundPreset(NotificationSound.ElementDefault)) + 1 -> state.eventSink(NotificationSettingsEvents.SelectMessageSoundPreset(NotificationSound.ElementFade)) + 2 -> state.eventSink(NotificationSettingsEvents.SelectMessageSoundPreset(NotificationSound.SystemDefault)) + else -> state.eventSink(NotificationSettingsEvents.LaunchMessageSoundPicker) + } + }, + onDismissRequest = { state.eventSink(NotificationSettingsEvents.DismissMessageSoundDialog) }, + ) +} + +@Composable +private fun CallRingtoneDialog(state: NotificationSettingsState) { + val initialSelection = when (state.callRingtone.sound) { + NotificationSound.SystemDefault -> 0 + else -> null + } + val subtitle = if (initialSelection == null) { + stringResource( + id = R.string.screen_notification_settings_message_sound_dialog_current_subtitle, + state.callRingtone.displayName, + ) + } else { + null + } + SingleSelectionDialog( + title = stringResource(id = R.string.screen_notification_settings_call_ringtone_label), + subtitle = subtitle, + options = persistentListOf( + ListOption(title = stringResource(id = R.string.screen_notification_settings_sound_system_default)), + ListOption(title = stringResource(id = R.string.screen_notification_settings_message_sound_dialog_choose_other)), + ), + initialSelection = initialSelection, + onSelectOption = { index -> + when (index) { + 0 -> state.eventSink(NotificationSettingsEvents.SelectCallRingtonePreset(NotificationSound.SystemDefault)) + else -> state.eventSink(NotificationSettingsEvents.LaunchCallRingtonePicker) + } + }, + onDismissRequest = { state.eventSink(NotificationSettingsEvents.DismissCallRingtoneDialog) }, + ) +} + +@Composable +private fun SoundCopyErrorRow( + onDismissClick: () -> Unit, +) { + ListItem( + modifier = Modifier + .background(ElementTheme.colors.bgSubtleSecondary) + .semantics { liveRegion = LiveRegionMode.Polite }, + headlineContent = { + Text( + text = stringResource(R.string.screen_notification_settings_sound_set_sound_error_title), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + ) + }, + trailingContent = ListItemContent.Custom { _ -> + IconButton(onClick = onDismissClick) { + Icon( + imageVector = CompoundIcons.Close(), + contentDescription = stringResource(R.string.screen_notification_settings_sound_set_sound_error_dismiss_a11y), + ) + } + }, + ) +} + +@Composable +private fun rememberSoundPickerOnClick( + type: Int, + current: NotificationSound, + defaultUri: Uri, + onSoundPicked: (NotificationSound) -> Unit, +): () -> Unit { + // Paparazzi previews don't provide a LocalActivityResultRegistryOwner, which + // rememberLauncherForActivityResult requires. Skip the launcher in inspection mode and + // return a no-op click handler — previews don't need to launch the picker. + if (LocalInspectionMode.current) return {} + val launcher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult(), + ) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val sound = result.data?.toPickedNotificationSound(defaultUri) + if (sound != null) { + onSoundPicked(sound) + } + } + } + return { + launcher.launch(buildRingtonePickerIntent(type = type, current = current, defaultUri = defaultUri)) + } +} + @Composable private fun getTitleForRoomNotificationMode(mode: RoomNotificationMode?) = when (mode) { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPicker.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPicker.kt new file mode 100644 index 0000000000..df9d8bb0c4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPicker.kt @@ -0,0 +1,55 @@ +/* + * 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.notifications + +import android.content.Intent +import android.media.RingtoneManager +import android.net.Uri +import androidx.core.content.IntentCompat +import androidx.core.net.toUri +import io.element.android.libraries.preferences.api.store.NotificationSound + +/** + * Builds an `ACTION_RINGTONE_PICKER` intent for [type] (notification or ringtone), pre-selecting + * the user's [current] choice and showing the system [defaultUri] as the "Default" option. + */ +internal fun buildRingtonePickerIntent( + type: Int, + current: NotificationSound, + defaultUri: Uri, +): Intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply { + putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, type) + putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) + putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true) + putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, defaultUri) + val existingUri: Uri? = when (current) { + // ElementDefault and ElementFade refer to bundled raw resources, which the system picker + // can't enumerate. Fall back to the picker's "Default" row so the user has something selected. + NotificationSound.SystemDefault, + NotificationSound.ElementDefault, + NotificationSound.ElementFade -> defaultUri + NotificationSound.Silent -> null + is NotificationSound.Custom -> current.uri.toUri() + } + putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, existingUri) +} + +/** + * Maps the URI returned by the ringtone picker into a [NotificationSound]: + * - null URI → the user picked "Silent", + * - URI matching [defaultUri] → the user picked "Default", + * - any other URI → the user picked a specific ringtone. + */ +internal fun Intent.toPickedNotificationSound(defaultUri: Uri): NotificationSound { + val pickedUri: Uri? = IntentCompat.getParcelableExtra(this, RingtoneManager.EXTRA_RINGTONE_PICKED_URI, Uri::class.java) + return when { + pickedUri == null -> NotificationSound.Silent + pickedUri == defaultUri -> NotificationSound.SystemDefault + else -> NotificationSound.Custom(pickedUri.toString()) + } +} diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index 7389a0433c..f2a3d87770 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -58,6 +58,7 @@ "Feeling experimental?" "Labs" "Additional settings" + "Call ringtone" "Audio and video calls" "Configuration mismatch" "We’ve simplified Notifications Settings to make options easier to find. Some custom settings you’ve chosen in the past are not shown here, but they’re still active. @@ -76,10 +77,15 @@ If you proceed, some of your settings may change." "Invitations" "Your homeserver does not support this option in encrypted rooms, you may not get notified in some rooms." "Mentions" + "Choose another sound…" + "Currently using %1$s" + "Message sound" + "Message sound" "All" "Mentions" "Notify me for" "Notify me on @room" + "Custom" "Custom sound…" "Error deleting file" "Element Default" @@ -87,7 +93,9 @@ If you proceed, some of your settings may change." "Error importing file" "Problem previewing alert sound" "Sound" + "Dismiss alert sound error" "Problem setting alert sound" + "Silent" "Alert" "Anticipate" "Bell" @@ -95,6 +103,7 @@ If you proceed, some of your settings may change." "Calypso" "Chime" "Choo Choo" + "System Default" "Descent" "Electronic" "Fanfare" diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt index 26bb0ba1ee..29e4b1c40a 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt @@ -17,21 +17,35 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.push.api.PushService +import io.element.android.libraries.push.api.notifications.NotificationSoundUpdater +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier import io.element.android.libraries.push.test.FakePushService +import io.element.android.libraries.push.test.notifications.FakeNotificationSoundUpdater +import io.element.android.libraries.push.test.notifications.FakeSoundDisplayNameResolver +import io.element.android.libraries.push.test.notifications.sound.FakeNotificationSoundCopier import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.api.PushProvider import io.element.android.libraries.pushproviders.test.FakePushProvider import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory +import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.awaitLastSequentialItem import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Test import kotlin.time.Duration.Companion.milliseconds +@Suppress("LargeClass") class NotificationSettingsPresenterTest { @Test fun `present - ensures initial state is correct`() = runTest { @@ -353,10 +367,756 @@ class NotificationSettingsPresenterTest { ) } + @Test + fun `present - SetMessageSound atomically persists, increments version, and recreates channel`() = runTest { + val recreateRecorder = lambdaRecorder { _, _ -> } + val appPreferencesStore = InMemoryAppPreferencesStore() + val customSound = NotificationSound.Custom("content://media/internal/audio/media/42") + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { sound, version -> recreateRecorder(sound, version) }, + ), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(initialState.messageSound.sound).isEqualTo(NotificationSound.SystemDefault) + + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(customSound)) + + val updatedState = consumeItemsUntilPredicate { it.messageSound.sound == customSound }.last() + assertThat(updatedState.messageSound.sound).isEqualTo(customSound) + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().messageSoundVersion).isEqualTo(1) + recreateRecorder.assertions().isCalledOnce().with(value(customSound), value(1)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - SetCallRingtone with Silent atomically persists and recreates channel`() = runTest { + val recreateRecorder = lambdaRecorder { _, _ -> } + val appPreferencesStore = InMemoryAppPreferencesStore() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateRingingCallChannelLambda = { sound, version -> recreateRecorder(sound, version) }, + ), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(initialState.callRingtone.sound).isEqualTo(NotificationSound.SystemDefault) + + initialState.eventSink(NotificationSettingsEvents.SetCallRingtone(NotificationSound.Silent)) + + val updatedState = consumeItemsUntilPredicate { it.callRingtone.sound == NotificationSound.Silent }.last() + assertThat(updatedState.callRingtone.sound).isEqualTo(NotificationSound.Silent) + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().callRingtoneVersion).isEqualTo(1) + recreateRecorder.assertions().isCalledOnce().with(value(NotificationSound.Silent), value(1)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - successive message sound changes increment version each time`() = runTest { + val versions = mutableListOf() + val appPreferencesStore = InMemoryAppPreferencesStore() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { _, version -> versions += version }, + ), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://a"))) + consumeItemsUntilPredicate { it.messageSound.sound == NotificationSound.Custom("content://a") } + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://b"))) + consumeItemsUntilPredicate { it.messageSound.sound == NotificationSound.Custom("content://b") } + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.SystemDefault)) + consumeItemsUntilPredicate { it.messageSound.sound == NotificationSound.SystemDefault } + + assertThat(versions).containsExactly(1, 2, 3).inOrder() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - SetMessageSound with SystemDefault clears existing custom URI`() = runTest { + val recreateRecorder = lambdaRecorder { _, _ -> } + val appPreferencesStore = InMemoryAppPreferencesStore(messageSound = NotificationSound.Custom("content://existing")) + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { sound, version -> recreateRecorder(sound, version) }, + ), + ) + presenter.test { + consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.messageSound.sound == NotificationSound.Custom("content://existing") + }.last().eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.SystemDefault)) + consumeItemsUntilPredicate { it.messageSound.sound == NotificationSound.SystemDefault } + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().messageSound).isEqualTo(NotificationSound.SystemDefault) + recreateRecorder.assertions().isCalledOnce().with(value(NotificationSound.SystemDefault), value(1)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - SetMessageSound surfaces DataStore failure via changeNotificationSettingAction`() = runTest { + val backing = InMemoryAppPreferencesStore() + val store = object : AppPreferencesStore by backing { + override suspend fun setMessageSoundAndIncrementVersion(sound: NotificationSound, title: String?): Int { + error("Simulated DataStore failure") + } + } + val presenter = createNotificationSettingsPresenter(appPreferencesStore = store) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://x"))) + + val errorState = consumeItemsUntilPredicate { + it.changeNotificationSettingAction.isFailure() + }.last() + assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - SystemDefault and Silent display names do not invoke the resolver`() = runTest { + val resolverCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.SystemDefault, + callRingtone = NotificationSound.Silent, + ), + soundDisplayNameResolver = FakeSoundDisplayNameResolver( + resolveLambda = { uri -> + resolverCalls += uri + "Should not appear" + }, + ), + ) + presenter.test { + // The synchronous branches (SystemDefault / Silent) feed the label directly without + // routing through produceState — so the resolver is never invoked, and the label + // never flashes from the default to itself. + consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(resolverCalls).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - ElementDefault and ElementFade display names do not invoke the resolver`() = runTest { + val resolverCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.ElementFade, + callRingtone = NotificationSound.ElementDefault, + ), + soundDisplayNameResolver = FakeSoundDisplayNameResolver( + resolveLambda = { uri -> + resolverCalls += uri + "Should not appear" + }, + ), + ) + presenter.test { + consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(resolverCalls).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - resolves Custom display name via SoundDisplayNameResolver`() = runTest { + val resolverCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore(messageSound = NotificationSound.Custom("content://media/42")), + soundDisplayNameResolver = FakeSoundDisplayNameResolver( + resolveLambda = { uri -> + resolverCalls += uri + "Pixel notification" + }, + ), + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.messageSound.displayName == "Pixel notification" + }.last() + assertThat(state.messageSound.displayName).isEqualTo("Pixel notification") + assertThat(resolverCalls).contains("content://media/42") + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - Custom display name falls back to localized Custom string when no persisted title and resolver returns null`() = runTest { + val resolverCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + // No persisted display name (legacy data path). Resolver returns null. Final fallback + // is the localised string resource (FakeStringProvider returns "A string" for any + // resource id) — never the default label, so the row is not mislabelled as "System default". + appPreferencesStore = InMemoryAppPreferencesStore(messageSound = NotificationSound.Custom("content://gone")), + soundDisplayNameResolver = FakeSoundDisplayNameResolver( + resolveLambda = { uri -> + resolverCalls += uri + null + }, + ), + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.messageSound.sound is NotificationSound.Custom && + it.messageSound.displayName == "A string" + }.last() + assertThat(state.messageSound.displayName).isEqualTo("A string") + assertThat(resolverCalls).contains("content://gone") + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - persisted in-app pick takes precedence over channel read`() = runTest { + // When DataStore holds a real in-app pick, the channel read must not run. Persisted + // value is what the user explicitly chose; channel state is only a fallback. + var channelReadCalls = 0 + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.Custom("content://persisted"), + messageSoundDisplayName = "Persisted Tone", + ), + notificationSoundUpdater = FakeNotificationSoundUpdater( + readNoisyChannelSoundLambda = { + channelReadCalls++ + NotificationSound.Custom("content://channel/should-not-appear") + }, + ), + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.messageSound.displayName == "Persisted Tone" + }.last() + assertThat(state.messageSound.sound).isEqualTo(NotificationSound.Custom("content://persisted")) + assertThat(channelReadCalls).isEqualTo(0) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - persisted display name takes precedence over live resolver probe`() = runTest { + val resolverCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.Custom("content://media/42"), + messageSoundDisplayName = "Captured at copy time", + ), + soundDisplayNameResolver = FakeSoundDisplayNameResolver( + resolveLambda = { uri -> + resolverCalls += uri + "Live probe (should not appear)" + }, + ), + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.messageSound.displayName == "Captured at copy time" + }.last() + assertThat(state.messageSound.displayName).isEqualTo("Captured at copy time") + // Live resolver must not be invoked when a persisted title is available. + assertThat(resolverCalls).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - SetMessageSound with Custom copies via copier and persists the FileProvider URI`() = runTest { + val recreateRecorder = lambdaRecorder { _, _ -> } + val appPreferencesStore = InMemoryAppPreferencesStore() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { sound, version -> recreateRecorder(sound, version) }, + ), + notificationSoundCopier = FakeNotificationSoundCopier(copyLambda = { _, _ -> + NotificationSoundCopier.CopyResult.Success( + fileProviderUriString = "content://my.app.fileprovider/notification_sounds/message_sound.ogg", + displayName = "Cool Tone", + ) + }), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://media/source"))) + advanceUntilIdle() + + val expectedSound = NotificationSound.Custom("content://my.app.fileprovider/notification_sounds/message_sound.ogg") + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().messageSound).isEqualTo(expectedSound) + assertThat(appPreferencesStore.getMessageSoundDisplayNameFlow().first()).isEqualTo("Cool Tone") + recreateRecorder.assertions().isCalledOnce().with(value(expectedSound), value(1)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - SetMessageSound copy failure surfaces inline error and leaves prior choice intact`() = runTest { + val priorChoice = NotificationSound.Custom("content://prior") + val appPreferencesStore = InMemoryAppPreferencesStore(messageSound = priorChoice) + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundCopier = FakeNotificationSoundCopier(copyLambda = { _, _ -> + NotificationSoundCopier.CopyResult.UnplayableSource + }), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://broken"))) + + val errorState = consumeItemsUntilPredicate { it.messageSound.copyError }.last() + assertThat(errorState.messageSound.copyError).isTrue() + // Persisted state is unchanged. + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().messageSound).isEqualTo(priorChoice) + + // Dismissing the inline error clears the flag without altering persistence. + errorState.eventSink(NotificationSettingsEvents.DismissMessageSoundCopyError) + val cleared = consumeItemsUntilPredicate { !it.messageSound.copyError }.last() + assertThat(cleared.messageSound.copyError).isFalse() + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().messageSound).isEqualTo(priorChoice) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - SetCallRingtone copy failure surfaces inline error and leaves prior choice intact`() = runTest { + val priorChoice = NotificationSound.Custom("content://prior") + val appPreferencesStore = InMemoryAppPreferencesStore(callRingtone = priorChoice) + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundCopier = FakeNotificationSoundCopier(copyLambda = { _, _ -> + NotificationSoundCopier.CopyResult.UnplayableSource + }), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initialState.eventSink(NotificationSettingsEvents.SetCallRingtone(NotificationSound.Custom("content://broken"))) + + val errorState = consumeItemsUntilPredicate { it.callRingtone.copyError }.last() + assertThat(errorState.callRingtone.copyError).isTrue() + // Persisted state is unchanged. + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().callRingtone).isEqualTo(priorChoice) + + // Dismissing the inline error clears the flag without altering persistence. + errorState.eventSink(NotificationSettingsEvents.DismissCallRingtoneCopyError) + val cleared = consumeItemsUntilPredicate { !it.callRingtone.copyError }.last() + assertThat(cleared.callRingtone.copyError).isFalse() + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().callRingtone).isEqualTo(priorChoice) + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - SystemDefault and Silent picks bypass the copier`() = runTest { + val copierCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { _, _ -> }, + recreateRingingCallChannelLambda = { _, _ -> }, + ), + notificationSoundCopier = FakeNotificationSoundCopier(copyLambda = { source, _ -> + copierCalls += source + NotificationSoundCopier.CopyResult.Success(source, "x") + }), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.SystemDefault)) + initialState.eventSink(NotificationSettingsEvents.SetCallRingtone(NotificationSound.Silent)) + advanceUntilIdle() + assertThat(copierCalls).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - non-Custom picks delete the stored slot file`() = runTest { + val deleteCalls = mutableListOf() + // Start from persisted Custom for both slots so the non-Custom picks below are real + // transitions (no-op short-circuit only fires when the new sound equals the persisted one). + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.Custom("content://prior-message"), + callRingtone = NotificationSound.Custom("content://prior-call"), + ), + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { _, _ -> }, + recreateRingingCallChannelLambda = { _, _ -> }, + ), + notificationSoundCopier = FakeNotificationSoundCopier( + copyLambda = { _, _ -> NotificationSoundCopier.CopyResult.Failure(IllegalStateException("not expected")) }, + deleteStoredSoundForLambda = { slot -> deleteCalls += slot }, + ), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.SystemDefault)) + initialState.eventSink(NotificationSettingsEvents.SetCallRingtone(NotificationSound.Silent)) + advanceUntilIdle() + assertThat(deleteCalls).containsExactly( + NotificationSoundCopier.SoundSlot.Message, + NotificationSoundCopier.SoundSlot.Call, + ) + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - re-selecting the persisted non-Custom sound is a no-op`() = runTest { + val recreateCalls = mutableListOf() + val deleteCalls = mutableListOf() + val copierCalls = mutableListOf() + val appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.ElementDefault, + messageSoundChannelVersion = 5, + callRingtone = NotificationSound.Silent, + callRingtoneChannelVersion = 3, + ) + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundCopier = FakeNotificationSoundCopier( + copyLambda = { source, _ -> + copierCalls += source + NotificationSoundCopier.CopyResult.Success(source, "title") + }, + deleteStoredSoundForLambda = { slot -> deleteCalls += slot }, + ), + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { _, version -> recreateCalls += version }, + recreateRingingCallChannelLambda = { _, version -> recreateCalls += version }, + ), + ) + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + + // Re-pick the persisted sound for both slots — neither should churn the channel, + // bump the version, or hit the copier / delete sweep. + initial.eventSink(NotificationSettingsEvents.SelectMessageSoundPreset(NotificationSound.ElementDefault)) + initial.eventSink(NotificationSettingsEvents.SetCallRingtone(NotificationSound.Silent)) + advanceUntilIdle() + + val config = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(config.messageSoundVersion).isEqualTo(5) + assertThat(config.callRingtoneVersion).isEqualTo(3) + assertThat(recreateCalls).isEmpty() + assertThat(copierCalls).isEmpty() + assertThat(deleteCalls).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - rapid back-to-back picks settle in deterministic order`() = runTest { + // Defends the persist+recreate window against rapid event firing (e.g. an accessibility + // service driving the dialog). The per-slot mutex in the presenter forces copy → persist + // → recreate to complete for the first pick before the second begins, so the recreated + // version sequence matches the persisted version sequence. + val recreatedVersions = mutableListOf() + val copyOrder = mutableListOf() + val appPreferencesStore = InMemoryAppPreferencesStore() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundCopier = FakeNotificationSoundCopier(copyLambda = { source, _ -> + copyOrder += source + NotificationSoundCopier.CopyResult.Success(source, "title") + }), + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { _, version -> recreatedVersions += version }, + ), + ) + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initial.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://A"))) + initial.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://B"))) + advanceUntilIdle() + + assertThat(copyOrder).containsExactly("content://A", "content://B").inOrder() + assertThat(recreatedVersions).containsExactly(1, 2).inOrder() + val config = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(config.messageSoundVersion).isEqualTo(2) + assertThat(config.messageSound).isEqualTo(NotificationSound.Custom("content://B")) + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - Custom pick does not invoke deleteStoredSoundFor (copier sweeps inline)`() = runTest { + val deleteCalls = mutableListOf() + val presenter = createNotificationSettingsPresenter( + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { _, _ -> }, + ), + notificationSoundCopier = FakeNotificationSoundCopier( + copyLambda = { _, _ -> + NotificationSoundCopier.CopyResult.Success( + fileProviderUriString = "content://my.app.fileprovider/notification_sounds/message_sound.mp3", + displayName = "New Tone", + ) + }, + deleteStoredSoundForLambda = { slot -> deleteCalls += slot }, + ), + ) + presenter.test { + val initialState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initialState.eventSink(NotificationSettingsEvents.SetMessageSound(NotificationSound.Custom("content://media/source"))) + advanceUntilIdle() + assertThat(deleteCalls).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - ShowMessageSoundDialog and DismissMessageSoundDialog toggle dialog visibility`() = runTest { + val presenter = createNotificationSettingsPresenter() + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(initial.showMessageSoundDialog).isFalse() + + initial.eventSink(NotificationSettingsEvents.ShowMessageSoundDialog) + val shown = consumeItemsUntilPredicate { it.showMessageSoundDialog }.last() + assertThat(shown.showMessageSoundDialog).isTrue() + + shown.eventSink(NotificationSettingsEvents.DismissMessageSoundDialog) + val hidden = consumeItemsUntilPredicate { !it.showMessageSoundDialog }.last() + assertThat(hidden.showMessageSoundDialog).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - SelectMessageSoundPreset persists ElementDefault, recreates the channel and closes the dialog`() = runTest { + val recreateRecorder = lambdaRecorder { _, _ -> } + val appPreferencesStore = InMemoryAppPreferencesStore() + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateNoisyChannelLambda = { sound, version -> recreateRecorder(sound, version) }, + ), + ) + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + initial.eventSink(NotificationSettingsEvents.ShowMessageSoundDialog) + val shown = consumeItemsUntilPredicate { it.showMessageSoundDialog }.last() + + shown.eventSink(NotificationSettingsEvents.SelectMessageSoundPreset(NotificationSound.ElementDefault)) + advanceUntilIdle() + consumeItemsUntilPredicate { + !it.showMessageSoundDialog && it.messageSound.sound == NotificationSound.ElementDefault + } + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().messageSound) + .isEqualTo(NotificationSound.ElementDefault) + recreateRecorder.assertions().isCalledOnce().with(value(NotificationSound.ElementDefault), value(1)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - LaunchMessageSoundPicker increments the picker token and closes the dialog`() = runTest { + val presenter = createNotificationSettingsPresenter() + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(initial.pendingMessageSoundPickerLaunch).isEqualTo(0) + initial.eventSink(NotificationSettingsEvents.ShowMessageSoundDialog) + val shown = consumeItemsUntilPredicate { it.showMessageSoundDialog }.last() + + shown.eventSink(NotificationSettingsEvents.LaunchMessageSoundPicker) + val launched = consumeItemsUntilPredicate { it.pendingMessageSoundPickerLaunch == 1 }.last() + assertThat(launched.showMessageSoundDialog).isFalse() + assertThat(launched.pendingMessageSoundPickerLaunch).isEqualTo(1) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - ShowCallRingtoneDialog and DismissCallRingtoneDialog toggle dialog visibility`() = runTest { + val presenter = createNotificationSettingsPresenter() + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(initial.showCallRingtoneDialog).isFalse() + + initial.eventSink(NotificationSettingsEvents.ShowCallRingtoneDialog) + val shown = consumeItemsUntilPredicate { it.showCallRingtoneDialog }.last() + assertThat(shown.showCallRingtoneDialog).isTrue() + + shown.eventSink(NotificationSettingsEvents.DismissCallRingtoneDialog) + val hidden = consumeItemsUntilPredicate { !it.showCallRingtoneDialog }.last() + assertThat(hidden.showCallRingtoneDialog).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - SelectCallRingtonePreset persists SystemDefault, recreates the channel and closes the dialog`() = runTest { + val recreateRecorder = lambdaRecorder { _, _ -> } + val appPreferencesStore = InMemoryAppPreferencesStore(callRingtone = NotificationSound.Silent) + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateRingingCallChannelLambda = { sound, version -> recreateRecorder(sound, version) }, + ), + ) + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.callRingtone.sound == NotificationSound.Silent + }.last() + initial.eventSink(NotificationSettingsEvents.ShowCallRingtoneDialog) + val shown = consumeItemsUntilPredicate { it.showCallRingtoneDialog }.last() + + shown.eventSink(NotificationSettingsEvents.SelectCallRingtonePreset(NotificationSound.SystemDefault)) + advanceUntilIdle() + consumeItemsUntilPredicate { + !it.showCallRingtoneDialog && it.callRingtone.sound == NotificationSound.SystemDefault + } + assertThat(appPreferencesStore.getNotificationSoundChannelConfig().callRingtone) + .isEqualTo(NotificationSound.SystemDefault) + recreateRecorder.assertions().isCalledOnce().with(value(NotificationSound.SystemDefault), value(1)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - LaunchCallRingtonePicker increments the picker token and closes the dialog`() = runTest { + val presenter = createNotificationSettingsPresenter() + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + assertThat(initial.pendingCallRingtonePickerLaunch).isEqualTo(0) + initial.eventSink(NotificationSettingsEvents.ShowCallRingtoneDialog) + val shown = consumeItemsUntilPredicate { it.showCallRingtoneDialog }.last() + + shown.eventSink(NotificationSettingsEvents.LaunchCallRingtonePicker) + val launched = consumeItemsUntilPredicate { it.pendingCallRingtonePickerLaunch == 1 }.last() + assertThat(launched.showCallRingtoneDialog).isFalse() + assertThat(launched.pendingCallRingtonePickerLaunch).isEqualTo(1) + cancelAndIgnoreRemainingEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - SelectCallRingtonePreset clears legacy ringtone classification`() = runTest { + // Legacy state: persisted SystemDefault + channel version 0 means the presenter probes the + // channel and surfaces whatever Android system has. We seed that probe with Silent so the + // initial row reads Silent even though DataStore holds SystemDefault. A preset pick must + // null the legacy classifier; otherwise re-reading state would still resolve to Silent + // after the SystemDefault selection persists. + val appPreferencesStore = InMemoryAppPreferencesStore( + callRingtone = NotificationSound.SystemDefault, + callRingtoneChannelVersion = 0, + ) + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = FakeNotificationSoundUpdater( + recreateRingingCallChannelLambda = { _, _ -> }, + readRingingCallChannelSoundLambda = { NotificationSound.Silent }, + ), + ) + presenter.test { + val initial = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.callRingtone.sound == NotificationSound.Silent + }.last() + initial.eventSink(NotificationSettingsEvents.SelectCallRingtonePreset(NotificationSound.SystemDefault)) + advanceUntilIdle() + val after = consumeItemsUntilPredicate { + it.callRingtone.sound == NotificationSound.SystemDefault + }.last() + assertThat(after.callRingtone.sound).isEqualTo(NotificationSound.SystemDefault) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - persisted ElementDefault renders Element default label`() = runTest { + val presenter = createNotificationSettingsPresenter( + appPreferencesStore = InMemoryAppPreferencesStore(messageSound = NotificationSound.ElementDefault), + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid && + it.messageSound.sound == NotificationSound.ElementDefault + }.last() + // FakeStringProvider returns "A string" for any resource, so this just verifies the + // ElementDefault branch is taken (vs falling through to the Custom resolver path). + assertThat(state.messageSound.displayName).isEqualTo("A string") + cancelAndIgnoreRemainingEvents() + } + } + private fun TestScope.createNotificationSettingsPresenter( notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), pushService: PushService = FakePushService(), fullScreenIntentPermissionsStateLambda: () -> FullScreenIntentPermissionsState = { aFullScreenIntentPermissionsState() }, + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), + notificationSoundUpdater: NotificationSoundUpdater = FakeNotificationSoundUpdater(), + // Default copier passes the picked URI string straight through as the FileProvider URI + // and uses the URI string as the display name. Tests that exercise copy failures override. + notificationSoundCopier: NotificationSoundCopier = FakeNotificationSoundCopier(copyLambda = { source, _ -> + NotificationSoundCopier.CopyResult.Success(source, source) + }), + soundDisplayNameResolver: FakeSoundDisplayNameResolver = FakeSoundDisplayNameResolver(), ): NotificationSettingsPresenter { val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) return NotificationSettingsPresenter( @@ -366,6 +1126,11 @@ class NotificationSettingsPresenterTest { pushService = pushService, systemNotificationsEnabledProvider = FakeSystemNotificationsEnabledProvider(), fullScreenIntentPermissionsPresenter = { fullScreenIntentPermissionsStateLambda() }, + appPreferencesStore = appPreferencesStore, + notificationSoundUpdater = notificationSoundUpdater, + notificationSoundCopier = notificationSoundCopier, + soundDisplayNameResolver = soundDisplayNameResolver, + stringProvider = FakeStringProvider(), sessionCoroutineScope = backgroundScope, ) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt index 66ed0339a3..dee0df511c 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt @@ -13,6 +13,7 @@ package io.element.android.features.preferences.impl.notifications import androidx.activity.ComponentActivity import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.v2.runAndroidComposeUiTest @@ -49,7 +50,7 @@ class NotificationSettingsViewTest { eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled) } - @Config(qualifiers = "h1024dp") + @Config(qualifiers = "h1280dp") @Test fun `clicking on troubleshoot notification invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() @@ -241,7 +242,7 @@ class NotificationSettingsViewTest { ) } - @Config(qualifiers = "h1024dp") + @Config(qualifiers = "h1280dp") @Test fun `clicking on Push notification provider emits the expected event`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() @@ -277,6 +278,43 @@ class NotificationSettingsViewTest { ) ) } + + @Config(qualifiers = "h1280dp") + @Test + fun `sounds preference category renders rows with current display names`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setNotificationSettingsView( + state = aValidNotificationSettingsState( + eventSink = eventsRecorder, + messageSoundDisplayName = "Pixel notification", + callRingtoneDisplayName = "Pixel ringtone", + ), + ) + onNodeWithText("Sound").assertIsDisplayed() + onNodeWithText("Message sound").assertIsDisplayed() + onNodeWithText("Call ringtone").assertIsDisplayed() + onNodeWithText("Pixel notification").assertIsDisplayed() + onNodeWithText("Pixel ringtone").assertIsDisplayed() + } + + @Config(qualifiers = "h1280dp") + @Test + fun `clicking the message sound row opens the preset dialog`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setNotificationSettingsView( + state = aValidNotificationSettingsState(eventSink = eventsRecorder), + ) + // The click now opens the in-app preset dialog instead of launching the system picker + // directly; the picker only fires from the dialog's "Choose another sound..." option + // (covered by Presenter tests + NotificationSoundPickerTest). + onNodeWithText("Message sound").performClick() + eventsRecorder.assertList( + listOf( + NotificationSettingsEvents.RefreshSystemNotificationsEnabled, + NotificationSettingsEvents.ShowMessageSoundDialog, + ) + ) + } } private fun AndroidComposeUiTest.setNotificationSettingsView( diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPickerTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPickerTest.kt new file mode 100644 index 0000000000..3031187f25 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundPickerTest.kt @@ -0,0 +1,90 @@ +/* + * 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.notifications + +import android.content.Intent +import android.media.RingtoneManager +import android.net.Uri +import android.provider.Settings +import androidx.core.net.toUri +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.preferences.api.store.NotificationSound +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class NotificationSoundPickerTest { + @Test + fun `buildRingtonePickerIntent encodes SystemDefault as the system default URI`() { + val intent = buildRingtonePickerIntent( + type = RingtoneManager.TYPE_NOTIFICATION, + current = NotificationSound.SystemDefault, + defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI, + ) + assertThat(intent.action).isEqualTo(RingtoneManager.ACTION_RINGTONE_PICKER) + assertThat(intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, -1)).isEqualTo(RingtoneManager.TYPE_NOTIFICATION) + assertThat(intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false)).isTrue() + assertThat(intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false)).isTrue() + @Suppress("DEPRECATION") + val existing: Uri? = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI) + assertThat(existing).isEqualTo(Settings.System.DEFAULT_NOTIFICATION_URI) + } + + @Test + fun `buildRingtonePickerIntent encodes Silent as a null existing URI`() { + val intent = buildRingtonePickerIntent( + type = RingtoneManager.TYPE_RINGTONE, + current = NotificationSound.Silent, + defaultUri = Settings.System.DEFAULT_RINGTONE_URI, + ) + @Suppress("DEPRECATION") + val existing: Uri? = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI) + assertThat(existing).isNull() + } + + @Test + fun `buildRingtonePickerIntent encodes Custom as the parsed URI`() { + val intent = buildRingtonePickerIntent( + type = RingtoneManager.TYPE_NOTIFICATION, + current = NotificationSound.Custom("content://media/internal/audio/media/42"), + defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI, + ) + @Suppress("DEPRECATION") + val existing: Uri? = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI) + assertThat(existing).isEqualTo("content://media/internal/audio/media/42".toUri()) + } + + @Test + fun `toPickedNotificationSound maps null URI to Silent`() { + val result = Intent().apply { + putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, null as Uri?) + } + assertThat(result.toPickedNotificationSound(Settings.System.DEFAULT_NOTIFICATION_URI)) + .isEqualTo(NotificationSound.Silent) + } + + @Test + fun `toPickedNotificationSound maps default URI to SystemDefault`() { + val result = Intent().apply { + putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, Settings.System.DEFAULT_NOTIFICATION_URI) + } + assertThat(result.toPickedNotificationSound(Settings.System.DEFAULT_NOTIFICATION_URI)) + .isEqualTo(NotificationSound.SystemDefault) + } + + @Test + fun `toPickedNotificationSound maps any other URI to Custom`() { + val customUri = "content://media/internal/audio/media/42".toUri() + val result = Intent().apply { + putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, customUri) + } + assertThat(result.toPickedNotificationSound(Settings.System.DEFAULT_NOTIFICATION_URI)) + .isEqualTo(NotificationSound.Custom(customUri.toString())) + } +} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundStorageTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundStorageTest.kt new file mode 100644 index 0000000000..7f8dba8226 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSoundStorageTest.kt @@ -0,0 +1,80 @@ +/* + * 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.notifications + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.preferences.api.store.NotificationSound.Companion.toStored +import org.junit.Test + +class NotificationSoundStorageTest { + @Test + fun `fromStored - null maps to SystemDefault`() { + assertThat(NotificationSound.fromStored(null)).isEqualTo(NotificationSound.SystemDefault) + } + + @Test + fun `fromStored - silent sentinel maps to Silent`() { + assertThat(NotificationSound.fromStored("silent")).isEqualTo(NotificationSound.Silent) + } + + @Test + fun `fromStored - element_default sentinel maps to ElementDefault`() { + assertThat(NotificationSound.fromStored("element_default")).isEqualTo(NotificationSound.ElementDefault) + } + + @Test + fun `fromStored - element_fade sentinel maps to ElementFade`() { + assertThat(NotificationSound.fromStored("element_fade")).isEqualTo(NotificationSound.ElementFade) + } + + @Test + fun `fromStored - any other string is treated as a Custom URI`() { + assertThat(NotificationSound.fromStored("content://media/42")) + .isEqualTo(NotificationSound.Custom("content://media/42")) + } + + @Test + fun `toStored - SystemDefault encodes as null`() { + assertThat(NotificationSound.SystemDefault.toStored()).isNull() + } + + @Test + fun `toStored - ElementDefault encodes as element_default`() { + assertThat(NotificationSound.ElementDefault.toStored()).isEqualTo("element_default") + } + + @Test + fun `toStored - ElementFade encodes as element_fade`() { + assertThat(NotificationSound.ElementFade.toStored()).isEqualTo("element_fade") + } + + @Test + fun `toStored - Silent encodes as silent`() { + assertThat(NotificationSound.Silent.toStored()).isEqualTo("silent") + } + + @Test + fun `toStored - Custom encodes as the URI string`() { + assertThat(NotificationSound.Custom("content://x").toStored()).isEqualTo("content://x") + } + + @Test + fun `round-trip preserves every variant`() { + val variants = listOf( + NotificationSound.SystemDefault, + NotificationSound.ElementDefault, + NotificationSound.ElementFade, + NotificationSound.Silent, + NotificationSound.Custom("content://media/42"), + ) + for (sound in variants) { + assertThat(NotificationSound.fromStored(sound.toStored())).isEqualTo(sound) + } + } +} diff --git a/libraries/preferences/api/build.gradle.kts b/libraries/preferences/api/build.gradle.kts index a441616657..7084c960c6 100644 --- a/libraries/preferences/api/build.gradle.kts +++ b/libraries/preferences/api/build.gradle.kts @@ -9,7 +9,7 @@ import extension.testCommonDependencies */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") } android { diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt index df8dc8acc9..b1877b3ae5 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt @@ -41,5 +41,27 @@ interface AppPreferencesStore { suspend fun setTracingLogPacks(targets: Set) fun getTracingLogPacksFlow(): Flow> + fun getMessageSoundFlow(): Flow + + /** + * Atomically persists [sound] (with copy-time [title] for Custom; cleared otherwise) and + * bumps the channel version. Single transaction so process death can't desync URI and version. + */ + suspend fun setMessageSoundAndIncrementVersion(sound: NotificationSound, title: String?): Int + + /** Title captured at copy time. Null for SystemDefault / Silent or pre-title persisted data. */ + fun getMessageSoundDisplayNameFlow(): Flow + + fun getCallRingtoneFlow(): Flow + + /** See [setMessageSoundAndIncrementVersion]. */ + suspend fun setCallRingtoneAndIncrementVersion(sound: NotificationSound, title: String?): Int + + /** See [getMessageSoundDisplayNameFlow]. */ + fun getCallRingtoneDisplayNameFlow(): Flow + + /** Single-snapshot read of all sound prefs; used at boot to seed channels without N reads. */ + suspend fun getNotificationSoundChannelConfig(): NotificationSoundChannelConfig + suspend fun reset() } diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/NotificationSound.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/NotificationSound.kt new file mode 100644 index 0000000000..f138dd592b --- /dev/null +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/NotificationSound.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.preferences.api.store + +import androidx.compose.runtime.Immutable + +/** + * The user's choice of notification sound for a notification channel. + */ +@Immutable +sealed interface NotificationSound { + /** Use the system's default tone for this channel (e.g. notification or ringtone). */ + data object SystemDefault : NotificationSound + + /** + * Use the bundled in-app sound. Semantically meaningful only for the noisy message channel, + * where it resolves to `R.raw.message`; the ringing-call channel has no bundled tone and + * treats this the same as [SystemDefault]. + */ + data object ElementDefault : NotificationSound + + /** + * Use the bundled in-app fade sound. Like [ElementDefault] this is meaningful only for the + * noisy message channel (`R.raw.element_fade`); the ringing-call channel has no bundled tone + * and treats this the same as [SystemDefault]. + */ + data object ElementFade : NotificationSound + + /** Produce no sound. */ + data object Silent : NotificationSound + + /** Use the ringtone at [uri]. */ + data class Custom(val uri: String) : NotificationSound + + companion object { + // String? round-trip used by [AppPreferencesStore]: + // null -> SystemDefault, "silent" -> Silent, "element_default" -> ElementDefault, + // "element_fade" -> ElementFade, else -> Custom(uri). + private const val STORED_SILENT = "silent" + private const val STORED_ELEMENT_DEFAULT = "element_default" + private const val STORED_ELEMENT_FADE = "element_fade" + + fun fromStored(value: String?): NotificationSound = when (value) { + null -> SystemDefault + STORED_SILENT -> Silent + STORED_ELEMENT_DEFAULT -> ElementDefault + STORED_ELEMENT_FADE -> ElementFade + else -> Custom(value) + } + + fun NotificationSound.toStored(): String? = when (this) { + SystemDefault -> null + Silent -> STORED_SILENT + ElementDefault -> STORED_ELEMENT_DEFAULT + ElementFade -> STORED_ELEMENT_FADE + is Custom -> uri + } + } +} + +/** + * Snapshot of the persisted notification-sound state, returned by + * [AppPreferencesStore.getNotificationSoundChannelConfig] in a single read. + */ +data class NotificationSoundChannelConfig( + val messageSound: NotificationSound, + val messageSoundVersion: Int, + val messageSoundDisplayName: String?, + val callRingtone: NotificationSound, + val callRingtoneVersion: Int, + val callRingtoneDisplayName: String?, +) diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt index 44260461da..af35ac3c44 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt @@ -20,8 +20,12 @@ import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.matrix.api.tracing.LogLevel import io.element.android.libraries.matrix.api.tracing.TraceLogPack import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.preferences.api.store.NotificationSound.Companion.toStored +import io.element.android.libraries.preferences.api.store.NotificationSoundChannelConfig import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map private val developerModeKey = booleanPreferencesKey("developerMode") @@ -32,6 +36,12 @@ private val timelineMediaPreviewValueKey = stringPreferencesKey("timelineMediaPr private val liveLocationMinimumDistanceUpdateKey = intPreferencesKey("liveLocationMinimumDistanceUpdate") private val logLevelKey = stringPreferencesKey("logLevel") private val traceLogPacksKey = stringPreferencesKey("traceLogPacks") +private val messageSoundUriKey = stringPreferencesKey("notificationMessageSoundUri") +private val messageSoundChannelVersionKey = intPreferencesKey("notificationMessageSoundChannelVersion") +private val messageSoundDisplayNameKey = stringPreferencesKey("notificationMessageSoundDisplayName") +private val callRingtoneUriKey = stringPreferencesKey("notificationCallRingtoneUri") +private val callRingtoneChannelVersionKey = intPreferencesKey("notificationCallRingtoneChannelVersion") +private val callRingtoneDisplayNameKey = stringPreferencesKey("notificationCallRingtoneDisplayName") @ContributesBinding(AppScope::class) class DefaultAppPreferencesStore( @@ -158,6 +168,75 @@ class DefaultAppPreferencesStore( } } + override fun getMessageSoundFlow(): Flow { + return store.data.map { prefs -> NotificationSound.fromStored(prefs[messageSoundUriKey]) } + } + + override suspend fun setMessageSoundAndIncrementVersion(sound: NotificationSound, title: String?): Int { + var newVersion = 0 + store.edit { prefs -> + val stored = sound.toStored() + if (stored != null) { + prefs[messageSoundUriKey] = stored + } else { + prefs.remove(messageSoundUriKey) + } + // Clear title on non-Custom so the picker doesn't show a stale label after a revert. + if (sound is NotificationSound.Custom && !title.isNullOrBlank()) { + prefs[messageSoundDisplayNameKey] = title + } else { + prefs.remove(messageSoundDisplayNameKey) + } + newVersion = (prefs[messageSoundChannelVersionKey] ?: 0) + 1 + prefs[messageSoundChannelVersionKey] = newVersion + } + return newVersion + } + + override fun getMessageSoundDisplayNameFlow(): Flow { + return store.data.map { prefs -> prefs[messageSoundDisplayNameKey] } + } + + override fun getCallRingtoneFlow(): Flow { + return store.data.map { prefs -> NotificationSound.fromStored(prefs[callRingtoneUriKey]) } + } + + override suspend fun setCallRingtoneAndIncrementVersion(sound: NotificationSound, title: String?): Int { + var newVersion = 0 + store.edit { prefs -> + val stored = sound.toStored() + if (stored != null) { + prefs[callRingtoneUriKey] = stored + } else { + prefs.remove(callRingtoneUriKey) + } + if (sound is NotificationSound.Custom && !title.isNullOrBlank()) { + prefs[callRingtoneDisplayNameKey] = title + } else { + prefs.remove(callRingtoneDisplayNameKey) + } + newVersion = (prefs[callRingtoneChannelVersionKey] ?: 0) + 1 + prefs[callRingtoneChannelVersionKey] = newVersion + } + return newVersion + } + + override fun getCallRingtoneDisplayNameFlow(): Flow { + return store.data.map { prefs -> prefs[callRingtoneDisplayNameKey] } + } + + override suspend fun getNotificationSoundChannelConfig(): NotificationSoundChannelConfig { + val prefs = store.data.first() + return NotificationSoundChannelConfig( + messageSound = NotificationSound.fromStored(prefs[messageSoundUriKey]), + messageSoundVersion = prefs[messageSoundChannelVersionKey] ?: 0, + messageSoundDisplayName = prefs[messageSoundDisplayNameKey], + callRingtone = NotificationSound.fromStored(prefs[callRingtoneUriKey]), + callRingtoneVersion = prefs[callRingtoneChannelVersionKey] ?: 0, + callRingtoneDisplayName = prefs[callRingtoneDisplayNameKey], + ) + } + override suspend fun reset() { store.edit { it.clear() } } diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt index 152de12e99..6499e70223 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt @@ -12,8 +12,11 @@ import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.matrix.api.tracing.LogLevel import io.element.android.libraries.matrix.api.tracing.TraceLogPack import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.preferences.api.store.NotificationSoundChannelConfig import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.updateAndGet class InMemoryAppPreferencesStore( isDeveloperModeEnabled: Boolean = false, @@ -23,16 +26,28 @@ class InMemoryAppPreferencesStore( theme: String? = null, liveLocationMinimumDistanceUpdate: Int = 10, logLevel: LogLevel = LogLevel.INFO, - traceLockPacks: Set = emptySet(), + traceLogPacks: Set = emptySet(), + messageSound: NotificationSound = NotificationSound.SystemDefault, + messageSoundChannelVersion: Int = 0, + messageSoundDisplayName: String? = null, + callRingtone: NotificationSound = NotificationSound.SystemDefault, + callRingtoneChannelVersion: Int = 0, + callRingtoneDisplayName: String? = null, ) : AppPreferencesStore { private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled) private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl) private val theme = MutableStateFlow(theme) private val liveLocationMinimumDistanceUpdate = MutableStateFlow(liveLocationMinimumDistanceUpdate) private val logLevel = MutableStateFlow(logLevel) - private val tracingLogPacks = MutableStateFlow(traceLockPacks) + private val tracingLogPacks = MutableStateFlow(traceLogPacks) private val hideInviteAvatars = MutableStateFlow(hideInviteAvatars) private val timelineMediaPreviewValue = MutableStateFlow(timelineMediaPreviewValue) + private val messageSound = MutableStateFlow(messageSound) + private val messageSoundChannelVersion = MutableStateFlow(messageSoundChannelVersion) + private val messageSoundDisplayName = MutableStateFlow(messageSoundDisplayName) + private val callRingtone = MutableStateFlow(callRingtone) + private val callRingtoneChannelVersion = MutableStateFlow(callRingtoneChannelVersion) + private val callRingtoneDisplayName = MutableStateFlow(callRingtoneDisplayName) override suspend fun setDeveloperModeEnabled(enabled: Boolean) { isDeveloperModeEnabled.value = enabled @@ -102,6 +117,45 @@ class InMemoryAppPreferencesStore( return tracingLogPacks } + override fun getMessageSoundFlow(): Flow { + return messageSound + } + + override suspend fun setMessageSoundAndIncrementVersion(sound: NotificationSound, title: String?): Int { + messageSound.value = sound + messageSoundDisplayName.value = if (sound is NotificationSound.Custom && !title.isNullOrBlank()) title else null + return messageSoundChannelVersion.updateAndGet { it + 1 } + } + + override fun getMessageSoundDisplayNameFlow(): Flow { + return messageSoundDisplayName + } + + override fun getCallRingtoneFlow(): Flow { + return callRingtone + } + + override suspend fun setCallRingtoneAndIncrementVersion(sound: NotificationSound, title: String?): Int { + callRingtone.value = sound + callRingtoneDisplayName.value = if (sound is NotificationSound.Custom && !title.isNullOrBlank()) title else null + return callRingtoneChannelVersion.updateAndGet { it + 1 } + } + + override fun getCallRingtoneDisplayNameFlow(): Flow { + return callRingtoneDisplayName + } + + override suspend fun getNotificationSoundChannelConfig(): NotificationSoundChannelConfig { + return NotificationSoundChannelConfig( + messageSound = messageSound.value, + messageSoundVersion = messageSoundChannelVersion.value, + messageSoundDisplayName = messageSoundDisplayName.value, + callRingtone = callRingtone.value, + callRingtoneVersion = callRingtoneChannelVersion.value, + callRingtoneDisplayName = callRingtoneDisplayName.value, + ) + } + override suspend fun reset() { // No op } diff --git a/libraries/push/api/build.gradle.kts b/libraries/push/api/build.gradle.kts index df6ac6120a..91e545daed 100644 --- a/libraries/push/api/build.gradle.kts +++ b/libraries/push/api/build.gradle.kts @@ -20,5 +20,6 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixmedia.api) + implementation(projects.libraries.preferences.api) implementation(projects.libraries.pushproviders.api) } diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationSoundUpdater.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationSoundUpdater.kt new file mode 100644 index 0000000000..b23c4122ad --- /dev/null +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationSoundUpdater.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.push.api.notifications + +import io.element.android.libraries.preferences.api.store.NotificationSound + +/** + * Reads and writes the sound on the message / ringing-call channels. Writes create a new + * versioned channel because Android forbids mutating sound after creation. + */ +interface NotificationSoundUpdater { + fun recreateNoisyChannel(sound: NotificationSound, version: Int) + + fun recreateRingingCallChannel(sound: NotificationSound, version: Int) + + /** Current channel sound classified into [NotificationSound]. Null when the channel doesn't exist. */ + suspend fun readNoisyChannelSound(): NotificationSound? + + /** See [readNoisyChannelSound]. */ + suspend fun readRingingCallChannelSound(): NotificationSound? +} diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/SoundDisplayNameResolver.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/SoundDisplayNameResolver.kt new file mode 100644 index 0000000000..a850b3e435 --- /dev/null +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/SoundDisplayNameResolver.kt @@ -0,0 +1,18 @@ +/* + * 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.notifications + +/** + * Resolves the user-facing title of a custom notification sound URI (the title shown by the + * system ringtone picker). Lifts the [android.media.RingtoneManager] side effect out of UI code + * so views and presenters stay testable. + */ +interface SoundDisplayNameResolver { + /** Returns the title of the ringtone at [uri], or null if it cannot be resolved. */ + suspend fun resolveCustomSoundTitle(uri: String): String? +} diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/sound/NotificationSoundCopier.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/sound/NotificationSoundCopier.kt new file mode 100644 index 0000000000..2268198353 --- /dev/null +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/sound/NotificationSoundCopier.kt @@ -0,0 +1,47 @@ +/* + * 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.notifications.sound + +/** + * Copies a picked notification sound into app-private storage and re-exposes it via the app's + * FileProvider, so the persisted reference outlives the original source. + */ +interface NotificationSoundCopier { + suspend fun copyToAppFiles(sourceUriString: String, slot: SoundSlot): CopyResult + + /** + * Removes any previously copied file for [slot] from app-private storage. No-op when no file + * exists. Call this when persisting a non-[NotificationSound.Custom] pick (SystemDefault / + * Silent) so the previous Custom copy doesn't linger as orphaned bytes — [copyToAppFiles] + * already sweeps stale files inline for Custom-to-Custom transitions. + */ + suspend fun deleteStoredSoundFor(slot: SoundSlot) + + enum class SoundSlot { Message, Call } + + sealed interface CopyResult { + /** + * @property fileProviderUriString FileProvider URI to persist as the channel sound. + * @property displayName [android.media.Ringtone.getTitle] for the source, or null. The + * picker substitutes a localised fallback label, so localisation stays in the UI layer. + */ + data class Success(val fileProviderUriString: String, val displayName: String?) : CopyResult + + /** [android.media.RingtoneManager] could not open the source URI as a Ringtone. */ + data object UnplayableSource : CopyResult + + /** The bytes copied successfully, but the resulting file is not a playable Ringtone. */ + data object UnplayableCopy : CopyResult + + /** Source exceeded the 5 MB cap. */ + data object FileTooLarge : CopyResult + + /** Any other I/O or unexpected failure. */ + data class Failure(val cause: Throwable) : CopyResult + } +} diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts index e8acda59da..b9082c50f6 100644 --- a/libraries/push/impl/build.gradle.kts +++ b/libraries/push/impl/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.libraries.troubleshoot.api) implementation(projects.libraries.workmanager.api) + implementation(projects.features.announcement.api) implementation(projects.features.call.api) implementation(projects.features.enterprise.api) implementation(projects.features.lockscreen.api) @@ -80,6 +81,7 @@ dependencies { testImplementation(projects.libraries.pushstore.test) testImplementation(projects.libraries.troubleshoot.test) testImplementation(projects.libraries.workmanager.test) + testImplementation(projects.features.announcement.test) testImplementation(projects.features.call.test) testImplementation(projects.features.enterprise.test) testImplementation(projects.features.lockscreen.test) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultSoundDisplayNameResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultSoundDisplayNameResolver.kt new file mode 100644 index 0000000000..b6237aba03 --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultSoundDisplayNameResolver.kt @@ -0,0 +1,35 @@ +/* + * 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.notifications + +import android.content.Context +import android.media.RingtoneManager +import androidx.core.net.toUri +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.push.api.notifications.SoundDisplayNameResolver +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +@ContributesBinding(AppScope::class) +class DefaultSoundDisplayNameResolver( + @ApplicationContext private val context: Context, +) : SoundDisplayNameResolver { + override suspend fun resolveCustomSoundTitle(uri: String): String? = withContext(Dispatchers.IO) { + val parsed = runCatchingExceptions { uri.toUri() }.getOrNull() ?: return@withContext null + // Probing our own FileProvider URI yields the internal filename ("call_sound.ogg"), + // not a user-meaningful tone name — better to fall through to the localised "Custom" + // label in the UI. + if (parsed.authority == context.notificationSoundFileProviderAuthority()) return@withContext null + runCatchingExceptions { + RingtoneManager.getRingtone(context, parsed)?.getTitle(context) + }.getOrNull() + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationSoundFileProviderAuthority.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationSoundFileProviderAuthority.kt new file mode 100644 index 0000000000..db9fa47c02 --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationSoundFileProviderAuthority.kt @@ -0,0 +1,18 @@ +/* + * 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.notifications + +import android.content.Context + +// Mirrors the FileProvider authority declared in AndroidManifest.xml as +// `${applicationId}.fileprovider`. Kept here so the resolver's skip-rule and the copier's URI +// construction never drift apart. +internal const val NOTIFICATION_SOUND_FILE_PROVIDER_AUTHORITY_SUFFIX = ".fileprovider" + +internal fun Context.notificationSoundFileProviderAuthority(): String = + packageName + NOTIFICATION_SOUND_FILE_PROVIDER_AUTHORITY_SUFFIX diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt index dc009c0b7d..8d9b776694 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.push.impl.notifications.channels import android.content.ContentResolver import android.content.Context +import android.content.Intent import android.media.AudioAttributes import android.media.AudioAttributes.USAGE_NOTIFICATION import android.media.AudioManager @@ -19,28 +20,50 @@ import android.provider.Settings import androidx.annotation.ChecksSdkIntAtLeast import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationManagerCompat +import androidx.core.net.toUri import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn +import dev.zacsweers.metro.binding import io.element.android.appconfig.NotificationConfig import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.push.api.notifications.NotificationSoundUpdater import io.element.android.libraries.push.impl.R import io.element.android.services.toolbox.api.strings.StringProvider +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import timber.log.Timber /* ========================================================================================== * IDs for channels * ========================================================================================== */ internal const val SILENT_NOTIFICATION_CHANNEL_ID = "DEFAULT_SILENT_NOTIFICATION_CHANNEL_ID_V2" -internal const val NOISY_NOTIFICATION_CHANNEL_ID = "DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID_V2" +internal const val NOISY_NOTIFICATION_CHANNEL_ID_BASE = "DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID_V2" internal const val CALL_NOTIFICATION_CHANNEL_ID = "CALL_NOTIFICATION_CHANNEL_ID_V3" -internal const val RINGING_CALL_NOTIFICATION_CHANNEL_ID = "RINGING_CALL_NOTIFICATION_CHANNEL_ID" +internal const val RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE = "RINGING_CALL_NOTIFICATION_CHANNEL_ID" + +private fun versionedChannelId(base: String, version: Int): String = + if (version <= 0) base else "${base}_v$version" + +internal fun noisyNotificationChannelId(version: Int): String = + versionedChannelId(NOISY_NOTIFICATION_CHANNEL_ID_BASE, version) + +internal fun ringingCallNotificationChannelId(version: Int): String = + versionedChannelId(RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE, version) /** * on devices >= android O, we need to define a channel for each notifications. + * + * Extends [NotificationSoundUpdater] so consumers can re-create the noisy and ringing-call + * channels when the user picks a new sound URI in settings. */ -interface NotificationChannels { +interface NotificationChannels : NotificationSoundUpdater { /** * Get the channel for incoming call. * @param ring true if the device should ring when receiving the call. @@ -66,14 +89,22 @@ interface NotificationChannels { private fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O @SingleIn(AppScope::class) -@ContributesBinding(AppScope::class) +@ContributesBinding(AppScope::class, binding = binding()) +@ContributesBinding(AppScope::class, binding = binding()) class DefaultNotificationChannels( private val notificationManager: NotificationManagerCompat, private val stringProvider: StringProvider, @ApplicationContext private val context: Context, private val enterpriseService: EnterpriseService, + private val appPreferencesStore: AppPreferencesStore, ) : NotificationChannels { + @Volatile private var currentNoisyChannelId: String = NOISY_NOTIFICATION_CHANNEL_ID_BASE + @Volatile private var currentRingingCallChannelId: String = RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE + + // Serializes concurrent recreate* calls; readers stay lock-free via @Volatile on the id fields. + private val recreateLock = Any() + init { createNotificationChannels() } @@ -88,9 +119,27 @@ class DefaultNotificationChannels( val accentColor = NotificationConfig.NOTIFICATION_ACCENT_COLOR + // Single-snapshot read; keep this path minimal — extra ContentResolver lookups here would + // risk a cold-start ANR. + val config = runBlocking { + val initial = appPreferencesStore.getNotificationSoundChannelConfig() + // Pre-dialog builds mapped the noisy `SystemDefault` to our bundled message.mp3. + // Now `SystemDefault` means Android's system tone, so untouched legacy state would + // silently flip sound. Promote it to `ElementDefault` once, gated on version==0 so the + // migration is idempotent. + if (initial.messageSoundVersion == 0 && initial.messageSound == NotificationSound.SystemDefault) { + appPreferencesStore.setMessageSoundAndIncrementVersion(NotificationSound.ElementDefault, title = null) + appPreferencesStore.getNotificationSoundChannelConfig() + } else { + initial + } + } + + currentNoisyChannelId = noisyNotificationChannelId(config.messageSoundVersion) + currentRingingCallChannelId = ringingCallNotificationChannelId(config.callRingtoneVersion) + // Migration - the noisy channel was deleted and recreated when sound preference was changed (id was DEFAULT_NOISY_NOTIFICATION_CHANNEL_ID_BASE // + currentTimeMillis). - // Now the sound can only be change directly in system settings, so for app upgrading we are deleting this former channel // Starting from this version the channel will not be dynamic for (channel in notificationManager.notificationChannels) { val channelId = channel.id @@ -111,30 +160,19 @@ class DefaultNotificationChannels( notificationManager.deleteNotificationChannel(channelId) } } + // Drop older versioned channels; only the current one remains. + deleteStaleVersionedChannels(NOISY_NOTIFICATION_CHANNEL_ID_BASE, currentNoisyChannelId) + deleteStaleVersionedChannels(RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE, currentRingingCallChannelId) // Default notification importance: shows everywhere, makes noise, but does not visually intrude. + val noisySoundUri = resolveNoisySoundUri(config.messageSound) + grantSoundUriToSystem(noisySoundUri) notificationManager.createNotificationChannel( - NotificationChannelCompat.Builder( - NOISY_NOTIFICATION_CHANNEL_ID, - NotificationManagerCompat.IMPORTANCE_DEFAULT + buildNoisyChannel( + channelId = currentNoisyChannelId, + soundUri = noisySoundUri, + accentColor = accentColor, ) - .setSound( - Uri.Builder() - .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - // Strangely we have to provide a "//" before the package name - .path("//" + context.packageName + "/" + R.raw.message) - .build(), - AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(USAGE_NOTIFICATION) - .build(), - ) - .setName(stringProvider.getString(R.string.notification_channel_noisy).ifEmpty { "Noisy notifications" }) - .setDescription(stringProvider.getString(R.string.notification_channel_noisy)) - .setVibrationEnabled(true) - .setLightsEnabled(true) - .setLightColor(accentColor) - .build() ) // Low notification importance: shows everywhere, but is not intrusive. @@ -166,40 +204,205 @@ class DefaultNotificationChannels( ) // Register a channel for incoming call notifications which will ring the device when received + val ringingSoundUri = resolveRingingSoundUri(config.callRingtone) + grantSoundUriToSystem(ringingSoundUri) notificationManager.createNotificationChannel( - NotificationChannelCompat.Builder( - RINGING_CALL_NOTIFICATION_CHANNEL_ID, - NotificationManagerCompat.IMPORTANCE_MAX, + buildRingingCallChannel( + channelId = currentRingingCallChannelId, + soundUri = ringingSoundUri, + accentColor = accentColor, ) - .setName(stringProvider.getString(R.string.notification_channel_ringing_calls).ifEmpty { "Ringing calls" }) - .setVibrationEnabled(true) - .setSound( - Settings.System.DEFAULT_RINGTONE_URI, - AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setLegacyStreamType(AudioManager.STREAM_RING) - .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) - .build() - ) - .setDescription(stringProvider.getString(R.string.notification_channel_ringing_calls)) - .setLightsEnabled(true) - .setLightColor(accentColor) - .build() ) } + private fun buildNoisyChannel(channelId: String, soundUri: Uri?, accentColor: Int): NotificationChannelCompat { + val builder = NotificationChannelCompat.Builder(channelId, NotificationManagerCompat.IMPORTANCE_DEFAULT) + .setName(stringProvider.getString(R.string.notification_channel_noisy).ifEmpty { "Noisy notifications" }) + .setDescription(stringProvider.getString(R.string.notification_channel_noisy)) + .setVibrationEnabled(true) + .setLightsEnabled(true) + .setLightColor(accentColor) + if (soundUri != null) { + builder.setSound( + soundUri, + AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(USAGE_NOTIFICATION) + .build(), + ) + } else { + builder.setSound(null, null) + } + return builder.build() + } + + private fun buildRingingCallChannel(channelId: String, soundUri: Uri?, accentColor: Int): NotificationChannelCompat { + val builder = NotificationChannelCompat.Builder(channelId, NotificationManagerCompat.IMPORTANCE_MAX) + .setName(stringProvider.getString(R.string.notification_channel_ringing_calls).ifEmpty { "Ringing calls" }) + .setDescription(stringProvider.getString(R.string.notification_channel_ringing_calls)) + .setVibrationEnabled(true) + .setLightsEnabled(true) + .setLightColor(accentColor) + if (soundUri != null) { + builder.setSound( + soundUri, + AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setLegacyStreamType(AudioManager.STREAM_RING) + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .build() + ) + } else { + builder.setSound(null, null) + } + return builder.build() + } + + private fun resolveNoisySoundUri(sound: NotificationSound): Uri? = when (sound) { + NotificationSound.Silent -> null + NotificationSound.SystemDefault -> Settings.System.DEFAULT_NOTIFICATION_URI + NotificationSound.ElementDefault -> bundledMessageSoundUri() + NotificationSound.ElementFade -> bundledFadeSoundUri() + is NotificationSound.Custom -> parseUriOrFallback(sound.uri) { bundledMessageSoundUri() } + } + + private fun resolveRingingSoundUri(sound: NotificationSound): Uri? = when (sound) { + NotificationSound.Silent -> null + // The ringing channel has no bundled tone — treat ElementDefault and ElementFade like SystemDefault here. + NotificationSound.SystemDefault, + NotificationSound.ElementDefault, + NotificationSound.ElementFade -> Settings.System.DEFAULT_RINGTONE_URI + is NotificationSound.Custom -> parseUriOrFallback(sound.uri) { Settings.System.DEFAULT_RINGTONE_URI } + } + + private fun bundledMessageSoundUri(): Uri = + "${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context.packageName}/${R.raw.message}".toUri() + + private fun bundledFadeSoundUri(): Uri = + "${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context.packageName}/${R.raw.element_fade}".toUri() + + /** + * Lets system_server ("android") and SystemUI read our FileProvider sound URI; no-op otherwise. + * SystemUI hosts the lock-screen notification surface on most OEMs, so a missing grant there + * silently mutes ringtones when the device is locked. + */ + private fun grantSoundUriToSystem(uri: Uri?) { + if (uri == null || uri.scheme != ContentResolver.SCHEME_CONTENT) return + for (pkg in arrayOf("android", "com.android.systemui")) { + runCatchingExceptions { + context.grantUriPermission(pkg, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION) + }.onFailure { Timber.w(it, "grantUriPermission(%s) failed for notification sound", pkg) } + } + } + + /** Parses [uriString], or returns [fallback] (the SystemDefault URI) on failure. */ + private inline fun parseUriOrFallback(uriString: String, fallback: () -> Uri): Uri = + runCatchingExceptions { uriString.toUri() } + .getOrElse { + // Don't pass the throwable: legacy persisted URIs may carry SAF auth tokens. + Timber.w("Failed to parse persisted sound URI; falling back to default cause=%s", it::class.simpleName) + fallback() + } + + private fun deleteStaleVersionedChannels(baseId: String, currentId: String) { + if (!supportNotificationChannels()) return + for (channel in notificationManager.notificationChannels) { + val id = channel.id + // Match either the unversioned base ID or any "${baseId}_v" variant. + val isBaseOrVersioned = id == baseId || id.startsWith("${baseId}_v") + if (isBaseOrVersioned && id != currentId) { + notificationManager.deleteNotificationChannel(id) + } + } + } + override fun getChannelForIncomingCall(ring: Boolean): String { - return if (ring) RINGING_CALL_NOTIFICATION_CHANNEL_ID else CALL_NOTIFICATION_CHANNEL_ID + return if (ring) currentRingingCallChannelId else CALL_NOTIFICATION_CHANNEL_ID } override fun getChannelIdForMessage(sessionId: SessionId, noisy: Boolean): String { return if (noisy) { enterpriseService.getNoisyNotificationChannelId(sessionId) - ?: NOISY_NOTIFICATION_CHANNEL_ID + ?: currentNoisyChannelId } else { SILENT_NOTIFICATION_CHANNEL_ID } } - override fun getChannelIdForTest(): String = NOISY_NOTIFICATION_CHANNEL_ID + override fun getChannelIdForTest(): String = currentNoisyChannelId + + override fun recreateNoisyChannel(sound: NotificationSound, version: Int) { + if (!supportNotificationChannels()) return + synchronized(recreateLock) { + val accentColor = NotificationConfig.NOTIFICATION_ACCENT_COLOR + val newChannelId = noisyNotificationChannelId(version) + val soundUri = resolveNoisySoundUri(sound) + grantSoundUriToSystem(soundUri) + // Create channel before publishing the id: a reader landing between the assignment and + // the create call would notify() against a missing id, which Android silently drops. + notificationManager.createNotificationChannel( + buildNoisyChannel(newChannelId, soundUri, accentColor) + ) + currentNoisyChannelId = newChannelId + deleteStaleVersionedChannels(NOISY_NOTIFICATION_CHANNEL_ID_BASE, newChannelId) + } + } + + override fun recreateRingingCallChannel(sound: NotificationSound, version: Int) { + if (!supportNotificationChannels()) return + synchronized(recreateLock) { + val accentColor = NotificationConfig.NOTIFICATION_ACCENT_COLOR + val newChannelId = ringingCallNotificationChannelId(version) + val soundUri = resolveRingingSoundUri(sound) + grantSoundUriToSystem(soundUri) + // See recreateNoisyChannel: the channel must exist before the id is published. + notificationManager.createNotificationChannel( + buildRingingCallChannel(newChannelId, soundUri, accentColor) + ) + currentRingingCallChannelId = newChannelId + deleteStaleVersionedChannels(RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE, newChannelId) + } + } + + override suspend fun readNoisyChannelSound(): NotificationSound? { + return readChannelSound( + channelId = currentNoisyChannelId, + bundledUri = bundledMessageSoundUri(), + bundledFadeUri = bundledFadeSoundUri(), + systemDefaultUri = Settings.System.DEFAULT_NOTIFICATION_URI, + ) + } + + override suspend fun readRingingCallChannelSound(): NotificationSound? { + return readChannelSound( + channelId = currentRingingCallChannelId, + bundledUri = null, + bundledFadeUri = null, + systemDefaultUri = Settings.System.DEFAULT_RINGTONE_URI, + ) + } + + /** + * Classifies the channel's sound URI: null → Silent, bundled → ElementDefault, bundled fade → + * ElementFade, system default → SystemDefault, else → Custom. Both bundled URIs are nullable + * because the ringing channel has no bundled tones. + */ + private suspend fun readChannelSound( + channelId: String, + bundledUri: Uri?, + bundledFadeUri: Uri?, + systemDefaultUri: Uri, + ): NotificationSound? { + if (!supportNotificationChannels()) return null + val channel = withContext(Dispatchers.IO) { + notificationManager.getNotificationChannel(channelId) + } ?: return null + return when (val sound = channel.sound) { + null -> NotificationSound.Silent + bundledUri -> NotificationSound.ElementDefault + bundledFadeUri -> NotificationSound.ElementFade + systemDefaultUri -> NotificationSound.SystemDefault + else -> NotificationSound.Custom(sound.toString()) + } + } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopier.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopier.kt new file mode 100644 index 0000000000..2eeb07189a --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopier.kt @@ -0,0 +1,208 @@ +/* + * 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.notifications.sound + +import android.content.ContentResolver +import android.content.Context +import android.media.RingtoneManager +import android.net.Uri +import android.provider.OpenableColumns +import android.webkit.MimeTypeMap +import androidx.core.content.FileProvider +import androidx.core.net.toUri +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.CopyResult +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.SoundSlot +import io.element.android.libraries.push.impl.notifications.notificationSoundFileProviderAuthority +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext +import timber.log.Timber +import java.io.File +import java.io.IOException +import java.io.InputStream + +private const val MAX_BYTES = 5L * 1024 * 1024 +private const val DIRECTORY_NAME = "notification_sounds" +private const val FALLBACK_EXTENSION = "bin" +private const val COPY_BUFFER_SIZE = 8 * 1024 +private const val MAX_DISPLAY_NAME_LENGTH = 256 + +// Defence-in-depth: we only ever expect URIs from the system ringtone picker (content://) or +// the bundled resource (android.resource://). Reject anything else before doing I/O so a future +// caller that constructs a NotificationSound.Custom from an untrusted intent can't trick the +// copier into reading file:// or unrelated providers. +private val ALLOWED_SOURCE_SCHEMES = setOf( + ContentResolver.SCHEME_CONTENT, + ContentResolver.SCHEME_ANDROID_RESOURCE, +) + +@ContributesBinding(AppScope::class) +class DefaultNotificationSoundCopier( + @ApplicationContext private val context: Context, +) : NotificationSoundCopier { + // Per-slot serialization: concurrent picks for the same slot would race on `.tmp`. + private val slotMutexes = SoundSlot.entries.associateWith { Mutex() } + + override suspend fun copyToAppFiles(sourceUriString: String, slot: SoundSlot): CopyResult = withContext(Dispatchers.IO) { + slotMutexes.getValue(slot).withLock { + runCatchingExceptions { performCopy(sourceUriString, slot) } + .getOrElse { ex -> + // Don't pass the throwable to Timber: SAF/MediaProvider exceptions sometimes + // embed the source URI (which can carry short-lived auth tokens). + Timber.w("Notification sound copy failed for slot=%s cause=%s", slot, ex::class.simpleName) + CopyResult.Failure(ex) + } + } + } + + override suspend fun deleteStoredSoundFor(slot: SoundSlot) { + withContext(Dispatchers.IO) { + slotMutexes.getValue(slot).withLock { + val dir = File(context.filesDir, DIRECTORY_NAME) + if (!dir.exists()) return@withLock + val slotBase = slotBaseFor(slot) + dir.listFiles { f -> f.isFile && f.name.startsWith("$slotBase.") } + ?.forEach { stale -> + if (!stale.delete()) { + Timber.w("Could not remove stored slot file %s", stale.name) + } + } + } + } + } + + private fun slotBaseFor(slot: SoundSlot): String = when (slot) { + SoundSlot.Message -> "message_sound" + SoundSlot.Call -> "call_sound" + } + + private fun performCopy(sourceUriString: String, slot: SoundSlot): CopyResult { + val source = sourceUriString.toUri() + if (source.scheme !in ALLOWED_SOURCE_SCHEMES) return CopyResult.UnplayableSource + // Reject unplayable sources up front instead of persisting a known-broken pick. + val sourceRingtone = RingtoneManager.getRingtone(context, source) + ?: return CopyResult.UnplayableSource + // Capture the source's display name before copy — once persisted, the row only sees the + // FileProvider URI, where Ringtone.getTitle() would resolve to our internal filename + // (e.g. "call_sound.ogg"). RingtoneManager → MediaStore TITLE → OpenableColumns covers + // system tones, MediaStore-indexed audio, and SAF-picked files respectively. The value + // crosses our security boundary (foreign provider → persisted state → UI), so cap and + // sanitize it. + val displayName = (sourceRingtone.getTitle(context)?.takeUnless { it.isBlank() } + ?: queryOpenableDisplayName(source)) + ?.let(::sanitizeDisplayName) + + // MIME comes from an arbitrary content provider; refuse extensions outside the platform + // table to keep filenames bounded to notification_sounds/. + val mimeMap = MimeTypeMap.getSingleton() + val candidateExtension = mimeMap.getExtensionFromMimeType(context.contentResolver.getType(source)) + val extension = candidateExtension + ?.takeIf { it.isNotBlank() && mimeMap.hasExtension(it) } + ?: FALLBACK_EXTENSION + + val slotBase = slotBaseFor(slot) + + val dir = File(context.filesDir, DIRECTORY_NAME).apply { mkdirs() } + val tmpFile = File(dir, "$slotBase.tmp").also { if (it.exists()) it.delete() } + val finalFile = File(dir, "$slotBase.$extension") + + val inputStream = context.contentResolver.openInputStream(source) + ?: return CopyResult.UnplayableSource + val bytesCopied = try { + inputStream.use { input -> tmpFile.outputStream().buffered().use { out -> input.copyToCapped(out, MAX_BYTES) } } + } catch (_: SizeLimitExceeded) { + tmpFile.delete() + Timber.w("Notification sound copy aborted: source exceeds %d bytes (slot=%s)", MAX_BYTES, slot) + return CopyResult.FileTooLarge + } + + // The finally below guarantees the temp file doesn't outlive a thrown probe / rename. + var committed = false + try { + // Probe through the FileProvider URI we'll actually persist (catches torn writes + // and OEM codec quirks). + val fileProviderUri = FileProvider.getUriForFile( + context, + context.notificationSoundFileProviderAuthority(), + tmpFile, + ) + if (RingtoneManager.getRingtone(context, fileProviderUri) == null) { + return CopyResult.UnplayableCopy + } + + // Sweep all `.*` so an extension change between picks doesn't leak orphans. + dir.listFiles { f -> f.isFile && f.name.startsWith("$slotBase.") && f.name != tmpFile.name } + ?.forEach { stale -> + if (!stale.delete()) { + Timber.w("Could not remove stale slot file %s", stale.name) + } + } + if (!tmpFile.renameTo(finalFile)) { + return CopyResult.Failure(IOException("Could not rename temp file to ${finalFile.name}")) + } + committed = true + + val finalUri = FileProvider.getUriForFile( + context, + context.notificationSoundFileProviderAuthority(), + finalFile, + ) + Timber.d("Notification sound copied: slot=%s bytes=%d", slot, bytesCopied) + return CopyResult.Success(finalUri.toString(), displayName) + } finally { + if (!committed) tmpFile.delete() + } + } + + private fun queryOpenableDisplayName(uri: Uri): String? { + return runCatchingExceptions { + context.contentResolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null) + ?.use { cursor -> + if (cursor.moveToFirst() && cursor.columnCount > 0) { + cursor.getString(0)?.takeUnless { it.isBlank() } + } else { + null + } + } + }.getOrNull() + } +} + +internal fun sanitizeDisplayName(raw: String): String? { + // Display name comes from a foreign content provider; strip C0 / DEL control characters and + // cap length so a hostile or malformed value can't bloat persisted state or break UI rendering. + val cleaned = buildString(raw.length.coerceAtMost(MAX_DISPLAY_NAME_LENGTH)) { + for (ch in raw) { + if (length >= MAX_DISPLAY_NAME_LENGTH) break + if (ch.code >= 0x20 && ch.code != 0x7F) append(ch) + } + }.trim() + return cleaned.takeUnless { it.isEmpty() } +} + +private class SizeLimitExceeded : IOException("Sound source exceeds the configured size limit") + +private fun InputStream.copyToCapped(out: java.io.OutputStream, maxBytes: Long): Long { + val buffer = ByteArray(COPY_BUFFER_SIZE) + var totalBytes = 0L + while (true) { + val read = read(buffer) + if (read == -1) break + totalBytes += read + if (totalBytes > maxBytes) throw SizeLimitExceeded() + out.write(buffer, 0, read) + } + out.flush() + return totalBytes +} diff --git a/libraries/push/impl/src/main/res/raw/element_fade.mp3 b/libraries/push/impl/src/main/res/raw/element_fade.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..bf31420e495ed94ffcf596a9cc229221476ff629 GIT binary patch literal 33645 zcmZshbyQSO{P*t$unSAq65_Iiv`b2NcMAy8-KAi$OLv2GcSxgv%F>OrfGCZmf-MO9 z)9>$j&UyZL=8t=4&YUx6?(4qi{kikGqopbe1^yKdQxg-lzjsOifau!aa}k#k5|$7W z#$f*I{of1W!u0=X{r{_4J}$n0d;Sgs+y;OMMF2`dN=`*fPmg3_W9PiV$0vvpm5`E= zmse8N(AG0FG%>fdwsmlFa`o``3%nN^`Y0?sDmFeoDK#TIx1hMVtg@#5SxZ}6XV=T# z{-L4KiRsyew<{}a>s!0~N1r~OefxQSN%%LDzjJo{H)qLzjsIIXA>994jZid9p;sbY zWI6$G@VV`4cr>$!P)Q8~bQnx>Oi$6Ch6OIcTiod=07faJAtDL8E?{@nf`y{O;qUh& z<4S-eeuB-~Pwh{H@;rtt!c|X~;jOJ3-@hpbsp|gjDV`Ayz3A!bMswYddV7D1qqi*h z+s$W}A+h;Iu~EOzV3(7KyBl^srL z1m+kmNg(h9E`80VY#R?1N#=f|e!S0m<}ts;&K&XfWu5^Tca%4?)$as}W0ig3_AwBa%$edzpQyG^rvF+_nG&kgI5GXejbiEzPY_xNFStmub0^ zU9%|-06Ai}1XI!QJgk2pcgOo-P2iC9Ep_jZHqPl8yKe^R_GL{IXJ$W*<>x>DI)0*X zJ!Pc){SFagOpRZc#ILzyY5)ey2Sp6# zH|=GVq7_IEmA4T_)pG0RhM{+UZ~gAtx+v1(G}igEc9z?b6SgO5)HJbk^#*ypqUf^zzEEEi<@`jhx?Welm3$%WYUyB zSYG#`lc(3CH=^J&epp|n0n46LA1`dkqb~gIr=K)pmIz-}hw})PqtOa~lq3zuqtFHQ z?7T+JZmfei-5tAi%0$)3#dL$wZ=--tSr7d;b8)7dl4zZDF5J|R>@U>7ZwkN1Ax$Ot zIHqX2keZ;tI}Fpe>Rk_4hQE7{%;?tCnK#k}-ZO7(5#67))Y6X47}w2at~BF1sIzFO zbXGfBtUB)CTa=;Ys`R+0eT+gW^HfV@Xp7JnrUTILPLG*KKMM@JbvG*3k$8|5PiXoR zLujkN`h3`-2#-1m5o55nqDDgPFzODEr2`dT+vOmgq5t@kL+P&R8pw3V`w4}=yCw_C zNVz5~{b}ze@I2}`=oB6;aGxsKRS}7rWJ>RxZ-g!K!MfiWn^@LkS|=IlR6})a1YSiI zoGjGp{9Ij(iR9N^syH9pVXj-Q;&trL!Mva6&&xwS`bt(tZ@(lvGTTTOYu}pNnCAZy z$Efjn!DOtM@V($2;f@Zp_-+M=rbLSiAd5zzEcT{0#NUKT}JqOwyEIU?dC4wccL3tTqz#Q$}LdB54be9yQ-=J&u?c9;1 z^03OMj>h$W{6mO|mPjE{>z7uUA9V!A!j~dIEMlF%1zqmdM8}=6kJ2~>&D_jk$z^ib zFS7g0u(sl<#LYgE@4S63YH*cpK_KK2E+3^ggLvrRPJKKIbA>pckB+#j1?=^~tW(i& zf`#cRl{JW#_CayKfsdsVI|^*D1cj~Gx6~Q~I4r9j0~t5D_LW@`)gDYq%u#iwzO75k@IDz(2|KS;mbPVZJ`9g21}x22Vw;vGbYCmlo{13@eWL` zQ3w<0=PMS8&yVN-gl*o%O{?(RI4fz;v#tgK%?&Lhf7%iogK`+?a&W47<_tM@Y)l&0 zh+{lUIcHqNF7af?Fri9U?#f?}1{}!}PMEFA4(}RYq_7Uv6_ZMC(0`Yj@G*9IAP^_% zT=V*dzFkkbo+p}Ft#8riyyC6xngjKcWLU34dWtP!Njof^;DrI&;&`M4n*kAMn4j_W z)`kaDiw&Z&r!5v+;_mjNcW$`VtDNfPsof25!9R3JRG~nVj#IKD|{s&Ue#**dUG^%Q+jCw0I2d^7`4Mce|2;bkd*VuP$8%cD&u zKER_kW>FsQ<~fbGzlv{*v3m3B5C|Ht2tA)eS@@WGhPZA$++a7;qM(Tq!0;fzSYm7P z8+DP9gP_b`q5F3B;dodi#M2GzN;B^#GOVYVJIt25R&`?n$ZRgKiMG*{f-0GlToPA~yvR^-ZcRguq51 zjP=e^0VPyAzetmzL}AbgYkwN8yGmN!{aAd0N#J_OWk;N+`^W`+ zJ$Uh-a_WMk;cWYLj(6z+M=EM&<&y6*Op(r!J>r0$%mdV2K6GuM0db*I`6u0VuRXw^^F>YcY~mPK3Mt*t*sR^+#vWz})(wcNh=v@!Rg(swnJ~ zmj`^e8g2;wlA=}4wAhP?1nZtZv(#fya?4E`O^JTCP(81tYi@x{ecj&SCVlD2hQ8+_ z>2ADIY{riNK{%gSumE&lSZBk4cNJEzE0t`+8O4bUsiP)*mngvwgEllz1b^PXMtR4W z&cz~l%IeXA#zQTd-_faV`vYNLzRBkRR0;y19>E?@Xso(IJG2l%!6K68cZHu3*3x5Y z-OQF3#wuwAzMN%}s1=gshM?PEL<{FuxnG;a!k*WUmkRHUtsnhf6LY+GbU7EzW+6%J zrpJ1OJk(wjM3=?fUJ|*&VOLF>s$Q%UuEb}6qvp=WW)LWisYvx}7ujgD#%{JU+pi&F z7JJ{XZ5H+tQ7ed=FIn>I+ca6|nXRN^?$u4?<7}>uXYs&Y;!z|p?n4A%0czyKc%x!~ zW}ph4FzE7M{6#>vRmNynjZZ~!-Pas-F_dcLXajE@{1R35K{@=rCOOJpo{d<`Pi1B+ z@zjrc8%3g8Z>e+jTdSN@_csx2e3uTKC3Vj}mUJ*cl%>(~_gX<;K}>D+!P%>T<|5PI z!quiw(^!R6-g(>D-87ZDrxkG-tB?Wphu5CZ)7q{RlwOHpK`co++ zNj1sl0{zw=P<)+*Or%GwSXx@jWuOT}9Pz};+;E^+6#+1l3v?^m@sNPdaLxQk(GH_YcO5X7Kc@|U z4?FsMgdVj#{FQ?`-lMYkV#8OhYVh_PAr(+B)oBM-E)QYG6s3+bOJR7>j+gu}LX)=vl-GK4D+ARP;h z6+2Lm!!C%IVB3UeCC*SUuJseYjh~h`&na*n{Dr@;8-JmnrmWvlr~#?$-%cwXMR5UO zcF;=$H#dB9!LaC~@vxxJ?9D^{2*mf|Zg@^VDuzyNoe3Nn9<|W~hvG-K^nC;eO$#Y! zh_IkZ5uzG4hO6}u+KX8Kjj2t)LHpY(I#f#Y69{=jvEkRIJF7aU;OL#Ah2lp) zkGVi3RxXM2cZ_YdsvGd<01SnN@ub6Hj#yKk$Y6$!^5?95|M-()A-QPtY4;64D&nYc ztOH2tBT|1q4q&vfJWb>cm#|2c*i1n{k({N`z zEf&U{i44i~ZW-N)y(zqrvF0Rgadr&=!oB$QOF;d23k&cBauIy#>4 z4Xz#?Sr4az(Mv(0ZiP~g=1Jt0I9RpMItviIwbf`^bt>YVyVtxYo@%*% zOW03SExr`fG9XBs`+wK`!egv7sY)XBRHxr>ZgBih5da{KCY-ULkQJ$2y(z19v&TG1 zw?>T|R(l#o@7;zZLmE6x{Ob;TOL* zho!OPthaS$)bcZTy-#hOtQ;-}TiGRQG};!@cSbt%=AdG!?b3m>OfT%h(Q0IlZiXRT^frmk~+&Unh7f$35_1uJ{ z+&}L7Zl99Bv7yRvSm)GBULMk)XU`eEbe}D$7fCA!czs2)Ys-9;Q10J+x6n22o+T#f zjxIELDxpQl*>UbYPga{g$+?INjFzmzG4QtD zka}<9@-T1lPFVTX57p<&Z-`~yVgK$ejSOKK&L(YO2!#61JR*vg^TdP}`xVSeluSYf zr7y!Z(v%Ip)+|f=$DaWTkykV@>5=*&f?iFuN9!c=f~54lKH}fTdy4%)WvBP`DXGY6 z%5+v6KO4Tq>#eg$-@tnfwfExN-K{Da;fHa_rfZG2csR#uA74xm+RNc93f}~2bJw@v zDOLaoM$=Bk5-f6$$`9vQ>PiO8s6?J~n`*Ks$awbrBKkQNKd`IbSoVV6!k6e-`HSRl#()y%ypIIX z=qE-TTNnvG4GmFrycvpb7)WG4u@a;?( zYYDquA26cy#6fGMN7EI6u!2bxl~1*e<~e?%z1jL;YIa)A%oBl2n1!nE5IsV$vyYXW z`6vHjHVaeCptBAm_d6oR_B^&>1>LZ!Zmly<+D$lBdv~U~!COl2R(*8|$Ipt&9si*XD=)f1fIG*t8$pNK+ddcAu6Fw@pJb{9e zeZ$xJ>EUA3sj7ch8ut*JVc^8QX93Jp23FK`eLWQQu_N?ZUpYRR9zdw(C#Y=>1)lTV z*J2LKl;yE`(#w?o+gcG`Vx_N|3(wj(&`*3W`d!_2dD;jbZk=i*OhC{j?N+pWTsHi3 z^O+zv`N;<|59HF}C@@Aey3>Mf+*(tc&HRCAwlDeOPmyTIEM37ri2Knf!jG3I)k)m2 zVf6M-U9^WF4rb%ua_M;1{=p1Y(F*+#pG$mg9z2lD?y>Mnsp@USClnt#`Q^3Sw)1>r zAr%4d&eqSX;~swpV5);TegG11GbTM%Xtxlt67v2a|Ft^RsP|(2aGo~B_SrxFY5=XM zl$qzvJJupwtFPoDZYCP;>Lke?oleE^2FFygy3@LK6;VN%uU!U(_~%;j0f3^fEq2r> zt*3I6wbfMPu3szoa~e(AgN)5TCsczro43HX;g2`H)Cb2;e&jiD3*}}R-I;qPcfj1P zpyL}7G_Kv2Vf2xDu5JtaWGJUAS^4n-Yu&tf3l*M$Deqz>B}+OLL?V`dPm59ug&A%V zi;rfcVURVLL{nQA=9cO9YtuZKiA@4Ohd-`HN$f)O-ha|z&aA_NiGcT6WZKH^Bg0D3 z5x9guNZ>jKNFibC8^#(9fv#^k4cT=*LDRfc*M)B0;iab-pnPE{U^y4DoA$i4>Ejo# z>iU(uY+GnUmKEj0JBmkTjjK(9uRh+{d4Bb!ckJ(~0nhsw0-AdFtJ0g9KA!t|vr!ws zzt{;^(Ek`yZSz=D(j(Ru4S84G^V_y@Rd(nPRdIfq%^Co}0Q@^F$!=-K>}U-@n9Q}KTLNwz8BCFUbuI*nu3L83|S79Uogy&Y|<_c?zh+&DQkqzT_romJw5~ z=R`v1v?>ZqfLB~^XEu*X_7hAsD-Xl1`jrRyZKAj4?`UwKP?9bjl3q`5_LUdyM^QrT zOpb}h6XM3E#Eq~>RN1=#fRhqjY1Ch5<|AUX+9PXwHfUl&zN9hTl=V)P`=M3f+4biL zgN;j3Wk1^lYkk==36~73RVfobkDF%W4!{{#x%AE=8Zj3r2 z+}3@6MiOrJ*a$9vvK8-5BCsbvln;*L=Mp+N`afa zITPHWO{T=ORM81csP0#aB}TFy_Xhe%Y91POdH9a9_i)vXfSa}RO2Ws3N@Le6hDJjaup4L#P2)1ySJOQAoNq7u>q#JpBx$wpC0BWEg zHS3USN%5SfQX3{0A5bLVZ{+fLv%jP}8zd7w=s8RJ@yVFPdf4(aP0ktbaxjf0r7XuYl=GVR#I%YB)!RB37QI5V5%#<9 zh2WF!K!ULx?yYMXV`X#cg~2r?0;UZ(gW6SY&N7&dnpOqViX7{+7Ow0_|LlMKqX3#I zkv9`wrn*wfhmCR^YH>47dJQdp{>Y5l?=eZmmeG>e*_{S8ng{v=-`MHiuBr~#S-r13 z@WtuQ!T?bNKxWw^*bG8C_^ZB!Wn2*pmA|ZCcGA@h5^5qXx-%wt(3x^XoIBM}*ZFS8 zHIx<3x!2b6yyf_didC|RY8^eSs43$SGvS*(?sFLcq}2mczTcB_?J#1o0oJdTiP3h! zINNVES#Q5G9Rz&I8Vxy6<)y8ozwb{$n(MUac8v$45okHr_~YKw8h?xB$=D0$7?lj3 zKc~j@Say#aENR$lA3=>Gm{~{8WO=<0@6>JD$83Erx6bwI3gcZoDU44AyfrF*{^-_o zW}4uWC=tx7_|Q0RmQ`aNTreocCvl$mht=e2V5$TFRILHZy2me$QJ-?@9=X)``AhcK zE8>_iyb5WTo>Fs2sT&Rx_BJ~8UtWd{D>dTUl5#@y!{s2j>`oD72j{WyqOV4i3Gc)mn-yNspv@_v0*s zDAgyTn_+6g`~uDw#&go-8~bZNurxgyl#8fLlk@nw_PNB;!=mOWm=vse;zois<_-*Y zBG!ZN-KgA~RIWmXbMvHc=7hE?64`@MK@jTTmDR^`h)7HArtdjxrX@_bmTM;vY*(WL z+T_3VOV#l8cRsSIFS*!gV}S%Mo}C(y^73;c7VSkpN&Sn{KvloQ1%pA^hB6UYHh7N@I|P@j+;~j zh4uUe5M1!JT+D^8PIqB=3vS)s-Ws5HL18)*9qcdyFGtPTkwCwwiF!ON6%+2oRyHg< z?br|xeu1_~hQC*!s$lSYb4@;2C)c(&MKBQVgs8U=IwZ3-W(2siW&oIuBHe;JosG#g ze^I4cEtTYFdcpb&E8TNR^HWj=3&AO+5dNDO-MmehP@^s`wux@m&_zBXso0x~ZQ*Z@ z@CDY^r}By~_s|qTG(*S~ciU0K!W{G96!H0)5yQrVu%Z1u<%s!qniYO85_e0-WrC)c zbjVaOL+{kUbIjwXaX;E91!CN1Z3cw$sWKKe{9`CsZr}j`-B?1D{xVfLCOY&SbWip} zxL}UOh%RYFUosC;Kz9EbnyS{KIdZJRSk_CwwMd6Ut7mnqfBt^q%>er))^!_$Fae{& z2cJL2Y6f~NuKWJLpD_LSJ1Qu^5TfQ1!LFzrk>Y?H5FO0mS2;%QT>@$3K6B zuzI8&z7pt|LI*c&Q4r)jJrkth-hJM}hS?vW_9gazfY-4voXyg|d`a^#)hA0`>A~3B zQm5|>#t&Z@zD-o{@1WVdhqT*n9cmgwosIzAP+;k;W z9d^?`zCL1Nk4S6yO^f2joDvf47jL?yEn8cnHe6hutUtOfH&ox{_Kj_kZ@r4fTUA)& z=AE65HdqV0W@4k+ePZWuwiebE`f?XidAJm(($Bu zAlB@Kt4r!cpEBUj_%@w9ETw(3n^cX9d=^^ke?PvsdoQh+NYZ+4H_Z1>9hM4UxWbb% zZv5Q~!u1FJ`KVKZg!>)PT-0k~sqTAjWu0xKTV|5m6{)o!v$frw`OiD#Vz?=L-orCK z;fal^X)Zf|PR0hU4KQ)Uju5N5_|Uobj>g_{dI*4C0O8Ag?m4iyKkXoP#H96r_T1SF#_Q01|o7AgGaZ1kf%!+DP?`0(~Ujy!^rLrrC zo9*{e`T*^j-^TLO?#UX;$T-!b44S%~a*jD=l1emA6+3u`&KU=4t4C0V?lNYvjuSdvpdz43UJo5M#TPr$!svqO-D zU-5U`E!*|a#X}V;e7*zsKe&*5X%l@Tdn-89&Y*-CD6*(0l|(Y;k!mBR_rywOX3rqk zi6#;;R8Avfr9|KujE>-HZjOvASgeM|j7P(~7(9^IVJ6D!?i7*9lP%!SF^tHxp|!|M zxbRtRIw|eA!J!i4u5X6@oBxo*le!$Hk3D!2Kdj2&0I<`9_b?N^r;bM&^^*w&v%0)U z=Uq^>XB8KYD1i=*7bUmzng$<9I6v@S3)2vKM!{COJMtk)c!F$->&v^mEnnH60ayqM z&@g$CNz5SxXPo5e7UgUh-EIRU)5IP_%*FokKaA`j|I0s5$?tafZxvr&ZPMi?VSRV5 zF^5dfxXDt{kV#cyN%y;PN1FUfPBKSZmK|H$f)+yj{PmncuG~3ifof)%Xk{;rXAh%3 z7@t>2cyMMYl`~F=LofhD)RGQ#PiG-ShO>IF?StKx;`?weT|eW2l6Zj`S|t(__v#x` zlGJsQDer=usd;nd*ylQ&xy60XzA&boo0m2YjZ3WS8{I4Lg6$?(oj-eBFO@@yRpNzV zNWl?F)BYF_%^mXyz9ik#V;XUmhs0K%kx)8S_j}hnP&~|*a2bUC%`{D#vpG>i1lP>@*d&v)N<{M7w=+SEp?8_+8HUHcH!j(97pi$4^#K8`VWxw2=GUH16l z3QN3eB1KPvN*Qc4wPJ@E4v`Soq}`2&&_U)#HcnsUAAc2!xvSVL#4#bsz-Y=BS~-fn zpR5G&t$QTPvUQK?vG@4LgYlwQ^*u!+YfotszheFdL#GXp@*3T!qTP|ufBv&i)Zg}( zf2bwid`C(p5T;9-*mP5G*EPHmg@v+H#1z(YT$N}vnD0z2zO{{Dyoq)0t zbevdu*_(d#Ea@%JrVx>hVUSbp^1YVWS_YM=LfT|W){s|w9zZjRl7=pn7z7^c`gj%- z#UA~#>uD)Gvc^Alu;yEvyk1bw($EeKD~Qe&L2r%gO#jc)Tzc1uy~N?RFmEHMa>O zvNSHWWi$Gp{ty1{fB8o<^0iJ4)I#Ikx7|ozwuqc;!qZsDs@yx7VPN)LmxI!hxi^Ao zPpR%BUcj^abaEwh>3S*hM^9go4>6ewcF)yRd~Fn05AmcqXzw1Hc;&hF#{0p=I&a%O zm+$dISr&^5h5%U!aKi53jHIH>=OjlK;ET-;(bkI0fJ zZKq6qZ*VuWeOLWU&6SDKlJ(=4+Sy{ATH1&?eIf7Gi=wX-Lg*Yq(w?=M$aTS9Jslf6 z;#n;zE&#^+Cx~g@z=b`arwsk_&DLWyi1q|DLoIBvf4|GMM|IV+we@~i_%T_&)w1tX z7niKMQ8BFL4yo{>85SOe@-dO~kf#TjjxB~8zT#MCtUpo8T zh}p0+UP{VyL3y%!t&V2chz}fVQIt5md8^tHM4ES^|Iy9xInO6gwgp!0X|ek7c%$Ac zLK8tb>_^pK@n`)4Q1P>ApcvZ0NESo^E_L+I7bf z)6{lEz&pRBB`C&-ag9G7o|V=iX$oqJMpNDMh{8{;JlV~IV=?h>JW9z#YB=2a^fqwZ9R5I9HPW$P{Bd#b15I4ZuyyyrK} zZ+tGhCA~80QoGCN-ZN|{RwK{Ccn!{DqyHn=*Sq6mnDd0-TTQKsABD+R&))YEjNUwN z3Y$~v#6k!Be8NRk*kwqsv-mUvFc<}E^AV3WWO>qNxcRQJ1&`g6C!rKj6@IH*CRFBD zsI9NNMD4eK?-D!F_!Oy`{(8O^bxfB%97j)G0{3{K=pN249M1W|NLDoBiEz83NTatX z9iMP|5(G2mXq@%3SDlAF3Lz%R`#4OVYNAjuK-KL|h+rINLDUSgj%Zcjk7I19o!yJt zEE%_Tt6}e?$G3(S0~1XMjV=#_mH}ZbcvVrSl@6lS=x@9+wLCbuku#DB{Nulm7@*+N zk;yR*(dO)mcXbmY!)FQj*t?esX1I`dGOZ1wUTU!S0%pRT30{put-^E3h7T@&4Ux zcOzwoU1GOXVn<2M`YD3 z_!FHjE%lP)UAuYe`ZtU9wm!VqIZH`e?ON)&Gqq$rqxTef`}+ppxW49B8H1&@Eu@hn zz$K4}Hk||ZceXvWD=P0`uOTI zwZqr%KPuwFjp}x045|+vM=463g$qYEZ?+g20*cgSp09p{CKXnYci#)U&rs{O%$#J5 zHP*hx+5Y#X{NsN_PD{!4PydEy=-;&WdA0Q(6*B7|9K>Fw*YG|q`K(AnHaJZukI3{M z^K#b{{`9;7=@Z|HN?-!Ss6 zR{?a}2`}(HnyA2=7>p8*MPeeE`)jQ>@+lT>XkVo6%CC~{RtWI4}>8fG<);D0#9i9ck602%6C0j1Q<1jNwI$T#)9U+$n$`t+rjeH6kt1a;MXY%h$ z#4U^{qgwck_;$m&+og}aYDw$r1^nWlw~r3IcL{N$6DLx>(V%?VC6jJq8PHZTqA(Kj z;qoy0$tRhQ3NJ73ot*Bo-&?oJTABf&P5<%#m`JO`rB1eLWvAw}YGWTBmt>m7tp89| zi6oJGx4PxJ-YNh=W|SmE=5k_*C_)fN8V{9xU`N57J>!B^Q_^bywMc7_JBs;@XvZhk z3?17h_Cv8JOAj-FV$^G(YX8%1quUt^U}`(ykoW674% zyKm&Chm<@6)A3&yo31X#KE9kkaqD@K1!F-oiim>x=e4Q7Qd+90zK9?r#vjbYD7xVa zXmgA(FE)58Sh;(`OUA}QQ2v|YEcefQ_CYfGuApuefB%4xh=BMj^J`kjj*6V@$F3#; z*BOEwlYTeGQUdC?OT7@ZWJ&9eiH{8?+o}dl~9(>h=G_|2~&mhWt#4 zVuiM#{l45}!BeDxbL}W0h17QkBTwa&AGqXi7qr_?en>(n42#_Y)_OV zL1Tvq3cHIdeJWm<8{{FI4joPS^sIpSwwJ)mkn!E@so|4`-*=%ZH7!53w@d;*sqFFn zn2xz`+|hy|?ZA4k6mzHHK&8Fv2k}%)F<)!bvGBN0xOi0DdaQ22V3LeZ1Q;AwAI0Pb zvOg$c+{3l^SMUMMLY@cTX#~R1Jz_2S=6=1%2iKn;iH&>+Ed1E35q^R5ipbhJSAE zrcNd;>+lWZ-DIJj%>3QrKdskP@Da?^*9C|TWjQ<>2?m5?jvoX<1;Z&odhb2Q2-X0` z$)oDFUh(hzo9Yqy+$$FKgr3knOU@Tt_jR;Mk7Jni-QD9{DLJ&>%P~ba0e|R%LQ6Ju zZ!m1H9<^)GR@!x13EuAGp!@a|L_NbQLTuS|9R%z%xln5v&M&g5z~4r?#m6v)s=f51X-6aWq)fEMPgA{TCtI&Ih?ZTP4E|KhJ^eh%}gHdIT+mq%7tHIP~8p{mi% zgkADynA#!oT7!p7!ja52Wu(jz#5CZnt!Q59s*|2w2mU%vwTg;y4tMfOG0z^k`h+o? zOYc&g*Kq_#(VOl!J&IzW=b4HS22`Hp1E&?GL@WCG}K6bSp@IwlK(jeESJULBdPNnNN>Je{%E(S(+9irPkxKgu@JhiYF9` zSRRx}gA{SLi?K1gf6#y~MULs{5Iiv^2Hs-f7@4YM&k4i>d`JcOy`U{@P}4R+Tt^%j zuO!9zZPr`Xa*7V~biI)udnkFc4hxaOPh@4&p23lOW*QhKty57ld7) zrXSecuqXAU-9RKc>`Ec^5s6v&@HKTVuRmzby38_C@hLJ(+hqZ>GxTv( zC^a2VkW+57^PdqeHtJai=}7%OtH546A|xPTnyKXnNcQck5J^unbRe>??-tY}&k{L> zKu@Wi2WTI`Vzf#E$CjV1&{FyZxacPuz1Q-y)-B!n!80T;DOL01qukTVLir3Po-J## zkj>EjXZ}c%rU)=r82QArPuIR?+FdN%L9-uaZnl9_3J17&0xTaE4$UMbVEHH%51+p+ z9g|Ip7Po4VGJQo|y_=dQIxUYur<=OQ)M?AR3Vf-aC{l!Uyj}T2eG20`)uTdDxM``| zVYS`81njUDjNPvTIy|#OD#)Sul)c=g z+47(N942n{v1{h%DSfd}iQT&IF0H*0!{+0BBhEaTW9&VX@E<;;p#=?i!gzd6YQ?rz z_-?2Bb;gQNH||RFFIDOD&Z0s~GTOi*jY&a+(@W&wZ7mf;H-nCb8n7b!H)#ex^_x*t z5Zd9kF@I4cQ3Q9cA`RBNkJ>}maib;_t7KosPC-Qqci~p!cu&7Af`1K+ zZGPO(==XhVMr=5N&|=TGPu365E6+Ui*+Tr<)?C$hfK$j}F&<0T*Qz-peB38mv)r&T zordg(q6SKG458I}W!|qR)@9@WNR134ddNijn=K{t^6lx}2*Jg71#=w4JZ%*Gdah~`Dai+U@QXCKV zbTgkiDa1QoO^GXK8U;60IsLX~ZmMfauI22Txh(HfD!2x?X>s6BV7R4oN0@H~%|1X@ z|6L|Q)v;L#HyLwVD%Ve+-t(XS4-x&ZnMN|Ywe2jRwUGNN`Upe}^6&R2$c54|?!7P% zlLgvR2?{5DjKeHltL2>t(sT)k6tPl(_xCMEr(eI3B=cZ+?yLeY z0Si~dq2NwrRF3@aKXDxM7G|+4*=r^OLQH&Cc8z>kP=0!B- z1@zV(SCL~0Vnaz>A4mA%B)?Hh!w|gwmEAmD5YJpBZR?)J=k^R{kj=+y^?*#29p~JT zDf-@zV|_k%a=D+|0yP7l9aSqh)D*$L`Oq7r@i0aphsxTMW54{@`EQ5-6ycI0w!gMe z!cN>xnTDdT<(||45yju7Mcax0dbRh92O93uo_FdQAo(sp7-$9(3i_Kud^1 zWp`hh7c|-tKWQzNJDb*?&?rGpzT z_0+-}QP!hv8Lg*8wW(kAOGZ0Uvvz%^Z|w9)D9a%oKj&nb_{mvt;}e|w)mNIL^Yu#6 zxSMdDdrBrJ80fUlpL$&~#3Y%DE$k!f`a5PIVtuH`YqSRw_h7uZsl_9>gfYeOlsamNP^)UK+2gS!JrX zONpx}*k;H$WxwDyiAjDLlBkFLdvvsc7~n|6LHS%fxW>ZSN8GgY+8tco;MqzebjbaG z{4(Rwec(J-0=)pOYG4sakxC!wZG? zg!S8tM}`uo;(dxpC~aPzA;exD|!{l{$2a@Wr8C zWt_y&v0a0N0|UBHj@uvNCdxA6wYX3G2>MqG?9S5Ll)PX?5?m#KW#4oY*hW6dDxBJ2 zCT2rga5Axx0TIZTpJ zZVZKAo7o!pe#Wo+_D*}6^P65}g6qEU_pqj8;Zj0R%ToXk2~ghxc+{2hYPfUMt(ZhJ zbFf4>qSDRN5lx1iBjSJh-;129VjQNuHd>;O-v1J)t~<7DdsDCSbW@Guul|{YOB!BM z!Ts>%T(epG8Z%6av%eYOH8qujArVl;t~Q6ttrQWWLA&w5ovjLHUIxeLq=f~sC9-4- z8kW*wr{T~ojg9?-$bJ`N2y&8%jM=zA>Bb~tNs}m+h?7n8i{USrTVO`ij&A(-z7HeR zEKHXjT{SnPy*|7?(u`3;d5z`g|G1numw8UOw7sf`FdqGSkB(Z8oED}DaYW-sEC!ut za^RE_-mnTDxRn76x6a4T4l7`1nxp5ezI*!@pZKq=l@^%@P1SMCJF;_Ys)b6)?t85_ zJ|K8l-Vy>h^6HaClSl;AMb;kY zXUTqplB$ur+sAvFjEg#S396BFP-|^SXB@kH_QuRMb(^`Zw;8-{9}4@`R`ulj)sTD7 z{TT>A**0CN_KH_EhfC;zxKkX5s)24Q}eg1 zcP24+8Q(W2;!FE^z%d3a50^0Lq9Qo^PpA+?IAE;~ILFe_!icD7nfIlc`ZIPA6i*%c z9frv)9S2KDU;~;Q{I0@tr2=A61s7{ONov*RMTG3f*8PDGr?wIe&ab_G*V}UuQs*Bw zKU>4-2vEqWVZ}Xf8D;P`DsURdvNP^kCDlHd*Ce0(T1-q&?AKo*b$X5NSv!No#LEQmR% zMH8McUk3Lw4_v!QyZrEZLom<%5}HM;r>E#q2L(xT4T!v#`>1(L`%nL$ z5(gMj>KR>DcDj(!{y;8W#G^0<18-NH0Obz(%f!=WW;rcJj>+xoBSz_^R;#&>I6r>< z$tRQOz4hCF!}Ni5MBuK?Sn2wS-5%sVf=Wd*Xm_H&AIzaw+>6t{Ho9#cK{b)|CrLBt4e z3XVMo)#}1`qapT!*$2&KwN3AUD9kg_uxlsQ+WQ={!cI`F-I5u%}*!_!lfa1 z|3ZOq6(ynwD-SdWYGFe!X(0lXJz^5zl7XA20mtJs5HT8|5Y=+yyQK@H;-r&G3|8Tc zBJ4_xj+CuC!9pvkV#p4jC!8?RfU{S^A#g#Ko=BpSY^F1%me<%|0HpM1*t~XIee{>hd4^t zFSb-MgOtNb14TtauF*P`gHd@0M}wZgvApPcx8#*d8Xw&a2)Z&dZ+dOC-+XfS=Tcbf z5Pg!hAmL9+(`69h#Pw>E4{YTDwX?5nI#j3BX2k`#D)uGkyHJpTBPA6F^N=}>?2mJ? zvW9y%_tHpxId9H}-W_?Cv(qX^W@d!Wip*yl9_{=T_GF#s#n+s4a-IFZkA%DMw#Fi^ z5htojOaf5yMx3r9MCm#OtXwGZA(aw`lX#B|;u>qIR~hE#^H9i&JQ(~zz3|r(BYrOK zW3~Cc-&;p!uaxEZf5Z~ad+A+f0ji4N+n|p0z87B^+K7{({khy#QllL++nSWZF_frp z?HV}tA&U5tLDvlU!_m9h@ta^k!RYCCSk4WyNr_lL72l<(A0OVmxuCK=cxZJ#O|@J{ z`y?$~dQ=G&ZYULNhox;M;EApaN09H^JK@uv0bI~O{vXNb4*&X3o|T=o%4q3*cUe*k zU!=Z$oRSoxTv6!5O6Pt43xa8EYiIVJh`tAD2?wQ-S>(3CM@>rzN z%zAf{(~Sse?Rn@cydJhyX3YaBMX6e06!xspqSG|g*@jibV|!( zc{2R(YW_SSi|qsll1jeqxT&PSdyj0G4^Ultw=EP23N1iNgt6GlH zTW4NAgrktc!E9b4the^%gZE_<@}j<9Y*l){Ken5z`L>r)qC7j9RfWJ5R~dRJ8O0jf zRpWpO7L^gsV0pQl8sC0v`SxU(JGdS5^mu50r*|8`>xo#?1FB|GavHI0l) zD_MIew8$#kyL#-PNWnl!T=2l1R{n}?x9fzK9!(-~LvNt-*2T{-*Y77+2@2 z4qtNsWoB4c8j(xt*Ju@@VX~sC>!3ZiW!_l4N-Gp2Y@z0z-Wx8F!XC`s{6UU%E)J^DT0{A~~M>!|&vN!+5j<_4!2 zC_h{enHQedVU%M`7oiLh2632`oh7H>MeOka+fkHS5~vprhHIFV#*_VK3vA{i zq>R6jtC{dD-?L{cZ|wK=SBUr`t=Cm+n25-W<#0q&Z9i91f#2z;(H14LIbBsz$|Y}^ zGPwVzyR+bGvy0kv@C1TeaHoMH!M#9mcZ$2azECI>cPQ>q+@UzdiaQjS0xj;^Vg(8r zI^V4M3$xbb4?M}W?q}zmE%&Biq!e}4w1S?(N=dX?t|~2PUiwd=pY#pwE`KH%o(yA# zGD|K+$XMC2pCWEPJRvR+vrnS{4gh0aZ#@Ym0c99YFg77|EdzeP6v^ee3f4dVzvJd# zQ%c9S`>DU(f%JPaD}uXhU-W<2$M=x|v|b1;rl#FMx7G0~29wZX_U3#^G-u1^H;6z< zdK3F?32CS$@|Kj-kJR*ocU22Hh=c?$M<(FYi}G&}2z>&elwgK00hDr7CX*RNlNkXh zZlcD#!U*P3EE#Qr0kG>YgDc2MaS)hT=yMXc4jn(foOVI&GrCm0!6Fig&5&vbWHN4s z=1tVQDWAKmlk*9@^f!rUbN3Y9ch7}oH^s*fq6GyAxz?N|0KmXw5CEAlWYGqmDD{Sy z4WDBw@Vn8p{4P`ektz(!^6yjKl=_t|tf;^mBz3ivA>E5Ro@avL!{wO7)Kn`OGMEjn zNuFqq`LIeT0YpbOACS-=DpH81@0)pS$dLRs>1LmtNgF|%Qm?7(tMzPpEFZ))r_XVF zdZXDAf)}Ic-IpQnu26YAWZAY{o5m4j;%fVftMgnX!*UZ#kNXu{Hz%SMfjBf|)vdeG zdCmx8m2=8a|3CFdo)>>4uBOE%O;B5W5! zt=P6N!L_o;H7&=}LGbtYkU5SJtsHqPO5GF76G%bTjc`-ZGT?rSuVCGpar+yqCr+e| zH$kw5(HAPGP_3NeYO7{|d z4xk|k^Qvs3v)8T+#hrgX?@>b_uEc&U=+>tj0+=C3zSBJFQoJjk#T3Zk|A;Uw;(d`u zm_S3kBG>~(_&R!WbP`x}dQ4oaZf2`ui^Cy4qlo3KzN`hV?lWp3j)Nc_|PP8=cSzw^KOr3mt|nAjob1g$Zp%T`pM z0J!L-{{-gTmX5}@rcS^hi_fWCqB?ge>!6{2|pteys z8tQ_h!nDlBf(i3y;tol;L}4)PoPBm6F1G#Rd+W-1X3dd~WIpB7!9@G=-zvTvZ^YVv zP1NjrqZm3;-$hB|lEmhndbJ!JKSnv-T+=_izR)eX!Qj_vpp6643ZZ!QDHBSG#yKFP zS@Y3FAQu9Ehho5y496n0!B?0G)=omV*^Afo+MY>;wkT1bcDwR^N{-~&#L*SPPcU;=GcnT=%YE1z~zyU0e>WL4)@7kS5EO8_Tmh~UnS^x1rkDF&E8B7V7 z#gmnan)8GzVxhjoAM0pI@wn}=DahplXI`@IrNzxhz^fY<#DmB!!r=I&rJ^7VKpAC3 zIrnXvo6ERjpPV5i9H=v#1I*FL)Cvt@B}p33%4*u5wTdjq_`(r-&my&C^w8gs_J}dv zAlPb_Gt<+`{4h`Bn#Q@{GanntKi zD^7%y!4MtcFDAf!;PXN9EaT~9xw^VshhAL~glr9=C2<+}9-N8M;|bBTkmlxzk^nJq zhm@h5)$sbL*E5E*E_|GxAUNwb;nv3+ez&7NIYm({@pkW&Emgr-UawQj=Jsv*DFQKj zDTehFmU1Asq14x&VNiau}vN7_yo3gd_v4(i-A(n(J61CW;aR4Fa{~OwM3VdS{SXi+jnNG zO8UIY714_RKI-=qq>SPLVGtxKNn=a_#$z|g=ZXpDO^210_s8l&Zuh|5&?RX_iyXKz ztHh>i111T_me`U|>!MuKI3Dz>w`~|L zA}hGH`b@}PoT{xfc3Ra|w;0*~vWEg3qo|X+`!45GXpt5!-WgE1RBur1t+fYzKn0){Kk-@u8-}uWNtn04!GD8f&MOFw`qelE`^eW$Y5=S6xmv50w zk5?5ukF=n~_JL@hd$&>c%x6o-3U;b1nr&#UJS#06J%+kOVL2s8Cyf>kM624`WTht| zwgbJ^?xUbL)RxLk^s4VPunZUeFz#U<-j$3gS-`F)S(*|hR!DByln2u z{b5o+Y4(bQP_uL*Oaka&P4p?NkdDwrFB2z>b?^51Q>pNWYp=HB;^jjf#)_9o%h7Q( z@??2%J?auj5Ig)V-WyAa&wP*@qV=DPW;u>_WQ~Lw6V%p{m-u5OQfzyYqK?^9>vpY6 zgRB21LU;>9L~iI1fv54i@k6Dr&l?+37OWg{!QW*+)rC32Xy5*b28W=V;7FI!_2F|R z75oa85#|OjIq=&q`BFyLGYW!`lhD;EAfB&Ex#(srh}>iR)*Sf%@js11UZokDe`lbs zzWrzT<@^JJTE0>dvo92mwalB$y!2(|5Hiw157e{Ah#n&D?z!l8IVrS%a0q-ld_L|u zCu?^>Ei5fqi6XEd$V45b&&&jZEgA*m7@6qFQHhii)49+h(G=mK6l3xQYBw-35j)V&q-aANY##gXbo=hZ)=TbiOH~RvM9-stjx|Ljef!ec?Z!=;*%5mj(;qX@?{!TC zJPA@ih1^!A_IOLbhe!i^$)&0*r3(iz`GTt1u0*4RuM;PZZwEfou#RVmuf$TWKD$|V zUE@a$4Hhe+{j7?stah5d$9B9(K94PT@NGNxyQy7$ObwU7l%114Sx2Sh`VH-aOF@;! zg6Yn3kt>B#zc@HwwNZI!MW9E@@V=(RVai}RCzfow({nps{`M)(rorlMv2>)-Q!_dX z+40Da8=kjkZO@QK%@G$H5w~p%&pS8L70)z=)7$)LO-&3bcjX z9Z86`rpOC_=|53(hh#GIdVVl{i$B3W49ZyY=6D?Dhkc=OMW89zA49adu|4m^p(29% z?)m*yd_DR0EvWMD(Ux^har51Oh({mir>BkB=ZysbK-hx-K-5rOgk*{2$x2E^zbUn% z$HJTTVAWKh9?o)vZO|^DyF$61KS?vYPS3`t$VbMLpB=+%mz?KpQER!3l*35p`d{7! z;=}PX;`;r__tjKnf`i47s7U5eMTq>H_v=w)9Tu1BtR{ehF;rZ7%>mk?mhka81%rGc z>5K8xD&1+DJZ5x)cV7Y>{&Mf7(DiWc=8!L#&+VVZvCuhn7gt$?!J8 zP%4d4N+&9E3L-0uQ5BgEhwN-2R`fopfwH%X{p)kxKH*GB@m}BVZ9roA2x_W9~|ZPn7VguYTXs0-Id+6#PE36 zxpwr_^PFpX<3*cA0Il6IX29JUbc_;=kW=x-FNf=prj=P4d?{jyqY(fcS66f0VIJSz zBfA61Pfip3|) zUh_;^K5x>kG0(vW6JRuFMCn5P>T)GXt%IMzyhopAm^2%ZR%1sFj9z`AJCa@vg-fGlko7*wuA@1nd+Jg2|CgGTkMq^CrIwuz1becddf?4ih4h0lB z^zdGMb)ceWFc6OZ85tkcpBhY$A33(YoS`iLFaA6Rh0Ku2YGo?I^pIDA|K%Stoe9pj z4*TG7MOiQLr!pw#?9)n)m0An?ux~yu5FT62T9)B%47G>7n$??BCTK!l>43xA@Q%}63k^?3%8Wu=RZSU4Cp@j&(@H-khnds9 zz7wqJEXVogUWyc&v(PKDzdQwtexgN2pRklh`}0$+_fXzWG&}L74h56T8vn=tCN8uJ z0*`ICuu=;-On=co=+cl#)!H_gJC0tVs}S0#eM?D{!J*IF_u7s9hW1es~Z+IqcM%h$m274^-#IBZ-6L_l8hHM~m$V!6xvkqDbxN#;%yNhW>_cD{}Anz|a`n)>9)65-%mC5q*qYA%X!r4xD z`NE?YZD-cJTqWY>ye#2!?V9*QH*2@fr$SpW-WoO72=FL~{y7Y}c-pd-hdC9`MvOiK zwx2JLY|p~DSmj#mwT7Q}61&mPoNYAtU5{R&k?3s^YfkgcO?NsX=4*_Ls-$6-i@4q5 zJzwn+Er57*7Vx?1xB{;b;J^?b@H*O+f&3z3?z{68S!?)Mg1+0HK5 zD!3>B#P(3#ss4}u6%Zwb3?BQ%qE{ZCg=u{xhe>2ka&B%L42>&N=xTtheJu%Ce6@Dx z^{xc*w+Nj#nn@?Ms|*v>{9=(_gU7c%zDe9gjoRjTCFF6 z4pF8IRYCzX?BD?g{O3d)zcf6J?+|^L{t~kbD?6t9D*>*s}LXoIGu4JFy4Hl5KvOaHwDBRzH5rApae;hvZ z4OhY@?w(J>oeKw+^hcWzv~wm(87^&z7OuBMGffsr_bu7)Q}&`wsTr5^Ekm!LpA{af zNqJeq(8%j=9bc+UQ0PoczBktZu~)Z8vn zy-8D=$zzR!5qZ09^7)ZG{Nt=fBbJzk?UXb559gdxuU}d`v^;{L}P-p zy~yCySaX>l1(&6!o&310rrS!H4RH+t3x|KYQx~fK^EzL=Q0*YiC6ov3kx69%$W9~@ zSU*kvvg!Yg{*5(i{Kh`px5+a`R$bVL4$EQ6g|f#lT+$R;rx1q$wA88&pR+;Z_Z6hZ zl!nqfa}3Lo9=RhMqFeP{zXu^fNnH_*&Lta@rRzT>R*W5~@t>X~dp? z_MN#d+f_O1j+N`oAf96Y0-EeKpYG~siV0MSqz8hdl+?ux%@{8ND20r~u{Vo4<-NZq z2J0L<%^fLJil1&KRSBYS>*Y`@clO=i++I&=A==q={B@qge#!1aFA7l8b+iFyLR;S= zUNPj6kBbR#O~Afy+Cm0W(9uNu=(rS#RP+ubk!6bY&&`?29TdrgfK#w#r_q1>uYnOxoU21}cdW*~h(76)q44 z(r(wl^`HmPhvei9XYf4SpcQ%7Jt7JSTjX}+MXlf20abEK@Cn$|u4ks_!w^N)+Nws@ zGvba$CJXaR*>=$5w{HSE@rCE$=;!}c%?U{)w^G};3Uf|%DCJ~7f{{w`j>CSIE{K0b&@r({%$Ah- zSSxTY{gH7?=4Uflai7WFVg7!JL-$tKz*Y}MAB`eQ5}CHLfEXSU%4>@xMQhcor5b4ow8zAYKctaVIy*dLULoi4mgWm zYMhtvIn=UO>?TCCiA?oA;+P<%ROC+7;5a+Ya3!7ZZPVQt9ov)FRnx@T^6{+1Yx&t3 zauV`ZfIMKDqn?$eH0Bj3H6|N3s43UplHHg|Dys_4;!e=_N6y)`2O^2Uu@b$5zZZ0n zSLx;#;O|tnQnMmzlsnfg5@1gi!zH#{|KTos$LFbH>HEAjDdV%1mnkpr0(}>cA!quX zyh1{|POdLEJX9Bh%DTfQD)ThMgy5|IsIpOSN$8*c&wwFQq*7QPrC@4B@)4eDyqLX) zcvD-^l5b)x$fjU37hXhN4R>m_7~dcqDnBs)t5&aCR71jdn^U$HPEJq}*QuC1U5z?_ zT+d(=t%ZF}r2lUc9jN`T)v720l}*J9YW3DUqOpCld-#Kvj9F%lNyHDHzl{eBgxc@i zD3;z%-8uj9=S&kT4KpZN4!m8};niFPUugQLFHm<#J@j1USuRYyK||SIlqd);voR0a zvQH!-3ju)2>?q9Okl`ThL{#3-#NeIt!sgQ8U*Ph-qjNGbi{!VTYaZ^8A9_Wk2MRsS z=N?*pe&~;r{&;dx1Td5O|E)~r*t;&isKg9nvCqilb#jwB3dfcc-F@*viwu{?YW_+?jOBDo(_@dZLs{Y46F*V14f)uYrhKDps2D^jf#a3cSVZ-zdfBw_| zRdoLeNq_7+3z(k8in*t}DCV^(xb}s=-HZNzz&0Cmb&w-;NzVOz2@GEU7*BrXcnT4gl`%}!A9x$gCVVOMXE9nE3cJkX zIe~)tdS!zWaQ*LwX7#+m@?9I<l%*%RzG$cIW@HO=W#7pXJeYNF}Ji9T7&*n6|9G+HsDNf%oKUksak3{&I zsXBxtMTg3P@3KTO0lUgvWUFp*^7XAQ#VRcMbz#w*V+FQo4EQ6%mfkC|E?uW!-J6@4 z(KL&qBEOK32E64bbm|`$sGPjk_;|xqRs|r8PX78a)ItE+N+BtwS$eYc4+V)A@56~J zoS477y1&sv+Z0*Dkxl-${^LS!UiiP{Kb5xaB0OK}UslGLs`dv+G%@Bw-LMLK25ap^ z_4(CYzSQUV*%r}!oJsBKl&8P!NTcEM^4(F72xIY6Pnybv$GvLA(}vlSq^=Z2i~s{) zjx-vIiYYjm8JUhc$XGbgV|Fxq5?02;ga;0|Iu+m zY9FKM`gavqI@g`!+K45BM)#nK!|A14bjkM4H+5SBs+d1xDI@^FeA-QU|BOaB%Y-Fbb@fz{nDkqVPL3J#TiP&`^w-ITXNT;p<g0|$#_E+Zg4y)s7qIklF{ zPepR|5F}rIr~|o7bzEo5m#SPu6Bf4HHkRi_dCENYWR8E+qB2U)E0q4Unp8odQ&@;$ zBf}jHfr)^#|{QPA3)~|BquOVX0{U85Z z5DFE^0HH5jT^0_lbOrN+?4DoW)s2rtil`XdWlEM~4=wFuj{CGl^ z!oxK2WdPFbJ3$9@TopjnP-MfH5gK4z;zHGn8@)M#Kt4O1&7K9m!it6wrtooRgBe{uAc7f0ORd zc(^+KC}8k2Rb->2=XmmwkD$dQN=~=77A07X^P>GZ`U+F58R z<&#?55%+iwEIDwj^6{Ar7a7O;ojX=W;d=%>-dxXRtP8XkZHLtQ1vOz<9Mfgj5BDmh z4@TCM?}>#wYvPZGQ*XeSyz64mOSAD8MGJ%6(=Ew{ z#Bd7I&DqqP6b@l&)R+8PA-K(TIiiTc`0RQv(2=>CDZL6u-(4G-_xqM(qFe;okBviZ zYf&P_TQi$yF3xwxY>h`vC}3ell?>S)CysSr2;^Sz>fK90(jGwFmmHfTdt=^POWR1C z_*ZV$j~I<{5z<1bz9Rx2$L6%FJnhlQjZ|3g9AT&EjSe4P@Y15 zr3BJj!sLCZBdf6%mRT)SamlY#L=x>-S+r_L$r&7;mvk*tY3n{Q+#qFJ}}T?7g@g|<5+9juf2Hk5pR0o zFa45#yCRhg)#H{h>i3oOR1yS2WJuXyqg&2Vg~WBDnQwh+V;=F17sRDo@ZvW7pGlX$ zD#ez5@*{m;`SrPu8fuSVLk71_qa!gZzJc(bzm^2bC1i$2S76B1!{g^|NsDUuMs#dM zX(S@)6(3d_6U$!*p6zzj>Tpk{8-gOyBh~Naz!p_T)@sb$2QhcjA3uulDNvKT!Dws2 z1JS&5(&^t@o5&O8d!YlPGhhBp`=Y!?jmsl&mG^7LvvMO${?t*k!;QIb`|V5^q`7Wui*)>9Dvr>68aYW~F!z9}3^$BzKIbiO5$jtv~Q6%V0987nwj? z#WqPu6`u58{{Ywb&zdL}N3t7eVwN?x^9qIIE1}UF>0_%3q1IErCy}VE@92nNsj6y= z_g>G7JYv9u?}#j$ZNXo!*_7qVIvuki)$c{h;I))iKi^t!D9^g9R8-j|iA}8!nVhj% z%}1U4YxqZZ1t?3Z$mr;x!utOh(GF_NRP1X>$G{T`$ATq@s2I@DR~1XAv6>5K&^Q`{ z=Eht`8?MH1!ZH@UxJ%ed55Ch)AJ88!EF9!$zUEU=8e`4&!PZI*wjFD@$&e2==mr6R z3&F_+>zkQP)RB@H+YRmfgLFngB?I&7{V}=Nl5x}K`o4MwQz`q1jCGI83TS-u*&wqff7pCrFl9%(}dqXsdpYzW5mm-|qu{~BDp6}a$~35^VfWHMWIC4978 zN)%12ba&ZQbYfZ{Zp&$;?bQE21jBL9koX}HOVMXR zJreuEhF~wapMhB8N=L028tE_3t!#wRG<`;o&?q%v4W zi;G-J;wy!nUTae2WER7W>hlY50X=?;VM>>J?x!9%gR# zJJp}vv8K5T_3IiIHH|dQszi016nO*;+bFCe&QpahRF;I~_ZSKprT4Hx0u3re&ysvL zk}{Ok@Lebr9zn-K&&#J#(Uhj!mfaZSByXl)3EVQbF7DqhU^TaOX+;GcmCkp_DoDA< zcc`Q;H$6O9^9I~YBi?#AIi_A;LmtVIUt5x*Am_d`(L(kldV?dFNQXkIwMbNK`-aL? zhe=F)sa^Di)K*w8+@JsEP&Y98V>vy@I4Y_!bRp<3e%{0lRWO{L*J110yBnrlcz?N% zH+{lLU;jH@eg_)w{?zy3Sjw}wRY#%%z?G~gO~`!)90;}qG$>Oe(>nl+H3HZC$Wi2D zhKb#P{j+SQXQy^kj~nDS70=4Q{^=hP7aGpfi#_O2Zg5CN8=K+-@f73u88ABz@Nokd+}u$p ze(9-9&jiWngh?-H?uU>Pe_2;}3};qyG7vI?cu7C&FQ@SiQ!8<|vG1fAjKH0FZ?NbI zm6GkUQ~4U+W?NoGlIj(|`n3R*Q`1H>x1nSl4BEEu^hz%5LpOvB%%k_d_>jZst_6ck z_ZWW{uk|B_bM2+McsZg|8_0AoH6x-S#eLaL(Rzu7!qI#}>0-w%Y!X#(Gt*w>NuV7& zB)r}7Vqmv%E$3g`_Ol7bZw zIjgusMELdd-Ouu;1FS8&4cZit+bu|&7_yoY8h58eNT&VM|3lmrHMc~pIdP*I z{1DF*B#WgkgU)t1B>58mgX9V`}2g~$j2fW3ss7fCMO_OXE z9<`<|p8o#rJb3bI9LJiM6`|oa!3M|WmM<~AKgFUm`D$P%NjCpOu2Hwg_}947<17A) z9v}3oN^fT^JY?(llli|{L$9!cn<0ud(&(|G5_kzByX?kapWeD1xO4`dkY8)eEsc3S z=lpb5x}hHe+8z~x6tS zI#Ys_K&21j{3dOfk5cq>2X~yq6Q^Rfnyo!K&FQb!zv|xEJS}JiidA3Ly)FFSEv^{+ zY>-0iTvv}bA@~SA5k)7@`fCRy8s!aSJhfB8G%YV9HPM&vr{4++pWO=s(eBmKme({Z za(F7e76j zn*rQeI0iVQJHkab*EfTV*J??4!a;TOy0jAND!i;Z6-4jow%w%{Vu4gaYVBaJkTctG zb3#TuWv?PjC3+qmHn1eCP`nr0v5idar=T=v|0?rH=yA59Rldh@d^UmZ>lprP!O9a) zLji~*Ig9)_Au)_W3pz0UQHWALG*ylpAgukRFxNwal=9W@Aaps%lUWKz@faKyg&W?~ zHWZvIaq<=a%WedHd5Df!t_6NuLh}Fk&pd($1YY%G`I2qx(L?E683Zxcg;3d@h9o`F zH)Xo&XD(BlSB`Z<_JTOPy=1Y(hQf2%b| zSN;_uR1Om%t2||!_|1Xq@NvMGXr@vM7TMwY`3rhk*=pdgn*>s0xUbVV(Gw04?pUrj z2=6Cjpcu^TTLe9uayN$NFqvkaPf;IQmRuKZrf^Uc)JA~@4U_a*p+YMfM;0`K4uM8+ zXwkFsb7j>Cg87jgZ)q!K8u za0$H-D83_55M(9*RC(#)l8vMtohmV_&?!^s6IiROj-jw8aGk5H3f1_S>_3;mM?;U5Tf0i*to$aeWE*G z?Vo7w;0b793z@kY=bOxtFrzo{b1+x&y^4L$@uxc`U;gn+4Z7>o%8c*Nbn63!#LL3u z3tk@L$l*`}8IXGLOi%K`&ra)Wi)@0A(T>eG6^5T9Cz1qpP`$dB@P|zbql%0Wp66N% zvKXa%qd}wlMWv~4nlzgwku>pm%wEb=YSJ6t@5po=k^NN8Krtc(lVJxfHE%)KwyD}2 z?KB(Q?PLr5PYYw;n>d3FIm#tNqmmRFd0n zhvkOLx06Z*uV6$&^0Cd!0SO-n)Qv}zl|n=045))%`rI7i4|Zm&Yr(%MDeray#lv?M ztr>t++5`8e|M=g=h0@cB$EuNQs`Y)*bOiBY@(Q3!nui2KBDVD6Y0c(;78JNPTIFee z*^n(FzEeB7N0euIqaM*1S6=K6tZvvGER1Y>_K;Gc3ir1x2sc80b;N2<@He;990l7= zF`2y)z)OAn{M7$@-F4C~af|aotC8MnzAT=SK>|U*U^Zp#I22t<1?0<$ z?qMuBAYl>0FlVI}K8oBlyDeCpS}m(|qMTbz6dKp>n$h+1FIw{bLgJvEl{!Ns8LW}} z;4VjFV$IWOW@&vKosU~~=YydA0R6X5snfQEC@we{EFTGiO33%9=!q`>+lrafSn@$@ zyLD17lMJQqDnlXRi0!3H984C8{_4}%L+%c#X)9$%D76r z1nnmeOBrTO%`+$31|>GXfWVSkDKKNAMALqd!{PXl;&3LTG3;vvGO~sNy9pjiIb)fO zt-+BNxiwLEbCqh1`ozlBI2zHfqOH&ad#TBhb`9D<*T%(A)^_-<)H{~#$<|d`ARLlb?NTS_7gIFUm|^bc*w*P&+wITrR;$wSZB?w0 zGx5L67SF%!sX+h$bB?N*r~8%zq1WJESNNNygW`JTV*`Yrtw7}65u#^F+q=4qPv{ta zP@EUZJL2`OgJFC$rj5iXK3L;rO0w6&E~g(>D~icgkcMv=dNK`Z35oyqL~tS?RMF4C z1J{&_-euU@68>1Sf|RCALTSC__iEkC58KqFEWP6vNp53=dZm>a1n1@H5O? zOGv3{2qd+|tHyA0d!BD|f|*7c^WA-1kgKXx(;6w@MF;0R78M&&nQ)YDQB@SK_31^` z1?`3|^#+B>?+t$RY-?!!a=X?~>kz&>iAFt6k>FV;!XZqbMae?DsUxQ#CoE}3 zh#jO1eF&^OvyJDH-=VdC&}j-Fk+;yNmcqbP3%znRg` zUPY6Pbq~0;Tt4|YZqvZ=>${V~Z-)};g{W_NO!R!=_@oCs=HChF4fj#b)kO9w6B#Ph zsAaDv`qcqB6QXI_Ta@NDAqzYmDxZ&?uUNv{-M{|dp-}qU3 zQ|z@fSF>Y(pQ;pqb0wG1ma)&j_nbc_0H-R6w`#ein#BYp0t@5Tu=K1`QqoJex3sxn z=^-+8cmk*FNT{N2rz|(JKolYp3IiKEwo}5|J&K1jmp;JT4yNfiiP-;q_>tMdOhh`Y z4NBK^t~s(a63KaA9ah!~v8&0bzH&*qq7m$Lyp3T(p1R0T`Bh680S+tag-@C4jSK{r zFiuT2BuFn(+I6iwnSv{Q|0}{|&iiWuF^iZA*DC1RmtS74%|Bb8nF9B9iqg(P4TtFL zwguQbUs>1JMf7wg4TTIMXN|oJ6JhHR)$S+GpF`{#!YEajnPBi7$eWhxN4W> zDX8o{(k%?-oC{nBq;*&LO??*(u2GsRX>Sv&tgimy_fP+bI4KdWo)mfVZ6(Q(8~acT zTt1UODiHUm0}R?xN=jPl5v4U9yCb3o)o)*7h+Wy1KTA0k=sypJ2=_PF_tDe7@mz?< zrVHU?N#>IqPNr7Aq#`YGcdpf64FCPxd63!h?*$uE3{p*O`dMiX)Ro~ME>2aec-`{5B2q6ZK8pdRoYxG z)y**vG2lv$bD`n+%6 zDu0z?3E7`&*`K#_o2p2}@)-Vpm%Dgw>xg!57}26EiLU*GrV%BbWn@DsAM874^<>W` zD*aj&7AAQ+IGIsE0l8+mfd3q_13UbeAh_?fvbQm#lz+1$akG}Lfatxk%xw+`h0 zd;iNr+(5E%H>>;ysXL$)&9A}7pCdiJ6`D$QAFji-{HltJX~+?vwUUpPB+WX8SiyI*tNPoGEY0={Fh*8pZ6tLt6G`a(1$ zZJqZhajA*q&IFip;`{X^Q0qy<{`Y_Cf9XKfSjYx@nP%NYBzn4%<*BXi|0}PARw_V~ z2MHA4O_(?BDt+-dBuUQ|L7&RBssZlB%Ov4@&tYQhhZfpf2{thF=~8bejph+jXv!#4 zX>%lUJ3p%>R&P(gb+0s?U}($`CLuc_aZH!dJ@69okExXWCjGE=CM z(-90E!2ItE$C7&Xn}+5D&_Ln;^nVI~58#Le3CpYN!(SCRV)3GTQDI4RhnS0Fym;tl zLSu;Nlc_bYA}5H6i!bB;%o@_aQ{Rw%t;EB_YP3plB;R^O6``HMW2~621c^&t3CJXJ zA_}$O^Vm+IDgXg)4AspUhDC5yKT&axi;}#uAzfoli6l5WZ=ra;`hZ!Otkd>HeZKLn zrH54Iuc80r*>E1h#nZ&%RAuV6O#68MjZL_--+lQr?hT8b4)%X*iQpBzvW-mOXs`U6 z5a-$qe?G23w?W5017OO55jsz1a6wv^YA6o$5I7H6dJcuM6T3 z$;J1YE0lgz&~BR}U|SmsfEXdU;fI|t8nT->l^LXpxm|OBn-UG#S6v zlWm>u!+0nB6QT6?rX^~EdCbkn*QOG84sMC4Q~I&&Ao_{*&17ij@AE;nSXGvLMBexM zI@Yi@h%XY8I<8g(To2#vo!-q>LtS#Pn)@P^46C~!^2@ICN<TTq}C!_U#`lxFP_ZccG5=)^pRK z&$MS#e0kbNh8t}hHZCs9>0kNxhf%LyIxCA#J5>h#nmOmLLH1JT2Q?>33^16&kaS z5TP~}&9K>;@*PnX+Rq|Kue2#^ddrybBzwlSxkpvKU+Hy8iX_84P5Ej5`Iqy*?!RE> zge7Cmu&0PwW!W(Ww@@@_Y3on7DK_&Yi5AgkEPO-+_#AJ@#Q9wufB5*=vr%f6siENF z;2ci)ul^-{0S?86cVdAl2qc1E?c?GSVr{A)vcsIlBFU(by5hEUB-REU!csI{P?!@K zN!}XW6$1_TOt0ty>*txL`H2p|e`?Az-$qV8?vjn^-sAJjH`SOG|70IU@NDIY-s|d{ zOX;XRj_1E0UEmp4ujkWGes6frI5hT1^ZX?dx;(Tk^~ECzF!G_!zm7iEd21jXVk7d_2WK0B@wbv6Dvd; z!|!osj;>s;OO4VzEN^Zm6KGPnlyg3l+A0ea5Bz@3rXo*;y0iaiY0$+FvIk)A-ESM?NZTjbmD}kD~7l4AFDy21!iXGDuP+ z)t-wKU9U;|OqW08UJ!F|AWGIh5SbDsTXx8=C7OClC4B2ml*MB`kk<9mQ&Dl@mX7AP ziZ<6ua4V{PL!{+5_A36DdIbC(TPo$7BmcC{~Pq6%mZc<2NLK5lfY(r~O41+4MR% zFG9I6Bvf*-rcv`*pE7#@!I!Sj`4=&|7!rbdXyvdpvFpf`u5ab>tp76MC&JbO{)j*{ zj_x6>5W1K#k#Gv%p41lNSdW)AR-=lcF)EYc5`_g7Y%o>x(@^>^KoU}LP|l2~RxIXZ zSUBRZ{wKt9;fEX6|9c;(`hWTP$Nw&3?uNK2R+$`byfy4@slce37MEJf=n7m%TacJ! Og#N$$e*eEe`+ot3YnfR9 literal 0 HcmV?d00001 diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt index 194caf7287..94d7905f6a 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt @@ -9,11 +9,19 @@ package io.element.android.libraries.push.impl.notifications.channels import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.tests.testutils.lambda.lambdaError class FakeNotificationChannels( var channelForIncomingCall: (ring: Boolean) -> String = { _ -> "" }, var channelIdForMessage: (sessionId: SessionId, noisy: Boolean) -> String = { _, _ -> "" }, - var channelIdForTest: () -> String = { "" } + var channelIdForTest: () -> String = { "" }, + // Side-effecting recreates default to lambdaError (matching FakeNotificationSoundUpdater) so a + // test that doesn't expect a channel rebuild loudly fails instead of silently swallowing the call. + var recreateNoisyChannelLambda: (sound: NotificationSound, version: Int) -> Unit = { _, _ -> lambdaError() }, + var recreateRingingCallChannelLambda: (sound: NotificationSound, version: Int) -> Unit = { _, _ -> lambdaError() }, + var readNoisyChannelSoundLambda: () -> NotificationSound? = { null }, + var readRingingCallChannelSoundLambda: () -> NotificationSound? = { null }, ) : NotificationChannels { override fun getChannelForIncomingCall(ring: Boolean): String { return channelForIncomingCall(ring) @@ -26,4 +34,16 @@ class FakeNotificationChannels( override fun getChannelIdForTest(): String { return channelIdForTest() } + + override fun recreateNoisyChannel(sound: NotificationSound, version: Int) { + recreateNoisyChannelLambda(sound, version) + } + + override fun recreateRingingCallChannel(sound: NotificationSound, version: Int) { + recreateRingingCallChannelLambda(sound, version) + } + + override suspend fun readNoisyChannelSound(): NotificationSound? = readNoisyChannelSoundLambda() + + override suspend fun readRingingCallChannelSound(): NotificationSound? = readRingingCallChannelSoundLambda() } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt index b004c35537..c53e98bc93 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt @@ -9,16 +9,23 @@ package io.element.android.libraries.push.impl.notifications.channels import android.os.Build +import android.provider.Settings import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationManagerCompat +import androidx.core.net.toUri import com.google.common.truth.Truth.assertThat import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.mockk.every import io.mockk.mockk +import io.mockk.slot import io.mockk.verify +import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @@ -45,7 +52,7 @@ class NotificationChannelsTest { val notificationChannels = createNotificationChannels() val ringingChannel = notificationChannels.getChannelForIncomingCall(ring = true) - assertThat(ringingChannel).isEqualTo(RINGING_CALL_NOTIFICATION_CHANNEL_ID) + assertThat(ringingChannel).isEqualTo(RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE) val normalChannel = notificationChannels.getChannelForIncomingCall(ring = false) assertThat(normalChannel).isEqualTo(CALL_NOTIFICATION_CHANNEL_ID) @@ -59,7 +66,7 @@ class NotificationChannelsTest { ), ) assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = true)) - .isEqualTo(NOISY_NOTIFICATION_CHANNEL_ID) + .isEqualTo(NOISY_NOTIFICATION_CHANNEL_ID_BASE) assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = false)) .isEqualTo(SILENT_NOTIFICATION_CHANNEL_ID) } @@ -81,16 +88,418 @@ class NotificationChannelsTest { fun `getChannelIdForTest - returns the right channel`() { val notificationChannels = createNotificationChannels() - assertThat(notificationChannels.getChannelIdForTest()).isEqualTo(NOISY_NOTIFICATION_CHANNEL_ID) + assertThat(notificationChannels.getChannelIdForTest()).isEqualTo(NOISY_NOTIFICATION_CHANNEL_ID_BASE) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `init - reads persisted message version and seeds versioned channel id`() { + val notificationChannels = createNotificationChannels( + appPreferencesStore = InMemoryAppPreferencesStore(messageSoundChannelVersion = 3), + enterpriseService = FakeEnterpriseService(getNoisyNotificationChannelIdResult = { null }), + ) + assertThat(notificationChannels.getChannelIdForTest()).isEqualTo("${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v3") + assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = true)) + .isEqualTo("${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v3") + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `init - reads persisted call ringtone version and seeds versioned channel id`() { + val notificationChannels = createNotificationChannels( + appPreferencesStore = InMemoryAppPreferencesStore(callRingtoneChannelVersion = 2), + ) + assertThat(notificationChannels.getChannelForIncomingCall(ring = true)) + .isEqualTo("${RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE}_v2") + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateNoisyChannel - creates new versioned channel and updates current id`() { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.Custom("content://media/internal/audio/media/42"), version = 7) + + val expectedId = "${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v7" + assertThat(channels.getChannelIdForTest()).isEqualTo(expectedId) + verify { notificationManager.createNotificationChannel(match { it.id == expectedId }) } + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateNoisyChannel - Silent produces channel with no sound`() { + val captured = slot() + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { createNotificationChannel(capture(captured)) } returns Unit + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.Silent, version = 1) + + // The last captured channel (the recreated one) should have a null sound and the new id. + assertThat(captured.captured.id).isEqualTo("${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v1") + assertThat(captured.captured.sound).isNull() + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateNoisyChannel - SystemDefault uses Android system notification URI`() { + val captured = slot() + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { createNotificationChannel(capture(captured)) } returns Unit + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.SystemDefault, version = 2) + + assertThat(captured.captured.sound).isEqualTo(Settings.System.DEFAULT_NOTIFICATION_URI) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateNoisyChannel - ElementDefault uses bundled message URI`() { + val captured = slot() + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { createNotificationChannel(capture(captured)) } returns Unit + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.ElementDefault, version = 1) + + assertThat(captured.captured.sound?.scheme).isEqualTo("android.resource") + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateNoisyChannel - ElementFade uses bundled fade URI`() { + val captured = slot() + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { createNotificationChannel(capture(captured)) } returns Unit + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.ElementFade, version = 1) + + val context = RuntimeEnvironment.getApplication() + val expected = "android.resource://${context.packageName}/${io.element.android.libraries.push.impl.R.raw.element_fade}".toUri() + assertThat(captured.captured.sound).isEqualTo(expected) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateNoisyChannel - deletes prior versioned channels`() { + val priorChannel = mockk(relaxed = true) { + every { id } returns "${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v3" + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns listOf(priorChannel) + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.SystemDefault, version = 4) + + verify { notificationManager.deleteNotificationChannel("${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v3") } + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateRingingCallChannel - creates new versioned channel and updates current id`() { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateRingingCallChannel(sound = NotificationSound.Custom("content://settings/system/ringtone"), version = 5) + + val expectedId = "${RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE}_v5" + assertThat(channels.getChannelForIncomingCall(ring = true)).isEqualTo(expectedId) + verify { notificationManager.createNotificationChannel(match { it.id == expectedId }) } + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreateRingingCallChannel - Silent produces channel with no sound`() { + val captured = slot() + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { createNotificationChannel(capture(captured)) } returns Unit + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateRingingCallChannel(sound = NotificationSound.Silent, version = 1) + + assertThat(captured.captured.id).isEqualTo("${RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE}_v1") + assertThat(captured.captured.sound).isNull() + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `recreate noisy then ringing produces both versioned channels with current ids`() { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + channels.recreateNoisyChannel(sound = NotificationSound.Custom("content://a"), version = 5) + channels.recreateRingingCallChannel(sound = NotificationSound.Custom("content://b"), version = 7) + + // Each recreate updates the corresponding currentId independently — the lock guarding + // recreate* against itself does not interfere across the two channel families. + assertThat(channels.getChannelIdForTest()).isEqualTo("${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v5") + assertThat(channels.getChannelForIncomingCall(ring = true)).isEqualTo("${RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE}_v7") + verify { notificationManager.createNotificationChannel(match { it.id == "${NOISY_NOTIFICATION_CHANNEL_ID_BASE}_v5" }) } + verify { + notificationManager.createNotificationChannel( + match { it.id == "${RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE}_v7" } + ) + } + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readNoisyChannelSound - returns Custom for non-default URI`() = runTest { + val customUri = "content://media/internal/audio/media/42".toUri() + val channel = mockk(relaxed = true) { + every { sound } returns customUri + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(NOISY_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readNoisyChannelSound() + + assertThat(result).isEqualTo(NotificationSound.Custom(customUri.toString())) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readNoisyChannelSound - classifies the bundled message URI as ElementDefault`() = runTest { + val context = RuntimeEnvironment.getApplication() + val ourBundled = "android.resource://${context.packageName}/${io.element.android.libraries.push.impl.R.raw.message}".toUri() + val channel = mockk(relaxed = true) { + every { sound } returns ourBundled + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(NOISY_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readNoisyChannelSound() + + assertThat(result).isEqualTo(NotificationSound.ElementDefault) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readNoisyChannelSound - classifies the bundled fade URI as ElementFade`() = runTest { + val context = RuntimeEnvironment.getApplication() + val ourFade = "android.resource://${context.packageName}/${io.element.android.libraries.push.impl.R.raw.element_fade}".toUri() + val channel = mockk(relaxed = true) { + every { sound } returns ourFade + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(NOISY_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readNoisyChannelSound() + + assertThat(result).isEqualTo(NotificationSound.ElementFade) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readNoisyChannelSound - classifies DEFAULT_NOTIFICATION_URI as SystemDefault`() = runTest { + val channel = mockk(relaxed = true) { + every { sound } returns Settings.System.DEFAULT_NOTIFICATION_URI + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(NOISY_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readNoisyChannelSound() + + assertThat(result).isEqualTo(NotificationSound.SystemDefault) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `init - migrates legacy SystemDefault message sound to ElementDefault when version is 0`() = runTest { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.SystemDefault, + messageSoundChannelVersion = 0, + ) + + createNotificationChannels( + notificationManager = notificationManager, + appPreferencesStore = appPreferencesStore, + ) + + val config = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(config.messageSound).isEqualTo(NotificationSound.ElementDefault) + assertThat(config.messageSoundVersion).isEqualTo(1) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `init - migration is idempotent across multiple instantiations`() = runTest { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.SystemDefault, + messageSoundChannelVersion = 0, + ) + + // First boot: migrate. + createNotificationChannels(notificationManager = notificationManager, appPreferencesStore = appPreferencesStore) + val afterFirst = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(afterFirst.messageSound).isEqualTo(NotificationSound.ElementDefault) + assertThat(afterFirst.messageSoundVersion).isEqualTo(1) + + // Second boot: gate (version == 0) no longer matches, so the version must not bump again. + createNotificationChannels(notificationManager = notificationManager, appPreferencesStore = appPreferencesStore) + val afterSecond = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(afterSecond.messageSound).isEqualTo(NotificationSound.ElementDefault) + assertThat(afterSecond.messageSoundVersion).isEqualTo(1) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `init - does not re-migrate when message version is non-zero`() = runTest { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.SystemDefault, + messageSoundChannelVersion = 5, + ) + + createNotificationChannels( + notificationManager = notificationManager, + appPreferencesStore = appPreferencesStore, + ) + + val config = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(config.messageSound).isEqualTo(NotificationSound.SystemDefault) + assertThat(config.messageSoundVersion).isEqualTo(5) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `init - does not migrate when persisted message sound is not SystemDefault`() = runTest { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + } + val appPreferencesStore = InMemoryAppPreferencesStore( + messageSound = NotificationSound.Silent, + messageSoundChannelVersion = 0, + ) + + createNotificationChannels( + notificationManager = notificationManager, + appPreferencesStore = appPreferencesStore, + ) + + val config = appPreferencesStore.getNotificationSoundChannelConfig() + assertThat(config.messageSound).isEqualTo(NotificationSound.Silent) + assertThat(config.messageSoundVersion).isEqualTo(0) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readNoisyChannelSound - returns Silent when channel sound is null`() = runTest { + val channel = mockk(relaxed = true) { + every { sound } returns null + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(NOISY_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readNoisyChannelSound() + + assertThat(result).isEqualTo(NotificationSound.Silent) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readNoisyChannelSound - returns null when channel does not exist`() = runTest { + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(NOISY_NOTIFICATION_CHANNEL_ID_BASE) } returns null + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readNoisyChannelSound() + + assertThat(result).isNull() + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readRingingCallChannelSound - returns SystemDefault when channel sound matches DEFAULT_RINGTONE_URI`() = runTest { + val channel = mockk(relaxed = true) { + every { sound } returns Settings.System.DEFAULT_RINGTONE_URI + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readRingingCallChannelSound() + + assertThat(result).isEqualTo(NotificationSound.SystemDefault) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) + fun `readRingingCallChannelSound - returns Custom for non-default URI`() = runTest { + val customUri = "content://media/external/audio/media/9001".toUri() + val channel = mockk(relaxed = true) { + every { sound } returns customUri + } + val notificationManager = mockk(relaxed = true) { + every { notificationChannels } returns emptyList() + every { getNotificationChannel(RINGING_CALL_NOTIFICATION_CHANNEL_ID_BASE) } returns channel + } + val channels = createNotificationChannels(notificationManager = notificationManager) + + val result = channels.readRingingCallChannelSound() + + assertThat(result).isEqualTo(NotificationSound.Custom(customUri.toString())) } private fun createNotificationChannels( notificationManager: NotificationManagerCompat = mockk(relaxed = true), enterpriseService: EnterpriseService = FakeEnterpriseService(), + // Default to ElementDefault so the legacy `(SystemDefault, version=0)` migration gate + // doesn't fire and silently rewrite the prefs store. Tests that exercise the migration + // construct their own store explicitly. + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(messageSound = NotificationSound.ElementDefault), ) = DefaultNotificationChannels( notificationManager = notificationManager, stringProvider = FakeStringProvider(), context = RuntimeEnvironment.getApplication(), enterpriseService = enterpriseService, + appPreferencesStore = appPreferencesStore, ) } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt index c58a29d866..53bea9e766 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt @@ -373,10 +373,12 @@ fun createNotificationChannels( enterpriseService: EnterpriseService = FakeEnterpriseService(), ): NotificationChannels { val context = RuntimeEnvironment.getApplication() + val notificationManagerCompat = NotificationManagerCompat.from(context) return DefaultNotificationChannels( - notificationManager = NotificationManagerCompat.from(context), + notificationManager = notificationManagerCompat, stringProvider = FakeStringProvider(""), context = context, enterpriseService = enterpriseService, + appPreferencesStore = io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore(), ) } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopierTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopierTest.kt new file mode 100644 index 0000000000..b8d652bafe --- /dev/null +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/sound/DefaultNotificationSoundCopierTest.kt @@ -0,0 +1,82 @@ +/* + * 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.notifications.sound + +import android.content.Context +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +@RunWith(RobolectricTestRunner::class) +class DefaultNotificationSoundCopierTest { + private val context: Context get() = RuntimeEnvironment.getApplication() + + @Test + fun `sanitizeDisplayName - trims surrounding whitespace`() { + assertThat(sanitizeDisplayName(" Hello World ")).isEqualTo("Hello World") + } + + @Test + fun `sanitizeDisplayName - DEL and control characters are dropped`() { + // Build the raw string programmatically — embedding control chars as source-file bytes + // doesn't survive editor / tool round-tripping reliably. + val bel = 0x07.toChar() + val tab = 0x09.toChar() + val newline = 0x0A.toChar() + val del = 0x7F.toChar() + val raw = "${bel}Hello$tab${newline}World$del" + assertThat(sanitizeDisplayName(raw)).isEqualTo("HelloWorld") + } + + @Test + fun `sanitizeDisplayName - truncates oversized input to 256 chars`() { + val long = "x".repeat(500) + val sanitized = sanitizeDisplayName(long) + assertThat(sanitized).isNotNull() + assertThat(sanitized!!.length).isEqualTo(256) + } + + @Test + fun `sanitizeDisplayName - returns null when nothing survives sanitization`() { + assertThat(sanitizeDisplayName("")).isNull() + assertThat(sanitizeDisplayName(" ")).isNull() + val controls = (0..0x1F).joinToString(separator = "") { it.toChar().toString() } + 0x7F.toChar() + assertThat(sanitizeDisplayName(controls)).isNull() + } + + @Test + fun `sanitizeDisplayName - preserves unicode beyond ASCII`() { + val input = "Element Tone " + 0x266A.toChar() + assertThat(sanitizeDisplayName(input)).isEqualTo(input) + } + + @Test + fun `copyToAppFiles - rejects file scheme`() = runTest { + val copier = DefaultNotificationSoundCopier(context) + val result = copier.copyToAppFiles("file:///tmp/evil.mp3", NotificationSoundCopier.SoundSlot.Message) + assertThat(result).isEqualTo(NotificationSoundCopier.CopyResult.UnplayableSource) + } + + @Test + fun `copyToAppFiles - rejects http scheme`() = runTest { + val copier = DefaultNotificationSoundCopier(context) + val result = copier.copyToAppFiles("https://attacker.example.com/sound.mp3", NotificationSoundCopier.SoundSlot.Call) + assertThat(result).isEqualTo(NotificationSoundCopier.CopyResult.UnplayableSource) + } + + @Test + fun `copyToAppFiles - rejects URI without a scheme`() = runTest { + val copier = DefaultNotificationSoundCopier(context) + val result = copier.copyToAppFiles("not-a-real-uri", NotificationSoundCopier.SoundSlot.Message) + assertThat(result).isEqualTo(NotificationSoundCopier.CopyResult.UnplayableSource) + } +} diff --git a/libraries/push/test/build.gradle.kts b/libraries/push/test/build.gradle.kts index 9dedeb3996..d125a2387e 100644 --- a/libraries/push/test/build.gradle.kts +++ b/libraries/push/test/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { api(projects.libraries.pushproviders.api) implementation(projects.libraries.designsystem) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.preferences.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.workmanager.api) implementation(projects.tests.testutils) diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationSoundUpdater.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationSoundUpdater.kt new file mode 100644 index 0000000000..1bbd410aec --- /dev/null +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationSoundUpdater.kt @@ -0,0 +1,31 @@ +/* + * 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.notifications + +import io.element.android.libraries.preferences.api.store.NotificationSound +import io.element.android.libraries.push.api.notifications.NotificationSoundUpdater +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeNotificationSoundUpdater( + private val recreateNoisyChannelLambda: (sound: NotificationSound, version: Int) -> Unit = { _, _ -> lambdaError() }, + private val recreateRingingCallChannelLambda: (sound: NotificationSound, version: Int) -> Unit = { _, _ -> lambdaError() }, + private val readNoisyChannelSoundLambda: () -> NotificationSound? = { null }, + private val readRingingCallChannelSoundLambda: () -> NotificationSound? = { null }, +) : NotificationSoundUpdater { + override fun recreateNoisyChannel(sound: NotificationSound, version: Int) { + recreateNoisyChannelLambda(sound, version) + } + + override fun recreateRingingCallChannel(sound: NotificationSound, version: Int) { + recreateRingingCallChannelLambda(sound, version) + } + + override suspend fun readNoisyChannelSound(): NotificationSound? = readNoisyChannelSoundLambda() + + override suspend fun readRingingCallChannelSound(): NotificationSound? = readRingingCallChannelSoundLambda() +} diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeSoundDisplayNameResolver.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeSoundDisplayNameResolver.kt new file mode 100644 index 0000000000..69bb77b65c --- /dev/null +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeSoundDisplayNameResolver.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.push.test.notifications + +import io.element.android.libraries.push.api.notifications.SoundDisplayNameResolver + +class FakeSoundDisplayNameResolver( + // Default resolves to a non-null sentinel so a default-constructed fake doesn't masquerade + // as "every Custom URI is unresolvable" — that would trip mid-session detection paths in + // every test that uses default fakes. Tests that need the unavailable case pass `{ null }`. + private val resolveLambda: suspend (uri: String) -> String? = { "FakeRingtoneTitle" }, +) : SoundDisplayNameResolver { + override suspend fun resolveCustomSoundTitle(uri: String): String? = resolveLambda(uri) +} diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/sound/FakeNotificationSoundCopier.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/sound/FakeNotificationSoundCopier.kt new file mode 100644 index 0000000000..9fe88b7718 --- /dev/null +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/sound/FakeNotificationSoundCopier.kt @@ -0,0 +1,24 @@ +/* + * 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.notifications.sound + +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.CopyResult +import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.SoundSlot +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeNotificationSoundCopier( + private val copyLambda: (String, SoundSlot) -> CopyResult = { _, _ -> lambdaError() }, + private val deleteStoredSoundForLambda: (SoundSlot) -> Unit = {}, +) : NotificationSoundCopier { + override suspend fun copyToAppFiles(sourceUriString: String, slot: SoundSlot): CopyResult = copyLambda(sourceUriString, slot) + + override suspend fun deleteStoredSoundFor(slot: SoundSlot) { + deleteStoredSoundForLambda(slot) + } +} 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 449fd0f352..88d8d712b0 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -480,10 +480,6 @@ Haluatko varmasti jatkaa?" "Vaihtoehdot" "Poista %1$s" "Asetukset" - - "%1$d aste" - "%1$d astetta" - "Kukaan ei jaa sijaintiaan" "Jaetaan reaaliaikaista sijaintia" 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 212b5eb79a..7d178cc105 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -480,10 +480,6 @@ Raison : %1$s." "Options" "Supprimer %1$s" "Paramètres" - - "%1$d degré" - "%1$d degrés" - "Personne ne partage sa position" "Partage de la position en direct" 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 c32cbca475..ab5f64fc9e 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -471,11 +471,6 @@ "選択肢" "%1$s を削除" "設定" - "画像を左に回転" - - "%1$d°" - - "写真を編集" "誰も位置情報を共有していません" "ライブ位置情報を共有しています" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index da3a5c2fea..7e0b78641e 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -489,13 +489,6 @@ Czy na pewno chcesz kontynuować?" "Opcje" "Usuń %1$s" "Ustawienia" - "Obróć obraz w lewo" - - "%1$d stopień" - "%1$d stopnie" - "%1$d stopni" - - "Edytuj zdjęcie" "Nikt nie udostępnia swojej lokalizacji" "Udostępnianie lokalizacji na żywo" 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 1b50794182..e40d369f76 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -469,11 +469,6 @@ "选项" "移除 %1$s" "设置" - "向左旋转图像" - - "%1$d 度" - - "编辑照片" "目前无人分享其位置" "共享实时位置" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 0b9490ae59..d74f532484 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -481,12 +481,6 @@ Are you sure you want to continue?" "Options" "Remove %1$s" "Settings" - "Rotate the image to the left" - - "%1$d degree" - "%1$d degrees" - - "Edit photo" "Nobody is sharing their location" "Sharing live location" diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_0_en.png index d927ea14b0..7b985075fa 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01999b61120bb58f8cfa56a2f5b1b5573d2755fc5be85d3929237d6a61244ab0 -size 54308 +oid sha256:2dd82d156d36a7c7141fd5a4eafdbcbfe9aacc7a8dcede267fdfde272519bee6 +size 52088 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_14_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_14_en.png new file mode 100644 index 0000000000..29adf28369 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_14_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72acb2485a98126e53c27459d63fe7d3718ebc94215a597207ff820d4c9e45a7 +size 43439 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_15_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_15_en.png new file mode 100644 index 0000000000..b79295b20d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_15_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8b4f5fe2d2aa5459aac05180882b3aaa9fc9777f84f4c817c9e995049485946 +size 42052 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_16_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_16_en.png new file mode 100644 index 0000000000..f85174c9c8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_16_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba8f5f9d0ce23de5e6d57660887478b04851680d13a9f8f70d1488c557a25afc +size 43261 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_17_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_17_en.png new file mode 100644 index 0000000000..e4c7c476f5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_17_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3dc8f7d0497632c723311c530d37807261686ed9fe4d7ff926c0a0fbf825cf23 +size 43179 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_18_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_18_en.png new file mode 100644 index 0000000000..e34ca68b36 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_18_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2cc1821e0f114837943f9b9ff76f43a1bf871cc49a4eff704e8c87b50cc384ba +size 44736 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_19_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_19_en.png new file mode 100644 index 0000000000..e9127c1ccd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_19_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbf8bd63967dc3e0739ea2cc62c42fbcbe7d0a9cdf50b41f24c1ccab1f300eab +size 39442 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_1_en.png index 4302a4c031..e4c7c476f5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52f7675544ba71ed73d2f4283287f46eaa0798d48993d7eb54fc28f87c89cf0e -size 43466 +oid sha256:3dc8f7d0497632c723311c530d37807261686ed9fe4d7ff926c0a0fbf825cf23 +size 43179 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_20_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_20_en.png new file mode 100644 index 0000000000..4c2b80b959 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_20_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0c31e3d7a0788e91287da4ed4f0b6e5e1ade8ce542392f4ba6029d524372c32 +size 41551 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_2_en.png index edcd62c95f..a35714aff4 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50cca191bf1c21a4d0f2765643712d0db6813dc23f2c4b70589ad65f2847b259 -size 40215 +oid sha256:176519a45ab97560dc2f8bf1416915759039616458f5fde22def7022595b4cc9 +size 39890 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_3_en.png index caf2a0b795..ce4c8a5f2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c13b82c858490228a4f5568b7489115d916af067a8cf2e01e22e44f56cd6c3e -size 39566 +oid sha256:7efafe0931f350b3369a73fc4cb4156f641d894db5e939202ab9fec5cec8423b +size 39229 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_4_en.png index caf2a0b795..ce4c8a5f2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c13b82c858490228a4f5568b7489115d916af067a8cf2e01e22e44f56cd6c3e -size 39566 +oid sha256:7efafe0931f350b3369a73fc4cb4156f641d894db5e939202ab9fec5cec8423b +size 39229 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_5_en.png index 4302a4c031..e4c7c476f5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52f7675544ba71ed73d2f4283287f46eaa0798d48993d7eb54fc28f87c89cf0e -size 43466 +oid sha256:3dc8f7d0497632c723311c530d37807261686ed9fe4d7ff926c0a0fbf825cf23 +size 43179 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png index 5b314cc55a..6ce1addb3a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38839f3e1cc1ed7fd02695e1ad68e44692fc836ee3fad075ada9d500a94b2554 -size 39554 +oid sha256:73cf2629ea291b423460d8756814e97b2e8720a064aaf7fc9f3f3a7cf9a34862 +size 39186 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png index b292bd42f5..e368d72b51 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fc4c290503b6ae3157cf4169b50a8e00bae953d87b2d319389e8ab3decb9ca3 -size 43856 +oid sha256:efb91f3ae38c55d585d86d1c83f8c52e7244b62b64c82f51ad145ac3ec9841a7 +size 43493 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_8_en.png index 4302a4c031..e4c7c476f5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52f7675544ba71ed73d2f4283287f46eaa0798d48993d7eb54fc28f87c89cf0e -size 43466 +oid sha256:3dc8f7d0497632c723311c530d37807261686ed9fe4d7ff926c0a0fbf825cf23 +size 43179 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_9_en.png index 4302a4c031..e4c7c476f5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52f7675544ba71ed73d2f4283287f46eaa0798d48993d7eb54fc28f87c89cf0e -size 43466 +oid sha256:3dc8f7d0497632c723311c530d37807261686ed9fe4d7ff926c0a0fbf825cf23 +size 43179 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_0_en.png index 5c281630e3..1859be12da 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8a677a3dbb1cf6cbb306d3b1e4ba612469cba408815320361365d74e188cf74 -size 52703 +oid sha256:5d921332fe1eb11a80750ed8934f3d386fa267e180bbd29960a750181bddcb49 +size 50570 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_14_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_14_en.png new file mode 100644 index 0000000000..f300562d3c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_14_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a189eca358d0bf0c2ed4f107252b667d996e560822ea8e39cf776511ebb0fde4 +size 41989 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_15_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_15_en.png new file mode 100644 index 0000000000..28dad18993 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_15_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:019e7a646c19f2056873f186e8c7ee73127e79468e5149034e85455460b689be +size 40637 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_16_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_16_en.png new file mode 100644 index 0000000000..16bbe20275 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_16_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a9585f68e045397a46c8f368e4affa1e9fde985bf415014403b91e73de6eb9e +size 41713 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_17_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_17_en.png new file mode 100644 index 0000000000..d6ac948791 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_17_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca8ace95c2cb039826be9e39da427eebada1a8f6f234d6ae82c9e2a69f9a2c8e +size 41760 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_18_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_18_en.png new file mode 100644 index 0000000000..0e5833c48b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_18_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43d661bd16a8343e1750faeed957fe5490cee65d0bcc033ecef6344c7ee85fba +size 42104 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_19_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_19_en.png new file mode 100644 index 0000000000..f169d5f9d8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_19_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cacac247776f92bf1aeaed8b0b11a2283d27e51c6999f4fcd08b62b8aae4c3d7 +size 36997 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_1_en.png index 05b8276ace..d6ac948791 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d92a5ffd43eac457c3384cfc22b9b29fbf8c21532fc16892258140c557788bd2 -size 41872 +oid sha256:ca8ace95c2cb039826be9e39da427eebada1a8f6f234d6ae82c9e2a69f9a2c8e +size 41760 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_20_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_20_en.png new file mode 100644 index 0000000000..03061e5717 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_20_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6685d37388f89b1a6f18a66deb1a7a35f23a88c2bd64e3d4b980f71cd9cc5aa +size 39185 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_2_en.png index 56334c1e2e..d1678d364f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd1599665f32844b4757a631542351303b7d4f4a34f32640ee9f60ad38089cab -size 38707 +oid sha256:50d4e41bfed974afdcdb1864f95e9b5ea26675f67c16cd17d82c431547be4b5b +size 38565 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_3_en.png index c7e3274c19..a6c678cb89 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea8532bc891ce639c492ed7d6edaaadefc2b99dd3b68873a575858b03b6fcbfe -size 36998 +oid sha256:6c31c52efbf995bcc237a309772be0c70221db7d30dec38c734bf01f75bb1a97 +size 36856 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_4_en.png index c7e3274c19..a6c678cb89 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea8532bc891ce639c492ed7d6edaaadefc2b99dd3b68873a575858b03b6fcbfe -size 36998 +oid sha256:6c31c52efbf995bcc237a309772be0c70221db7d30dec38c734bf01f75bb1a97 +size 36856 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_5_en.png index 05b8276ace..d6ac948791 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d92a5ffd43eac457c3384cfc22b9b29fbf8c21532fc16892258140c557788bd2 -size 41872 +oid sha256:ca8ace95c2cb039826be9e39da427eebada1a8f6f234d6ae82c9e2a69f9a2c8e +size 41760 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png index 1f3b3e2b91..aa887109d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68d4a4cd27afda0d23438451124ef997dadd116e1ea5db4b5a6af0045d95ba2b -size 36998 +oid sha256:64b969354abd79e131dc6bf644f48e2218216fd4a6b8e93527f52defc8b2cb38 +size 36836 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png index bbc69da0c3..4e38e5b2bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:784b744139daa4216d4137aaaca3a4f1a86ef7297ce2996bb9e9eb78c8aa93fb -size 41201 +oid sha256:b07d98cdb41d4daf9bec18285588ad5bf99992a52ef27f2da66545734b8db843 +size 41036 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_8_en.png index 05b8276ace..d6ac948791 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d92a5ffd43eac457c3384cfc22b9b29fbf8c21532fc16892258140c557788bd2 -size 41872 +oid sha256:ca8ace95c2cb039826be9e39da427eebada1a8f6f234d6ae82c9e2a69f9a2c8e +size 41760 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_9_en.png index 05b8276ace..d6ac948791 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d92a5ffd43eac457c3384cfc22b9b29fbf8c21532fc16892258140c557788bd2 -size 41872 +oid sha256:ca8ace95c2cb039826be9e39da427eebada1a8f6f234d6ae82c9e2a69f9a2c8e +size 41760 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 9936341cee..64976003d5 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -330,6 +330,7 @@ "screen\\.advanced_settings\\..*", "screen_edit_profile_.*", "screen_notification_settings_.*", + "screen\\.notification_settings\\..*", "screen_blocked_users_.*", "full_screen_intent_banner_.*", "troubleshoot_notifications_entry_point_.*", From e1aab57b964865b115524187d2dad2e4bdda49eb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 May 2026 15:07:36 +0000 Subject: [PATCH 0535/1083] Update tspascoal/get-user-teams-membership action to v4.0.2 --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f0c8fd1e6f..e24847280e 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Check membership if: github.event.pull_request.user.login != 'renovate[bot]' - uses: tspascoal/get-user-teams-membership@818140d631d5f29f26b151afbe4179f87d9ceb5e # v4.0.1 + uses: tspascoal/get-user-teams-membership@b2546c5affc730fd8e3d8483ae9ad3621938c2f9 # v4.0.2 id: teams with: username: ${{ github.event.pull_request.user.login }} From 6fd602a08fbbd9c269fde0e53ab9d9ff7e47a4eb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 May 2026 15:07:59 +0000 Subject: [PATCH 0536/1083] Update actions/stale action to v10.3.0 --- .github/workflows/stale-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml index 1958e80083..622fecc403 100644 --- a/.github/workflows/stale-issues.yml +++ b/.github/workflows/stale-issues.yml @@ -12,7 +12,7 @@ jobs: permissions: issues: write steps: - - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 + - uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0 with: only-labels: "X-Needs-Info" days-before-issue-stale: 30 From 40f8b48256beec447d66d836c68c27beb7d71c3e Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Thu, 28 May 2026 09:06:01 -0700 Subject: [PATCH 0537/1083] Reuse UnreadAtom composable --- .../messages/impl/timeline/TimelineView.kt | 31 +++++++------------ .../atomic/atoms/UnreadIndicatorAtom.kt | 4 +++ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index cca3c1f96c..aaf06bfd87 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -16,6 +16,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -87,6 +88,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState import io.element.android.libraries.androidutils.system.copyToClipboard +import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom import io.element.android.libraries.designsystem.components.dialogs.AlertDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -561,30 +563,19 @@ private fun JumpToPositionButton( } } val dotYOffset = if (dotAlignment == Alignment.BottomCenter) 4.dp else (-4).dp - TimelineUnreadIndicator( - isVisible = hasUnread, - modifier = Modifier - .align(dotAlignment) - .offset { IntOffset(x = 0, y = dotYOffset.roundToPx()) }, - ) + if (hasUnread) { + UnreadIndicatorAtom( + modifier = Modifier + .align(dotAlignment) + .offset { IntOffset(x = 0, y = dotYOffset.roundToPx()) }, + color = ElementTheme.colors.iconSuccessPrimary, + border = BorderStroke(2.dp, ElementTheme.colors.bgCanvasDefault), + ) + } } } } -@Composable -private fun TimelineUnreadIndicator( - isVisible: Boolean, - modifier: Modifier = Modifier, -) { - if (!isVisible) return - Box( - modifier = modifier - .size(12.dp) - .background(color = ElementTheme.colors.iconSuccessPrimary, shape = CircleShape) - .border(width = 2.dp, color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape), - ) -} - @PreviewsDayNight @Composable internal fun TimelineViewPreview( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt index d2db3aec8e..f162677e49 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt @@ -8,7 +8,9 @@ package io.element.android.libraries.designsystem.atomic.atoms +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape @@ -32,6 +34,7 @@ fun UnreadIndicatorAtom( color: Color = ElementTheme.colors.unreadIndicator, isVisible: Boolean = true, contentDescription: String? = null, + border: BorderStroke? = null, ) { Box( modifier = modifier @@ -41,6 +44,7 @@ fun UnreadIndicatorAtom( .size(size) .clip(CircleShape) .background(if (isVisible) color else Color.Transparent) + .then(if (border != null) Modifier.border(border, CircleShape) else Modifier) ) } From 2c2d803e5828ef3f3e116296acc560d439a8300c Mon Sep 17 00:00:00 2001 From: Jenna Vassar <5023996+jennaharris7@users.noreply.github.com> Date: Thu, 28 May 2026 09:06:31 -0700 Subject: [PATCH 0538/1083] Update a11y string --- libraries/ui-strings/src/main/res/values/temporary.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index 29dadb0418..fd1edb0759 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -7,5 +7,5 @@ "Mark as read" - "Jump to unread messages" + "Jump to first unread message" From 510588b93eac98658f757b2ab1020abdd5638f26 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 28 May 2026 18:19:48 +0200 Subject: [PATCH 0539/1083] Use simple custom LocationTrackingEffect waiting for a fix from maplibre --- .../common/ui/SimpleLocationTrackingEffect.kt | 52 +++++++++++++++++++ .../impl/common/ui/UserLocationPuck.kt | 37 +++++-------- .../location/impl/show/ShowLocationView.kt | 4 +- 3 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt new file mode 100644 index 0000000000..7a7a1551cf --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common.ui + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.snapshotFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import org.maplibre.compose.location.Location +import org.maplibre.compose.location.UserLocationState +import kotlin.math.abs + +/** + * Drop-in replacement for the library's LocationTrackingEffect. + * TODO remove once https://github.com/maplibre/maplibre-compose/issues/808 is fixed + */ +@Composable +internal fun SimpleLocationTrackingEffect( + locationState: UserLocationState, + enabled: Boolean = true, + precision: Double = 0.00001, + onLocationChange: suspend (Location?) -> Unit, +) { + val latestOnLocationChange by rememberUpdatedState(onLocationChange) + + LaunchedEffect(locationState, enabled) { + if (!enabled) return@LaunchedEffect + val locationStateFlow = snapshotFlow { locationState.location } + locationStateFlow + .distinctUntilChanged { oldLocation, newLocation -> + if (oldLocation != null && newLocation != null) { + when { + abs(oldLocation.position.value.latitude - newLocation.position.value.latitude) >= precision -> false + abs(oldLocation.position.value.longitude - newLocation.position.value.longitude) >= precision -> false + else -> true + } + } else { + false + } + } + .collect { location -> + latestOnLocationChange(location) + } + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt index 6f47903c9c..7bad736911 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt @@ -13,19 +13,15 @@ import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.impl.common.MapDefaults -import kotlinx.coroutines.flow.SharingStarted import org.maplibre.compose.camera.CameraState import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationPuckColors import org.maplibre.compose.location.LocationPuckSizes -import org.maplibre.compose.location.LocationTrackingEffect import org.maplibre.compose.location.UserLocationState import org.maplibre.compose.location.rememberAndroidLocationProvider import org.maplibre.compose.location.rememberNullLocationProvider import org.maplibre.compose.location.rememberUserLocationState -import org.maplibre.spatialk.units.Bearing -import org.maplibre.spatialk.units.extensions.inDegrees import org.maplibre.spatialk.units.extensions.meters import kotlin.time.Duration.Companion.seconds @@ -35,28 +31,24 @@ fun UserLocationPuck( locationState: UserLocationState, trackUserLocation: Boolean, ) { + SimpleLocationTrackingEffect( + locationState = locationState, + enabled = trackUserLocation, + ) { currentLocation -> + val target = currentLocation?.position?.value ?: cameraState.position.target + val newPosition = cameraState.position.copy( + target = target, + // Force pointing to NORTH + bearing = 0.0, + zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM) + ) + cameraState.animateTo(newPosition) + } val location = locationState.location if (location != null) { - // Moved inside this block so it correctly tracks the updated locationState value - LocationTrackingEffect( - locationState = locationState, - enabled = trackUserLocation, - ) { - val newTarget = currentLocation.location?.position?.value - val newBearing = currentLocation.orientation?.orientation?.value?.clockwiseRotationTo(Bearing.North)?.inDegrees - if (newTarget != null || newBearing != null) { - val finalPosition = cameraState.position.copy( - target = newTarget ?: cameraState.position.target, - bearing = newBearing ?: cameraState.position.bearing, - zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM) - ) - cameraState.animateTo(finalPosition) - } - } - LocationPuck( idPrefix = "user-location", - location = locationState.location, + location = location, cameraState = cameraState, accuracyThreshold = Float.POSITIVE_INFINITY, showBearingAccuracy = false, @@ -85,7 +77,6 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState updateInterval = 5.seconds, desiredAccuracy = DesiredAccuracy.High, minDistance = 5.meters, - sharingStarted = SharingStarted.Eagerly, ) } return rememberUserLocationState(locationProvider) 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 6766fa6424..eb2cae0539 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 @@ -153,7 +153,9 @@ fun ShowLocationView( val position = CameraPosition( padding = sheetPaddings, target = Position(locationShare.location.lon, locationShare.location.lat), - zoom = MapDefaults.DEFAULT_ZOOM + // Force pointing to NORTH + bearing = 0.0, + zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM), ) coroutineScope.launch { cameraState.animateTo(finalPosition = position) From c5f9b554338912a862cc75a3bad6275b433dd995 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 28 May 2026 18:20:22 +0200 Subject: [PATCH 0540/1083] Keep accuracy from position (no default) --- .../location/impl/live/service/LiveLocationSharingService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt index aba45f30c1..a926f1255b 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -104,7 +104,7 @@ class LiveLocationSharingService : Service() { ApiLocation( lat = location.position.value.latitude, lon = location.position.value.longitude, - accuracy = location.position.accuracy?.inMeters?.toFloat() ?: 0f, + accuracy = location.position.accuracy?.inMeters?.toFloat(), ) } .onEach(coordinator::dispatch) From e0cda170a9f5f0b4a74ef943ba66c93132417477 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 29 May 2026 10:18:12 +0300 Subject: [PATCH 0541/1083] Do not hide own media (#6898) --- .../messages/impl/MessagesPresenter.kt | 2 +- .../pinned/list/PinnedMessagesListView.kt | 2 +- .../TimelineItemGroupedEventsRow.kt | 4 +- .../timeline/components/TimelineItemRow.kt | 2 +- .../impl/timeline/protection/TimelineItem.kt | 46 +++++++++++-------- .../protection/TimelineProtectionState.kt | 10 ++-- .../protection/TimelineProtectionStateTest.kt | 15 ++++++ 7 files changed, 53 insertions(+), 28 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 6754d703a3..d3737f5fae 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -550,7 +550,7 @@ class MessagesPresenter( val replyToDetails = loadReplyDetails(targetEvent.eventId).map(permalinkParser) val composerMode = MessageComposerMode.Reply( replyToDetails = replyToDetails, - hideImage = timelineProtectionState.hideMediaContent(targetEvent.eventId), + hideImage = timelineProtectionState.hideMediaContent(targetEvent.eventId, targetEvent.isMine), ) composerState.eventSink( MessageComposerEvent.SetMode(composerMode) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index 7190aa174f..9811b07c02 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -284,7 +284,7 @@ private fun TimelineItemEventContentViewWrapper( } else { TimelineItemEventContentView( content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId), + hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt index df2b9d8691..12f7a52f99 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt @@ -63,7 +63,7 @@ fun TimelineItemGroupedEventsRow( { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentView( content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId), + hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, @@ -136,7 +136,7 @@ private fun TimelineItemGroupedEventsRowContent( { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentView( content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId), + hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index a02413d534..2b72be722d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -78,7 +78,7 @@ internal fun TimelineItemRow( { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentView( content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId), + hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, onContentClick = { onContentClick(event) }, onLongClick = { onLongClick(event) }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt index 5a5363f0c6..fcaa28a108 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineItem.kt @@ -34,26 +34,32 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt */ fun TimelineItem.mustBeProtected(): Boolean { return when (this) { - is TimelineItem.Event -> when (content) { - is TimelineItemImageContent, - is TimelineItemVideoContent, - is TimelineItemStickerContent -> true - is TimelineItemAudioContent, - is TimelineItemRtcNotificationContent, - is TimelineItemEncryptedContent, - is TimelineItemFileContent, - TimelineItemLegacyCallInviteContent, - is TimelineItemLocationContent, - is TimelineItemPollContent, - TimelineItemRedactedContent, - is TimelineItemProfileChangeContent, - is TimelineItemRoomMembershipContent, - is TimelineItemStateEventContent, - is TimelineItemEmoteContent, - is TimelineItemNoticeContent, - is TimelineItemTextContent, - TimelineItemUnknownContent, - is TimelineItemVoiceContent -> false + is TimelineItem.Event -> { + if (isMine) { + false + } else { + when (content) { + is TimelineItemImageContent, + is TimelineItemVideoContent, + is TimelineItemStickerContent -> true + is TimelineItemAudioContent, + is TimelineItemRtcNotificationContent, + is TimelineItemEncryptedContent, + is TimelineItemFileContent, + TimelineItemLegacyCallInviteContent, + is TimelineItemLocationContent, + is TimelineItemPollContent, + TimelineItemRedactedContent, + is TimelineItemProfileChangeContent, + is TimelineItemRoomMembershipContent, + is TimelineItemStateEventContent, + is TimelineItemEmoteContent, + is TimelineItemNoticeContent, + is TimelineItemTextContent, + TimelineItemUnknownContent, + is TimelineItemVoiceContent -> false + } + } } is TimelineItem.Virtual -> false is TimelineItem.GroupedEvents -> false diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionState.kt index 169e5ba7f4..df31c205e9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionState.kt @@ -16,9 +16,13 @@ data class TimelineProtectionState( val protectionState: ProtectionState, val eventSink: (TimelineProtectionEvent) -> Unit, ) { - fun hideMediaContent(eventId: EventId?) = when (protectionState) { - is ProtectionState.RenderAll -> false - is ProtectionState.RenderOnly -> eventId !in protectionState.eventIds + fun hideMediaContent(eventId: EventId?, isMine: Boolean = false) = if (isMine) { + false + } else { + when (protectionState) { + is ProtectionState.RenderAll -> false + is ProtectionState.RenderOnly -> eventId !in protectionState.eventIds + } } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionStateTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionStateTest.kt index 645039b30c..c5709588f0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionStateTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionStateTest.kt @@ -42,4 +42,19 @@ class TimelineProtectionStateTest { assertThat(sut.hideMediaContent(AN_EVENT_ID)).isFalse() assertThat(sut.hideMediaContent(AN_EVENT_ID_2)).isTrue() } + + @Test + fun `when isMine is true, hideMediaContent always returns false regardless of state`() { + val sutRenderAll = aTimelineProtectionState( + protectionState = ProtectionState.RenderAll + ) + assertThat(sutRenderAll.hideMediaContent(null, isMine = true)).isFalse() + assertThat(sutRenderAll.hideMediaContent(AN_EVENT_ID, isMine = true)).isFalse() + + val sutRenderOnly = aTimelineProtectionState( + protectionState = ProtectionState.RenderOnly(persistentSetOf()) + ) + assertThat(sutRenderOnly.hideMediaContent(null, isMine = true)).isFalse() + assertThat(sutRenderOnly.hideMediaContent(AN_EVENT_ID, isMine = true)).isFalse() + } } From 64b6a1523d05ee8138dc7bb5fdc07051cfcdbfb5 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 29 May 2026 10:56:18 +0000 Subject: [PATCH 0542/1083] Revert screen recomposition fixes --- .../impl/timeline/TimelinePresenter.kt | 27 ++++--------- .../factories/TimelineItemsFactory.kt | 39 ------------------- 2 files changed, 8 insertions(+), 58 deletions(-) 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 3af7326ff5..0b99c45e06 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -51,7 +51,6 @@ import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers -import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin @@ -255,25 +254,15 @@ class TimelinePresenter( } .launchIn(this) - var previousItems: List? = null combine(timelineController.timelineItems(), room.membersStateFlow) { items, membersState -> - val roomMembers = membersState.roomMembers().orEmpty() - if (previousItems !== items) { - previousItems = items - val parent = analyticsService.getLongRunningTransaction(DisplayFirstTimelineItems) - val transaction = parent?.startChild("timelineItemsFactory.replaceWith", "Processing timeline items") - transaction?.putExtraData(AnalyticsUserData.TIMELINE_ITEM_COUNT, items.count().toString()) - timelineItemsFactory.replaceWith( - timelineItems = items, - roomMembers = roomMembers - ) - transaction?.finish() - } else { - timelineItemsFactory.updateRoomMembers( - timelineItems = items, - roomMembers = roomMembers - ) - } + val parent = analyticsService.getLongRunningTransaction(DisplayFirstTimelineItems) + val transaction = parent?.startChild("timelineItemsFactory.replaceWith", "Processing timeline items") + transaction?.putExtraData(AnalyticsUserData.TIMELINE_ITEM_COUNT, items.count().toString()) + timelineItemsFactory.replaceWith( + timelineItems = items, + roomMembers = membersState.roomMembers().orEmpty() + ) + transaction?.finish() items } .onEach(redactedVoiceMessageManager::onEachMatrixTimelineItem) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt index d1ec5b648a..dc8bdddc92 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt @@ -72,45 +72,6 @@ class TimelineItemsFactory( } } - /** - * Lightweight update that only refreshes member-derived data (e.g., read receipt display names) - * on cached items without rebuilding the diff cache or creating new items. - * Skips emission if no cached items have member-dependent state. - */ - suspend fun updateRoomMembers( - timelineItems: List, - roomMembers: List, - ) = withContext(dispatchers.computation) { - lock.withLock { - var hasUpdates = false - val updatedStates = ArrayList() - for (index in diffCache.indices().reversed()) { - val cacheItem = diffCache.get(index) - if (cacheItem is TimelineItem.Event && roomMembers.isNotEmpty()) { - val updatedItem = eventItemFactory.update( - timelineItem = cacheItem, - receivedMatrixTimelineItem = timelineItems[index] as MatrixTimelineItem.Event, - roomMembers = roomMembers - ) - diffCache[index] = updatedItem - hasUpdates = true - updatedStates.add(updatedItem) - } else if (cacheItem != null) { - updatedStates.add(cacheItem) - } else { - buildAndCacheItem(timelineItems, index, roomMembers)?.also { timelineItemState -> - updatedStates.add(timelineItemState) - } - } - } - if (hasUpdates) { - val result = timelineItemGrouper.group(updatedStates).toImmutableList() - val filteredResult = filterEmptyDaySeparators(result) - _timelineItems.emit(filteredResult) - } - } - } - private suspend fun buildAndEmitTimelineItemStates( timelineItems: List, roomMembers: List, From a8e1274786c19230e989c9bca76f23222e3ae4cc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 29 May 2026 15:01:45 +0200 Subject: [PATCH 0543/1083] Rename parameter `onSoundPicked` to `onSoundPick`. --- .../impl/notifications/NotificationSettingsView.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 5652276c23..2009970448 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -286,7 +286,7 @@ private fun SoundsPreferenceCategory(state: NotificationSettingsState) { type = RingtoneManager.TYPE_NOTIFICATION, current = state.messageSound.sound, defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI, - onSoundPicked = { sound -> state.eventSink(NotificationSettingsEvents.SetMessageSound(sound)) }, + onSoundPick = { sound -> state.eventSink(NotificationSettingsEvents.SetMessageSound(sound)) }, ) // Skip the initial 0 emission so the picker doesn't auto-open on screen entry; only // increments fired by LaunchMessageSoundPicker should launch it. @@ -313,7 +313,7 @@ private fun SoundsPreferenceCategory(state: NotificationSettingsState) { type = RingtoneManager.TYPE_RINGTONE, current = state.callRingtone.sound, defaultUri = Settings.System.DEFAULT_RINGTONE_URI, - onSoundPicked = { sound -> state.eventSink(NotificationSettingsEvents.SetCallRingtone(sound)) }, + onSoundPick = { sound -> state.eventSink(NotificationSettingsEvents.SetCallRingtone(sound)) }, ) // Skip the initial 0 emission so the picker doesn't auto-open on screen entry; only // increments fired by LaunchCallRingtonePicker should launch it. @@ -441,7 +441,7 @@ private fun rememberSoundPickerOnClick( type: Int, current: NotificationSound, defaultUri: Uri, - onSoundPicked: (NotificationSound) -> Unit, + onSoundPick: (NotificationSound) -> Unit, ): () -> Unit { // Paparazzi previews don't provide a LocalActivityResultRegistryOwner, which // rememberLauncherForActivityResult requires. Skip the launcher in inspection mode and @@ -453,7 +453,7 @@ private fun rememberSoundPickerOnClick( if (result.resultCode == Activity.RESULT_OK) { val sound = result.data?.toPickedNotificationSound(defaultUri) if (sound != null) { - onSoundPicked(sound) + onSoundPick(sound) } } } From 156473636640aa2099399de6bc1ef6add7cfd055 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 29 May 2026 14:26:45 +0200 Subject: [PATCH 0544/1083] Report problem: add an optional TextField to provide a GitHub issue number. --- .../rageshake/api/reporter/BugReporter.kt | 2 ++ .../impl/bugreport/BugReportEvents.kt | 1 + .../impl/bugreport/BugReportPresenter.kt | 6 +++- .../impl/bugreport/BugReportState.kt | 2 ++ .../rageshake/impl/bugreport/BugReportView.kt | 35 +++++++++++++++++++ .../impl/reporter/DefaultBugReporter.kt | 4 +++ .../impl/src/main/res/values/localazy.xml | 2 ++ .../impl/bugreport/BugReportPresenterTest.kt | 12 +++++++ .../impl/bugreport/FakeBugReporter.kt | 1 + 9 files changed, 64 insertions(+), 1 deletion(-) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt index 79b05ea32e..631a51a686 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt @@ -20,6 +20,7 @@ interface BugReporter { * @param problemDescription the bug description * @param canContact true if the user opt in to be contacted directly * @param sendPushRules true to include the push rules + * @param ghIssueNumber it not null, the GitHub issue number to link the bug report to. * @param listener the listener */ suspend fun sendBugReport( @@ -29,6 +30,7 @@ interface BugReporter { problemDescription: String, canContact: Boolean = false, sendPushRules: Boolean = false, + ghIssueNumber: Int? = null, listener: BugReporterListener ) diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt index 90751873dd..94897d1bad 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt @@ -18,4 +18,5 @@ sealed interface BugReportEvents { data class SetCanContact(val canContact: Boolean) : BugReportEvents data class SetSendScreenshot(val sendScreenshot: Boolean) : BugReportEvents data class SetSendPushRules(val sendPushRules: Boolean) : BugReportEvents + data class SetGhIssueNumber(val ghIssueNumber: Int?) : BugReportEvents } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt index 4985f9b30e..85731ae959 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt @@ -113,6 +113,9 @@ class BugReportPresenter( sendingProgress.floatValue = 0f sendingAction.value = AsyncAction.Uninitialized } + is BugReportEvents.SetGhIssueNumber -> updateFormState(formState) { + copy(ghIssueNumber = event.ghIssueNumber) + } } } @@ -142,7 +145,8 @@ class BugReportPresenter( problemDescription = formState.description, canContact = formState.canContact, sendPushRules = formState.sendPushRules, - listener = listener + ghIssueNumber = formState.ghIssueNumber, + listener = listener, ) } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt index 65cc055ec9..8e07b3c4e8 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt @@ -32,6 +32,7 @@ data class BugReportFormState( val canContact: Boolean, val sendScreenshot: Boolean, val sendPushRules: Boolean, + val ghIssueNumber: Int?, ) : Parcelable { companion object { val Default = BugReportFormState( @@ -40,6 +41,7 @@ data class BugReportFormState( canContact = false, sendScreenshot = false, sendPushRules = false, + ghIssueNumber = null, ) } } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt index c2c34835c9..0e6241c1f3 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt @@ -155,6 +155,41 @@ fun BugReportView( title = stringResource(R.string.screen_bug_report_send_notification_settings_title), subtitle = stringResource(R.string.screen_bug_report_send_notification_settings_description), ) + PreferenceRow { + var ghIssueNumberState by textFieldState( + stateValue = state.formState.ghIssueNumber?.toString() ?: "" + ) + TextField( + value = ghIssueNumberState, + modifier = Modifier + .fillMaxWidth() + .onTabOrEnterKeyFocusNext(LocalFocusManager.current), + enabled = isFormEnabled, + label = stringResource(id = R.string.screen_bug_report_github_issue_label), + placeholder = "1234", + supportingText = stringResource(id = R.string.screen_bug_report_github_issue_description), + onValueChange = { + if (it.isEmpty()) { + ghIssueNumberState = "" + eventSink(BugReportEvents.SetGhIssueNumber(null)) + } else { + val number = it.toIntOrNull()?.takeIf { ghInt -> ghInt in 1..99_999 } + number?.let { ghIssueNumber -> + ghIssueNumberState = ghIssueNumber.toString() + eventSink(BugReportEvents.SetGhIssueNumber(ghIssueNumber)) + } + } + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Next, + ), + keyboardActions = KeyboardActions(onNext = { + keyboardController?.hide() + }), + singleLine = true, + ) + } // Submit PreferenceRow { Button( diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt index 2568a6fba9..735bb1cea0 100755 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt @@ -123,6 +123,7 @@ class DefaultBugReporter( problemDescription: String, canContact: Boolean, sendPushRules: Boolean, + ghIssueNumber: Int?, listener: BugReporterListener, ) { val url = bugReporterUrlProvider.provide().first() @@ -144,6 +145,9 @@ class DefaultBugReporter( val crashCallStack = crashDataStore.crashInfo().first() val bugDescription = buildString { append(problemDescription) + ghIssueNumber?.let { + append("\n\nhttps://github.com/element-hq/element-x-android/issues/$it") + } if (crashCallStack.isNotEmpty() && withCrashLogs) { append("\n\n\n\n--------------------------------- crash call stack ---------------------------------\n") append(crashCallStack) diff --git a/features/rageshake/impl/src/main/res/values/localazy.xml b/features/rageshake/impl/src/main/res/values/localazy.xml index 85af2af4a7..d1dc52f3e4 100644 --- a/features/rageshake/impl/src/main/res/values/localazy.xml +++ b/features/rageshake/impl/src/main/res/values/localazy.xml @@ -8,6 +8,8 @@ "Describe the problem…" "If possible, please write the description in English." "The description is too short, please provide more details about what happened. Thanks!" + "You can enter the number of an associated GitHub issue, if any." + "GitHub issue" "Send crash logs" "Allow logs" "Your logs are excessively large so cannot be included in this report, please send them to us another way." diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt index 148c375e25..afbcc939a6 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt @@ -107,6 +107,18 @@ class BugReportPresenterTest { } } + @Test + fun `present - set GitHub issue number`() = runTest { + val presenter = createPresenter() + presenter.test { + val initialState = awaitItem() + initialState.eventSink.invoke(BugReportEvents.SetGhIssueNumber(1)) + assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(ghIssueNumber = 1)) + initialState.eventSink.invoke(BugReportEvents.SetGhIssueNumber(null)) + assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(ghIssueNumber = null)) + } + } + @Test fun `present - reset all`() = runTest { val presenter = createPresenter( diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt index 36cc185e86..659145caa9 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt @@ -28,6 +28,7 @@ class FakeBugReporter(val mode: Mode = Mode.Success) : BugReporter { problemDescription: String, canContact: Boolean, sendPushRules: Boolean, + ghIssueNumber: Int?, listener: BugReporterListener, ) { delay(100) From 488ef54cbc3ef59fcfe8a90c71d25be1b69f4178 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 29 May 2026 15:39:16 +0200 Subject: [PATCH 0545/1083] Add leading icon `#`. --- .../features/rageshake/impl/bugreport/BugReportView.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt index 0e6241c1f3..36b407a669 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import coil3.request.CachePolicy import coil3.request.ImageRequest +import io.element.android.compound.theme.ElementTheme import io.element.android.features.rageshake.impl.R import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.components.async.AsyncActionView @@ -168,6 +169,13 @@ fun BugReportView( label = stringResource(id = R.string.screen_bug_report_github_issue_label), placeholder = "1234", supportingText = stringResource(id = R.string.screen_bug_report_github_issue_description), + leadingIcon = { + Text( + text = "#", + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textSecondary, + ) + }, onValueChange = { if (it.isEmpty()) { ghIssueNumberState = "" From 24c11e1b0f31c567f4a105dc96851cce89617d66 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 29 May 2026 15:59:54 +0200 Subject: [PATCH 0546/1083] Add Stefan's etiquette to the project. (#6909) --- .github/pull_request_template.md | 1 + AGENTS.md | 13 ++++++++----- CONTRIBUTING.md | 25 +++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 95f322a2e4..9ed1919e0e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -52,6 +52,7 @@ Uncomment this markdown table below and edit the last line `|||`: +- [ ] I am aware of the [etiquette](https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#etiquette). - This PR was made with the help of AI: - [ ] Yes. In this case, please request a review by Copilot. - [ ] No. diff --git a/AGENTS.md b/AGENTS.md index 454c347a9f..d206be98c6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,11 +44,14 @@ PRs must meet these rules. ## Pull Request Guidelines -- Use sentence-style commit/PR messages (no conventional commits). -- Apply exactly **one** `PR-` label for changelog categorization. -- PR title = changelog entry — make it descriptive; no "Fixes #…" prefixes. -- Include screenshots or screen recordings for any UI changes. -- Keep PRs focused; split changes over 1000 lines. +- Sentence-style titles (no conventional commits). +- Exactly one `pr-` label (see `.github/release.yml`). +- Title = changelog entry — descriptive, no "Fixes #…". +- Leave description template for the developer. Redirect them to the [contributing etiquette](CONTRIBUTING.md#etiquette). +- Screenshots/videos for visual changes. +- 500 additions max — split large changes. +- Commits need a title and description; no tiny or massive commits. +- No history rewrites. --- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0126d89a9c..ec131aa65f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,8 @@ * [I want to help translating Element](#i-want-to-help-translating-element) * [I want to fix a bug](#i-want-to-fix-a-bug) * [I want to add a new feature or enhancement](#i-want-to-add-a-new-feature-or-enhancement) -* [Developer onboarding](#developer-onboarding) + * [Etiquette](#etiquette) + * [Developer onboarding](#developer-onboarding) * [Submitting the PRs](#submitting-the-prs) * [Android Studio settings](#android-studio-settings) * [Compilation](#compilation) @@ -63,7 +64,27 @@ Once we know that you want to contribute and have confirmed that the new feature Only once all of the above is met should you open a PR with your proposed changes. -## Developer onboarding +### Etiquette + +* As stated above all significant changes should be communicated through an issue before opening a PR +* We are happy to receive contributions but features always require maintenance, so depending on the change we might not be willing to accept it +* We are also fine with AI led contributions within reasonable bounds + * You are completely responsible for the quality of the PR + * If the PR doesn't show minimal effort (code does not compile, code does not work as expected, etc.) on your part it will be closed + * Please write the description yourself, we don't have the bandwidth to read LLM essays. The code needs to speak for itself. +* We use git for version control and GitHub for reviews, so in order to make everybody's life easier please: + * Keep the existing pull request template + * Don't submit large PRs, especially if not previously talked about. Anything above 200 lines is large (excluding generated code e.g. tests, translations, mocks) + * Please don't open unfinished PRs and expect us to fill in the details + * If you would like our opinion/direction on unfinished code please link your branch or idea in the ticket + * Please limit the number of commits in a single PR. We are perfectly happy with splitting work across multiple sessions as long as they're logically independant and show promise of progress (ideally expressed through a ticket) + * Each and every commit should stand on its own, clearly explaining what it does and why +* Once a PR goes into review please don't rewrite the history unless agreed so with the reviewer. + * Tweaks and fixes following review can be directly committed (to be interactively rebased later) or as fixups + +*The reviewer's response time will generally match yours. Switching contexts is very hard so please act accordingly. You are responsible for making the reviewers job enjoyable!* + +### Developer onboarding For a detailed overview of the project, see [Developer Onboarding](./docs/_developer_onboarding.md). From d0db687a0680873f58552a96969dc97d3cfdb003 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 29 May 2026 14:13:04 +0000 Subject: [PATCH 0547/1083] Update screenshots --- ...eatures.rageshake.impl.bugreport_BugReportViewDay_0_en.png | 4 ++-- ...eatures.rageshake.impl.bugreport_BugReportViewDay_1_en.png | 4 ++-- ...eatures.rageshake.impl.bugreport_BugReportViewDay_2_en.png | 4 ++-- ...eatures.rageshake.impl.bugreport_BugReportViewDay_3_en.png | 4 ++-- ...eatures.rageshake.impl.bugreport_BugReportViewDay_4_en.png | 4 ++-- ...tures.rageshake.impl.bugreport_BugReportViewNight_0_en.png | 4 ++-- ...tures.rageshake.impl.bugreport_BugReportViewNight_1_en.png | 4 ++-- ...tures.rageshake.impl.bugreport_BugReportViewNight_2_en.png | 4 ++-- ...tures.rageshake.impl.bugreport_BugReportViewNight_3_en.png | 4 ++-- ...tures.rageshake.impl.bugreport_BugReportViewNight_4_en.png | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png index b81b524b86..0599f2300a 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a10513e98757e17cc3ffb8302807896839a78d036331e79bb207686f3f9db86 -size 47842 +oid sha256:a4b243025f40d5d4a91e32d59a6cac9ec21a273aaddbfac020cb26b3dc86c906 +size 53339 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png index 0700c94bb7..9e2407229c 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05efb0fa45bb6440e75e9280b219cfdac83c372efe9e6d6254b4bbe516f8b998 -size 112842 +oid sha256:e98722e0c21fe6b509b2bdf4a9ce7f78a1c83b606411329d2fd97a676fc4bed3 +size 113728 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png index 61e347497e..bfd0f366be 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:833d21633cb0f153b660112fcfd0923c588cd26b64005403a007d7782ecfe5d5 -size 45138 +oid sha256:44eed3e8a093977f51d706acbec65cf29d592dcf0af3cdc9fce85d2b8e570eb9 +size 51038 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png index b81b524b86..0599f2300a 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a10513e98757e17cc3ffb8302807896839a78d036331e79bb207686f3f9db86 -size 47842 +oid sha256:a4b243025f40d5d4a91e32d59a6cac9ec21a273aaddbfac020cb26b3dc86c906 +size 53339 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png index 948604dd84..1a5d877a24 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebe22ec065cc6dff2133dcc573a82e003d9061ae0446c2d8c13f4e1fba1f3c19 -size 37056 +oid sha256:781287977ff2637fe6479c3653270783c4374bc10fffb91da8b45d4e4f588a98 +size 41744 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png index 9b379990c3..3fea4591cd 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f647e92bf813ead7affcdb6ad07076fe9d739f6a4c0016b9787912f032e27476 -size 46567 +oid sha256:f690c34f97eec23f01bfdc3c2606a229bb12abb91fe86fb79c89da79b08480a0 +size 52049 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png index fcdfe6ba7d..957e19a4ce 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdfbb9f70a97724a1b6687ad4f199efc2c9bcc5f29fe9475a17ee6e52e5ecf8e -size 110829 +oid sha256:751b442e5aecd9d3938817f8a1af11b7cc1d250c1166c9e8bd3154a85268471d +size 111765 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png index 6760c96a86..390d0faf7e 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cfab4886243e6c914f466f5f127ec0347b0ab30ee43fb95c7bc82d2b16325d5 -size 43727 +oid sha256:0719e803112640729fe2b59c40373343db3e9f2e8dded9258d4b6c44547f8fd1 +size 49420 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png index 9b379990c3..3fea4591cd 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f647e92bf813ead7affcdb6ad07076fe9d739f6a4c0016b9787912f032e27476 -size 46567 +oid sha256:f690c34f97eec23f01bfdc3c2606a229bb12abb91fe86fb79c89da79b08480a0 +size 52049 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png index 6b7ad4a825..4fd1ecbc0e 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c24515cc18b3c5cc52f2acfcee4faa65c02d8d5c8be847d4b1ec5671a858210 -size 35201 +oid sha256:1cb10ddf4a9dee4a001276554cf32cf874062e1e5d7d0ebb673f6417641530bf +size 39730 From 8c29a7b55c2e27c516ba604fe5e1eefb9bbd49dc Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 29 May 2026 18:46:35 +0300 Subject: [PATCH 0548/1083] Merge pull request #6889 from bxdxnn/fix/read-receipt-calls Fix read receipts not shown for calls --- .../components/TimelineItemCallNotifyView.kt | 105 ++++++++++++------ .../timeline/components/TimelineItemRow.kt | 4 +- ...ts_TimelineItemCallNotifyView_Day_0_en.png | 4 +- ..._TimelineItemCallNotifyView_Night_0_en.png | 4 +- 4 files changed, 76 insertions(+), 41 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index 61273ff07a..fea4f92de5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -32,7 +32,11 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.aTimelineItemReadReceipts import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo +import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState +import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView +import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent @@ -48,46 +52,63 @@ internal fun TimelineItemCallNotifyView( timelineRoomInfo: TimelineRoomInfo, event: TimelineItem.Event, content: TimelineItemRtcNotificationContent, + renderReadReceipts: Boolean, + isLastOutgoingMessage: Boolean, onLongClick: (TimelineItem.Event) -> Unit, + onReadReceiptsClick: (TimelineItem.Event) -> Unit, modifier: Modifier = Modifier ) { - Row( - modifier = modifier - .fillMaxWidth() - .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(8.dp)) - .combinedClickable( - enabled = true, - onClick = {}, - onLongClick = { onLongClick(event) }, - onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), + Column(modifier = modifier) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, top = 16.dp) + .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, RoundedCornerShape(8.dp)) + .combinedClickable( + enabled = true, + onClick = {}, + onLongClick = { onLongClick(event) }, + onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), + ) + .onKeyboardContextMenuAction { onLongClick(event) } + .padding(12.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + modifier = Modifier.size(20.sp.toDp()), + imageVector = getIcon(timelineRoomInfo, content), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary, ) - .onKeyboardContextMenuAction { onLongClick(event) } - .padding(12.dp), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - modifier = Modifier.size(20.sp.toDp()), - imageVector = getIcon(timelineRoomInfo, content), - contentDescription = null, - tint = ElementTheme.colors.iconSecondary, - ) - Text( - modifier = Modifier.weight(1f), - text = stringResource(getTextRes(timelineRoomInfo, content)), - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) + Text( + modifier = Modifier.weight(1f), + text = stringResource(getTextRes(timelineRoomInfo, content)), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) - Text( - text = event.sentTime, - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, + Text( + text = event.sentTime, + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + + TimelineItemReadReceiptView( + state = ReadReceiptViewState( + sendState = event.localSendState, + isLastOutgoingMessage = isLastOutgoingMessage, + receipts = event.readReceiptState.receipts, + ), + renderReadReceipts = renderReadReceipts, + onReadReceiptsClick = { onReadReceiptsClick(event) }, + modifier = Modifier.padding(top = 4.dp), ) } } @@ -125,7 +146,10 @@ private fun getIcon( @PreviewsDayNight @Composable internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { - Column(modifier = Modifier.padding(2.dp), verticalArrangement = Arrangement.spacedBy(2.dp)) { + val readReceiptState = aTimelineItemReadReceipts( + receipts = List(3) { aReadReceiptData(it) }, + ) + Column(modifier = Modifier.padding(bottom = 16.dp)) { listOf(false, true).forEach { isDm -> listOf(CallIntent.AUDIO, CallIntent.VIDEO).forEach { callIntent -> listOf( @@ -136,9 +160,18 @@ internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { val content = TimelineItemRtcNotificationContent(callIntent, state) TimelineItemCallNotifyView( timelineRoomInfo = aTimelineRoomInfo(isDm = isDm), - event = aTimelineItemEvent(content = content), + event = aTimelineItemEvent( + content = content, + readReceiptState = readReceiptState, + ), content = content, + // Render read receipts for the first item only + renderReadReceipts = !isDm && + callIntent == CallIntent.AUDIO && + state == RtcNotificationState.Started, + isLastOutgoingMessage = false, onLongClick = {}, + onReadReceiptsClick = {}, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 2b72be722d..5dc69bba8b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -124,11 +124,13 @@ internal fun TimelineItemRow( } is TimelineItemRtcNotificationContent -> { TimelineItemCallNotifyView( - modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp), timelineRoomInfo = timelineRoomInfo, event = timelineItem, content = timelineItem.content, + renderReadReceipts = renderReadReceipts, + isLastOutgoingMessage = isLastOutgoingMessage, onLongClick = onLongClick, + onReadReceiptsClick = onReadReceiptClick, ) } else -> { diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png index e89697a8cc..510521faa5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5529e89e00208e38522f5206f5b8d304bd472b27071cab4e0d3c2daf3cb64db0 -size 49741 +oid sha256:aeaeef2348e2844e300c83b257027468ff51977bcfa2d6c540f8c882d2624826 +size 44173 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png index 37037907c8..5dcea94a33 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa29aaa82f21912dd5147ffb6fdc457fd5880e8be4abde4f0177d0ab1a412fe2 -size 48245 +oid sha256:4a6c9b24bfc9159fc70b6431f106836031c69cf5308674c20d88c1570f15d105 +size 43144 From d6892dd0907e479a5e40c46dab451a6a55a950c4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 29 May 2026 18:21:18 +0200 Subject: [PATCH 0549/1083] change: replace the maplibre-compose UserLocationState to a simpler one --- .../location/impl/common/UserLocationState.kt | 43 +++++++++++++++++++ .../common/ui/SimpleLocationTrackingEffect.kt | 3 +- .../impl/common/ui/UserLocationPuck.kt | 26 +---------- .../location/impl/share/ShareLocationView.kt | 4 +- .../location/impl/show/ShowLocationView.kt | 2 +- 5 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt new file mode 100644 index 0000000000..632ddef38d --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalInspectionMode +import org.maplibre.compose.location.DesiredAccuracy +import org.maplibre.compose.location.Location +import org.maplibre.compose.location.rememberAndroidLocationProvider +import org.maplibre.compose.location.rememberNullLocationProvider +import org.maplibre.spatialk.units.extensions.meters +import kotlin.time.Duration.Companion.seconds + +class UserLocationState(locationState: State) { + val location: Location? by locationState +} + +@SuppressLint("MissingPermission") +@Composable +fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState { + val isPreview = LocalInspectionMode.current + val locationProvider = if (isPreview || !hasLocationPermission) { + rememberNullLocationProvider() + } else { + rememberAndroidLocationProvider( + updateInterval = 5.seconds, + desiredAccuracy = DesiredAccuracy.High, + minDistance = 5.meters, + ) + } + val locationState = locationProvider.location.collectAsState() + return remember { UserLocationState(locationState) } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt index 7a7a1551cf..cda360be9e 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt @@ -12,9 +12,9 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.snapshotFlow +import io.element.android.features.location.impl.common.UserLocationState import kotlinx.coroutines.flow.distinctUntilChanged import org.maplibre.compose.location.Location -import org.maplibre.compose.location.UserLocationState import kotlin.math.abs /** @@ -29,7 +29,6 @@ internal fun SimpleLocationTrackingEffect( onLocationChange: suspend (Location?) -> Unit, ) { val latestOnLocationChange by rememberUpdatedState(onLocationChange) - LaunchedEffect(locationState, enabled) { if (!enabled) return@LaunchedEffect val locationStateFlow = snapshotFlow { locationState.location } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt index 7bad736911..5bcbf6a9b2 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt @@ -7,23 +7,15 @@ package io.element.android.features.location.impl.common.ui -import android.annotation.SuppressLint import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.UserLocationState import org.maplibre.compose.camera.CameraState -import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationPuckColors import org.maplibre.compose.location.LocationPuckSizes -import org.maplibre.compose.location.UserLocationState -import org.maplibre.compose.location.rememberAndroidLocationProvider -import org.maplibre.compose.location.rememberNullLocationProvider -import org.maplibre.compose.location.rememberUserLocationState -import org.maplibre.spatialk.units.extensions.meters -import kotlin.time.Duration.Companion.seconds @Composable fun UserLocationPuck( @@ -65,19 +57,3 @@ fun UserLocationPuck( ) } } - -@SuppressLint("MissingPermission") -@Composable -fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState { - val isPreview = LocalInspectionMode.current - val locationProvider = if (isPreview || !hasLocationPermission) { - rememberNullLocationProvider() - } else { - rememberAndroidLocationProvider( - updateInterval = 5.seconds, - desiredAccuracy = DesiredAccuracy.High, - minDistance = 5.meters, - ) - } - return rememberUserLocationState(locationProvider) -} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index 68dcee36ac..da7410f0bb 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -39,11 +39,12 @@ import io.element.android.features.location.api.Location import io.element.android.features.location.api.internal.centerBottomEdge import io.element.android.features.location.impl.R import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.UserLocationState +import io.element.android.features.location.impl.common.rememberUserLocationState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialog import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold import io.element.android.features.location.impl.common.ui.UserLocationPuck -import io.element.android.features.location.impl.common.ui.rememberUserLocationState import io.element.android.features.location.impl.share.ShareLocationEvent.StartLiveLocationShare import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.components.LocationPin @@ -69,7 +70,6 @@ import kotlinx.collections.immutable.ImmutableList import org.maplibre.compose.camera.CameraMoveReason import org.maplibre.compose.camera.CameraState import org.maplibre.compose.camera.rememberCameraState -import org.maplibre.compose.location.UserLocationState import kotlin.time.Duration @OptIn(ExperimentalMaterial3Api::class) 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 5d5295871c..ba60a22225 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 @@ -37,13 +37,13 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.rememberUserLocationState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialog import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton import io.element.android.features.location.impl.common.ui.LocationPinMarkers import io.element.android.features.location.impl.common.ui.LocationShareRow import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold import io.element.android.features.location.impl.common.ui.UserLocationPuck -import io.element.android.features.location.impl.common.ui.rememberUserLocationState import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight From 4c1a167e2b96d0b19fe4adc9cabc1a3476df9609 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 29 May 2026 18:18:12 +0000 Subject: [PATCH 0550/1083] Add HS capability check --- .../slashcommands/impl/DefaultSlashCommandService.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt index 6cd8688cad..8234116bb1 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt @@ -99,6 +99,14 @@ class DefaultSlashCommandService( override suspend fun proceedAdmin( slashCommand: SlashCommand.SlashCommandAdmin, ): Result { + if (slashCommand is SlashCommand.ChangeDisplayNameForRoom) { + val canUserChangeDisplayName = withTimeoutOrNull(5.seconds) { + capabilitiesProvider.canChangeDisplayName().getOrNull() + } ?: false + if (!canUserChangeDisplayName) { + return Result.failure(Exception("Changing display name is not allowed")) + } + } return commandExecutor.proceedAdmin( slashCommand = slashCommand, ) From a98fd963030dc47f1ac9be449755f645108fd10b Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Sat, 30 May 2026 14:14:55 +0000 Subject: [PATCH 0551/1083] Add skin tone picker --- .../components/customreaction/EmojiItem.kt | 163 ++++++++++++++++-- .../customreaction/picker/EmojiPicker.kt | 44 +++++ .../customreaction/picker/SkinTonePicker.kt | 131 ++++++++++++++ 3 files changed, 326 insertions(+), 12 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt index 629eaa72ab..4a8d2e6cca 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt @@ -8,32 +8,51 @@ package io.element.android.features.messages.impl.timeline.components.customreaction +import androidx.compose.foundation.Canvas import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.indication import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.PressInteraction import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.ripple import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.drawscope.Fill +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Popup import io.element.android.compound.theme.ElementTheme import io.element.android.emojibasebindings.Emoji import io.element.android.features.messages.impl.timeline.a11y.a11yReactionAction +import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinTonePadding +import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinTonePickerContent +import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinToneSlotSize +import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinToneSlotSpacing import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.theme.components.Text import kotlinx.collections.immutable.persistentListOf @@ -44,12 +63,22 @@ fun EmojiItem( onSelectEmoji: (Emoji) -> Unit, modifier: Modifier = Modifier, emojiSize: TextUnit = 20.sp, + onLongPress: ((Emoji) -> Unit)? = null, + skinPickerEmoji: Emoji? = null, + onDismissSkinPicker: (() -> Unit)? = null, + selectedSkinUnicodes: Set = emptySet(), + hasSelectedSkin: Boolean = false, ) { - val backgroundColor = if (isSelected) { - ElementTheme.colors.bgActionPrimaryRest - } else { - Color.Transparent + val backgroundColor = when { + isSelected -> ElementTheme.colors.bgActionPrimaryRest + hasSelectedSkin -> ElementTheme.colors.bgActionTertiarySelected + else -> Color.Transparent } + val density = LocalDensity.current + var itemSize by remember { mutableStateOf(IntSize.Zero) } + var hoveredIndex by remember { mutableStateOf(-1) } + var dismissed by remember { mutableStateOf(false) } + val interactionSource = remember { MutableInteractionSource() } val description = a11yReactionAction( emoji = item.unicode, userAlreadyReacted = isSelected, @@ -57,13 +86,88 @@ fun EmojiItem( Box( modifier = modifier .sizeIn(minWidth = 40.dp, minHeight = 40.dp) + .onSizeChanged { itemSize = it } .background(backgroundColor, CircleShape) - .clickable( - enabled = true, - onClick = { onSelectEmoji(item) }, - indication = ripple(bounded = false, radius = emojiSize.toDp() / 2 + 10.dp), - interactionSource = remember { MutableInteractionSource() } - ) + .indication(interactionSource, ripple()) + .pointerInput(item) { + detectTapGestures( + onPress = { pressOffset -> + val press = PressInteraction.Press(pressOffset) + interactionSource.emit(press) + if (tryAwaitRelease()) { + interactionSource.emit(PressInteraction.Release(press)) + } else { + interactionSource.emit(PressInteraction.Cancel(press)) + } + }, + onTap = { onSelectEmoji(item) }, + ) + } + .pointerInput(item) { + detectDragGesturesAfterLongPress( + onDragStart = { _ -> + if (item.skins != null && onLongPress != null) { + dismissed = false + onLongPress(item) + hoveredIndex = -1 + } + }, + onDrag = { change, _ -> + if (item.skins != null && !dismissed) { + change.consume() + val yThresholdPx = with(density) { 100.dp.toPx() } + if (change.position.y > yThresholdPx) { + dismissed = true + hoveredIndex = -1 + onDismissSkinPicker?.invoke() + } else { + val skinCount = item.skins!!.size + val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } + val spacingPx = with(density) { SkinToneSlotSpacing.toPx() } + val paddingPx = with(density) { SkinTonePadding.toPx() } + val totalSlots = 1 + skinCount + val pickerWidthPx = 2 * paddingPx + totalSlots * slotWidthPx + (totalSlots - 1) * spacingPx + val pickerHalfWidthPx = pickerWidthPx / 2f + val centerXPx = itemSize.width / 2f + val pickerLeftPx = centerXPx - pickerHalfWidthPx + val xInPicker = change.position.x - pickerLeftPx + val index = if (xInPicker >= 0f && xInPicker <= pickerWidthPx) { + (xInPicker / slotWidthPx).toInt().coerceIn(0, totalSlots - 1) + } else { + -1 + } + hoveredIndex = index + } + } + }, + onDragEnd = { + if (!dismissed) { + val idx = hoveredIndex + val skinCount = item.skins?.size ?: 0 + if (idx in 0..skinCount) { + if (idx == 0) { + onSelectEmoji(item) + } else { + val skin = item.skins?.getOrNull(idx - 1) + if (skin != null) { + onSelectEmoji(item.copy(unicode = skin.unicode)) + } + } + } else if (idx < 0) { + onSelectEmoji(item) + } + } + dismissed = false + hoveredIndex = -1 + onDismissSkinPicker?.invoke() + }, + onDragCancel = { + dismissed = false + hoveredIndex = -1 + onDismissSkinPicker?.invoke() + }, + ) + } .clearAndSetSemantics { contentDescription = description }, @@ -73,6 +177,41 @@ fun EmojiItem( text = item.unicode, style = LocalTextStyle.current.copy(fontSize = emojiSize), ) + if (item.skins != null) { + Canvas( + modifier = Modifier + .align(Alignment.BottomEnd) + .size(8.dp), + ) { + val path = Path().apply { + moveTo(size.width, size.height) + lineTo(size.width, 0f) + lineTo(0f, size.height) + close() + } + drawPath(path, color = Color.Gray.copy(alpha = 0.5f), style = Fill) + } + } + + if (skinPickerEmoji == item) { + val pickerHeight = SkinTonePadding * 2 + SkinToneSlotSize + val popupOffsetPx = with(density) { -pickerHeight.roundToPx() } + Popup( + onDismissRequest = { onDismissSkinPicker?.invoke() }, + alignment = Alignment.BottomCenter, + offset = IntOffset(0, popupOffsetPx), + ) { + SkinTonePickerContent( + emoji = item, + onSelect = { selectedEmoji -> + onSelectEmoji(selectedEmoji) + onDismissSkinPicker?.invoke() + }, + hoveredIndex = hoveredIndex, + selectedUnicodes = selectedSkinUnicodes, + ) + } + } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt index 0575341d3d..a0cd4928fc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt @@ -25,7 +25,11 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SecondaryTabRow import androidx.compose.material3.Tab import androidx.compose.runtime.Composable +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.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter @@ -54,6 +58,26 @@ fun EmojiPicker( ) { val coroutineScope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { state.categories.size }) + var skinPickerEmoji by remember { mutableStateOf(null) } + + val selectedSkinUnicodes = remember(skinPickerEmoji, selectedEmojis) { + if (skinPickerEmoji != null) { + val emoji = skinPickerEmoji!! + val variants = emoji.skins.orEmpty() + .map { it.unicode } + .filter { it in selectedEmojis } + if (variants.isNotEmpty()) { + variants.toSet() + } else if (emoji.unicode in selectedEmojis) { + setOf(emoji.unicode) + } else { + emptySet() + } + } else { + emptySet() + } + } + Column(modifier) { SearchBar( modifier = Modifier.padding(bottom = 10.dp), @@ -68,6 +92,11 @@ fun EmojiPicker( emojis = emojis, isEmojiSelected = { selectedEmojis.contains(it.unicode) }, onSelectEmoji = onSelectEmoji, + onLongPress = { skinPickerEmoji = it }, + skinPickerEmoji = skinPickerEmoji, + onDismissSkinPicker = { skinPickerEmoji = null }, + selectedEmojis = selectedEmojis, + selectedSkinUnicodes = selectedSkinUnicodes, ) } @@ -106,6 +135,11 @@ fun EmojiPicker( emojis = emojis, isEmojiSelected = { selectedEmojis.contains(it.unicode) }, onSelectEmoji = onSelectEmoji, + onLongPress = { skinPickerEmoji = it }, + skinPickerEmoji = skinPickerEmoji, + onDismissSkinPicker = { skinPickerEmoji = null }, + selectedEmojis = selectedEmojis, + selectedSkinUnicodes = selectedSkinUnicodes, ) } } @@ -117,6 +151,11 @@ private fun EmojiResults( emojis: ImmutableList, isEmojiSelected: (Emoji) -> Boolean, onSelectEmoji: (Emoji) -> Unit, + onLongPress: ((Emoji) -> Unit)? = null, + skinPickerEmoji: Emoji? = null, + onDismissSkinPicker: (() -> Unit)? = null, + selectedEmojis: ImmutableSet = persistentSetOf(), + selectedSkinUnicodes: Set = emptySet(), ) { LazyVerticalGrid( modifier = Modifier.fillMaxSize(), @@ -131,7 +170,12 @@ private fun EmojiResults( item = item, isSelected = isEmojiSelected(item), onSelectEmoji = onSelectEmoji, + onLongPress = onLongPress, + skinPickerEmoji = skinPickerEmoji, + onDismissSkinPicker = onDismissSkinPicker, emojiSize = 32.dp.toSp(), + selectedSkinUnicodes = selectedSkinUnicodes, + hasSelectedSkin = item.skins?.any { skin -> skin.unicode in selectedEmojis } == true, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt new file mode 100644 index 0000000000..cdabf5772a --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.timeline.components.customreaction.picker + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.LocalTextStyle +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.emojibasebindings.Emoji +import io.element.android.emojibasebindings.EmojiSkin +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.text.toSp +import io.element.android.libraries.designsystem.theme.components.Surface +import io.element.android.libraries.designsystem.theme.components.Text +import kotlinx.collections.immutable.persistentListOf + +val SkinToneSlotSize = 48.dp +val SkinToneSlotSpacing = 2.dp +val SkinTonePadding = 4.dp + +@Composable +fun SkinTonePickerContent( + emoji: Emoji, + onSelect: (Emoji) -> Unit, + modifier: Modifier = Modifier, + hoveredIndex: Int = -1, + selectedUnicodes: Set = emptySet(), +) { + val skins = emoji.skins.orEmpty() + val emojiSize = 32.dp.toSp() + + Surface( + modifier = modifier, + shape = RoundedCornerShape(12.dp), + color = ElementTheme.colors.bgCanvasDefault, + tonalElevation = 4.dp, + ) { + Row( + modifier = Modifier.padding(SkinTonePadding), + horizontalArrangement = Arrangement.spacedBy(SkinToneSlotSpacing), + ) { + SkinToneSlot( + unicode = emoji.unicode, + emojiSize = emojiSize, + isHovered = hoveredIndex == 0, + isSelected = emoji.unicode in selectedUnicodes, + onClick = { onSelect(emoji) }, + ) + skins.forEachIndexed { index, skin -> + SkinToneSlot( + unicode = skin.unicode, + emojiSize = emojiSize, + isHovered = hoveredIndex == index + 1, + isSelected = skin.unicode in selectedUnicodes, + onClick = { onSelect(emoji.copy(unicode = skin.unicode)) }, + ) + } + } + } +} + +@Composable +private fun SkinToneSlot( + unicode: String, + emojiSize: TextUnit, + isHovered: Boolean, + isSelected: Boolean, + onClick: () -> Unit, +) { + val background = when { + isSelected && isHovered -> ElementTheme.colors.bgActionPrimaryPressed + isSelected -> ElementTheme.colors.bgActionPrimaryRest + isHovered -> ElementTheme.colors.bgActionPrimaryHovered + else -> Color.Transparent + } + Box( + modifier = Modifier + .size(SkinToneSlotSize) + .clip(CircleShape) + .background(background, CircleShape) + .clickable(onClick = onClick), + contentAlignment = Alignment.Center, + ) { + Text( + text = unicode, + style = LocalTextStyle.current.copy(fontSize = emojiSize), + ) + } +} + +@PreviewsDayNight +@Composable +internal fun SkinTonePickerContentPreview() = ElementPreview { + SkinTonePickerContent( + emoji = Emoji( + hexcode = "1F44D", + label = "thumbs up", + tags = null, + shortcodes = persistentListOf("+1", "thumbsup"), + unicode = "👍", + skins = persistentListOf( + EmojiSkin("1F44D-1F3FB", "thumbs up: light skin tone", "👍🏻"), + EmojiSkin("1F44D-1F3FC", "thumbs up: medium-light skin tone", "👍🏼"), + EmojiSkin("1F44D-1F3FD", "thumbs up: medium skin tone", "👍🏽"), + EmojiSkin("1F44D-1F3FE", "thumbs up: medium-dark skin tone", "👍🏾"), + EmojiSkin("1F44D-1F3FF", "thumbs up: dark skin tone", "👍🏿"), + ), + ), + onSelect = {}, + ) +} From aeadd9879e43ec36f15a7d0df47c8b1affef193f Mon Sep 17 00:00:00 2001 From: ElementBot Date: Sat, 30 May 2026 14:48:33 +0000 Subject: [PATCH 0552/1083] Update screenshots --- ...ts.customreaction.picker_SkinTonePickerContent_Day_0_en.png | 3 +++ ....customreaction.picker_SkinTonePickerContent_Night_0_en.png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Day_0_en.png new file mode 100644 index 0000000000..de4d90383b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0e294bf94727e3599cc94a80668dba83742f1897c55bf7476bbb4b4fb4116c1 +size 18794 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Night_0_en.png new file mode 100644 index 0000000000..9e526ca3cb --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ab6d6139c2e15334980c753f97feedc688285a9704650e47956df502cadb6ef +size 18539 From 81ed41d580fa85e0b3971c8f9106c619edfc65a2 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 1 Jun 2026 09:52:14 +0200 Subject: [PATCH 0553/1083] Sync Strings (#6921) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 7 + .../src/main/res/values-fi/translations.xml | 4 + .../src/main/res/values-fr/translations.xml | 4 + .../src/main/res/values-ja/translations.xml | 5 + .../src/main/res/values-pl/translations.xml | 7 + .../src/main/res/values-ru/translations.xml | 8 + .../src/main/res/values-zh/translations.xml | 5 + .../src/main/res/values-et/translations.xml | 43 + .../src/main/res/values-pl/translations.xml | 9 + .../src/main/res/values-ru/translations.xml | 33 + .../src/main/res/values-zh/translations.xml | 13 +- .../src/main/res/values-et/translations.xml | 2 + .../src/main/res/values-zh/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 3 + .../src/main/res/values-pl/translations.xml | 3 +- .../src/main/res/values-ru/translations.xml | 7 + .../src/main/res/values-zh/translations.xml | 4 +- .../src/main/res/values/localazy.xml | 1 + ....impl.share_ShareLocationView_Day_9_de.png | 3 + ...on.impl.show_ShowLocationView_Day_8_de.png | 3 + ...eeditor_AttachmentImageEditorView_0_de.png | 3 + ...eeditor_AttachmentImageEditorView_1_de.png | 3 + ...eeditor_AttachmentImageEditorView_2_de.png | 3 + ...eeditor_AttachmentImageEditorView_3_de.png | 3 + ...eeditor_AttachmentImageEditorView_4_de.png | 3 + ...eeditor_AttachmentImageEditorView_5_de.png | 3 + ...ts.preview_AttachmentsPreviewView_0_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_1_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_2_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_3_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_4_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_5_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_6_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_7_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_8_de.png | 4 +- ...ts.preview_AttachmentsPreviewView_9_de.png | 3 + ...ts_TimelineItemCallNotifyView_Day_0_de.png | 4 +- ...ions_NotificationSettingsView_Day_0_de.png | 4 +- ...ons_NotificationSettingsView_Day_14_de.png | 3 + ...ons_NotificationSettingsView_Day_15_de.png | 3 + ...ons_NotificationSettingsView_Day_16_de.png | 3 + ...ons_NotificationSettingsView_Day_17_de.png | 3 + ...ons_NotificationSettingsView_Day_18_de.png | 3 + ...ons_NotificationSettingsView_Day_19_de.png | 3 + ...ions_NotificationSettingsView_Day_1_de.png | 4 +- ...ons_NotificationSettingsView_Day_20_de.png | 3 + ...ions_NotificationSettingsView_Day_2_de.png | 4 +- ...ions_NotificationSettingsView_Day_3_de.png | 4 +- ...ions_NotificationSettingsView_Day_4_de.png | 4 +- ...ions_NotificationSettingsView_Day_5_de.png | 4 +- ...ions_NotificationSettingsView_Day_6_de.png | 4 +- ...ions_NotificationSettingsView_Day_7_de.png | 4 +- ...ions_NotificationSettingsView_Day_8_de.png | 4 +- ...ions_NotificationSettingsView_Day_9_de.png | 4 +- ...e.impl.bugreport_BugReportViewDay_0_de.png | 4 +- ...e.impl.bugreport_BugReportViewDay_1_de.png | 4 +- ...e.impl.bugreport_BugReportViewDay_2_de.png | 4 +- ...e.impl.bugreport_BugReportViewDay_3_de.png | 4 +- ...e.impl.bugreport_BugReportViewDay_4_de.png | 4 +- screenshots/html/data.js | 2150 +++++++++-------- 61 files changed, 1337 insertions(+), 1122 deletions(-) create mode 100644 screenshots/de/features.location.impl.share_ShareLocationView_Day_9_de.png create mode 100644 screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_14_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_15_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_16_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_17_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_18_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_19_de.png create mode 100644 screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_20_de.png 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 39900a6f0b..575adc6bb9 100644 --- a/features/home/impl/src/main/res/values-zh/translations.xml +++ b/features/home/impl/src/main/res/values-zh/translations.xml @@ -4,7 +4,7 @@ "禁用优化" "通知未送达?" "通知提示音已升级:更清晰、更快速、干扰更少。" - "我们已更新你的声音" + "我们已更新提示音" "你的聊天已被端到端加密自动备份。如果你无法访问所有设备,则需要使用恢复密钥并保留数字身份。" "获取恢复密钥" "备份聊天" diff --git a/features/messages/impl/src/main/res/values-et/translations.xml b/features/messages/impl/src/main/res/values-et/translations.xml index 506b5ce195..aa5a9045d1 100644 --- a/features/messages/impl/src/main/res/values-et/translations.xml +++ b/features/messages/impl/src/main/res/values-et/translations.xml @@ -16,6 +16,12 @@ "Reisimine ja kohad" "Hiljutised emojid" "Sümbolid" + "Pööra pilti vasakule" + + "%1$d kraad" + "%1$d kraadi" + + "Muuda fotot" "Selgitused ja alapealkirjad ei pruugi olla nähtavad vanemate rakenduste kasutajatele." "Klõpsa üleslaaditava video kvaliteedi muutmiseks" "Faili üleslaadimine ei õnnestunud." @@ -26,6 +32,7 @@ "Objekt %1$d/%2$d" "Optimeeri pildikvaliteeti" "Töötlen…" + "Lisa meediumi" "Blokeeri kasutaja" "Vali see eelistus, kui sa soovid peita selle kasutaja kõik senised ja tulevased sõnumid" "Teade selle sõnumi kohta edastatakse sinu koduserveri haldajale. Haldajal ei ole võimalik lugeda krüptitud sõnumite sisu." diff --git a/features/messages/impl/src/main/res/values-fi/translations.xml b/features/messages/impl/src/main/res/values-fi/translations.xml index 33e8f64d57..25f434ec25 100644 --- a/features/messages/impl/src/main/res/values-fi/translations.xml +++ b/features/messages/impl/src/main/res/values-fi/translations.xml @@ -16,6 +16,10 @@ "Matkustaminen ja paikat" "Viimeaikaiset emojit" "Symbolit" + + "%1$d aste" + "%1$d astetta" + "Kuvatekstit eivät välttämättä näy ihmisille, jotka käyttävät vanhempia sovelluksia." "Napauta muuttaaksesi videon lähetyslaatua" "Tiedostoa ei voitu lähettää." diff --git a/features/messages/impl/src/main/res/values-fr/translations.xml b/features/messages/impl/src/main/res/values-fr/translations.xml index 0d8dab284f..9137d5dae6 100644 --- a/features/messages/impl/src/main/res/values-fr/translations.xml +++ b/features/messages/impl/src/main/res/values-fr/translations.xml @@ -16,6 +16,10 @@ "Voyages & lieux" "Emojis récents" "Symboles" + + "%1$d degré" + "%1$d degrés" + "Les légendes peuvent ne pas être visibles pour les utilisateurs d’anciennes applications." "Cliquez pour modifier la qualité d’envoi de la vidéo" "Le fichier n’a pas pu être envoyé." diff --git a/features/messages/impl/src/main/res/values-ja/translations.xml b/features/messages/impl/src/main/res/values-ja/translations.xml index 93c10d13d8..f1a4bde02f 100644 --- a/features/messages/impl/src/main/res/values-ja/translations.xml +++ b/features/messages/impl/src/main/res/values-ja/translations.xml @@ -16,6 +16,11 @@ "旅・場所" "最近使用" "記号" + "画像を左に回転" + + "%1$d°" + + "写真を編集" "古いアプリケーションを使用しているユーザーはキャプションを見られない可能性があります。" "動画のアップロード画質を変更するにはタップしてください" "ファイルをアップロードに失敗しました。" diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index a0b9c24af2..1a9dc12f1c 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -16,6 +16,13 @@ "Podróż i miejsca" "Ostatnie emoji" "Symbole" + "Obróć obraz w lewo" + + "%1$d stopień" + "%1$d stopnie" + "%1$d stopni" + + "Edytuj zdjęcie" "Opis może być niedostępny dla osób korzystających ze starszej wersji aplikacji." "Dotknij, aby zmienić jakość przesyłania wideo." "Nie udało się przesłać pliku." diff --git a/features/messages/impl/src/main/res/values-ru/translations.xml b/features/messages/impl/src/main/res/values-ru/translations.xml index a7d22b6542..5c3aa6f5e1 100644 --- a/features/messages/impl/src/main/res/values-ru/translations.xml +++ b/features/messages/impl/src/main/res/values-ru/translations.xml @@ -16,6 +16,13 @@ "Путешествия и места" "Недавние эмодзи" "Символы" + "Повернуть изображение влево." + + "%1$d градус" + "%1$d градуса" + "%1$d градусов" + + "Редактировать фото" "Подпись может быть не видна пользователям старых приложений." "Нажмите, чтобы изменить качество загружаемого видео." "Файл не может быть загружен." @@ -26,6 +33,7 @@ "%1$d из %2$d" "Оптимизировать качество изображения" "Обработка…" + "Добавить медиа" "Заблокировать пользователя" "Отметьте, хотите ли вы скрыть все текущие и будущие сообщения от этого пользователя" "Это сообщение будет передано администратору вашего домашнего сервера. Они не смогут прочитать зашифрованные сообщения." diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index bdd898d26f..c572b737f1 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -16,6 +16,11 @@ "文旅景点" "最近的 Emoji" "符号" + "向左旋转图像" + + "%1$d 度" + + "编辑照片" "使用旧版应用程序的用户可能无法看到字幕。" "点按以更改视频上传质量" "无法上传该文件。" diff --git a/features/preferences/impl/src/main/res/values-et/translations.xml b/features/preferences/impl/src/main/res/values-et/translations.xml index d1e2b91d58..fab8eeff41 100644 --- a/features/preferences/impl/src/main/res/values-et/translations.xml +++ b/features/preferences/impl/src/main/res/values-et/translations.xml @@ -58,6 +58,7 @@ "Kas tahad katsetada?" "Katsed" "Täiendavad seadistused" + "Kõne helin" "Hääl- ja videokõned" "Eelistused ei sobi omavahel" "Et eelistusi oleks kergem leida, me oleme lihtsustanud teavituste seadistusi. Kuigi mõned varem valitud eelistused pole siin näha, siis nad kehtivad jätkuvalt. @@ -76,10 +77,52 @@ Kui sa jätkad muutmist, siis võivad muutuda ka need peidetud eelistused.""Kutsed" "Sinu koduserver ei toeta seda funktsionaalsust krüptitud jututubades ja seega ei pruugi kõik teavitused sinuni jõuda." "Mainimiste alusel" + "Vali muu ​​helin…" + "Hetkel on kasutusel %1$s" + "Sõnumi heli" + "Sõnumi heli" "Kõik" "Mainimiste alusel" "Teavita mind" "Teavita mind @jututoa puhul" + "Kohandatud" + "Sinu valitud helin…" + "Viga faili kustutamisel" + "Elementi vaikimisi väärtus" + "Elemendi hajumine" + "Viga faili importimisel" + "Viga helina eelvaate esitamisel" + "Helin" + "Sulge helinavea viga" + "Viga helina seadistamisel" + "Vaikne" + "Hoiatus" + "Ootus" + "Kelluke" + "Õitsemine" + "Kalüpso" + "Kellamäng" + "Tšuhh-tšuhh" + "Süsteemi vaikimisi väärtus" + "Laskumine" + "Elektrooniline" + "Tuututamine" + "Klaas" + "Pasun" + "Redel" + "Menuett" + "Uudisvälgatus" + "Sünge" + "Sherwoodi mets" + "Loits" + "Põnevus" + "Vihin-vuhin" + "Telegraaf" + "Kikivarvul" + "Kolmetooniline" + "Säuts" + "Kirjutusmasinad" + "Uuenda" "Teavituste saamiseks palun muuda oma %1$s." "süsteemi seadistusi" "Süsteemi teavitused on välja lülitatud" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index ca81984032..44bb62acfe 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -59,6 +59,7 @@ "Chcesz poeksperymentować?" "Laboratoria" "Dodatkowe ustawienia" + "Dzwonek połączenia" "Połączenia audio i wideo" "Niezgodność konfiguracji" "Uprościliśmy Ustawienia powiadomień, aby ułatwić nawigowanie między opcjami. Niektóre ustawienia, które wybrałeś mogły zniknąć, lecz są wciąż aktywne. @@ -77,10 +78,15 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "Zaproszenia" "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi." "Wzmianki" + "Wybierz inny dźwięk…" + "Aktualnie używany %1$s" + "Dźwięk wiadomości" + "Dźwięk wiadomości" "Wszystkie" "Wzmianki" "Powiadamiaj mnie przez" "Powiadom mnie na @pokój" + "Własny" "Własny dźwięk…" "Błąd usuwania pliku" "Domyślny Element" @@ -88,7 +94,9 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "Błąd importowania pliku" "Wystąpił błąd podczas podglądania dźwięku powiadomień" "Dźwięk" + "Pomiń dźwięk błędu" "Nie udało się ustawić dźwięku powiadomień" + "Cichy" "Alert" "Oczekiwanie" "Dzwonek" @@ -96,6 +104,7 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "Kalipso" "Gong" "Ciuchcia" + "Ustawienie domyślne" "Opadający" "Elektroniczna" "Fanfary" diff --git a/features/preferences/impl/src/main/res/values-ru/translations.xml b/features/preferences/impl/src/main/res/values-ru/translations.xml index eb4ad2245d..1987a17643 100644 --- a/features/preferences/impl/src/main/res/values-ru/translations.xml +++ b/features/preferences/impl/src/main/res/values-ru/translations.xml @@ -81,6 +81,39 @@ "Упоминания" "Уведомлять меня" "Уведомлять меня при упоминании @room" + "Пользовательский звук…" + "Ошибка при удалении файла" + "Element по умолчанию" + "Ошибка импорта файла" + "Ошибка предварительного прослушиванием звука" + "Звук" + "Проблема с настройкой звукового оповещения" + "Оповещение" + "Anticipate" + "Bell" + "Bloom" + "Calypso" + "Chime" + "Choo Choo" + "Descent" + "Electronic" + "Fanfare" + "Glass" + "Horn" + "Ladder" + "Minuet" + "News Flash" + "Noir" + "Sherwood Forest" + "Spell" + "Suspense" + "Swish" + "Telegraph" + "Tiptoes" + "Tri-tone" + "Tweet" + "Typewriters" + "Обновить" "Чтобы получать уведомления, измените %1$s." "системные настройки" "Системные уведомления выключены" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 3726b82206..b5d9d702c9 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -57,6 +57,7 @@ "想尝试新功能?" "实验室" "更多设置" + "来电铃声" "音视频通话" "配置不匹配" "我们简化了通知设置,使选项更易于查找。你曾经选择的某些自定义设置未在此处显示,但它们仍然有效。 @@ -75,18 +76,25 @@ "邀请" "主服务器不支持在加密房间中的此选项,因此在某些房间你可能无法收到通知。" "提及" + "选择其它提示音…" + "当前正在使用 %1$s" + "消息提示音" + "消息提示音" "全部" "提及" "通知我以下类型" "提及所有成员(@room)时通知我" - "自定义声音…" + "自定义" + "自定义提示音…" "删除文件时出错" "Element 默认" "Element 淡入" "导入文件时出错" "预览提示音时出现问题" - "声音" + "提示音" + "忽略提示音错误" "设置提示音时出现问题" + "静默" "提醒声" "悉心期盼" "铃铛" @@ -94,6 +102,7 @@ "即兴曲调" "风铃" "火车鸣笛" + "系统默认" "渐弱" "电子乐" "嘹亮吹奏声" diff --git a/features/rageshake/impl/src/main/res/values-et/translations.xml b/features/rageshake/impl/src/main/res/values-et/translations.xml index 2f55a9b6b5..1f61849fa5 100644 --- a/features/rageshake/impl/src/main/res/values-et/translations.xml +++ b/features/rageshake/impl/src/main/res/values-et/translations.xml @@ -8,6 +8,8 @@ "Palun kirjelda probleemi…" "Kui vähegi võimalik, siis kirjuta inglise keeles." "Kirjeldus on liiga lühike. Palun jaga täpsemat teavet selle kohta, mis juhtus. Tänud juba ette!" + "Võid sisestada seotud GitHubi veateate numbri, kui see on olemas." + "Veateade GitHubis" "Saada krahhilogid" "Luba logide saatmine" "Sinu logid on väga mahukad ja neid ei saa siia lisada. Palun saada logid meile mõnel muul viisil." diff --git a/features/rageshake/impl/src/main/res/values-zh/translations.xml b/features/rageshake/impl/src/main/res/values-zh/translations.xml index c42141d291..17cac7de3b 100644 --- a/features/rageshake/impl/src/main/res/values-zh/translations.xml +++ b/features/rageshake/impl/src/main/res/values-zh/translations.xml @@ -8,6 +8,7 @@ "描述问题…" "请尽可能用英文描述。" "描述太短,请提供详细情况。谢谢!" + "你可以输入与之相关的 GitHub issue 编号(如果有)。" "发送崩溃日志" "允许日志" "日志文件过大,无法包含在本次报告中,请通过其它方式发送给我们。" 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 f1c7d8d225..fd45849e7d 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -18,6 +18,7 @@ "Teave" "Liitu kõnega" "Mine lõppu" + "Mine lugemata sõnumite juurde" "Nihuta kaart minu asukohta" "Ainult mainimised" "Summutatud" @@ -98,6 +99,7 @@ "Keeldu ja blokeeri" "Kustuta" "Kustuta kasutajakonto" + "Kustuta fail" "Kustuta küsitlus" "Eemalda kõik valikud" "Lülita välja" @@ -303,6 +305,7 @@ Põhjus: %1$s." "Palun oota…" "Kas oled kindel, et soovid selle küsitluse lõpetada?" "Küsitlus: %1$s" + "Küsitlus" "Hääli kokku: %1$s" "Tulemused on näha peale küsitluse lõppemist" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index 7e0b78641e..baa2eb8506 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -308,6 +308,7 @@ Powód: %1$s." "Proszę czekać…" "Jesteś pewien, że chcesz zakończyć tę ankietę?" "Ankieta: %1$s" + "Ankieta" "Łączna liczba głosów: %1$s" "Wyniki zostaną wyświetlone po zakończeniu ankiety" @@ -424,7 +425,7 @@ Powód: %1$s." "Balans między jakością a szybkością przesyłania" "Wiadomość głosowa" "Oczekiwanie…" - "Oczekiwanie na tę wiadomość" + "Oczekiwanie wiadomości" "Czekam na lokalizację na żywo…" "Każdy może zobaczyć historię" "Ty" 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 3596bc04fe..b35d346484 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -10,6 +10,7 @@ "Введено %1$d цифры" "Введено %1$d цифр" + "Продолжительность: %1$s" "Изменить аватар" "Полный адрес %1$s" "Сведения о шифровании" @@ -18,6 +19,7 @@ "Информация" "Присоединиться к звонку" "Перейти вниз" + "Перейти к непрочитанным" "Переместить карту к моему местоположению" "Только упоминания" "Без звука" @@ -34,6 +36,7 @@ "Скорость воспроизведения" "Опрос" "Завершённый опрос" + "Позиция: %1$s" "QR-код" "Реагировать вместе с %1$s" "Реакция с помощью эмодзи" @@ -50,12 +53,15 @@ "Аватар комнаты" "Отправить файлы" "Местоположение отправителя" + "Отправлено пользователем %1$s в %2$s" "Требуется действие, на которое есть ограничение по времени, у вас есть одна минута для проверки" "Настройки, требуется действие" "Показать пароль" "Начать звонок" "Начать видеозвонок" "Начать голосовой вызов" + "Обсуждение в %1$s" + "Обсуждения в %1$s" "Брошенная комната" "Аватар пользователя" "Меню пользователя" @@ -302,6 +308,7 @@ "Подождите…" "Вы действительно хотите завершить данный опрос?" "Опрос: %1$s" + "Опрос" "Всего голосов: %1$s" "Результаты будут показаны после завершения опроса" 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 e40d369f76..2acc9df99f 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -96,6 +96,7 @@ "拒绝并屏蔽" "删除" "删除账户" + "删除文件" "删除投票" "取消全选" "禁用" @@ -218,7 +219,7 @@ "正在创建房间…" "正在创建空间…" "申请已取消" - "离开房间" + "已离开房间" "离开空间" "邀请已拒绝" "解密错误" @@ -299,6 +300,7 @@ "请稍候…" "确定要结束这个投票吗?" "投票:%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 d74f532484..823c0fad72 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -99,6 +99,7 @@ "Decline and block" "Delete" "Delete account" + "Delete file" "Delete Poll" "Deselect all" "Disable" diff --git a/screenshots/de/features.location.impl.share_ShareLocationView_Day_9_de.png b/screenshots/de/features.location.impl.share_ShareLocationView_Day_9_de.png new file mode 100644 index 0000000000..d8b464213f --- /dev/null +++ b/screenshots/de/features.location.impl.share_ShareLocationView_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1ab182dfc2b45c80972722b1963a75c29175c1d09369fafb96c7b0ea04bf08a +size 21171 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png new file mode 100644 index 0000000000..a49023fb61 --- /dev/null +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa435ee5d684b82c66c7207e0bcdc2d608a634e02d534530cccf8abd0f40f784 +size 21292 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png new file mode 100644 index 0000000000..6c398bfae2 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56f7a86707c00d1833ebbb26182ad9f9f010ed8f016713076232d4134c8bb6e7 +size 329737 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png new file mode 100644 index 0000000000..25ae9b6949 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6907cdde67cfb41246b9b86af19d0d46bf92914b21f9ab68d522f07dd83af153 +size 284058 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png new file mode 100644 index 0000000000..0d11558b0e --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ec83baa6376355fcfa1e9a088faee47f5d7d87ed7608bcbe35e7438f9e0cdea +size 257324 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png new file mode 100644 index 0000000000..6fadc05d09 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17bd7ae449ad1fb92c75e09848bddf907d15cfcbbcb9554350893c7a6019add5 +size 278513 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png new file mode 100644 index 0000000000..3eba67d146 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e692a9e204db51af62fa83af8c1c7dda4fdfe81077d3abced093f3f8dfdef2df +size 252607 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png new file mode 100644 index 0000000000..cb1f4a9175 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e881c0e26edfd9f4f2eb7325e307edcd4220aae42337ce8d238cd64c88722de4 +size 312002 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png index 3d408f0ee2..c9ec0e5253 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c110f007c954fd01fad8d4e9810abae47bb89c330141c7c1d6412d3995943f4b -size 400985 +oid sha256:14a4be90563169ef442341a03c8add67df6ad2385b23221f7a484b296d47cab9 +size 405385 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_de.png index 4ce254bb81..a1fdd29d48 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af9841032d9faebbee6f759259ef14b0d4cca3424ac110e1dfd1d3357768e436 -size 399354 +oid sha256:c15b4ac06b3327c95f4e40556e2c7cc0fdd0de6942dcc41a06545b03f3d7efb9 +size 403700 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png index d466ee2bc4..7700d70b06 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8fae17aad6ac7dfb2fd2fac83c2c1b6d9e0743fa9d3d1a874fe269284149ce29 -size 62760 +oid sha256:608236a6a1864f0036fb0d2bcd85d7269557dc3453876495585573471d08d2de +size 65085 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png index 3d408f0ee2..c9ec0e5253 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c110f007c954fd01fad8d4e9810abae47bb89c330141c7c1d6412d3995943f4b -size 400985 +oid sha256:14a4be90563169ef442341a03c8add67df6ad2385b23221f7a484b296d47cab9 +size 405385 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png index c45996cc7b..c9b90482e3 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbcda50596ea08167fda422fae89758bc46c719cd320103def3c90cea0a152ff -size 62616 +oid sha256:116502f69435e6d7a5fe9fe9a2a604fcca36d1c6e1e09836595769cf8e8022d9 +size 64937 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png index a1ae4a1c9b..c10cca29ea 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b1172f37d89f97ec0360402c013328ad65bfb62422d5b81a8d06e9d8dc3cbba -size 67739 +oid sha256:eb69e3738018bd6138e1f04478b5f7b5758816b9516f871dc8643ea037ba1c65 +size 71377 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png index 3baea3a223..11e4bb1119 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29d6a3980b5928907e5d5203ba4a5010feed5ca67107ef464933717664d72fb1 -size 71937 +oid sha256:130c46b4bd3589cc6a6e45a04f9793b742631daf21cbbf971f8e79a00f589ce8 +size 329628 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png index be72870cdf..d68e7eb35d 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df744636336e3b7dcf4b8c20a3a9dcf70247ea0a5602c11665bb020925c94dd1 -size 407934 +oid sha256:6bea145d686c295829e91a0a19e4172155ddd03ae62730241ee55e3c759d5f88 +size 75505 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png index 48b54318d5..b40455736b 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea59b97a710eab6b10192373c7058b301e0d2b4bfe07d16f952d69593b8b78d7 -size 88581 +oid sha256:7587dfe56eb8de6c4ed8117ad9bf1066cd53b5e89430be66a9b9f3ae357343fe +size 412192 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_de.png new file mode 100644 index 0000000000..dee57573b1 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a1a324578ba710175ade8d54b2f99e8103b893d7a3e7d1353ddc2b2c0c3a285 +size 91939 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png index d005896ab7..b6f95124eb 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08984e24e297742f065201c4cea3d07eda34e4c80fbcb4689e539ac64f32f1db -size 53795 +oid sha256:a2d68bc8db6190fbd5205fdaa386c250ae3a2014804a5372052d851a313a6ef1 +size 47808 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_0_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_0_de.png index 446b8185f5..3506d44218 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_0_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26f2620aa348febb2db9ebe379a964b76220819f7165fa7a5be5e2a38c2534a2 -size 67183 +oid sha256:cdde4c4250683a2cf63988a92dc03cbc64581794c9f25567ecca61675edea9dc +size 64428 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_14_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_14_de.png new file mode 100644 index 0000000000..4b59292eaa --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_14_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:168c2399ac6262c65e1026e3c79fe2c93dd6805ac73b9bc26adfaad8afeab724 +size 53258 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_15_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_15_de.png new file mode 100644 index 0000000000..de235a8eb6 --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_15_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:950b6b93b0b31d0bef28e6b7ff0759e1e6e3ee48fac8278035665247f1176e8b +size 51887 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_16_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_16_de.png new file mode 100644 index 0000000000..d46754d4f0 --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_16_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d53770762a7b2477787fb21acb17303b671d549b4eab5f54ccbf6d1c566aa50 +size 53023 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_17_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_17_de.png new file mode 100644 index 0000000000..06c3f12377 --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_17_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32abcd8e957508558dde739c881f2ce9efac648404c420aac44127d0b449d5c4 +size 53000 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_18_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_18_de.png new file mode 100644 index 0000000000..6e9281a6b2 --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_18_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6bf8bb2491b685153fb11542be0de2a95cdd00ab294cf0bf882e890f8f5f697 +size 48682 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_19_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_19_de.png new file mode 100644 index 0000000000..7439ba1f73 --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_19_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4f67eb6df70b214682b9b337886cee1653c3804be2b3a6ed581247c22fc0d5f +size 44778 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_1_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_1_de.png index e0fac995a2..06c3f12377 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_1_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9ebab37f3d289cd684d616961b2f4b993a851a34bb8d41ce889443ce51c4c5f -size 53981 +oid sha256:32abcd8e957508558dde739c881f2ce9efac648404c420aac44127d0b449d5c4 +size 53000 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_20_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_20_de.png new file mode 100644 index 0000000000..10bda48dc6 --- /dev/null +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_20_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:058a2ef322426a6c996698c5c0df64f8d4cec5107b918101478a6f478897c3c1 +size 46365 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_2_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_2_de.png index 286ee2d3e3..5cd18f7bfa 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_2_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d578725c9ef0c37be7115017fe1b7f7da41c02a54f932ee389d4683f2ec3f524 -size 48465 +oid sha256:78109755f9bb674e0b026f8696dcc5024e1aa07838d404954e17edcf8d752e80 +size 47441 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png index 8428aafe61..252f3c7397 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e949b9fc728afe5da33073a5273aebe797a7c45a68fc6049e9292d0a256adad7 -size 49632 +oid sha256:288f3c3887439cfe8b4fea6ba7b5091c2342cf9e962ad2ddbbeea99243feddaf +size 48577 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png index 8428aafe61..252f3c7397 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e949b9fc728afe5da33073a5273aebe797a7c45a68fc6049e9292d0a256adad7 -size 49632 +oid sha256:288f3c3887439cfe8b4fea6ba7b5091c2342cf9e962ad2ddbbeea99243feddaf +size 48577 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_5_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_5_de.png index e0fac995a2..06c3f12377 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_5_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9ebab37f3d289cd684d616961b2f4b993a851a34bb8d41ce889443ce51c4c5f -size 53981 +oid sha256:32abcd8e957508558dde739c881f2ce9efac648404c420aac44127d0b449d5c4 +size 53000 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png index b107216acc..dbc959895b 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23548dc4c9b3ede93580ce56989ff05d4317605aaa584744f73a5897d0cd6c51 -size 46743 +oid sha256:56fbcdd514a6fc964e0713ee18490f801bee4b5b91f1ebbf9471262af37830e1 +size 45656 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png index 058db215b6..9d81cecd3f 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a284cc8503c3cd6227afbd593d36e6f9a9eeadbd323b5cf66d77e3b5eeb6681 -size 51713 +oid sha256:a2bc82e2fa80c56ef65b462421c4b0204e6077547226b799c5a9a47367a1dfb2 +size 50724 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_8_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_8_de.png index e0fac995a2..06c3f12377 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_8_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9ebab37f3d289cd684d616961b2f4b993a851a34bb8d41ce889443ce51c4c5f -size 53981 +oid sha256:32abcd8e957508558dde739c881f2ce9efac648404c420aac44127d0b449d5c4 +size 53000 diff --git a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_9_de.png b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_9_de.png index e0fac995a2..06c3f12377 100644 --- a/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_9_de.png +++ b/screenshots/de/features.preferences.impl.notifications_NotificationSettingsView_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9ebab37f3d289cd684d616961b2f4b993a851a34bb8d41ce889443ce51c4c5f -size 53981 +oid sha256:32abcd8e957508558dde739c881f2ce9efac648404c420aac44127d0b449d5c4 +size 53000 diff --git a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_0_de.png b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_0_de.png index 42885de40c..429f3b3bf0 100644 --- a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_0_de.png +++ b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f935cbeb516a345549877793ed1e0e5d82b0b1b81b65d54f028d8ee30a3eeb7c -size 50075 +oid sha256:b3309c34f8127f41b85f915246d87b257befd909c6ea13151f018f2af838cee3 +size 55553 diff --git a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_1_de.png b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_1_de.png index afb28a7513..3386f18dd6 100644 --- a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_1_de.png +++ b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54c0d5db8026616d766d1ceb94fbac1c3588be1ac3baa38e05ef4f665aa9419f -size 115721 +oid sha256:4d11dbfc86f54a219d989672e5a5f2c729e1373706be22256aa913d3a2f67eb8 +size 116355 diff --git a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_2_de.png b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_2_de.png index 4b03d29ff9..46a240da00 100644 --- a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_2_de.png +++ b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8efca7b9be49bd84f809fac58de983e6126714914250ce4b0dcb96a56125bb7 -size 46915 +oid sha256:2a786030fface63e75009179d2473c5ec880cfb194ba43a85f2bbef3090a205b +size 52774 diff --git a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_3_de.png b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_3_de.png index 42885de40c..429f3b3bf0 100644 --- a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_3_de.png +++ b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f935cbeb516a345549877793ed1e0e5d82b0b1b81b65d54f028d8ee30a3eeb7c -size 50075 +oid sha256:b3309c34f8127f41b85f915246d87b257befd909c6ea13151f018f2af838cee3 +size 55553 diff --git a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_4_de.png b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_4_de.png index 473b887d73..6b799d3180 100644 --- a/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_4_de.png +++ b/screenshots/de/features.rageshake.impl.bugreport_BugReportViewDay_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3d7c97667774e00e618be65e63423d9d62c8b30dfe95cddad1d5dc62255e38c -size 39638 +oid sha256:90360b93852bbcbcf694f892075401d9019f0b28f34abbe24f3546a9db62fd81 +size 44307 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 119bc1e013..edcd08b481 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -2,99 +2,105 @@ export const screenshots = [ ["en","en-dark","de",], ["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",0,], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20595,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20602,], ["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",20595,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20595,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20595,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20595,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20595,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20595,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20595,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20595,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20595,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20595,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20595,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20602,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20602,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20602,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20602,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20602,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20602,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20602,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20602,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20602,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20602,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20602,], ["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",20595,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20595,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20602,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20602,], ["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",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20602,], ["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",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20595,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20595,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20595,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20595,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20595,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20595,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20595,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20595,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20595,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20595,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20602,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20602,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20602,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20602,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20602,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20602,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20602,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20602,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20602,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20595,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20595,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20595,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20595,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20595,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20602,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20602,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20602,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20602,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20602,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20595,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20595,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20595,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20595,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20602,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20602,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20602,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20602,], ["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",20595,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20602,], ["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",20595,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20602,], ["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",20595,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20602,], ["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",20595,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en","",20605,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20605,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20605,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20605,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20605,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20605,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20602,], ["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,], @@ -104,19 +110,20 @@ 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","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20595,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20595,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20602,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20605,], ["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",20595,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20602,], ["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,], @@ -146,22 +153,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",20595,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20602,], ["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",20595,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20595,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20595,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20595,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20595,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20595,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20595,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20602,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20595,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20595,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20595,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20595,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20595,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20602,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20602,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20602,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20602,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20602,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -172,141 +179,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",20595,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20595,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20602,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20602,], ["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",20595,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20602,], ["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",20595,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20595,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20595,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20595,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20595,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20595,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20602,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20602,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20602,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20602,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20602,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20602,], ["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",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20595,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20595,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20595,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20602,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20602,], ["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",20595,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20595,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20595,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20595,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20595,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20602,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20602,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20602,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20602,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20602,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20595,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20602,], ["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",20595,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20595,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20595,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20595,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20595,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20595,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20595,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20595,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20602,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20602,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20602,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20602,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20602,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20602,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20602,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20602,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], -["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20595,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20602,], ["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",20595,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20595,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20595,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20595,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20595,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20595,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20595,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20602,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20602,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20602,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20602,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20602,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20602,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20602,], ["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","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20595,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20595,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20595,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20595,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20595,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20595,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20602,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20602,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20602,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20602,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20602,], ["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",20595,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20595,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20595,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20595,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20595,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20595,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20595,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20595,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20595,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20595,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20595,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20595,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20595,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20595,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20595,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20595,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20595,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20595,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20595,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20595,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20602,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20602,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20602,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20602,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20602,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20602,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20602,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20602,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20602,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20602,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20602,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20602,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20602,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20602,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20602,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20602,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20602,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20602,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20602,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20602,], ["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","",20595,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20595,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20595,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20595,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20595,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20595,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20595,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20602,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20602,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20602,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20602,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20602,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20602,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20602,], ["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",20595,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20595,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20595,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20602,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20602,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20602,], ["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",20595,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20602,], ["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",20595,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20595,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20595,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20595,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20595,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20595,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20595,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20595,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20595,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20602,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20602,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20602,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20602,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20602,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20602,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20602,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20602,], ["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,], @@ -319,20 +326,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",20595,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20595,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20595,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20595,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20595,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20595,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20595,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20595,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20595,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20595,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20595,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20595,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20595,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20595,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20602,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20602,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20602,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20602,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20602,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20602,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20602,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20602,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20602,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20602,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20602,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20602,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20602,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20602,], ["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,], @@ -340,29 +347,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20595,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20595,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20602,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20602,], ["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",20595,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20595,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20595,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20595,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20595,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20595,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20595,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20595,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20595,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20595,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20602,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20602,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20602,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20602,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20602,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20602,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20602,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20602,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20602,], ["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,], @@ -382,49 +389,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",20595,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20595,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20595,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20602,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20602,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20602,], ["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",20595,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20595,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20602,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20602,], ["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",20595,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20602,], ["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",20595,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20595,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20595,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20595,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20595,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20602,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20602,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20602,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20602,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20602,], ["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",20595,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20595,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20602,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20602,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20595,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20595,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20602,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20602,], ["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",20595,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20595,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20595,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20595,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20595,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20595,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20595,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20595,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20595,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20595,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20595,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20595,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20595,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20602,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20602,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20602,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20602,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20602,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20602,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20602,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20602,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20602,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20602,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20602,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20602,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20602,], ["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,], @@ -439,8 +446,8 @@ export const screenshots = [ ["appicon.enterprise_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",20595,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20595,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20602,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20602,], ["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,], @@ -448,119 +455,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",20595,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20602,], ["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",20595,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20602,], ["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",20595,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20595,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20602,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20602,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20595,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20595,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20602,], ["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",20595,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20595,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20595,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20602,], ["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",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20602,], ["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",20595,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20595,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20595,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20602,], ["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",20595,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20595,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20595,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20595,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20595,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20595,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20595,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20595,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20602,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20602,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20602,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20602,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20602,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20602,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20602,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20602,], ["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",20595,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20595,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20595,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20595,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20595,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20602,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20602,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20602,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20595,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20595,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20602,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20602,], ["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",20595,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20595,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20595,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20595,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20595,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20595,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20595,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20595,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20602,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20602,], ["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",20595,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20595,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20595,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20595,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20595,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20595,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20602,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20602,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20602,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20602,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20602,], ["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",20595,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20602,], ["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,], @@ -613,48 +620,48 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextNoPadding_List_supporting_text_-_no_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], -["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20595,], +["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20602,], ["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",20595,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20602,], ["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",20595,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20595,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20595,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20602,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20602,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20602,], ["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",20595,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20595,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20595,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20595,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20595,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20595,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20595,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20595,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20595,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20595,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20595,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20595,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20595,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20595,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20595,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20595,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20595,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20595,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20595,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20595,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20595,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20595,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20595,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20595,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20595,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20595,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20595,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20602,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20602,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20602,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20602,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20602,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20602,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20602,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20602,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20602,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20602,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20602,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20602,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20602,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20602,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20602,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20602,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20602,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20602,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20602,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20602,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20602,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20602,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20602,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20602,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20602,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20602,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20602,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20595,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20595,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20595,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20595,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20602,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20602,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20602,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20602,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -667,26 +674,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20595,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20595,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20595,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20595,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20595,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20595,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20602,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20602,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20602,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20602,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20602,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20602,], ["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",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20595,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20595,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20602,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20602,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -694,10 +701,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20595,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20602,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20602,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], @@ -707,7 +714,7 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20602,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -717,10 +724,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20595,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20602,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20602,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], @@ -730,7 +737,7 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerView_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20595,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20602,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -744,7 +751,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",20595,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20602,], ["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,], @@ -753,7 +760,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",20595,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20602,], ["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,], @@ -762,24 +769,24 @@ 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",20595,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20595,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20595,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20595,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20595,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20595,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20595,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20595,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20595,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20595,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20595,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20595,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20595,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20595,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20595,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20595,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20602,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20602,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20602,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20602,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20602,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20602,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20602,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20602,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20602,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20602,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20602,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20602,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20602,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20602,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20602,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20602,], ["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",20595,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20602,], ["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,], @@ -790,117 +797,124 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20595,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20595,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20595,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20605,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20602,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20602,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20602,], ["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",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20595,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20595,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20602,], ["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",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20595,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20602,], ["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",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20595,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20595,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20602,], ["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",20595,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20595,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20595,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20595,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20595,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20595,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20602,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20602,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20602,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20602,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20602,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20602,], ["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",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20595,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20595,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20602,], ["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",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20595,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20595,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20595,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20595,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20595,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20595,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20602,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20602,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20602,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20602,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20602,], ["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",20595,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20595,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20595,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20595,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20595,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20602,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20602,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20602,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20602,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20602,], ["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",20595,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20595,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20595,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20595,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20595,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20595,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20595,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20595,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20595,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20595,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20595,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20602,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20602,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20602,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20602,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20602,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20602,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20602,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20602,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20602,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20602,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20602,], ["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,], @@ -914,225 +928,225 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20595,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20595,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20602,], ["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","",20595,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20595,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20602,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20602,], ["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",20595,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20595,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20595,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20595,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20595,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20595,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20595,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20595,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20595,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20595,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20595,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20595,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20595,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20595,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20595,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20595,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20595,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20595,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20595,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20595,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20595,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20602,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20602,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20602,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20602,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20602,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20602,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20602,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20602,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20602,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20602,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20602,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20602,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20602,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20602,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20602,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20602,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20602,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20602,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20602,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20602,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20602,], ["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",20595,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20595,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20602,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20602,], ["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",20595,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20595,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20595,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20595,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20595,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20595,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20595,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20602,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20602,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20602,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20602,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20602,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20602,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20602,], ["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",20595,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20595,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20595,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20595,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20595,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20595,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20595,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20595,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20595,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20595,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20595,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20595,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20595,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20595,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20595,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20595,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20595,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20602,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20602,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20602,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20602,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20602,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20602,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20602,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20602,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20602,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20602,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20602,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20602,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20602,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20602,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20602,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20602,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20602,], ["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",20595,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20595,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20595,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20595,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20595,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20602,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20602,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20602,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20602,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20602,], ["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",20595,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20595,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20602,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20602,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20595,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20595,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20595,], -["features.roomdetails.impl_RoomDetails_0_en","",20595,], -["features.roomdetails.impl_RoomDetails_10_en","",20595,], -["features.roomdetails.impl_RoomDetails_11_en","",20595,], -["features.roomdetails.impl_RoomDetails_12_en","",20595,], -["features.roomdetails.impl_RoomDetails_13_en","",20595,], -["features.roomdetails.impl_RoomDetails_14_en","",20595,], -["features.roomdetails.impl_RoomDetails_15_en","",20595,], -["features.roomdetails.impl_RoomDetails_16_en","",20595,], -["features.roomdetails.impl_RoomDetails_17_en","",20595,], -["features.roomdetails.impl_RoomDetails_18_en","",20595,], -["features.roomdetails.impl_RoomDetails_19_en","",20595,], -["features.roomdetails.impl_RoomDetails_1_en","",20595,], -["features.roomdetails.impl_RoomDetails_20_en","",20595,], -["features.roomdetails.impl_RoomDetails_21_en","",20595,], -["features.roomdetails.impl_RoomDetails_22_en","",20595,], -["features.roomdetails.impl_RoomDetails_2_en","",20595,], -["features.roomdetails.impl_RoomDetails_3_en","",20595,], -["features.roomdetails.impl_RoomDetails_4_en","",20595,], -["features.roomdetails.impl_RoomDetails_5_en","",20595,], -["features.roomdetails.impl_RoomDetails_6_en","",20595,], -["features.roomdetails.impl_RoomDetails_7_en","",20595,], -["features.roomdetails.impl_RoomDetails_8_en","",20595,], -["features.roomdetails.impl_RoomDetails_9_en","",20595,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20595,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20595,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20595,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20595,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20595,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20595,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20595,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20595,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20595,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20602,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20602,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20602,], +["features.roomdetails.impl_RoomDetails_0_en","",20602,], +["features.roomdetails.impl_RoomDetails_10_en","",20602,], +["features.roomdetails.impl_RoomDetails_11_en","",20602,], +["features.roomdetails.impl_RoomDetails_12_en","",20602,], +["features.roomdetails.impl_RoomDetails_13_en","",20602,], +["features.roomdetails.impl_RoomDetails_14_en","",20602,], +["features.roomdetails.impl_RoomDetails_15_en","",20602,], +["features.roomdetails.impl_RoomDetails_16_en","",20602,], +["features.roomdetails.impl_RoomDetails_17_en","",20602,], +["features.roomdetails.impl_RoomDetails_18_en","",20602,], +["features.roomdetails.impl_RoomDetails_19_en","",20602,], +["features.roomdetails.impl_RoomDetails_1_en","",20602,], +["features.roomdetails.impl_RoomDetails_20_en","",20602,], +["features.roomdetails.impl_RoomDetails_21_en","",20602,], +["features.roomdetails.impl_RoomDetails_22_en","",20602,], +["features.roomdetails.impl_RoomDetails_2_en","",20602,], +["features.roomdetails.impl_RoomDetails_3_en","",20602,], +["features.roomdetails.impl_RoomDetails_4_en","",20602,], +["features.roomdetails.impl_RoomDetails_5_en","",20602,], +["features.roomdetails.impl_RoomDetails_6_en","",20602,], +["features.roomdetails.impl_RoomDetails_7_en","",20602,], +["features.roomdetails.impl_RoomDetails_8_en","",20602,], +["features.roomdetails.impl_RoomDetails_9_en","",20602,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20602,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20602,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20602,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20602,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20602,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20602,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20602,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20602,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20602,], ["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",20595,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20595,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20595,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20595,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20595,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20595,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20595,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20595,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20595,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20595,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20595,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20602,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20602,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20602,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20602,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20602,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20602,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20602,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20602,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20602,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20602,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20602,], ["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",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20595,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20595,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20595,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20602,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20602,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20602,], ["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",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20595,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20595,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20602,], ["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",20595,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20595,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20595,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20595,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20595,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20595,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20602,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20602,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20602,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20602,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20602,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20602,], ["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,], @@ -1155,16 +1169,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20595,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20595,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20602,], ["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",20595,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20602,], ["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,], @@ -1174,118 +1188,118 @@ export const screenshots = [ ["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,], ["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_0_en","appnav.root_RootView_Night_0_en",20595,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20595,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20595,], -["appicon.element_RoundIcon_en","",0,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20602,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20602,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20602,], ["appicon.enterprise_RoundIcon_en","",0,], +["appicon.element_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",20595,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20595,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20595,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20595,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20595,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20595,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20595,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20595,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20602,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20602,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20602,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20602,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20602,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20602,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20602,], ["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","",20595,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20602,], ["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","",20595,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20595,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20595,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20595,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20595,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20595,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20595,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20595,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20595,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20595,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20595,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20595,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20595,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20595,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20595,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20602,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20602,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20602,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20602,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20602,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20602,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20602,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20602,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20602,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20602,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20602,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20602,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20602,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20602,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20602,], ["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,], @@ -1308,38 +1322,40 @@ 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",20595,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20595,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20595,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20595,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20595,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20595,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20595,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20595,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20595,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20595,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20595,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20595,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20595,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20595,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20595,], -["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20595,], -["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20595,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20602,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20602,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20602,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20602,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20602,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20602,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20602,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20602,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20602,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20602,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20602,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20602,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20602,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20602,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20602,], +["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20602,], +["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20602,], +["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20605,], ["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",20595,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20595,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20595,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20595,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20595,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20595,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20595,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20595,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20595,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20595,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20598,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20595,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20602,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20602,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20602,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20602,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20602,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20602,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20602,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20602,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20602,], +["features.location.impl.show_ShowLocationView_Day_8_en","features.location.impl.show_ShowLocationView_Night_8_en",20605,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20602,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20602,], ["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,], @@ -1349,106 +1365,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",20595,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20602,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20595,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20595,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20595,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20595,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20595,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20602,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20602,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20602,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20602,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20602,], ["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",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20595,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20595,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20595,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20595,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20595,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20595,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20595,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20595,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20595,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20595,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20595,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20595,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20595,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20595,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20595,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20602,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20602,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20602,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20602,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20602,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20602,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20602,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20602,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20602,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20602,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20602,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20602,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20602,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20602,], ["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",20595,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20595,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20595,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20595,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20595,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20595,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20602,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20602,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20602,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20602,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20602,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20602,], ["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",20595,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20602,], ["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",20595,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20602,], ["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",20595,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20595,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20595,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20595,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20595,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20595,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20595,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20595,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20595,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20595,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20595,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20595,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20595,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20595,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20595,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20595,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20602,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20602,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20602,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20602,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20602,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20602,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20602,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20602,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20602,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20602,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20602,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20602,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20602,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20602,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20602,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20602,], ["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",20595,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20595,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20602,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20602,], ["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,], @@ -1461,17 +1477,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20595,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20595,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20602,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20602,], ["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","",20595,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20595,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20595,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20602,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20602,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20602,], ["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",20595,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20595,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20602,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20602,], ["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,], @@ -1481,18 +1497,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",20595,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20602,], ["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",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20602,], ["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,], @@ -1500,18 +1516,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",20595,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20602,], ["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",20595,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20595,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20602,], ["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",20595,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20602,], ["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,], @@ -1520,44 +1536,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20602,], ["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",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20602,], ["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",20595,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20602,], ["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","",20595,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20602,], ["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",20595,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20602,], ["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",20595,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20602,], ["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",20595,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20595,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20595,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20602,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20602,], ["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",20595,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20595,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20602,], ["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",20595,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20602,], ["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,], @@ -1566,8 +1582,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",20595,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20602,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20602,], ["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,], @@ -1582,8 +1598,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",20595,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20595,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20602,], ["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,], @@ -1606,84 +1622,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",20595,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20595,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20595,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20602,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20602,], ["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",20595,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20602,], ["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",20595,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20602,], ["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",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20595,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20595,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20602,], ["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",20595,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20595,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20595,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20595,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20595,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20595,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20602,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20602,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20602,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20602,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20602,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20602,], ["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","",20595,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20602,], ["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",20595,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20595,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20595,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20595,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20602,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20602,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20602,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20602,], ["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",20595,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20602,], ["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",20595,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20602,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20595,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20595,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20595,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20595,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20595,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20595,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20595,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20595,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20595,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20595,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20595,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20595,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20595,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20602,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20602,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20602,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20602,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20602,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20602,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20602,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20602,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20602,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20602,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20602,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20602,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20602,], ["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.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20595,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20595,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20602,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20602,], ["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",20595,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20602,], ["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,], From 4b99e5914e8dc7303a3b535c223039b39096d0fd Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 1 Jun 2026 11:22:11 +0300 Subject: [PATCH 0554/1083] Address review --- .../slashcommands/impl/DefaultSlashCommandService.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt index 8234116bb1..6cd8688cad 100644 --- a/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt +++ b/libraries/slashcommands/impl/src/main/kotlin/io/element/android/libraries/slashcommands/impl/DefaultSlashCommandService.kt @@ -99,14 +99,6 @@ class DefaultSlashCommandService( override suspend fun proceedAdmin( slashCommand: SlashCommand.SlashCommandAdmin, ): Result { - if (slashCommand is SlashCommand.ChangeDisplayNameForRoom) { - val canUserChangeDisplayName = withTimeoutOrNull(5.seconds) { - capabilitiesProvider.canChangeDisplayName().getOrNull() - } ?: false - if (!canUserChangeDisplayName) { - return Result.failure(Exception("Changing display name is not allowed")) - } - } return commandExecutor.proceedAdmin( slashCommand = slashCommand, ) From 0e5a7e93965efa09727cdc7ee8f1d47716be932d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 1 Jun 2026 11:37:55 +0200 Subject: [PATCH 0555/1083] Fix selection behaviour when long pressing emojis with no skin tone variants Also improve the threshold calculation to dismiss the displayed skin tone picker a bit --- .../components/customreaction/EmojiItem.kt | 149 ++++++++++-------- 1 file changed, 81 insertions(+), 68 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt index 4a8d2e6cca..b981055e61 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.Fill @@ -48,7 +49,7 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.emojibasebindings.Emoji import io.element.android.features.messages.impl.timeline.a11y.a11yReactionAction import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinTonePadding -import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinTonePickerContent +import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinTonePicker import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinToneSlotSize import io.element.android.features.messages.impl.timeline.components.customreaction.picker.SkinToneSlotSpacing import io.element.android.libraries.designsystem.preview.ElementPreview @@ -83,6 +84,7 @@ fun EmojiItem( emoji = item.unicode, userAlreadyReacted = isSelected, ) + val hasSkinTones = !item.skins.isNullOrEmpty() Box( modifier = modifier .sizeIn(minWidth = 40.dp, minHeight = 40.dp) @@ -90,12 +92,88 @@ fun EmojiItem( .background(backgroundColor, CircleShape) .indication(interactionSource, ripple()) .pointerInput(item) { + // Only detect drag after long press for those items which have a skin tone picker + if (hasSkinTones) { + var startOffset = Offset.Zero + detectDragGesturesAfterLongPress( + onDragStart = { position -> + if (onLongPress != null) { + startOffset = position + dismissed = false + onLongPress(item) + hoveredIndex = -1 + } + }, + onDrag = { change, _ -> + if (!dismissed) { + change.consume() + // It's a valid drag event if it's within ~2 items height above, so, on top of the current one or the skin tone selector, + // or 1 item below, which should be far enough to not be triggered by mistake + val isValidDrag = if (change.position.y < startOffset.y) { + startOffset.y - change.position.y <= itemSize.height * 2f + } else { + change.position.y - startOffset.y <= itemSize.height + } + if (!isValidDrag) { + dismissed = true + hoveredIndex = -1 + onDismissSkinPicker?.invoke() + } else { + val skinCount = item.skins!!.size + val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } + val spacingPx = with(density) { SkinToneSlotSpacing.toPx() } + val paddingPx = with(density) { SkinTonePadding.toPx() } + val totalSlots = 1 + skinCount + val pickerWidthPx = 2 * paddingPx + totalSlots * slotWidthPx + (totalSlots - 1) * spacingPx + val pickerHalfWidthPx = pickerWidthPx / 2f + val centerXPx = itemSize.width / 2f + val pickerLeftPx = centerXPx - pickerHalfWidthPx + val xInPicker = change.position.x - pickerLeftPx + val index = if (xInPicker in 0f..pickerWidthPx) { + (xInPicker / slotWidthPx).toInt().coerceIn(0, totalSlots - 1) + } else { + -1 + } + hoveredIndex = index + } + } + }, + onDragEnd = { + if (!dismissed) { + val idx = hoveredIndex + val skinCount = item.skins?.size ?: 0 + if (idx in 0..skinCount) { + if (idx == 0) { + onSelectEmoji(item) + } else { + val skin = item.skins?.getOrNull(idx - 1) + if (skin != null) { + onSelectEmoji(item.copy(unicode = skin.unicode)) + } + } + } else if (idx < 0) { + onSelectEmoji(item) + } + } + dismissed = false + hoveredIndex = -1 + onDismissSkinPicker?.invoke() + }, + onDragCancel = { + dismissed = false + hoveredIndex = -1 + }, + ) + } + + // Always detect long press and tap gestures detectTapGestures( onPress = { pressOffset -> val press = PressInteraction.Press(pressOffset) interactionSource.emit(press) if (tryAwaitRelease()) { interactionSource.emit(PressInteraction.Release(press)) + onSelectEmoji(item) } else { interactionSource.emit(PressInteraction.Cancel(press)) } @@ -103,71 +181,6 @@ fun EmojiItem( onTap = { onSelectEmoji(item) }, ) } - .pointerInput(item) { - detectDragGesturesAfterLongPress( - onDragStart = { _ -> - if (item.skins != null && onLongPress != null) { - dismissed = false - onLongPress(item) - hoveredIndex = -1 - } - }, - onDrag = { change, _ -> - if (item.skins != null && !dismissed) { - change.consume() - val yThresholdPx = with(density) { 100.dp.toPx() } - if (change.position.y > yThresholdPx) { - dismissed = true - hoveredIndex = -1 - onDismissSkinPicker?.invoke() - } else { - val skinCount = item.skins!!.size - val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } - val spacingPx = with(density) { SkinToneSlotSpacing.toPx() } - val paddingPx = with(density) { SkinTonePadding.toPx() } - val totalSlots = 1 + skinCount - val pickerWidthPx = 2 * paddingPx + totalSlots * slotWidthPx + (totalSlots - 1) * spacingPx - val pickerHalfWidthPx = pickerWidthPx / 2f - val centerXPx = itemSize.width / 2f - val pickerLeftPx = centerXPx - pickerHalfWidthPx - val xInPicker = change.position.x - pickerLeftPx - val index = if (xInPicker >= 0f && xInPicker <= pickerWidthPx) { - (xInPicker / slotWidthPx).toInt().coerceIn(0, totalSlots - 1) - } else { - -1 - } - hoveredIndex = index - } - } - }, - onDragEnd = { - if (!dismissed) { - val idx = hoveredIndex - val skinCount = item.skins?.size ?: 0 - if (idx in 0..skinCount) { - if (idx == 0) { - onSelectEmoji(item) - } else { - val skin = item.skins?.getOrNull(idx - 1) - if (skin != null) { - onSelectEmoji(item.copy(unicode = skin.unicode)) - } - } - } else if (idx < 0) { - onSelectEmoji(item) - } - } - dismissed = false - hoveredIndex = -1 - onDismissSkinPicker?.invoke() - }, - onDragCancel = { - dismissed = false - hoveredIndex = -1 - onDismissSkinPicker?.invoke() - }, - ) - } .clearAndSetSemantics { contentDescription = description }, @@ -177,7 +190,7 @@ fun EmojiItem( text = item.unicode, style = LocalTextStyle.current.copy(fontSize = emojiSize), ) - if (item.skins != null) { + if (hasSkinTones) { Canvas( modifier = Modifier .align(Alignment.BottomEnd) @@ -201,7 +214,7 @@ fun EmojiItem( alignment = Alignment.BottomCenter, offset = IntOffset(0, popupOffsetPx), ) { - SkinTonePickerContent( + SkinTonePicker( emoji = item, onSelect = { selectedEmoji -> onSelectEmoji(selectedEmoji) From 77dbd56e4e129e9420943c4c2bae2682e83da013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 1 Jun 2026 11:38:02 +0200 Subject: [PATCH 0556/1083] Fix Konsist lint issue --- .../components/customreaction/picker/SkinTonePicker.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt index cdabf5772a..7fdfbfb1a4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt @@ -39,7 +39,7 @@ val SkinToneSlotSpacing = 2.dp val SkinTonePadding = 4.dp @Composable -fun SkinTonePickerContent( +fun SkinTonePicker( emoji: Emoji, onSelect: (Emoji) -> Unit, modifier: Modifier = Modifier, @@ -110,8 +110,8 @@ private fun SkinToneSlot( @PreviewsDayNight @Composable -internal fun SkinTonePickerContentPreview() = ElementPreview { - SkinTonePickerContent( +internal fun SkinTonePickerPreview() = ElementPreview { + SkinTonePicker( emoji = Emoji( hexcode = "1F44D", label = "thumbs up", From bfcce0e94bf40179af2f02394ab6f873ab87f08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 1 Jun 2026 11:38:35 +0200 Subject: [PATCH 0557/1083] Tweak Konsist check to allow `LongPress` actions --- .../element/android/tests/konsist/KonsistParameterNameTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistParameterNameTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistParameterNameTest.kt index f202148464..752acb2864 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistParameterNameTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistParameterNameTest.kt @@ -19,7 +19,7 @@ class KonsistParameterNameTest { Konsist.scopeFromProject() .functions() .withParameter { parameter -> - parameter.name.endsWith("Press") + parameter.name.endsWith("Press") && !parameter.name.endsWith("LongPress") } .assertEmpty(additionalMessage = "Please rename the parameter, for instance from 'onBackPress' to 'onBackClick'.") } From f52fc9c1c2123984522680d6431f503d707703ec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 14:41:26 +0200 Subject: [PATCH 0558/1083] Fix image resizing behavior. --- .../preview/imageeditor/AttachmentImageEditorView.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt index 6011b52c41..d580a6376e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorView.kt @@ -316,11 +316,13 @@ private fun BoxScope.CropEditorCanvas( ) { change, dragAmount -> val activeTarget = dragTarget ?: return@detectDragGestures change.consume() + val gestureAreaWidth = imageRect.width.takeIf { it > 0f } ?: size.width.toFloat() + val gestureAreaHeight = imageRect.height.takeIf { it > 0f } ?: size.height.toFloat() onCropRectChange( latestCropRect.applyChange( dragTarget = activeTarget, - deltaX = dragAmount.x / size.width.toFloat(), - deltaY = dragAmount.y / size.height.toFloat(), + deltaX = dragAmount.x / gestureAreaWidth, + deltaY = dragAmount.y / gestureAreaHeight, ) ) } From 80de3e4c5d2e8e87303ebccf769053fc48fa4f32 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 1 Jun 2026 15:11:04 +0200 Subject: [PATCH 0559/1083] Create log messages from `WebView` just once (#6923) We were creating the same message twice by mistake. Also, check the retrieved message for passwords before formatting the log line instead of after: this way we don't create a new formatted log line to just discard it --- .../browser/ConsoleMessageLogger.kt | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt index d165da8640..18d9990c0b 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt @@ -33,6 +33,11 @@ class DefaultConsoleMessageLogger : ConsoleMessageLogger { else -> Log.DEBUG } + // Avoid logging any messages that contain "password" to prevent leaking sensitive information + if (consoleMessage.message().contains("password=")) { + return + } + val message = buildString { append(consoleMessage.sourceId()) append(":") @@ -41,20 +46,6 @@ class DefaultConsoleMessageLogger : ConsoleMessageLogger { append(consoleMessage.message()) } - // Avoid logging any messages that contain "password" to prevent leaking sensitive information - if (message.contains("password=")) { - return - } - - Timber.tag(tag).log( - priority = priority, - message = buildString { - append(consoleMessage.sourceId()) - append(":") - append(consoleMessage.lineNumber()) - append(" ") - append(consoleMessage.message()) - }, - ) + Timber.tag(tag).log(priority = priority, message = message) } } From b68c78526f3b7190819c3cb876f1bfc49119c42c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 15:49:53 +0200 Subject: [PATCH 0560/1083] Use secondary color (default) for leading icons. Fixes #6910 --- .../features/home/impl/roomlist/RoomListContextMenu.kt | 5 ----- .../features/messages/impl/actionlist/ActionListView.kt | 2 +- .../impl/messagecomposer/AttachmentsBottomSheet.kt | 8 -------- .../impl/root/RolesAndPermissionsView.kt | 1 - .../roommembermoderation/impl/RoomMemberModerationView.kt | 1 - .../userprofile/shared/blockuser/BlockUserSection.kt | 1 - .../matrix/ui/components/AvatarActionBottomSheet.kt | 2 +- .../mediaviewer/impl/details/MediaDetailsBottomSheet.kt | 5 ----- 8 files changed, 2 insertions(+), 23 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt index 66982961fd..03db82f252 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContextMenu.kt @@ -119,7 +119,6 @@ private fun RoomListModalBottomSheetContent( leadingContent = ListItemContent.Icon( iconSource = IconSource.Vector(CompoundIcons.MarkAsRead()) ), - style = ListItemStyle.Primary, ) } else { ListItem( @@ -133,7 +132,6 @@ private fun RoomListModalBottomSheetContent( leadingContent = ListItemContent.Icon( iconSource = IconSource.Vector(CompoundIcons.MarkAsUnread()) ), - style = ListItemStyle.Primary, ) } val (textResId, icon) = if (contextMenu.isFavorite) { @@ -159,7 +157,6 @@ private fun RoomListModalBottomSheetContent( onClick = { onFavoriteChange(!contextMenu.isFavorite) }, - style = ListItemStyle.Primary, ) ListItem( headlineContent = { @@ -174,7 +171,6 @@ private fun RoomListModalBottomSheetContent( CompoundIcons.Settings(), ) ), - style = ListItemStyle.Primary, ) if (canReportRoom) { ListItem( @@ -211,7 +207,6 @@ private fun RoomListModalBottomSheetContent( leadingContent = ListItemContent.Icon( iconSource = IconSource.Vector(CompoundIcons.Delete()) ), - style = ListItemStyle.Primary, ) } } 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 e10dd2e1bc..c2d97dcf80 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 @@ -249,7 +249,7 @@ private fun ActionListViewContent( leadingContent = ListItemContent.Icon(IconSource.Resource(action.icon)), style = when { action.destructive -> ListItemStyle.Destructive - else -> ListItemStyle.Primary + else -> ListItemStyle.Default } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt index 405e2b0be9..4f7523cbf3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt @@ -34,7 +34,6 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight 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.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.Text @@ -106,25 +105,21 @@ private fun AttachmentSourcePickerMenu( modifier = Modifier.clickable { state.eventSink(MessageComposerEvent.PickAttachmentSource.PhotoFromCamera) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.TakePhoto())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) }, - style = ListItemStyle.Primary, ) ListItem( modifier = Modifier.clickable { state.eventSink(MessageComposerEvent.PickAttachmentSource.VideoFromCamera) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VideoCall())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_camera_video)) }, - style = ListItemStyle.Primary, ) ListItem( modifier = Modifier.clickable { state.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Image())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_gallery)) }, - style = ListItemStyle.Primary, ) ListItem( modifier = Modifier.clickable { state.eventSink(MessageComposerEvent.PickAttachmentSource.FromFiles) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Attachment())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_files)) }, - style = ListItemStyle.Primary, ) if (state.canShareLocation) { ListItem( @@ -134,7 +129,6 @@ private fun AttachmentSourcePickerMenu( }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.LocationPin())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_location)) }, - style = ListItemStyle.Primary, ) } ListItem( @@ -144,14 +138,12 @@ private fun AttachmentSourcePickerMenu( }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Polls())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_poll)) }, - style = ListItemStyle.Primary, ) if (enableTextFormatting) { ListItem( modifier = Modifier.clickable { state.eventSink(MessageComposerEvent.ToggleTextFormatting(enabled = true)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.TextFormatting())), headlineContent = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) }, - style = ListItemStyle.Primary, ) } } diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt index 2f8dab8029..964518da10 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/root/RolesAndPermissionsView.kt @@ -181,7 +181,6 @@ private fun ChangeOwnRoleBottomSheet( ListItem( headlineContent = { Text(stringResource(CommonStrings.action_cancel)) }, onClick = ::dismiss, - style = ListItemStyle.Primary, ) } } diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt index 53bf667c6e..08d9143e0b 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt @@ -278,7 +278,6 @@ private fun RoomMemberActionsBottomSheet( when (val action = actionState.action) { is ModerationAction.DisplayProfile -> { ListItem( - style = ListItemStyle.Primary, headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_member_user_info)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), onClick = { diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt index c3caffa7f3..62efbf1f0f 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt @@ -84,7 +84,6 @@ private fun PreferenceBlockUser( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), onClick = { if (!isLoading) eventSink(UserProfileEvents.UnblockUser(needsConfirmation = true)) }, trailingContent = if (isLoading) ListItemContent.Custom(loadingCurrentValue) else null, - style = ListItemStyle.Primary, ) } else { ListItem( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt index 880a7a9df6..32899a8d2c 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt @@ -104,7 +104,7 @@ private fun AvatarActionBottomSheetContent( leadingContent = ListItemContent.Icon(IconSource.Resource(action.iconResourceId)), style = when { action.destructive -> ListItemStyle.Destructive - else -> ListItemStyle.Primary + else -> ListItemStyle.Default } ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt index 0c73bfd17c..1f16391265 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt @@ -105,7 +105,6 @@ fun MediaDetailsBottomSheet( ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VisibilityOn())), headlineContent = { Text(stringResource(CommonStrings.action_view_in_timeline)) }, - style = ListItemStyle.Primary, onClick = { onViewInTimeline(state.eventId) } @@ -113,7 +112,6 @@ fun MediaDetailsBottomSheet( ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), headlineContent = { Text(stringResource(CommonStrings.action_share)) }, - style = ListItemStyle.Primary, onClick = { onShare(state.eventId) } @@ -121,7 +119,6 @@ fun MediaDetailsBottomSheet( ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Forward())), headlineContent = { Text(stringResource(CommonStrings.action_forward)) }, - style = ListItemStyle.Primary, onClick = { onForward(state.eventId) } @@ -129,7 +126,6 @@ fun MediaDetailsBottomSheet( ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), headlineContent = { Text(stringResource(CommonStrings.action_download)) }, - style = ListItemStyle.Primary, onClick = { onDownload(state.eventId) } @@ -148,7 +144,6 @@ fun MediaDetailsBottomSheet( ListItem( leadingContent = icon, headlineContent = { Text(wording) }, - style = ListItemStyle.Primary, onClick = { onOpenWith(state.eventId) } From 31776a74f7af7ce6385cadaaa17f3a56359ea18c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 1 Jun 2026 14:09:23 +0000 Subject: [PATCH 0561/1083] Update screenshots --- ...atures.home.impl.roomlist_RoomListContextMenu_Day_0_en.png | 4 ++-- ...atures.home.impl.roomlist_RoomListContextMenu_Day_1_en.png | 4 ++-- ...atures.home.impl.roomlist_RoomListContextMenu_Day_2_en.png | 4 ++-- ...ures.home.impl.roomlist_RoomListContextMenu_Night_0_en.png | 4 ++-- ...ures.home.impl.roomlist_RoomListContextMenu_Night_1_en.png | 4 ++-- ...ures.home.impl.roomlist_RoomListContextMenu_Night_2_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_6_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_7_en.png | 4 ++-- .../snapshots/images/features.home.impl_HomeView_Day_8_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_6_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_7_en.png | 4 ++-- .../images/features.home.impl_HomeView_Night_8_en.png | 4 ++-- ...ssages.impl.actionlist_ActionListViewContent_Day_10_en.png | 4 ++-- ...ssages.impl.actionlist_ActionListViewContent_Day_11_en.png | 4 ++-- ...ssages.impl.actionlist_ActionListViewContent_Day_12_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_2_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_3_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_4_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_5_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_6_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_7_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_8_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_9_en.png | 4 ++-- ...ages.impl.actionlist_ActionListViewContent_Night_10_en.png | 4 ++-- ...ages.impl.actionlist_ActionListViewContent_Night_11_en.png | 4 ++-- ...ages.impl.actionlist_ActionListViewContent_Night_12_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_2_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_3_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_4_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_5_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_6_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_7_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_8_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_9_en.png | 4 ++-- ...pl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en.png | 4 ++-- ....messagecomposer_AttachmentSourcePickerMenu_Night_0_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_1_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_1_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_0_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_1_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_2_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_3_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_0_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_1_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_2_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_3_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_2_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_5_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_2_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_5_en.png | 4 ++-- ....matrix.ui.components_AvatarActionBottomSheet_Day_0_en.png | 4 ++-- ...atrix.ui.components_AvatarActionBottomSheet_Night_0_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 4 ++-- ...ies.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png | 4 ++-- ...s.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png | 4 ++-- 61 files changed, 122 insertions(+), 122 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png index 6b4037b3eb..83ee2f4342 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c755a7dcfc2c9f48d449e570a3f1af1cde299fd90ddd4478e9a4c315cf03128 -size 23810 +oid sha256:aec4d2f2ec1b277afa895e47739b503d86b3104d315b6d20fce223324c57f51b +size 23960 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png index e64ae4c3cf..84b0af9394 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efa5408c3af0fcd39659b8d30b21ace43be46d2876815ad592f802a7887b5eb9 -size 23678 +oid sha256:82f48053958a8bd72245365ee0cc4c1649c5c06dde6f66c95c23bf5009edd2f3 +size 23879 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png index 82b04fc045..d7fec262ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fc512e71e168473e0e976be3e3e6cd24b455273257ad0adf970fc2641da43bb -size 25679 +oid sha256:e50eaee3dc1512f76566d1170c2db8a07230d7c9f159c5f52c43ac9e810e2a72 +size 25938 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png index f52d785548..8a06c99645 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de71af50bba66a285b5ef44e1a4fe76ce6dc2e094c4c09ddf701deb9a5db898d -size 22025 +oid sha256:3abd359bba25e19e231d723cc3de7dcf394c35a5948a935b2703d81940e00120 +size 22391 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png index eef2177c3b..9fa6aa895a 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88b3583d55c6855027f13a152a6fc414f6b9e11d65e5b5403463b84fafe38c3f -size 21891 +oid sha256:4910c5904a53dacc578b32d0033e3fe64fa084602b62dff13930b68ee83e0cf5 +size 22298 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png index 87d3f56720..f7c703f8ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.roomlist_RoomListContextMenu_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e64367832735139b68269a8c679b9c6f2b929b906124a0ee93735cbdd9202d6d -size 23826 +oid sha256:82ed1ed8042d4d6f9633144cc5f34567cfc09c6303e005a7157954917837054d +size 24160 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_6_en.png index 99940a4489..807a0404c4 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e74b9b1819bf778ddb397a40113f71b2eb0ada0dcb26af85dab26bbc53ed079 -size 54210 +oid sha256:6833382305574e875ab2b5cbfa0ae441d06e405ae64f69a8b9de6e2f3da96922 +size 54461 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_7_en.png index 2532044b27..102ab5d046 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4e56509b4f10e97283d25432edd7be4b511987f0879acc3026ac16dab25b75c -size 54012 +oid sha256:45d4703616e98579df79f9d23f1f0c954f937b75f7eeab1452675b8eaa3c0770 +size 54266 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_8_en.png index 0baf9cf023..d133b74182 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe76cc652842cce967d975fae7a387f5cff118153b345bda452d5dbc618b22f8 -size 52255 +oid sha256:ea4983028fd8b8044df7d87125d49346bca92920217f14b7ce2aaac9dbe8af4b +size 52534 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_6_en.png index ead9ed0d6d..6dfedf5331 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2d17c9021392f93fc022ce0ba4305f0739acaeab3ebfd51b7d3294ace365807 -size 51156 +oid sha256:86cd78d9ac357bfcbc017440b57e1d643255b6ffbe47e78c3df197405c185495 +size 51522 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_7_en.png index 33f2b46a34..4260283a5d 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:286af36457c34621e10b91226b13c5a9fde77af6b63827d39a0a95697972d4ab -size 50896 +oid sha256:ff899eb696998139c0b28b1596aa71fcb477cc534892bbfdeb81405412a6121b +size 51286 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_8_en.png index 733a66bb38..abd2fd13fa 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34a5fe14ee5ede42d962e657e4338f58f56e79e0f9a3f65ba24e37810a9c1250 -size 49205 +oid sha256:73d1f08075d303b49e5f3b76f06744e59620eddd6dd45c8715fb2ec21c82e568 +size 49555 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png index 3783974c39..96240c9b67 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9912a8d83fd78d27fa6b01fd9034a03e50bc598f10330681c51fc776d5541bce -size 29420 +oid sha256:eeef211d5fb4e9474545ce91ddc7470703a1e04a0ea25048eada1d5700c62f90 +size 29595 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png index f594f885e0..c3a33f959d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab09bad33db524c5bf21815b0573cce94a5a04a3cb1a7c5eac08788a6fd43bc6 -size 48565 +oid sha256:34dc91f10333b05fb7d25293847e8ef8cc455ac416f95a57e7c21fa107f17924 +size 48938 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png index 336b672698..2eb5dd6e27 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:028dc1af0a32614235945f29b86fc75f7e4101115ca6bb24a8519d9b540e3446 -size 50076 +oid sha256:447c10f67637776e73fbb73a9d38cccf6dd5dc6629b84b95230099c0466f489d +size 50451 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png index 5a7092ba16..cb7e98ab69 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:050194b3070ce4e062b419467c0429b4ec025bda070dbf9499ebf22094d930e1 -size 43582 +oid sha256:9d9f5edcae6f3d64b7ee92b2fdde6a78fd4535e001a590c0ba0f31658d9bbfcb +size 43748 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png index 8888dbdfcb..a6bb00e532 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:979969357697032a7b7e5e715f42434cee98e6ad6eed439baf79ca0b972cef42 -size 46476 +oid sha256:4ec56befb7c774bf4545b8ee56c392a2b7a83511efb524703bb44659ace359fa +size 46839 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png index f1b598d66b..94ff687fbb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6ca9ef59f9e436190c1342dcc0376c88bf46c8b6b2f84b6a487d3bf998e94bc -size 44877 +oid sha256:13ca2d6273c2e9b76271ab42aa2e435fc7547bd675d29113f6a285da91c7efbe +size 45100 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png index d70c672fda..c2165768a6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb661596edcdda0d2a5f57c72a396624ab6f4291d07c0224cdcdeba67fa48071 -size 41955 +oid sha256:e6401ce52238a6f7f874993713139b0b4bbb435a24931b95dd2be0cc904a40e4 +size 42210 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png index cb1af3bb6e..d49b066f2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:834245a21eb2bb644b5d9afda81346c37a3a6121d20d5c14c562b100cc5b913c -size 45046 +oid sha256:b61cdf6910a74a2d2593c95dee752a3e4f5b4b9288227544a7b4aaa813fee89e +size 45417 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png index 8b6616fc18..ac761dc5d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bb9f6d15e6556e692a6d879202bf6036d9cf1b353f317b911cc7ca379c2a90e -size 43190 +oid sha256:4cff72a2042e4fdf61d09eb118e5d14bea1fd78533b2540356374e3641eb9719 +size 43445 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png index 02318d8ce5..2102db6ed8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e01aa32704fb8d1f2b7f4325f94635b345ce3117e384923e8132a68b566d8968 -size 44964 +oid sha256:bd07b8f9652520c7819689908e5067589f9b02aae28497ea417e896d1976b6a9 +size 45208 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png index 9b0b7bfe4f..5a3dbf94f9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45eb96b553465eaccc2e5081bb8b867a8cd2d4e5ed1ce66767828bfb3b7fc0fc -size 34176 +oid sha256:e54261b95e0bd072ab51e289f48dafb611dfa0eed1f30bd1e8f964dfe15b8656 +size 34516 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png index 6170e24768..111dbec964 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9a6d982e6a414650a917da3e66b2155f8b6ce3285ca4fefd4afcd0df7f6184c -size 28432 +oid sha256:dbf8d20a5de034e5487dd6a53e112995abf15c7d2f3da132ab5d25e8a90ac3d0 +size 28882 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png index cb440db48d..35034a2a18 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06180ecb1a875d6d007a528730d53d4913c733d8b1218ee69daa3df557130806 -size 47781 +oid sha256:f241204e1bf54222cc82b8a8f85278e347a5978308ea48fae4231ccf61950845 +size 48275 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png index dba9e6d4c8..97c55b2bef 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:670bbfdc5ae48ba97911716db461ab391a57e94764508eae88c594b68e96e826 -size 49278 +oid sha256:3fddb43c6de6277f396d82755650136304c310d8f5607fb5b87d6d9c03a5ed78 +size 49754 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png index dfccd98a28..82b82ae51e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0d0257a4d2eed51e9c18f3afbe0e39fffb7440e0ce749eec8959c9b4e5e063a -size 42723 +oid sha256:de93101b9a5c06d0e31b9ac83f34a3db18e8a98f15d3bd2c62e13d4c3bb8074b +size 43187 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png index 4022cb1368..c2ef33efd4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05e6093a0a7e2387c2c06270416e53c0654353cd1e348829c31f1377c618374f -size 45875 +oid sha256:e4f77edfdf5c82a807a5a4b8aecbd391da8b403082caade04c53b6ac09adeea6 +size 46293 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png index 7f7642064e..61a1a6b088 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b021dfc67025bf99ca1b6ad8b28afcb29611716635a57f4c3e2b250515f63da6 -size 44357 +oid sha256:a359101a1b23fb039d30060f7eb49c8e0188594ae2810a209fcdec0e68984245 +size 44755 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png index dc562de97b..b6b850a8b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:199ae1aa490d6b7c3e4e0a2c4efedc5fd8f9140d18be74baf9b67023f9bc2165 -size 40888 +oid sha256:3a496227e12ffd07749a13ff805d7e385bedd04c6aebcd527a9815709636ee8c +size 41378 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png index e79cd5a5d5..54e2d716bd 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b5a85043479aff4f13fe1b2e86ad4700410dd9c57219659c0b2cf93acfdc6a2 -size 44679 +oid sha256:853a39c07503f5878a52d99e3d076bdf929b7867339b28bab73ecc0ea764eb1a +size 45041 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png index 4825735975..d3b6d14e50 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bcf537c2f4d01fef81785ddc0b8f5133e2bc1966e6837e239ccfc0a06f14d18 -size 42111 +oid sha256:a569526be5f0568a6b9631006b9f08ccde11190b6f3ab5cee345ba991e7d1a2f +size 42554 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png index 225a8b94d7..e6a5be294c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f27444a111e07658820b19dcc780219ea80b2ea5d01495ecee1255c0e84650e -size 44507 +oid sha256:d710b57a36ba6d73dc1b81ff2189ee36d0314c5ca1ab9da2f2f54cf3bcc3bc55 +size 44867 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png index 46c4f1942e..d9f2017597 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_ActionListViewContent_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbe4516b52f897a4f91d229f3a0f1bcd3a867d9494ac894d11452bcdf9407f2c -size 33013 +oid sha256:69fc6332d8c7607b14dc7c2ad595d545f83f52cc0e42da5fee05f127fed5713a +size 33424 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en.png index 303a32a04d..8f4e2dfe50 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36926eca7b934f7794ddd73e7929861d8837e9ac51341520c883043dc53d1927 -size 25026 +oid sha256:bfc50e8997f52f2b0b808af90b09000a27c9943505460692fbe541a3bd95c440 +size 25622 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en.png index 32c4015a76..862e26b1d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:493ed64dc981851887506ce33cdd063a107c8d5e6376027e7949a248b88e2a42 -size 24167 +oid sha256:4faa8dc1a367649a4a862e8647e733d77dd31737b34f9a8a5997f2345dab50a0 +size 25035 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png index ef8699b324..9685e6cbc9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f21b1799dec6cb466378a748adb5227f76bd6cf611be694922ef63a951fdf692 -size 39910 +oid sha256:d1a28720d554bc4698eb52e27e7c6228ac9c14b3703a8c139c3113f8b8fa284e +size 40355 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png index 51a300b462..d7eb027558 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84a6b1ef879f1a9be16526efdd546aa554e03ea74b0e8ec03178b2a860b752e5 -size 38089 +oid sha256:5789d10db607ad77acd5d9391b970b2e0a0f962c205b3bf40db5c78d0dcea48b +size 38821 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png index b5ff7ebce2..adc8e30fdb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49ecd29e87c23ac92f0b5775e95a1b46dda41bbd7bb52a5cbfbcf7cd039824c9 -size 17240 +oid sha256:8b15da251ba8ac26c61fd21079f09e3b614fd20e8ded4805cda0da180631afcc +size 17347 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png index ae186ece30..1e3ab791b8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ac03bbed84ae266088d0e487e36ac30ddaac22bdaea6218423a8a41b77f4c5b -size 20217 +oid sha256:fc4a3ba905c3599ad8f6451787906ba61f8dc716464d81e8c1c1bc86023032c3 +size 20345 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png index 6311df6e6d..5253ae2439 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d44e5119301f217903d1ca232f17ae54ba96da9a6878e668f603c57bcc23761 -size 22612 +oid sha256:5704d02932451bc129ec92f3a9dab7fd66bb55bfdf3e142a4f3a436ad1d3b129 +size 22722 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png index 90b562aa09..b905c2d8cb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:980b9744a36174bb8b080a431b277b544dfc045869102147fb9d1186e396b5e9 -size 22720 +oid sha256:8755fa3568186a798047a7fbf05404c0f738b168ca77f16afecc815bbec084ab +size 22828 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png index 1a59277355..f4922aad1c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ebad5a2935050fa87c16c518323bdf3db4494fd8a14a5a03809e3e51f047b70 -size 16318 +oid sha256:ba469dd7ffb3b27261cc4f227584b7cc03bf2ddcb974a4a1150c9515a075ac78 +size 16562 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png index 9e8644ac62..c79de434d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b427494aa12528f795a49f27912b90ebb59392be0420fc27e3c4014a3599680 -size 19155 +oid sha256:d21c293e519e998d8820171766f1651d2440b18dad6f002c6580ca3fe2f24d69 +size 19397 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png index 01b60a339f..dfa20ea763 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d301576daafc3b86949208e281479183558d61cbadeb412007ee8436aa7eebb9 -size 21590 +oid sha256:24a1a6004dc058573f264a5f02ffc85ca925e9f0c01f7ceacbaf972b3335d327 +size 21819 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png index b96d820784..07547bf79a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc69bdbe8ac22e7d6470a8b547ba364e3421f6d61ccd0c364492dd860b1ce093 -size 21682 +oid sha256:cf93cbb2ce344639162524714d254c0db21cab448dec38ee1d4820265678a7ec +size 21909 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png index 7951440a2f..3419a50b07 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8185065602221f9bf675398d42c16f9e0c7ae65952b865689263878f43c545d -size 24110 +oid sha256:9973d9a9fa00d362eae8f50c2936e5ae0adc2653b4671413b856c1e73538eb73 +size 24261 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_5_en.png index 12563b1b76..7e6ca5d507 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c3ff3444b2f720b09de118af05e1376001bf3cfe9be66acec4a68cecfe9ae6b -size 22357 +oid sha256:4a4154169fd6e74358001ecc151a0cb4635423bf4a0b2d72f1d5bb12dfb0ea95 +size 22446 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png index 61d82d6084..224210123e 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2f2787f0aacfa36596b9fa0e25d990710870bf5ed25d831b47c5c71ac1d3de9 -size 23377 +oid sha256:e28754f90d584c329a5e3c51eba89c166320c69fda309b6b06b6f5ee9c74c1b2 +size 23549 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_5_en.png index 90376bc952..408be83664 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e7e43be60d1a545621d9d64ae3500980056f2c405c8d22629ab63e149aad224 -size 21816 +oid sha256:3b815d4cf8ed95cb983072d75419637c10bd4808ddfbf14865409d0a4fd64c37 +size 22070 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en.png index f5d8e0173e..362e750080 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:368aec8db00c98f5e2b73763826f484c4ca395bfee9156cc7796029f57ceb907 -size 13464 +oid sha256:7a804cd9678ae0aa149065dfc7ce98bacb30956ac75a17f80a7f32acbbb6681c +size 13598 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en.png index e16de72924..1aaf062713 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:707eaf1db064e542041746c1fff6f81a47e95a45579a9738f7f02573ce6db0f8 -size 12261 +oid sha256:44fa03d304319f972c0e9c6e297e4b86bd0603a90945126f47f657d566241911 +size 12500 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png index 8a527331d9..c187b29009 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67be1e8e93d0c10366f4b37f14ca0f90c1f4ccd5da9024c9a396d3d46507e18c -size 40339 +oid sha256:be6223e16a2b9936164ec4ba659129ceb80ed5746e3376f32559b4942b271502 +size 40656 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png index 8a527331d9..c187b29009 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67be1e8e93d0c10366f4b37f14ca0f90c1f4ccd5da9024c9a396d3d46507e18c -size 40339 +oid sha256:be6223e16a2b9936164ec4ba659129ceb80ed5746e3376f32559b4942b271502 +size 40656 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png index d53b0ecf7e..b95ce472ff 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f89a1039bc2d101af319c0b6259d8eebc9d313ae34947aedee525945be23799 -size 44604 +oid sha256:b57d412a5815756b453d907543bc74b4a154814633d8664a3dcffaa0057c7279 +size 44962 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png index e16a2bc691..a86d65d8f8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a512016e96b933f6089e60b634fa77f140dfa7de50d3a8c1a62092ad552d7f2d -size 39216 +oid sha256:5e3e43f4dbd1bf0e271de57c962b93100720439d608a7d552669ede42141dbc1 +size 39705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png index e16a2bc691..a86d65d8f8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a512016e96b933f6089e60b634fa77f140dfa7de50d3a8c1a62092ad552d7f2d -size 39216 +oid sha256:5e3e43f4dbd1bf0e271de57c962b93100720439d608a7d552669ede42141dbc1 +size 39705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png index e36f282ba2..782df4dbaa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8608e63ef9ff79fd698c202d60a8c73f8874f8610601a0ff6dc85663ed82c7da -size 43537 +oid sha256:086c64f4094cb2e0fda8e415a0d8d89b7dafe67f4d42088eded7abbf45b8de93 +size 44088 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png index 809459297c..6c70063773 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ddbddbf5303bb86f901cdd880ca2fde15c7c4af22dd7cf1a7903dcab5df25b3 -size 40254 +oid sha256:ad4bf14c2f6d2d36c978d90c7641fc8b3a9c71062d6b23362eea12c0b7ff24e4 +size 40572 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png index 1ceb7c6b68..40d55d29a1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89e17d0b8fdd749b6e97385e8369132d52b0e10adf7d23157c3bdbeb7721e694 -size 39007 +oid sha256:7b44ce089c932019d58e7f1c993f80871352878adf0f5a133a72edce18f5bcb9 +size 39496 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png index 1ceb7c6b68..40d55d29a1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89e17d0b8fdd749b6e97385e8369132d52b0e10adf7d23157c3bdbeb7721e694 -size 39007 +oid sha256:7b44ce089c932019d58e7f1c993f80871352878adf0f5a133a72edce18f5bcb9 +size 39496 From 1df94a563c53628ee931a66c443175210e27da26 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 1 Jun 2026 17:25:33 +0200 Subject: [PATCH 0562/1083] Use reverse ordering for `FilterEmptyDayPostProcessor` (#6927) It turns out the previous ordering was right: timestamp ordering is ascending, not descending --- .../FilterEmptyDayPostProcessor.kt | 8 ++++-- .../FilterEmptyDayPostProcessorTest.kt | 28 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt index b7dceafa25..b4d21b36be 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessor.kt @@ -18,10 +18,10 @@ class FilterEmptyDayPostProcessor { * Filters out day separators from [items] for days that don't contain any events. */ fun process(items: List): List = buildList { - // The timeline is ordered by descending timestamp, so events that happened during a day appear before the day separator for that day. - // We can use this to determine if a day separator should be kept or not. + // The timeline is ordered by ascending timestamp, so events that happened during a day appear after the day separator for that day. + // We can use this to determine if a day separator should be kept or not by traversing the list in reverse. var hasEvent = false - for (item in items) { + for (item in items.asReversed()) { if (item is MatrixTimelineItem.Event) { hasEvent = true add(item) @@ -35,4 +35,6 @@ class FilterEmptyDayPostProcessor { } } } + // Then reverse the result to restore the original order, minus the empty day separators. + .asReversed() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt index 7a3a091f4e..67d7e3621d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/FilterEmptyDayPostProcessorTest.kt @@ -32,36 +32,36 @@ class FilterEmptyDayPostProcessorTest { @Test fun `filterEmptyDaySeparators keeps day separator with events after it`() { val items = listOf( - anEvent, aDaySeparator(TODAY), + anEvent, ) val result = FilterEmptyDayPostProcessor().process(items) assertThat(result).hasSize(2) - assertThat(result[0]).isEqualTo(anEvent) - assertThat(result[1]).isEqualTo(aDaySeparator(TODAY)) + assertThat(result[0]).isEqualTo(aDaySeparator(TODAY)) + assertThat(result[1]).isEqualTo(anEvent) } @Test fun `filterEmptyDaySeparators removes day separator with no events after it`() { val items = listOf( - aDaySeparator(TODAY), aDaySeparator(YESTERDAY), + aDaySeparator(TODAY), ) val result = FilterEmptyDayPostProcessor().process(items) assertThat(result).isEmpty() } @Test - fun `filterEmptyDaySeparators removes first day separator and keeps second when only second has events`() { + fun `filterEmptyDaySeparators removes second day separator and keeps first when only first has events`() { val items = listOf( - aDaySeparator(TODAY), - anEvent, aDaySeparator(YESTERDAY), + anEvent, + aDaySeparator(TODAY), ) val result = FilterEmptyDayPostProcessor().process(items) assertThat(result).hasSize(2) - assertThat(result[0]).isEqualTo(anEvent) - assertThat(result[1]).isEqualTo(aDaySeparator(YESTERDAY)) + assertThat(result[0]).isEqualTo(aDaySeparator(YESTERDAY)) + assertThat(result[1]).isEqualTo(anEvent) } @Test @@ -78,15 +78,15 @@ class FilterEmptyDayPostProcessorTest { @Test fun `filterEmptyDaySeparators keeps all items when no day separators`() { val items = listOf( - anEvent, anEvent.copy(uniqueId = UniqueId("event2")), + anEvent, ) val result = FilterEmptyDayPostProcessor().process(items) assertThat(result).hasSize(2) } @Test - fun `filterEmptyDaySeparators removes day separator followed by non-event virtual item`() { + fun `filterEmptyDaySeparators removes day separator preceded by non-event virtual item`() { val readMarker = MatrixTimelineItem.Virtual( uniqueId = UniqueId("readMarker"), virtual = VirtualTimelineItem.ReadMarker @@ -107,12 +107,12 @@ class FilterEmptyDayPostProcessorTest { virtual = VirtualTimelineItem.ReadMarker ) val items = listOf( - anEvent, - readMarker, aDaySeparator(TODAY), + readMarker, + anEvent, ) val result = FilterEmptyDayPostProcessor().process(items) assertThat(result).hasSize(3) - assertThat(result[2]).isEqualTo(aDaySeparator(TODAY)) + assertThat(result[0]).isEqualTo(aDaySeparator(TODAY)) } } From 6222416b1764445b7e010803f3308bb9187f2bdd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 17:34:36 +0200 Subject: [PATCH 0563/1083] Romo details: reorder items Fixes #6824 --- .../roomdetails/impl/RoomDetailsPresenter.kt | 4 +- .../roomdetails/impl/RoomDetailsState.kt | 2 +- .../impl/RoomDetailsStateProvider.kt | 6 +- .../roomdetails/impl/RoomDetailsView.kt | 149 +++++++++--------- .../roomdetails/impl/RoomDetailsViewTest.kt | 4 +- .../preview/PreviewWithLargeHeight.kt | 3 + 6 files changed, 85 insertions(+), 83 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index e6617d1dd5..6a88350360 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -174,7 +174,7 @@ class RoomDetailsPresenter( } } - val roomMemberDetailsState = roomMemberDetailsPresenter?.present() + val dmOtherMemberDetailsState = roomMemberDetailsPresenter?.present() val hasMemberVerificationViolations by produceState(false) { room.roomMemberIdentityStateChange(waitForEncryption = true) @@ -196,7 +196,7 @@ class RoomDetailsPresenter( canEdit = roomType == RoomDetailsType.Room && permissions.editDetailsPermissions.hasAny, roomCallState = roomCallState, roomType = roomType, - roomMemberDetailsState = roomMemberDetailsState, + dmOtherMemberDetailsState = dmOtherMemberDetailsState, leaveRoomState = leaveRoomState, roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), isFavorite = isFavorite, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index bd3b90d416..4464058701 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -31,7 +31,7 @@ data class RoomDetailsState( val memberCount: Long, val isEncrypted: Boolean, val roomType: RoomDetailsType, - val roomMemberDetailsState: UserProfileState?, + val dmOtherMemberDetailsState: UserProfileState?, val canEdit: Boolean, val canInvite: Boolean, val roomCallState: RoomCallState, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index 7182d2ec04..935b7293ae 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -106,7 +106,7 @@ fun aRoomDetailsState( canEdit: Boolean = false, roomCallState: RoomCallState = aStandByCallState(), roomType: RoomDetailsType = RoomDetailsType.Room, - roomMemberDetailsState: UserProfileState? = null, + dmOtherMemberDetailsState: UserProfileState? = null, leaveRoomState: LeaveRoomState = aLeaveRoomState(), roomNotificationSettings: RoomNotificationSettings = aRoomNotificationSettings(), isFavorite: Boolean = false, @@ -137,7 +137,7 @@ fun aRoomDetailsState( canEdit = canEdit, roomCallState = roomCallState, roomType = roomType, - roomMemberDetailsState = roomMemberDetailsState, + dmOtherMemberDetailsState = dmOtherMemberDetailsState, leaveRoomState = leaveRoomState, roomNotificationSettings = roomNotificationSettings, isFavorite = isFavorite, @@ -184,7 +184,7 @@ fun aDmRoomDetailsState( isEncrypted = isEncrypted, canInvite = true, roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)), - roomMemberDetailsState = aUserProfileState( + dmOtherMemberDetailsState = aUserProfileState( isBlocked = AsyncData.Success(isDmMemberIgnored), verificationState = dmRoomMemberVerificationState, ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 40210279fa..27eba6f91f 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -43,6 +43,7 @@ import im.vector.app.features.analytics.plan.Interaction import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.roomcall.api.hasPermissionToJoin +import io.element.android.features.userprofile.api.UserProfileState import io.element.android.features.userprofile.api.UserProfileVerificationState import io.element.android.features.userprofile.shared.blockuser.BlockUserDialogs import io.element.android.features.userprofile.shared.blockuser.BlockUserSection @@ -64,7 +65,7 @@ import io.element.android.libraries.designsystem.modifiers.niceClickable 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.PreviewWithExtraLargeHeight import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem @@ -229,66 +230,11 @@ fun RoomDetailsView( ) } } + // Room content PreferenceCategory { - if (state.roomNotificationSettings != null) { - NotificationItem( - isDefaultMode = state.roomNotificationSettings.isDefault, - openRoomNotificationSettings = openRoomNotificationSettings - ) - } - - FavoriteItem( - isFavorite = state.isFavorite, - onFavoriteChanges = { - state.eventSink(RoomDetailsEvent.SetFavorite(it)) - } + MediaGalleryItem( + onClick = openMediaGallery ) - - if (state.canShowSecurityAndPrivacy) { - SecurityAndPrivacyItem( - onClick = onSecurityAndPrivacyClick - ) - } - } - - state.roomMemberDetailsState?.let { dmMemberDetails -> - if (state.canInvite) { - PreferenceCategory { - InviteItem(onClick = invitePeople) - } - } - PreferenceCategory { - ProfileItem( - verificationState = dmMemberDetails.verificationState, - onClick = { onProfileClick(dmMemberDetails.userId) } - ) - } - } - - if (state.roomType is RoomDetailsType.Room) { - PreferenceCategory { - MembersItem( - memberCount = state.memberCount, - hasVerificationViolations = state.hasMemberVerificationViolations, - openRoomMemberList = openRoomMemberList, - ) - if (state.canShowKnockRequests) { - KnockRequestsItem( - knockRequestsCount = state.knockRequestsCount, - onKnockRequestsClick = onKnockRequestsClick - ) - } - if (state.displayRolesAndPermissionsSettings) { - ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())), - onClick = openAdminSettings, - ) - } - } - } - - PreferenceCategory { PinnedMessagesItem( pinnedMessagesCount = state.pinnedMessagesCount, onPinnedMessagesClick = onPinnedMessagesClick @@ -296,23 +242,72 @@ fun RoomDetailsView( PollsItem( openPollHistory = openPollHistory ) - MediaGalleryItem( - onClick = openMediaGallery + } + when (state.roomType) { + is RoomDetailsType.Room -> { + PreferenceCategory { + MembersItem( + memberCount = state.memberCount, + hasVerificationViolations = state.hasMemberVerificationViolations, + openRoomMemberList = openRoomMemberList, + ) + if (state.canShowKnockRequests) { + KnockRequestsItem( + knockRequestsCount = state.knockRequestsCount, + onKnockRequestsClick = onKnockRequestsClick + ) + } + if (state.displayRolesAndPermissionsSettings) { + ListItem( + headlineContent = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())), + onClick = openAdminSettings, + ) + } + } + } + is RoomDetailsType.Dm -> { + if (state.canInvite) { + // Note: for rooms the invite action is a Main action + PreferenceCategory { + InviteItem(onClick = invitePeople) + } + } + state.dmOtherMemberDetailsState?.let { dmMemberDetails -> + PreferenceCategory { + ProfileItem( + verificationState = dmMemberDetails.verificationState, + onClick = { onProfileClick(dmMemberDetails.userId) } + ) + } + } + } + } + PreferenceCategory { + if (state.roomNotificationSettings != null) { + NotificationItem( + isDefaultMode = state.roomNotificationSettings.isDefault, + openRoomNotificationSettings = openRoomNotificationSettings + ) + } + FavoriteItem( + isFavorite = state.isFavorite, + onFavoriteChanges = { + state.eventSink(RoomDetailsEvent.SetFavorite(it)) + } ) + if (state.canShowSecurityAndPrivacy && state.roomType is RoomDetailsType.Room) { + SecurityAndPrivacyItem( + onClick = onSecurityAndPrivacyClick + ) + } } - - if (state.roomType is RoomDetailsType.Dm && state.roomMemberDetailsState != null) { - val roomMemberState = state.roomMemberDetailsState - BlockUserSection(roomMemberState) - BlockUserDialogs(roomMemberState) - } - OtherActionsSection( + dmOtherMemberDetailsState = state.dmOtherMemberDetailsState, canReportRoom = state.canReportRoom, onReportRoomClick = onReportRoomClick, onLeaveRoomClick = { state.eventSink(RoomDetailsEvent.LeaveRoom(needsConfirmation = true)) } ) - if (state.showDebugInfo) { DebugInfoSection( roomId = state.roomId, @@ -803,9 +798,13 @@ private fun OtherActionsSection( canReportRoom: Boolean, onReportRoomClick: () -> Unit, onLeaveRoomClick: () -> Unit, + dmOtherMemberDetailsState: UserProfileState?, ) { - PreferenceCategory(showTopDivider = true) { - if (canReportRoom) { + PreferenceCategory { + if (dmOtherMemberDetailsState != null) { + BlockUserSection(dmOtherMemberDetailsState) + BlockUserDialogs(dmOtherMemberDetailsState) + } else if (canReportRoom) { ListItem( headlineContent = { Text(stringResource(CommonStrings.action_report_room)) @@ -832,7 +831,7 @@ private fun DebugInfoSection( roomVersion: String?, ) { val context = LocalContext.current - PreferenceCategory(showTopDivider = true) { + PreferenceCategory { val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) ListItem( headlineContent = { @@ -870,17 +869,17 @@ private fun DebugInfoSection( } } -@PreviewWithLargeHeight +@PreviewWithExtraLargeHeight @Composable internal fun RoomDetailsPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) = ElementPreviewLight { ContentToPreview(state) } -@PreviewWithLargeHeight +@PreviewWithExtraLargeHeight @Composable internal fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) = ElementPreviewDark { ContentToPreview(state) } -@PreviewWithLargeHeight +@PreviewWithExtraLargeHeight @Composable internal fun RoomDetailsA11yPreview() = ElementPreview { ContentToPreview( diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 9494df5d44..4e0640953b 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -334,7 +334,7 @@ class RoomDetailsViewTest { setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), - roomMemberDetailsState = aUserProfileState(userId = A_USER_ID), + dmOtherMemberDetailsState = aUserProfileState(userId = A_USER_ID), ), onProfileClick = callback, ) @@ -352,7 +352,7 @@ class RoomDetailsViewTest { roomType = RoomDetailsType.Dm( aDmRoomMember(userId = UserId("@other:local.org")), ), - roomMemberDetailsState = aUserProfileState(userId = A_USER_ID), + dmOtherMemberDetailsState = aUserProfileState(userId = A_USER_ID), canInvite = true, ), invitePeople = callback, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewWithLargeHeight.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewWithLargeHeight.kt index 163ee21590..8d745ec0e7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewWithLargeHeight.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewWithLargeHeight.kt @@ -16,3 +16,6 @@ import androidx.compose.ui.tooling.preview.Preview */ @Preview(heightDp = 1000) annotation class PreviewWithLargeHeight + +@Preview(heightDp = 1600) +annotation class PreviewWithExtraLargeHeight From ac93c6bd7044dae052e66603e803d3d15ffadbbb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 17:38:24 +0200 Subject: [PATCH 0564/1083] Move logic to the presenter --- .../android/features/roomdetails/impl/RoomDetailsPresenter.kt | 2 +- .../android/features/roomdetails/impl/RoomDetailsView.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 6a88350360..b916fa7188 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -209,7 +209,7 @@ class RoomDetailsPresenter( knockRequestsCount = knockRequestsCount, canShowSecurityAndPrivacy = canShowSecurityAndPrivacy, hasMemberVerificationViolations = hasMemberVerificationViolations, - canReportRoom = canReportRoom, + canReportRoom = !isDm && canReportRoom, isTombstoned = roomInfo.successorRoom != null, showDebugInfo = isDeveloperModeEnabled, roomVersion = roomInfo.roomVersion, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 27eba6f91f..88aaffc573 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -804,7 +804,8 @@ private fun OtherActionsSection( if (dmOtherMemberDetailsState != null) { BlockUserSection(dmOtherMemberDetailsState) BlockUserDialogs(dmOtherMemberDetailsState) - } else if (canReportRoom) { + } + if (canReportRoom) { ListItem( headlineContent = { Text(stringResource(CommonStrings.action_report_room)) From d7788a8c014da75681fa1eb62e9ec52f08f2dc04 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 17:41:29 +0200 Subject: [PATCH 0565/1083] Remember presenter only on userId. Avoid creating again the presenter when other parameter of the room member are changing. --- .../features/roomdetails/impl/RoomDetailsPresenter.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index b916fa7188..9a602d06c0 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -38,6 +38,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDis import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.JoinedRoom @@ -117,7 +118,7 @@ class RoomDetailsPresenter( val canonicalAlias by remember { derivedStateOf { roomInfo.canonicalAlias } } val isEncrypted by remember { derivedStateOf { roomInfo.isEncrypted == true } } val dmMember by room.getDirectRoomMember(membersState) - val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember) + val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember?.userId) val roomType = getRoomType(dmMember) val roomCallState = roomCallStatePresenter.present() val joinedMemberCount by remember { derivedStateOf { roomInfo.joinedMembersCount } } @@ -220,9 +221,9 @@ class RoomDetailsPresenter( } @Composable - private fun roomMemberDetailsPresenter(dmMemberState: RoomMember?) = remember(dmMemberState) { - dmMemberState?.let { roomMember -> - roomMembersDetailsPresenterFactory.create(roomMember.userId) + private fun roomMemberDetailsPresenter(userId: UserId?) = remember(userId) { + userId?.let { userId -> + roomMembersDetailsPresenterFactory.create(userId) } } From 6c804e734d3957addfe1bf24dd651dc914539b6d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 17:46:25 +0200 Subject: [PATCH 0566/1083] Add missing "Security" section. --- .../features/roomdetails/impl/RoomDetailsView.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 88aaffc573..3d9d41d4c3 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -302,6 +302,21 @@ fun RoomDetailsView( ) } } + if (state.isEncrypted) { + PreferenceCategory( + title = stringResource(R.string.screen_room_details_security_title) + ) { + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), + headlineContent = { + Text(stringResource(id = R.string.screen_room_details_encryption_enabled_title)) + }, + supportingContent = { + Text(stringResource(id = R.string.screen_room_details_encryption_enabled_subtitle)) + }, + ) + } + } OtherActionsSection( dmOtherMemberDetailsState = state.dmOtherMemberDetailsState, canReportRoom = state.canReportRoom, From ee4e4ee701e77765fa8caa7781d2c74493e962b8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 17:48:21 +0200 Subject: [PATCH 0567/1083] Add Figma link --- .../android/features/roomdetails/impl/RoomDetailsView.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 3d9d41d4c3..591ff7ff1e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -97,6 +97,9 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList +/** + * Ref: https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=21-120385 + */ @Composable fun RoomDetailsView( state: RoomDetailsState, From 7a05fc118a602fd2bac3b5522cae492a5ab1c2de Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 1 Jun 2026 18:15:02 +0200 Subject: [PATCH 0568/1083] Fix test --- .../android/features/roomdetails/impl/RoomDetailsViewTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 4e0640953b..7c5b8e4ac8 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -334,6 +334,7 @@ class RoomDetailsViewTest { setRoomDetailView( state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), + roomType = RoomDetailsType.Dm(aDmRoomMember(userId = A_USER_ID)), dmOtherMemberDetailsState = aUserProfileState(userId = A_USER_ID), ), onProfileClick = callback, From b016fb3dc234d4a3ae9c278776397739c0665b18 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 1 Jun 2026 16:36:13 +0000 Subject: [PATCH 0569/1083] Update screenshots --- .../images/features.roomdetails.impl_RoomDetailsA11y_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_0_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_10_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_11_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_12_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_13_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_14_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_15_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_16_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_17_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_18_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_19_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_1_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_20_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_21_en.png | 4 ++-- .../features.roomdetails.impl_RoomDetailsDark_22_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_2_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_3_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_4_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_5_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_6_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_7_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_8_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetailsDark_9_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_0_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_10_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_11_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_12_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_13_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_14_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_15_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_16_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_17_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_18_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_19_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_1_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_20_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_21_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_22_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_2_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_3_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_4_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_5_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_6_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_7_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_8_en.png | 4 ++-- .../images/features.roomdetails.impl_RoomDetails_9_en.png | 4 ++-- 47 files changed, 94 insertions(+), 94 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png index 25302db21d..2ad3818d42 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7c187e173ae6d02d6c95c03bcc24cce91b0922e6aa5a08677732748aab0fc30 -size 85320 +oid sha256:9dc6120d4320dafa66be77e8386a4b636b6b8a77e30ac10d9d6f31932839036a +size 67337 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png index 739ff5f268..d45df5d881 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8979ec6209ad6e0deb6946e00ce227f3db41a565218afe31b72b889bee224daa -size 46268 +oid sha256:6a2dc4ca92e9ab49a29158ef001408ae1ca5d7f8cfed30876c223a4bea31624d +size 40091 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png index 7609f5e725..951db894ff 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16200632461dcbbf0f6211b7064b61a1e2fa04cd34e14946beb12b9e9f4d7b7f -size 43901 +oid sha256:4c31008e2eff545cee39d267475c1f346fe96c6c3600572d812a903659f79604 +size 38262 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png index ef1954720c..e57d2d4d66 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2279893a284e620cf487f6370982a14278fd57bb278e53932a5fd7c5cab8e95e -size 43033 +oid sha256:a5a22703e5a398443ff2457f5705177648f2ce5172c91294e10860ff16ceb25a +size 38258 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png index a0cee002e6..a7b98bd9a5 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d4da60a94c56b13b65efb797825c54c1e107fe4440f56b1fcac5d47779cbf64 -size 44502 +oid sha256:e121018b1e0344c0f07453fa63c99ec382797f82b6828c0291c9724a4e8bdcc9 +size 38601 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png index eb330780d8..3db8f3bf06 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee2899f7870b09f287b45b327d5d0462b423ba65afa1087dec1be862507378de -size 44411 +oid sha256:bd3f8738d58814fa420f683c7bd80a8f805195b15e4973bed1d33b5aa3062533 +size 38535 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png index e09c2dfd95..2277a942a3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78ba2ddfdfc47febc0503daa0985a5fdf04ef15bdc391b4a88c3c630b1946b35 -size 46004 +oid sha256:00e744b9f2652c2cd4cc05f798786d2a090843483d616e1f4868e0431f5495d8 +size 39947 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png index cc49f40494..e036045426 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a832b0e395498b15e176529ea55c50ed129f6d2330fbec4ff1f8e3dcaeab93f -size 46543 +oid sha256:b7832f9cca5732d13dc8d2f282df245c5b09e908c84b37104f3f9764fb2ca189 +size 40271 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png index e8c0ec1046..47de1311bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8e738bd873339d195b4190f65a18016f2f0eb1bbc9f513a2b25467cb5f5828c -size 44745 +oid sha256:fc2f69b95a34c455534f04a21f9edde12acfbdd4c57c190ad7aa22352c2206ec +size 38838 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png index 5098ecb3a2..25d803c185 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:892dd301ab08c6a302e8286d3f86878178130a22baf550402f2102ba98f0d21c -size 43982 +oid sha256:096bfadc7faa370132e03822cb9c66eacdc2b7fa07a65ce501fe1fec7c0d8a81 +size 38236 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index 899ef403a4..d8355a82b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:809c597757d6f1385803c1378a494f24309b533168df59c7e06852c1ce34b8d3 -size 41408 +oid sha256:2710ef0a99a60eca8b369a6c2b0d45658f7d1b2e44900137a625ade9891986bd +size 37199 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 0625fcfe05..7f46bba7b2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3756793e5d92f0fac18e96a49e69ac7ed6901c1195d3e6526088027405e82dbf -size 41361 +oid sha256:3e51350f6799f4b5ed3a0dadfa226d839e4be8e7182bad82ba168381c5a7f7b7 +size 37223 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png index 346c9cf052..58108d410a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:099f571485ce8476d4b8a2313610b6c1d03a7d7420132e06d6258b483d640a08 -size 39130 +oid sha256:922caafea1f17073dfe1352762f194694d4dec8facc93cfa901be111fc99832d +size 34856 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png index a58193c18f..135a83f7ae 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66fd2cfb9f343c77b8db0a4fbc0d7a1571a4dfe1d70c78823a4ba03bfbc846eb -size 44934 +oid sha256:7764a75469a6e2f585c2b919ebad99e61a627d1adef05a6de85370eeb08a0df1 +size 38934 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png index 37bb88b0fb..e872ff70af 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:465ecd337f705262c8f533b3b01daa6a548c6ee88752be405609660ddfaf56b1 -size 44676 +oid sha256:fd3546dd3a61245c611fbd94ba510ba96ea0b3c63048aa6537a91479a45542a4 +size 38696 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png index 6356cec349..85cd90d544 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cca233c171b6c6709a94163ca1f0024a42ff66200383fdbcaf57b321251522e -size 44390 +oid sha256:bbbfc332a093a408354d75064d960f20ca761f606741349723c46d8ab68b6f59 +size 38585 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png index 3846aec585..21798e9560 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e5e8b39197d115c6190b89fd54033b3319b36dfbf5c6f152dd84e6c79147bbb -size 37877 +oid sha256:7ab49c4c721c0b192786afb47c47fe9d205e10734e6c20410a522b0a33624b47 +size 32001 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png index 08ca4ad1e6..755dc1c30b 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4899d2ffcc6da1f414f7fb223440b8463250dc5ac07558cfaee2947f95c93362 -size 42236 +oid sha256:1dde565f1a8a2b58c1eb9446b04e4c954dbb6e1c2d2fa843acac9e7ae850bd31 +size 30785 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png index 062c440463..f095b87dd2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:577381a33e7f0a88ceebb7f2be6528c3e99417cf1351b74c134aab948664cc64 -size 42149 +oid sha256:bd58ff9f30ac4aadf4c7db8d26f0127e8182f6806febd54bbc2a69a071b9606b +size 37445 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index 1ff34bd6e4..29a2163b26 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2bc2699d8dcf770103726c571a6966eacf173cbbad05c4fa6188815aa9ae231 -size 41052 +oid sha256:3cfc733deef5472fc65f0de1e6318e6bac781be6a399c9b1441fd1e2e4123c26 +size 36925 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png index c1decbd918..91cdc6312f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9cba49398954a404def6b37f3cde057cb88d6f59249b943f1689403ccd902326 -size 42024 +oid sha256:0e3d91ed010211048d9d1e7d659d5159ec7c771af53672cf61825ce8a719c6fc +size 31495 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png index 379f61db22..c6781a1908 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:405a29c158295616560152c5790f189a8019bd635a53a69b581c8aa595e6e9ea -size 45494 +oid sha256:167eb16cc4197529054fd0522a73db2b36b4369f149bce46c65a7d2deb449559 +size 39193 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png index d0ffc70f42..68a1b92944 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f948e9cc2eb7bc73b0441fbdea72d582a042895b3404c8302b7e182c3481fae -size 44425 +oid sha256:b49f74cb3db16cb8f4c8c0cfadf08f64a29b147598e420e264bfd9121b485d35 +size 38615 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png index 2894ac3c71..915d514b07 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4702b18ad5d203050140e6e1a18553344f52eb5482fcaf6ab497698b9ec59fd -size 44432 +oid sha256:50463dcf8b496677bb8d6c8ac1af92378aca52fde19a421e227337425a22457c +size 38765 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png index afabfcecf5..224efc8973 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4189b58dd1263a81566ea86d9881c02f053ecb2a91ba9442553fbe0f230e6860 -size 47105 +oid sha256:3cedec6cfed8804e7ef5814255da7b690051a7f29178094aa558dd151bebec5f +size 41410 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png index 9f07ad1624..085716f2b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fced9019f81e5804ea57c0b1a2750868626ad35b9a7227009a796d289595556 -size 44659 +oid sha256:578c3e724112d29557432e08bc442fe127163dc2c33ec22560e7e9768b14bc79 +size 39456 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png index 74c4a9eef1..252f8ae7da 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be9bb839a503d169d67d4332a133ce2b3d76b3ff4c52c063436521f8a74c973e -size 43894 +oid sha256:74daf2e85aaee7e01bfd50446e25d1cfe057ad95adfda6efcc8fd74ee4894cb7 +size 39318 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png index bd85882fde..e7045c0261 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82c2781c37b7cefa198f2061a2c8e900b27bd57653db88733be5ff55dfaf5eee -size 45251 +oid sha256:4c3484c638961188614a9b70c8d9c5fb20c8c5da04fa7907274bc809ee305b2e +size 39828 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png index cac488f3b8..931dac5c8e 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36feab599a6a2d4269b68f42149a6f82832ac0f6f0e9f01fb49adc21b3a58d93 -size 45172 +oid sha256:5add6a8689ea768e86cd035958f6d06f71bf882a8059e3addaa4efef25e77f91 +size 39779 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png index 3e7cfcf672..87c688b249 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04bedd62b5ceba766197dd18da9efb0ff086c2c01c9c19446f8a3c42ed43ad87 -size 46813 +oid sha256:0c9bf7f1707d5304bd9df44f086ae966ee7ce6aeefd1f3f830ca9ad5aff9e6e6 +size 41261 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png index 27ec9f7a25..6d461a206e 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:828b065aaeeccd826e98e9601069819d7a75ffabab9820a834cacb627416edc0 -size 47409 +oid sha256:5d7cc787ca66a1d32df5af87ce2b5c17837a8c650622c8a87b133fe63bbdcecf +size 41662 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png index f96e1aec74..9314d95855 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4740bcd118f8583334dd1c03b5011e33c5384ea6810d1c83711f538cf9f1d165 -size 45521 +oid sha256:522ac292a26b23b260305de8e7ad03b9603c2fa7490c2f420d226c2821914a18 +size 40062 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png index 4d88149a93..10007bb5c6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fab53a63021ddae8384aed8eaf0a3803d06e8c80645ecc13f79a7f5cced6e68 -size 45024 +oid sha256:c4d7cc1bc96f2271efd707d2f8e5a8cc0e19a2eab8981bb1e27e822e54cae904 +size 39615 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index fa7e99aef2..3a1a686dde 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89a2c619412ad9ca43c79cb76ebe72b827da71743dda7044a9b44de2990f160b -size 42388 +oid sha256:e24cb3232d0c59c8ce020def10be0210860de81be50314706fda1c37f928ce51 +size 38529 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index 9b27b61083..c2e89cf6b5 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56ceed440bb51039ffe7e4419477a57a235eed153a0188838e6265c241896a82 -size 42262 +oid sha256:22d74ec9cc245f83fdb71fcb67bff0f4ca061ddd410f64fde61a12ccbb2ffa68 +size 38492 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png index 0542085126..55b742c30c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b03e9da2d73cc0e3d0485b73470e576d7ebd4b8b5f375f2a478f1c1524772fa -size 39948 +oid sha256:1d91aed4496b28952522a084145819947c0eeb704bfafab638f12fa11876acda +size 36068 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png index a320657a26..ca7d80865a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a686a2596b9b85b17c6882aa986b12e13a83a47ed217c4eb6de6aa2cb3ec2d50 -size 45717 +oid sha256:42a2011218c00319b7511ced2bc0187d5aeebb874e236a71a6fcd59ea2190feb +size 40240 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png index 920b670806..50b6f8a28d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6bda369c1754e2c07216f4bff0285e017f87b550fe0dc6bb5f127845d52c9b6 -size 45462 +oid sha256:d87aab87e3d86ede030054a68e905cf793046ff7443233a1418e12b067d8021b +size 39942 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png index aeaa04b269..68d6690ed4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:285045769d912e98df0371c829affd925642c8a20cd0b6b09dfa92ab5f143538 -size 45131 +oid sha256:8f3719a8515a3e9edeaa0db8e1d02eccb5c4330a7767d99f25051d4dce46f7b2 +size 39812 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png index e7fe0e7cef..de4aaa99d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:463548e170b48509d68c0993acb000748b19921e5d4be784b07ce83252c8a5bb -size 38613 +oid sha256:688c59277fd440e8b96c83857084be78a23218151845ef5483175b0b2e322401 +size 33306 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png index 76eb564d8c..33c465e48f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1d19c2b8c6b3c80b68214da2bb9f54a6897a279aa70e2d8cab88c291332cece -size 42980 +oid sha256:1c424390f8c4930db36d474806290c525edfd4b2e25689c95516fe74e5bdc77b +size 31484 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png index 40ab9e310a..534bdb2100 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2057479cad5d3b9a89ec835ee1d06705c6c459f7810c2875bea26b975944bcf7 -size 42960 +oid sha256:e76c8967b4cd416dc4a09e94290dba727e1ca6de51186afd7993ed7561ad49e4 +size 38593 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index e549a92821..99fdc036ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:073addf26e8d0b638bce93db99d1fe9740abd89613a1eb8ef5bb4324e489d6fa -size 41924 +oid sha256:2edc249c3352db53a478c033ca5ebee16a3bfde7c9110b893315b739792f2409 +size 38215 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png index 29a8b0b4b1..86b249d17c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56d72cab4a9d7af568cc497b68d6ca9055874544cfd462c93da37fe368801fdf -size 42984 +oid sha256:9f8a90a86b7dca19bd6964a2a78c610308915d4c55327601499b03f58b104236 +size 32498 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png index 91cf700f52..2f07c45fd6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9141f5fa4e054dc5cf70126309830bc38d564d467a215eaa1130f3601b15e761 -size 46350 +oid sha256:aa079faa553ee5f223cd96c50c89dcd207b226b108da92287f1f70fb83078ee6 +size 40503 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png index fe0b629925..530f089571 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a062b8cbe4dfbd94a5b068b1f7c4654ed8b697a7e98ae4c2bcb6c3e5bf473b49 -size 45289 +oid sha256:d98ec0320a6360b56c01ddd193da24c397ca95b0127b31f56375e0fc970264ac +size 39913 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png index 26d59539db..93915f1e2e 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46aafd39e1a93f8d357def4c5f3f024ad0ee13931ebdb9f72475dbc911fd7532 -size 45266 +oid sha256:037424649684d6559b0a62d7ef1001c63b5a7547bff8398aaa27cc37002d1491 +size 39939 From 97135272ec5832f6e8a8d9b6ecda19472ec15524 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 2 Jun 2026 10:22:34 +0200 Subject: [PATCH 0570/1083] [Media viewer] Improve rendering of files Closes #6899 Closes #6908 --- .../libraries/mediaviewer/api/MediaInfo.kt | 24 ++++++ .../impl/local/DefaultLocalMediaRenderer.kt | 1 + .../mediaviewer/impl/local/LocalMediaView.kt | 3 +- .../impl/local/file/MediaFileView.kt | 74 ++++++++++--------- .../impl/local/file/MediaInfoFileProvider.kt | 8 +- .../impl/viewer/MediaViewerView.kt | 5 ++ 6 files changed, 78 insertions(+), 37 deletions(-) diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt index fedf376a60..adfffd8af4 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt @@ -103,6 +103,30 @@ fun aPdfMediaInfo( duration = null, ) +fun aZipMediaInfo( + filename: String = "a zip file.zip", + caption: String? = null, + formattedCaption: CharSequence? = null, + senderName: String? = null, + dateSent: String? = null, + dateSentFull: String? = null, +): MediaInfo = MediaInfo( + filename = filename, + fileSize = 12 * 1024 * 1024, + caption = caption, + formattedCaption = formattedCaption, + mimeType = MimeTypes.Pdf, + formattedFileSize = "45MB", + fileExtension = "zip", + senderId = UserId("@alice:server.org"), + senderName = senderName, + senderAvatar = null, + dateSent = dateSent, + dateSentFull = dateSentFull, + waveform = null, + duration = null, +) + fun anApkMediaInfo( senderId: UserId? = UserId("@alice:server.org"), senderName: String? = null, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt index 96450d99bf..319aebe33e 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt @@ -41,6 +41,7 @@ class DefaultLocalMediaRenderer( textFileViewer = textFileViewer, audioFocus = audioFocus, onClick = {}, + onOpenWith = null, ) } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt index cc276b52c8..c19b1a24c0 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt @@ -31,6 +31,7 @@ fun LocalMediaView( bottomPaddingInPixels: Int, audioFocus: AudioFocus?, onClick: () -> Unit, + onOpenWith: (() -> Unit)?, textFileViewer: TextFileViewer, modifier: Modifier = Modifier, isDisplayed: Boolean = true, @@ -80,7 +81,7 @@ fun LocalMediaView( uri = localMedia?.uri, info = mediaInfo, modifier = modifier, - onClick = onClick, + onOpenWith = onOpenWith, ) } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt index 912ea88e99..a1c57ef272 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaFileView.kt @@ -9,23 +9,16 @@ package io.element.android.libraries.mediaviewer.impl.local.file import android.net.Uri -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.rotate +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter @@ -33,55 +26,54 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.core.bool.orFalse +import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeAudio +import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.theme.components.IconSource +import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.helper.formatFileExtensionAndSize +import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.mediaviewer.impl.local.LocalMediaViewState import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState +import io.element.android.libraries.ui.strings.CommonStrings +/** + * Ref: https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=3361-16623 + */ @Composable fun MediaFileView( localMediaViewState: LocalMediaViewState, uri: Uri?, info: MediaInfo?, - onClick: () -> Unit, + onOpenWith: (() -> Unit)?, modifier: Modifier = Modifier, ) { val isAudio = info?.mimeType.isMimeTypeAudio().orFalse() localMediaViewState.isReady = uri != null - - val interactionSource = remember { MutableInteractionSource() } Box( modifier = modifier - .padding(horizontal = 8.dp) - .clickable( - onClick = onClick, - interactionSource = interactionSource, - indication = null - ), + .padding(horizontal = 8.dp), contentAlignment = Alignment.Center ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { - Box( - modifier = Modifier - .size(72.dp) - .clip(CircleShape) - .background(ElementTheme.colors.iconPrimary), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = if (isAudio) CompoundIcons.Audio() else CompoundIcons.Attachment(), - contentDescription = null, - tint = ElementTheme.colors.iconOnSolidPrimary, - modifier = Modifier - .size(32.dp) - .rotate(if (isAudio) 0f else -45f), - ) + val isApk = info?.mimeType == MimeTypes.Apk + val icon = when { + isAudio -> CompoundIcons.Audio() + isApk -> CompoundIcons.Bug() + else -> CompoundIcons.Files() } + BigIcon( + modifier = Modifier.align(Alignment.CenterHorizontally), + style = BigIcon.Style.Default( + vectorIcon = icon, + usePrimaryTint = true, + ), + ) if (info != null) { Spacer(modifier = Modifier.height(20.dp)) Text( @@ -100,6 +92,20 @@ fun MediaFileView( overflow = TextOverflow.Ellipsis, color = ElementTheme.colors.textPrimary ) + if (onOpenWith != null) { + val (icon, textResId) = if (isApk) { + IconSource.Resource(R.drawable.ic_apk_install) to CommonStrings.common_install_apk_android + } else { + IconSource.Vector(CompoundIcons.PopOut()) to CommonStrings.action_open_with + } + OutlinedButton( + modifier = Modifier.padding(top = 24.dp), + size = ButtonSize.Small, + leadingIcon = icon, + onClick = onOpenWith, + text = stringResource(id = textResId), + ) + } } } } @@ -115,6 +121,6 @@ internal fun MediaFileViewPreview( localMediaViewState = rememberLocalMediaViewState(), uri = null, info = info, - onClick = {}, + onOpenWith = {}, ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt index 8e41a4809a..3214236253 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/file/MediaInfoFileProvider.kt @@ -10,11 +10,15 @@ package io.element.android.libraries.mediaviewer.impl.local.file import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.mediaviewer.api.MediaInfo -import io.element.android.libraries.mediaviewer.api.aPdfMediaInfo +import io.element.android.libraries.mediaviewer.api.aZipMediaInfo +import io.element.android.libraries.mediaviewer.api.anApkMediaInfo +import io.element.android.libraries.mediaviewer.api.anAudioMediaInfo open class MediaInfoFileProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aPdfMediaInfo(), + aZipMediaInfo(), + anAudioMediaInfo(), + anApkMediaInfo(), ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 3a7c006593..c56b6b64fe 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -239,6 +239,9 @@ fun MediaViewerView( onRetry = { state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) }, + onOpenWith = { + state.eventSink(MediaViewerEvent.OpenWith(dataForPage)) + }, onDismissError = { state.eventSink(MediaViewerEvent.ClearLoadingError(dataForPage)) }, @@ -333,6 +336,7 @@ private fun MediaViewerPage( isUserSelected: Boolean, onDismiss: () -> Unit, onRetry: () -> Unit, + onOpenWith: () -> Unit, onDismissError: () -> Unit, onShowOverlayChange: (Boolean) -> Unit, audioFocus: AudioFocus?, @@ -387,6 +391,7 @@ private fun MediaViewerPage( currentOnShowOverlayChange(!currentShowOverlay) } }, + onOpenWith = onOpenWith, isUserSelected = isUserSelected, audioFocus = audioFocus, ) From 1713555a67984fb64c939f714d8f5cd687381320 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jun 2026 10:29:23 +0200 Subject: [PATCH 0571/1083] Introduce PlatformLocationProvider to replace the maplibre one. --- .../impl/common/PlatformLocationProvider.kt | 130 ++++++++++++++++++ .../location/impl/common/UserLocationState.kt | 3 +- .../service/LiveLocationSharingService.kt | 4 +- 3 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt new file mode 100644 index 0000000000..dbc4ac9040 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common + +import android.Manifest +import android.annotation.SuppressLint +import android.content.Context +import android.content.pm.PackageManager +import android.location.LocationManager +import android.os.Handler +import android.os.HandlerThread +import androidx.annotation.RequiresPermission +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.platform.LocalContext +import androidx.core.location.LocationListenerCompat +import androidx.core.location.LocationManagerCompat +import androidx.core.location.LocationRequestCompat +import androidx.core.os.ExecutorCompat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.stateIn +import org.maplibre.compose.location.DesiredAccuracy +import org.maplibre.compose.location.Location +import org.maplibre.compose.location.LocationProvider +import org.maplibre.compose.location.PermissionException +import org.maplibre.compose.location.asMapLibreLocation +import org.maplibre.spatialk.units.Length +import org.maplibre.spatialk.units.extensions.inMeters +import kotlin.time.Duration + +@SuppressLint("InlinedApi") +class PlatformLocationProvider( + context: Context, + private val updateInterval: Duration, + private val minDistance: Length, + private val desiredAccuracy: DesiredAccuracy = DesiredAccuracy.High, + coroutineScope: CoroutineScope, + sharingStarted: SharingStarted = SharingStarted.WhileSubscribed(stopTimeoutMillis = 1000), +) : LocationProvider { + override val location: StateFlow + + init { + if (!handlerThread.isAlive) handlerThread.start() + if ( + context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && + context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED + ) { + throw PermissionException() + } + + val locationManager = context.getSystemService(LocationManager::class.java) + val provider = PROVIDERS_BY_PRIORITY.firstOrNull { LocationManagerCompat.hasProvider(locationManager, it) } + val locationFlow = if (provider != null) { + createProviderFlow(locationManager, provider) + } else { + emptyFlow() + } + location = locationFlow.stateIn(coroutineScope, sharingStarted, null) + } + + @RequiresPermission( + anyOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION] + ) + private fun createProviderFlow(locationManager: LocationManager, provider: String) = callbackFlow { + send(locationManager.getLastKnownLocation(provider)?.asMapLibreLocation()) + val listener = LocationListenerCompat { trySend(it.asMapLibreLocation()) } + val request = LocationRequestCompat.Builder(updateInterval.inWholeMilliseconds) + .setQuality(desiredAccuracy.toLocationRequestQuality()) + .setMinUpdateDistanceMeters(minDistance.inMeters.toFloat()) + .build() + LocationManagerCompat.requestLocationUpdates( + locationManager, + provider, + request, + ExecutorCompat.create(Handler(handlerThread.looper)), + listener, + ) + awaitClose { LocationManagerCompat.removeUpdates(locationManager, listener) } + } + + private companion object { + private val PROVIDERS_BY_PRIORITY = listOf( + LocationManager.FUSED_PROVIDER, + LocationManager.GPS_PROVIDER, + LocationManager.NETWORK_PROVIDER, + ) + private val handlerThread by lazy { HandlerThread("PlatformLocationProvider") } + } +} + +private fun DesiredAccuracy.toLocationRequestQuality(): Int = when (this) { + DesiredAccuracy.Highest, DesiredAccuracy.High -> LocationRequestCompat.QUALITY_HIGH_ACCURACY + DesiredAccuracy.Balanced -> LocationRequestCompat.QUALITY_BALANCED_POWER_ACCURACY + DesiredAccuracy.Low, DesiredAccuracy.Lowest -> LocationRequestCompat.QUALITY_LOW_POWER +} + +@Composable +@RequiresPermission( + anyOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION] +) +fun rememberPlatformLocationProvider( + updateInterval: Duration, + minDistance: Length, + desiredAccuracy: DesiredAccuracy = DesiredAccuracy.High, + context: Context = LocalContext.current, + coroutineScope: CoroutineScope = rememberCoroutineScope(), + sharingStarted: SharingStarted = SharingStarted.WhileSubscribed(stopTimeoutMillis = 1000), +): PlatformLocationProvider { + return remember(context, updateInterval, minDistance, desiredAccuracy, coroutineScope, sharingStarted) { + PlatformLocationProvider( + context = context, + updateInterval = updateInterval, + minDistance = minDistance, + desiredAccuracy = desiredAccuracy, + coroutineScope = coroutineScope, + sharingStarted = sharingStarted, + ) + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt index 632ddef38d..01533a421d 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt @@ -16,7 +16,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalInspectionMode import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.compose.location.Location -import org.maplibre.compose.location.rememberAndroidLocationProvider import org.maplibre.compose.location.rememberNullLocationProvider import org.maplibre.spatialk.units.extensions.meters import kotlin.time.Duration.Companion.seconds @@ -32,7 +31,7 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState val locationProvider = if (isPreview || !hasLocationPermission) { rememberNullLocationProvider() } else { - rememberAndroidLocationProvider( + rememberPlatformLocationProvider( updateInterval = 5.seconds, desiredAccuracy = DesiredAccuracy.High, minDistance = 5.meters, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt index a926f1255b..b5b8342b96 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -14,6 +14,7 @@ import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION import android.os.IBinder import androidx.core.app.ServiceCompat import dev.zacsweers.metro.Inject +import io.element.android.features.location.impl.common.PlatformLocationProvider import io.element.android.features.location.impl.di.LocationBindings import io.element.android.features.location.impl.live.notification.LiveLocationSharingNotificationCreator import io.element.android.libraries.architecture.bindings @@ -34,7 +35,6 @@ import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach -import org.maplibre.compose.location.AndroidLocationProvider import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.spatialk.units.extensions.inMeters import org.maplibre.spatialk.units.extensions.meters @@ -90,7 +90,7 @@ class LiveLocationSharingService : Service() { Timber.d("LiveLocationSharingService listening to location updates") appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() .flatMapLatest { minDistanceMeters -> - val locationProvider = AndroidLocationProvider( + val locationProvider = PlatformLocationProvider( context = applicationContext, updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, minDistance = minDistanceMeters.meters, From a9bf48779b7b9385bdf51ecfd3fc2e4f4adfe2bf Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 2 Jun 2026 08:43:54 +0000 Subject: [PATCH 0572/1083] Update screenshots --- ...ies.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png | 4 ++-- ...ies.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png | 3 +++ ...ies.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png | 3 +++ ...s.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png | 4 ++-- ...s.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png | 3 +++ ...s.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png | 3 +++ ....mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png | 4 ++-- 10 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png index a094305aad..0ee71c18e5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f520fc8eac5e100bc4e8b0bf0c84e615078dabbdf502411e6dca5a4d579cfcab -size 12255 +oid sha256:4decbb84ca2cab1260c41fdeec92fe41671cf09b666657ef6c26469b5b18856a +size 12942 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png new file mode 100644 index 0000000000..1523f18525 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dac26ebe7db7c63c3f3c443d80a5eb7c33bc7171872c605d694265113931bfca +size 14305 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png new file mode 100644 index 0000000000..f2e777c40d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ce76770f233a9098af885c172147f15acb520c3732cc6ab476e5e0e54fcd0b8 +size 14515 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png index 3692cfba78..03a0d65856 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79fd6fba99568650dcbdac47a0ecfda6faa2cd893ded73d5ac4cbf852b59bd63 -size 11889 +oid sha256:1290c1fb2023cb95f54b6c8d31b044b52d78d7159bf641080cebc6be77588ce7 +size 12482 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png new file mode 100644 index 0000000000..a9818dae5a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bef8e1712b4a6e52e9289e9670dcefa437db08466d74a46c90c5025effa0a83 +size 13867 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png new file mode 100644 index 0000000000..81bb4deb1b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd9fefe7c4c46dfc419576f04470bd0b36f0ce3fab6d7fbb4d6c676341ba4cb8 +size 14071 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png index a092bf37ac..6a08be241c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e23aad00065523bf1ee0e26cd094eb6a9bdd73d65f0bd9cac62cb79e7876481 -size 196533 +oid sha256:311f06e3b866362380c570d7831b69d72b98de07c3d6c0a1b84abb260362084a +size 197521 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png index 619bd4e8c6..04bf989a7e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d98ceaeb669342160d04783f07fbb21929d8be46d30181b60e0f09a99abfe79 -size 197127 +oid sha256:50860f113539dbd61adec9b60ebe0bf43e7c6775c6285caa875987fc0b44e168 +size 198108 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png index 31403f8980..5d8a4a590a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9cd21b6d9a9d0a9ef656bf895d6d135ba76160695355ce034fe985991d6955b -size 123949 +oid sha256:77eda575306e00e2b6fc5b434a3f5c276bf3689266b043fd3b1563784d28e628 +size 125448 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png index bc0720e4b4..5bd06e6364 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dce0794e50116043fde9f6eb76b0c05ca21fc9cee26bde01618024c24c154b2 -size 14952 +oid sha256:bc51776a66a9289423196ae9cb39cd57ba718fab2c795631ff1d9e7517cdf763 +size 16580 From 0a1ef5d121e9c0ea13e3b80ffa21d6732f9b4cac Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 2 Jun 2026 10:43:15 +0200 Subject: [PATCH 0573/1083] [Media viewer] Increase topAppBarHeight so that text and PDF files are not rendered below the top app bar. --- .../libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index c56b6b64fe..2d72875ecb 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -106,7 +106,7 @@ import me.saket.telephoto.zoomable.OverzoomEffect import me.saket.telephoto.zoomable.ZoomSpec import me.saket.telephoto.zoomable.rememberZoomableState -val topAppBarHeight = 88.dp +val topAppBarHeight = 112.dp /** * Ref: https://www.figma.com/design/pDlJZGBsri47FNTXMnEdXB/Compound-Android-Templates?node-id=3361-16623 From bdf32eac97a4e5cc029125879d118a98322466c3 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 2 Jun 2026 09:36:10 +0000 Subject: [PATCH 0574/1083] Update screenshots --- ...ediaviewer.impl.local.txt_TextFileContentView_Day_2_en.png | 4 ++-- ...iaviewer.impl.local.txt_TextFileContentView_Night_2_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_2_en.png index 511027b648..99b5263e02 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:94b71c47da614e247f1c9bbe6df50ae036c5587b964f4df460859927d4807d37 -size 6154 +oid sha256:db3ad4fbd7c140588ed40887455e3ee6b77968ca8682769826f0a447d867ac2f +size 6115 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_2_en.png index cf25daf7f0..2c843d2676 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5d66ac02ac2d39125c26406f70880f2b58f3ffb88569f19b0e5104a03293034 -size 6097 +oid sha256:8b91198bf6f1cc53e13eea6c7092142800760c7103349c37ca931d722a549616 +size 6064 From cd64b5e3763a1f6e0c95851525c9184185a0359b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 2 Jun 2026 11:50:26 +0200 Subject: [PATCH 0575/1083] Remove apparently unneeded `selectedSkinUnicodes` --- .../customreaction/picker/EmojiPicker.kt | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt index a0cd4928fc..05fb849ce9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt @@ -60,24 +60,6 @@ fun EmojiPicker( val pagerState = rememberPagerState(pageCount = { state.categories.size }) var skinPickerEmoji by remember { mutableStateOf(null) } - val selectedSkinUnicodes = remember(skinPickerEmoji, selectedEmojis) { - if (skinPickerEmoji != null) { - val emoji = skinPickerEmoji!! - val variants = emoji.skins.orEmpty() - .map { it.unicode } - .filter { it in selectedEmojis } - if (variants.isNotEmpty()) { - variants.toSet() - } else if (emoji.unicode in selectedEmojis) { - setOf(emoji.unicode) - } else { - emptySet() - } - } else { - emptySet() - } - } - Column(modifier) { SearchBar( modifier = Modifier.padding(bottom = 10.dp), @@ -96,7 +78,6 @@ fun EmojiPicker( skinPickerEmoji = skinPickerEmoji, onDismissSkinPicker = { skinPickerEmoji = null }, selectedEmojis = selectedEmojis, - selectedSkinUnicodes = selectedSkinUnicodes, ) } @@ -139,7 +120,6 @@ fun EmojiPicker( skinPickerEmoji = skinPickerEmoji, onDismissSkinPicker = { skinPickerEmoji = null }, selectedEmojis = selectedEmojis, - selectedSkinUnicodes = selectedSkinUnicodes, ) } } @@ -155,7 +135,6 @@ private fun EmojiResults( skinPickerEmoji: Emoji? = null, onDismissSkinPicker: (() -> Unit)? = null, selectedEmojis: ImmutableSet = persistentSetOf(), - selectedSkinUnicodes: Set = emptySet(), ) { LazyVerticalGrid( modifier = Modifier.fillMaxSize(), @@ -174,7 +153,7 @@ private fun EmojiResults( skinPickerEmoji = skinPickerEmoji, onDismissSkinPicker = onDismissSkinPicker, emojiSize = 32.dp.toSp(), - selectedSkinUnicodes = selectedSkinUnicodes, + selectedSkinUnicodes = selectedEmojis, hasSelectedSkin = item.skins?.any { skin -> skin.unicode in selectedEmojis } == true, ) } From 1a40e460aea4557659470cf97a3eb55cf953c952 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jun 2026 12:23:14 +0200 Subject: [PATCH 0576/1083] Handle unrecoverable location errors and stop sharing --- .../impl/common/PlatformLocationProvider.kt | 1 - .../DefaultActiveLiveLocationShareManager.kt | 5 ++++ .../impl/live/service/LiveLocationReceiver.kt | 3 +- .../service/LiveLocationSharingCoordinator.kt | 11 ++++++++ .../service/LiveLocationSharingService.kt | 28 ++++++++++++------- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt index dbc4ac9040..7988c73e68 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt @@ -58,7 +58,6 @@ class PlatformLocationProvider( ) { throw PermissionException() } - val locationManager = context.getSystemService(LocationManager::class.java) val provider = PROVIDERS_BY_PRIORITY.firstOrNull { LocationManagerCompat.hasProvider(locationManager, it) } val locationFlow = if (provider != null) { diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt index fd16bea515..c24d3f9cc2 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt @@ -133,6 +133,11 @@ class DefaultActiveLiveLocationShareManager( } } + override suspend fun onUnrecoverableError() { + Timber.d("ActiveLiveLocationShareManager unrecoverable error, stopping all shares") + localSharingRoomIds.value.toList().forEach { stopShare(it) } + } + override suspend fun onLocationUpdate(location: Location) { val activeSharesCount = localSharingRoomIds.value.size Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)") diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt index adba75730c..90311e7d4a 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt @@ -9,6 +9,7 @@ package io.element.android.features.location.impl.live.service import io.element.android.features.location.api.Location -fun interface LiveLocationReceiver { +interface LiveLocationReceiver { suspend fun onLocationUpdate(location: Location) + suspend fun onUnrecoverableError() {} } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt index e39acb14e8..63618baa3c 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt @@ -77,6 +77,17 @@ class LiveLocationSharingCoordinator internal constructor( } } + suspend fun dispatchUnrecoverableError() { + Timber.d("LiveLocationSharingCoordinator dispatching unrecoverable error") + receivers.forEach { (sessionId, receiver) -> + runCatchingExceptions { + receiver.onUnrecoverableError() + }.onFailure { + Timber.e(it, "Failed to dispatch unrecoverable error for session $sessionId") + } + } + } + suspend fun dispatch(location: Location) { val currentTimeMillis = nowMillis() val millisSincePrevious = currentTimeMillis - lastDispatchMillis.load() diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt index b5b8342b96..d682ba0df6 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -30,12 +30,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import org.maplibre.compose.location.DesiredAccuracy +import org.maplibre.compose.location.PermissionException import org.maplibre.spatialk.units.extensions.inMeters import org.maplibre.spatialk.units.extensions.meters import timber.log.Timber @@ -48,7 +51,6 @@ class LiveLocationSharingService : Service() { @Inject lateinit var coordinator: LiveLocationSharingCoordinator @Inject lateinit var notificationCreator: LiveLocationSharingNotificationCreator @Inject lateinit var appPreferencesStore: AppPreferencesStore - @Inject lateinit var appForegroundStateService: AppForegroundStateService @AppCoroutineScope @@ -62,8 +64,8 @@ class LiveLocationSharingService : Service() { override fun onCreate() { super.onCreate() Timber.d("LiveLocationSharingService onCreate") + bindings().inject(this) runCatchingExceptions { - bindings().inject(this) appForegroundStateService.updateIsSharingLiveLocation(true) coroutineScope = appCoroutineScope.childScope(Dispatchers.Default, "LiveLocationSharingService") val notificationId = NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.LIVE_LOCATION) @@ -81,6 +83,7 @@ class LiveLocationSharingService : Service() { startLocationUpdatesListener() }.onFailure { Timber.e(it, "Failed to start live location sharing service") + appCoroutineScope.launch { coordinator.dispatchUnrecoverableError() } stopSelf() } } @@ -90,14 +93,19 @@ class LiveLocationSharingService : Service() { Timber.d("LiveLocationSharingService listening to location updates") appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() .flatMapLatest { minDistanceMeters -> - val locationProvider = PlatformLocationProvider( - context = applicationContext, - updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, - minDistance = minDistanceMeters.meters, - desiredAccuracy = DesiredAccuracy.Balanced, - coroutineScope = coroutineScope - ) - locationProvider.location + try { + PlatformLocationProvider( + context = applicationContext, + updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, + minDistance = minDistanceMeters.meters, + desiredAccuracy = DesiredAccuracy.Balanced, + coroutineScope = coroutineScope + ).location + } catch (exception: PermissionException) { + Timber.e(exception, "Failed to create PlatformLocationProvider") + coordinator.dispatchUnrecoverableError() + emptyFlow() + } } .filterNotNull() .map { location -> From 1c058037beec40912d82c42d534f56c97ee4b15f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 2 Jun 2026 12:50:51 +0200 Subject: [PATCH 0577/1083] Update the way we display file format and size. --- .../mediaviewer/api/helper/FileExtensionAndSizeFormatter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/helper/FileExtensionAndSizeFormatter.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/helper/FileExtensionAndSizeFormatter.kt index fc40bca8dd..e546f50565 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/helper/FileExtensionAndSizeFormatter.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/helper/FileExtensionAndSizeFormatter.kt @@ -12,8 +12,8 @@ fun formatFileExtensionAndSize(extension: String, size: String?): String { return buildString { append(extension.uppercase()) if (size != null) { - append(' ') - append("($size)") + append(" • ") + append(size) } } } From 5e3b1463d477063be563e4ba6e5bc1b4c4b99be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 2 Jun 2026 12:55:23 +0200 Subject: [PATCH 0578/1083] Fix skin tone picker always selecting the middle item by default instead of based on the current pointer position --- .../components/customreaction/EmojiItem.kt | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt index b981055e61..ee5055176c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt @@ -25,6 +25,8 @@ import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -35,7 +37,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.Fill import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.layout.positionInParent import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription @@ -77,7 +81,8 @@ fun EmojiItem( } val density = LocalDensity.current var itemSize by remember { mutableStateOf(IntSize.Zero) } - var hoveredIndex by remember { mutableStateOf(-1) } + var itemOffsetPercent by remember { mutableFloatStateOf(0f) } + var hoveredIndex by remember { mutableIntStateOf(-1) } var dismissed by remember { mutableStateOf(false) } val interactionSource = remember { MutableInteractionSource() } val description = a11yReactionAction( @@ -87,6 +92,17 @@ fun EmojiItem( val hasSkinTones = !item.skins.isNullOrEmpty() Box( modifier = modifier + .onPlaced { coordinates -> + val position = coordinates.positionInParent() + val parentBounds = coordinates.parentLayoutCoordinates?.size ?: return@onPlaced + // Calculate the offset of the item inside its parent as a percentage, to be able to set the initial offset + // for the selection inside the skin tone picker relative to its size. + itemOffsetPercent = if (parentBounds.width > 0) { + position.x / parentBounds.width + } else { + 0f + } + } .sizeIn(minWidth = 40.dp, minHeight = 40.dp) .onSizeChanged { itemSize = it } .background(backgroundColor, CircleShape) @@ -94,6 +110,9 @@ fun EmojiItem( .pointerInput(item) { // Only detect drag after long press for those items which have a skin tone picker if (hasSkinTones) { + val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } + val spacingPx = with(density) { SkinToneSlotSpacing.toPx() } + val paddingPx = with(density) { SkinTonePadding.toPx() } var startOffset = Offset.Zero detectDragGesturesAfterLongPress( onDragStart = { position -> @@ -119,16 +138,16 @@ fun EmojiItem( hoveredIndex = -1 onDismissSkinPicker?.invoke() } else { - val skinCount = item.skins!!.size - val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } - val spacingPx = with(density) { SkinToneSlotSpacing.toPx() } - val paddingPx = with(density) { SkinTonePadding.toPx() } - val totalSlots = 1 + skinCount + val skinItemsCount = item.skins!!.size + // Original + variants + val totalSlots = 1 + skinItemsCount + // Calculate the whole size of the skin tone picker val pickerWidthPx = 2 * paddingPx + totalSlots * slotWidthPx + (totalSlots - 1) * spacingPx - val pickerHalfWidthPx = pickerWidthPx / 2f - val centerXPx = itemSize.width / 2f - val pickerLeftPx = centerXPx - pickerHalfWidthPx - val xInPicker = change.position.x - pickerLeftPx + // Calculate the initial offset inside the picker, given the relative position of the item inside its parent + val initialOffset = pickerWidthPx * itemOffsetPercent + val xInPicker = initialOffset + change.position.x + + // If it's a valid offset, calculate the hovered index, otherwise, set it to -1 to indicate that no item is hovered val index = if (xInPicker in 0f..pickerWidthPx) { (xInPicker / slotWidthPx).toInt().coerceIn(0, totalSlots - 1) } else { From ab69c3e1583091a88de40d747556d5dab12d153a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 2 Jun 2026 11:06:59 +0000 Subject: [PATCH 0579/1083] Update screenshots --- ...sages.impl.pinned.list_PinnedMessagesListView_Day_3_en.png | 4 ++-- ...ges.impl.pinned.list_PinnedMessagesListView_Night_3_en.png | 4 ++-- ...meline.components.event_TimelineItemAudioView_Day_0_en.png | 4 ++-- ...meline.components.event_TimelineItemAudioView_Day_1_en.png | 4 ++-- ...meline.components.event_TimelineItemAudioView_Day_2_en.png | 4 ++-- ...meline.components.event_TimelineItemAudioView_Day_3_en.png | 4 ++-- ...meline.components.event_TimelineItemAudioView_Day_4_en.png | 4 ++-- ...line.components.event_TimelineItemAudioView_Night_0_en.png | 4 ++-- ...line.components.event_TimelineItemAudioView_Night_1_en.png | 4 ++-- ...line.components.event_TimelineItemAudioView_Night_2_en.png | 4 ++-- ...line.components.event_TimelineItemAudioView_Night_3_en.png | 4 ++-- ...line.components.event_TimelineItemAudioView_Night_4_en.png | 4 ++-- ...imeline.components.event_TimelineItemFileView_Day_0_en.png | 4 ++-- ...imeline.components.event_TimelineItemFileView_Day_1_en.png | 4 ++-- ...imeline.components.event_TimelineItemFileView_Day_2_en.png | 4 ++-- ...imeline.components.event_TimelineItemFileView_Day_3_en.png | 4 ++-- ...imeline.components.event_TimelineItemFileView_Day_4_en.png | 4 ++-- ...eline.components.event_TimelineItemFileView_Night_0_en.png | 4 ++-- ...eline.components.event_TimelineItemFileView_Night_1_en.png | 4 ++-- ...eline.components.event_TimelineItemFileView_Night_2_en.png | 4 ++-- ...eline.components.event_TimelineItemFileView_Night_3_en.png | 4 ++-- ...eline.components.event_TimelineItemFileView_Night_4_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_4_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_5_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_6_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_7_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_4_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_5_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_6_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_7_en.png | 4 ++-- ...s.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png | 4 ++-- ...mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png | 4 ++-- ...ies.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png | 4 ++-- ...ies.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png | 4 ++-- ...ies.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png | 4 ++-- ...s.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png | 4 ++-- ...s.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png | 4 ++-- ...s.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png | 4 ++-- ....mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png | 4 ++-- 46 files changed, 92 insertions(+), 92 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en.png index ac1b698ddd..8a295a919c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70b06a4411aaf9fccb7dbb68878ee4a01b0987fe592a1aef6fe474dd555dbd0b -size 42536 +oid sha256:e28b5fb8181f780a372aa944291ef23349f4acc3460786ee152d8e281e85b866 +size 41993 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en.png index fc55c74f1c..14e06bbe27 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ed9d6c254ac362f84b9be0761f0bbd7aecb14343a131d54da4b2be0ad033f87 -size 41165 +oid sha256:d20f6311164e291ae60542c2316cb4d438058322fca1b0db0980f0579874f9c6 +size 40650 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en.png index c056ddecb1..e76e0db72d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcd8208f3737b5b5949af591d2417d16f2da18609f3770201f2e87577b250b2e -size 8947 +oid sha256:45b2370c78dd907e5bf7c5df18b98df636e1099cd1de5b54923f7beb9bd17ccc +size 8680 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en.png index 775c2483f8..429d9d0355 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d114f04976fbce895cc53c2c57df8af1e968067d4ed451c4a11b00ea008e14e -size 11127 +oid sha256:cbbbc103c2a7b5e8d942e0af113568c28dd62863ba0cd1dfb7a5dc9de56b3760 +size 10863 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en.png index 4854996fc2..c45bb0c16b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36487e20168db4594c519e4a6901b18d0e10604aaf10f07f9aa95d44647bdbd6 -size 20287 +oid sha256:f758005da7c969bef056ccf52d27a099e3bc5e900643e50990be430d640edfce +size 20031 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en.png index a27104d999..faf7f18e65 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3576dad3e0443c638112c329854fc4d8818f2045dd2e17fe3a0ccbe9a9b1394d -size 11048 +oid sha256:c43d85e4658b9fb930ef76258479a876d5cde3b545bc4f4a76d86e4ef2d7a82f +size 10773 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en.png index c2273c12ee..f8f7b243b3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b4dde4370b8bd6d2bcd8d3c9a877595661ee1b1296dec0f73b041fb556a3921 -size 21282 +oid sha256:c836c0a00fb5697138349028540d5e1cb4f1fddd2fd50d388cb5a1b55ccaa8f4 +size 21023 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en.png index 7fed1167fe..ee33147a2f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc2da3562566b433c6fc5dba185c13127f86890b26644e41d9b5c88f1d130fb3 -size 8671 +oid sha256:3c5351b6f9f14198aec7bb4bd6353b43bbf9f487e192a5c927791756dc354ad9 +size 8431 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en.png index c74490bfdf..802d8b0445 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0870cf3f791d9a1f5203e4d81c01fa986a03a5fa44589befa9f8163c834637e3 -size 10799 +oid sha256:92feff534e8ae02d574f5bddc927bf642e3199dc4f2d89a584d087058d18fc01 +size 10565 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en.png index e3f7918645..013938783e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2031bd6ed35ec1de5a17d1f85aa52c4cb62278e56f1ec5df48c0afe2ddcade38 -size 19216 +oid sha256:2dee0c45a8848f8771bcb0b60f368ccfef29beb7528c227a1a9f07c71a0457dc +size 18940 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en.png index 6ddee33e8c..f5db366e09 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9cac5229b5129b2bc21cae8ead0e7d19b58922056064f28bf0f59074b4e21e6 -size 10742 +oid sha256:9fa672f2cb7dbf0fff171d507e66d1ed8494cbcd93b48bef1ee1b9b75d6717e7 +size 10499 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en.png index 826b4193f0..2ed11e26e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b693ccea2549b9140beacbf2ffaa8ce409ae7c7f2f9cea0050e56527c2c03fe -size 20380 +oid sha256:5735813e0f9c40e5d861ba0c35ba73689ff7ee41224829289ce017746323922c +size 20150 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en.png index 357520ad31..6e88f8cb19 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:043671b3e2176b35ab9519be38ed5711f3eee99a8583583c6fde11f58250aa48 -size 8251 +oid sha256:e155260fd46cf1550c823e2b0a51f3f6529acfd131fc73a7e66dcaca24f3449e +size 7934 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en.png index 36d8c49114..65beb3b8f8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd96a7daf5c19176ef997fbc80a75c3eeb19d470519ae1d57027b5f388736b1c -size 10526 +oid sha256:49a670d25e379b2385ae14a814cd4aca9a0bdff00c3d62d31b146139c2d0edbe +size 10210 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en.png index 317cdaa271..33772989e8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bba55beec2451cdd8eb5237e85ccaf37d98ff86435015ce019f8ef2f131fe31c -size 20520 +oid sha256:d633e28eea9674914bb018b113313c2e3aed6463e2de5901243f5432087a3c1f +size 20237 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en.png index adf5f2263f..c65619f05d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:207dd1bfa213f3153cf2096d6e961d4c1048664fb2bbaea546af843bb96769a4 -size 10349 +oid sha256:10b79226a4eb5c67afc1fc8ace8c6fb49429a69b1e1518b622dcfd20bc2820ea +size 10032 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en.png index a2ec73f85d..d68ac1725c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15a00a56cdb8156a78905fffd95dc5196f4267768a60a08416417322ec6c9801 -size 20640 +oid sha256:085310083c4150fb70e48087881e529f17005df69cc01dd53807a06266f4f4bb +size 20317 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en.png index c7503a4391..4441c3db6b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1b8818e2f1e5f822b9560ec30297460bab89f05d94e36a989aaee4277ae1216 -size 8071 +oid sha256:555333bf67a1f4460c0f0d71393c03914fc67cfe6f4e5161468aec1d95e587e2 +size 7803 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en.png index 6a70eee4fa..2755d2b93d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f3bbd229376c0f2731f93cda00e4580c45971e4ac07bac7b2578d45b48ba079 -size 10220 +oid sha256:36009b81c172786ab1d87834b05550af706b355f8d044d364b1f15e58097c8c7 +size 9945 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en.png index febf7e36c2..5c5063083a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2e3ff1bf09d9e616862c74ef29f07c280bf07af8355eb282e51745e0f6927bb -size 19380 +oid sha256:d40a8265e7bffd24954d6fa3194c8c8c65b600518c23d6089b540adabcb751e5 +size 19141 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en.png index 5e1065d2b2..48242a7b75 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0aadd6c4d503ebf0224a941c798363e3302018fcc9e726bc31808ab7c5381504 -size 10130 +oid sha256:4ef1884c4cac3debea52affbab071110a49b40cebfd38b316693085464fcc440 +size 9859 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en.png index a9fcd11f7e..3146070439 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f44732ffe4caa44b3fb62bac8a6da3e15a7917f0918314d0f1407b08c8b72da -size 19820 +oid sha256:983620627af06dc1937b040fe21b3e12920e84116cc584fe76a7ef799473540c +size 19547 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png index 482736f6a3..193049ba0f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31b6fd539808d47a692e33948145732b530e465eed7356e3a47bf7da157dcb18 -size 66920 +oid sha256:80436cf3797f7fe641e3312074d29d5385d09e93cf58927702cd5a2d9bda6a40 +size 65249 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png index 44091f5537..91a9536188 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea2bb433c696a382c2006381c987eae227b72a159d03d3e654397b00c909f203 -size 82141 +oid sha256:2928e30fe5c473b93644cced7f8826696b6a8018b10ab96d89152b76c835b006 +size 80674 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png index d56d0cb66a..c19f4e5cf7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50307dd635bc606def8fe4b80068b7c209e17828718c7a5992127953226cd4e2 -size 71172 +oid sha256:bda29daa05fd2ca70ee96e430e887c02d6a05e62accd298b0206dd1c532a77d3 +size 69548 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png index 72315f46c2..0b4707fc0f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f0a63b3877b4ce2e7613164e9103a9ba935d64886ccb18646f51e0fd9750885 -size 100976 +oid sha256:991669a0939c78b1d1238cdc5f0197e123e5e21229332c53a7e0d65ff5f11ab7 +size 99624 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png index 41d2ac5ad9..e8f46dab8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bfcf8909d3414e517357d82c203c5464071b3f673d7623d4f75b6c18f25e22e -size 65742 +oid sha256:08c51bcd425352f667189a6fdf98067322f90f76d506029f3d8db640c943654f +size 64109 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png index ecf72ec264..a987d5874c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d3d27b7a366ac20b287f7587866dba06dc5667ba8cd3b6dc040d8ee7e3adb94 -size 80499 +oid sha256:31b76164389481cbe53ea7caa1b1754202314274a0634b8737ad7023bed62a02 +size 79065 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png index 17f8b1974c..837304dde2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdf2031afb6d849812555f8b38f6b0f1f65aa959f3cc9e468fdeece65c150858 -size 69980 +oid sha256:d9962689d7ea7eedd28c7dbec66244df0321bcf45238b47fb9beac50ee81b4cd +size 68585 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png index 780f2f9094..6130f85eed 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0034ff36f0d58e30ac75b36f0869dc27f617d9f1dfb1cf00b88c9bf32d23986 -size 98632 +oid sha256:58d5217e29f95074a403572449d54a072d5969852d09c3a1ddacb43949f4a570 +size 97346 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png index 3c218ccbbc..cdb602aae4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b918ce7162d95c873f0029a657ee07fca2e34926e4c3cdb39eaeb10123a08721 -size 25340 +oid sha256:2c2976543550c63540f3e4533685e342ef5775018a37f5e282bf889e42c199e6 +size 24955 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png index e6925f9f5b..148d707197 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d62cf7beeba92ee47193a871becad07f50d27e6f6fa0b85f6c620c3f1b04b6ce -size 24697 +oid sha256:c8eb14a3df5edff4af450b39224e6af6efce20f0734119835e6fbec210491412 +size 24251 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png index 0ee71c18e5..fcf2e1f03a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4decbb84ca2cab1260c41fdeec92fe41671cf09b666657ef6c26469b5b18856a -size 12942 +oid sha256:71381d66fb321f01d6d874c025681489224626ad9700c0f15fe619f73f1a648e +size 12532 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png index 1523f18525..779d297fb6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dac26ebe7db7c63c3f3c443d80a5eb7c33bc7171872c605d694265113931bfca -size 14305 +oid sha256:cb2ac4d88f51c8c1718a525a5abeccbe2bb19df75a100d504de0cb106ff3117c +size 13857 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png index f2e777c40d..e3e7f9da05 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ce76770f233a9098af885c172147f15acb520c3732cc6ab476e5e0e54fcd0b8 -size 14515 +oid sha256:a3eea2cd53364f9d0c85b803c8faa29f083f9db59123ba6e980a79bff7779402 +size 14113 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png index 03a0d65856..b7daa3bf21 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1290c1fb2023cb95f54b6c8d31b044b52d78d7159bf641080cebc6be77588ce7 -size 12482 +oid sha256:d834acd383dfe8da50426e28e267a1076e5634fc2f96e1e7593cb6a05988600f +size 12074 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png index a9818dae5a..f2a9faa5ab 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bef8e1712b4a6e52e9289e9670dcefa437db08466d74a46c90c5025effa0a83 -size 13867 +oid sha256:a14ccc9724a15a7ae3f477a8cda366be345acf10b7a98ce63c4889bc1708844b +size 13379 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png index 81bb4deb1b..bc3991b8ce 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd9fefe7c4c46dfc419576f04470bd0b36f0ce3fab6d7fbb4d6c676341ba4cb8 -size 14071 +oid sha256:26e4aa8610c1dede0d1b637072e773b5c46fef24bc436b9e7444e26f3ba9814c +size 13689 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png index 6a08be241c..3afa92e837 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:311f06e3b866362380c570d7831b69d72b98de07c3d6c0a1b84abb260362084a -size 197521 +oid sha256:515d5a47d530117ff21cb922d1cb2cb81b22d02c083c51bbff69964f92260bbe +size 197095 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png index 04bf989a7e..d78b959356 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50860f113539dbd61adec9b60ebe0bf43e7c6775c6285caa875987fc0b44e168 -size 198108 +oid sha256:b9f402d6f56e6b9eb8d46add584ef28bf88d4a6c16ae050b7773895faafa8d38 +size 197707 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png index 77e9dad534..6ac98e0150 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:094c1de97c33431390f3ff71d73019d9af9a62ed57ba98c94e53f1f9680851fa -size 210728 +oid sha256:2871bd26b6c21d31ca251761eb5a203468406b4d18c13662fa815c53f015b5e1 +size 210297 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png index c3caba08ff..6f49e5ee89 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a17d0f4bc47305b9c8a3866f70cdddb16fcb5ba10c8007c8739a329025e846a -size 211342 +oid sha256:d9dadffc89e0a66b54a0e6b94006f392569e1907dda2c6d0b6134aad187ff84a +size 210913 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png index 5d8a4a590a..3bcf436edd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77eda575306e00e2b6fc5b434a3f5c276bf3689266b043fd3b1563784d28e628 -size 125448 +oid sha256:9fe5efbf527ef99de18a44e05edb9654b5bc58c17a2fd2d05f57567fbe27ef2c +size 125021 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png index 5bd06e6364..b76993df30 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc51776a66a9289423196ae9cb39cd57ba718fab2c795631ff1d9e7517cdf763 -size 16580 +oid sha256:7ef585a08fc39f7038e861abe6bbb108c3147eab3445722e5500046deb8afe94 +size 16190 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png index 932ddfb632..9d961aa468 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43ab4873fc5fc812bf18af50cbe620c83b273ee70305b5ea06a7aeabdf8dbc93 -size 137637 +oid sha256:58e3353ce8aecff415158d146347206b1dbf167d15523301847f47c2e81b1c5b +size 137215 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png index 924e24ba8a..32ba291890 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33048dafab286cf0e5c84040c034d93a42d69c234edd53132d918a4a1c135ece -size 137908 +oid sha256:2a6b181d16c5ac2e77d11efa8cfb5a6ce7473deaa502502d97c232311878c46a +size 137497 From a9fe0a356071f3e493805fb8119dc2ff7f6fd96e Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jun 2026 13:14:03 +0200 Subject: [PATCH 0580/1083] Fix LiveLocationReceiver interface and update tests --- .../impl/live/service/LiveLocationReceiver.kt | 2 +- .../LiveLocationSharingCoordinatorTest.kt | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt index 90311e7d4a..697a074093 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt @@ -11,5 +11,5 @@ import io.element.android.features.location.api.Location interface LiveLocationReceiver { suspend fun onLocationUpdate(location: Location) - suspend fun onUnrecoverableError() {} + suspend fun onUnrecoverableError() } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt index f74322b4c5..6cee53a482 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt @@ -27,7 +27,7 @@ class LiveLocationSharingCoordinatorTest { nowMillis = { 0L }, ) - coordinator.register(A_SESSION_ID, LiveLocationReceiver { }) + coordinator.register(A_SESSION_ID, liveLocationReceiver()) coordinator.unregister(A_SESSION_ID) assertThat(startCount).isEqualTo(1) @@ -43,8 +43,8 @@ class LiveLocationSharingCoordinatorTest { nowMillis = { 4_000L }, ) - coordinator.register(A_SESSION_ID) { error("boom") } - coordinator.register(A_SESSION_ID_2) { location -> delivered += location } + coordinator.register(A_SESSION_ID, liveLocationReceiver { error("boom") }) + coordinator.register(A_SESSION_ID_2, liveLocationReceiver { delivered += it }) coordinator.dispatch(Location(lat = 1.0, lon = 2.0, accuracy = 3f)) assertThat(delivered).containsExactly(Location(lat = 1.0, lon = 2.0, accuracy = 3f)) @@ -60,7 +60,7 @@ class LiveLocationSharingCoordinatorTest { nowMillis = { nowMillis }, ) - coordinator.register(A_SESSION_ID) { location -> delivered += location } + coordinator.register(A_SESSION_ID, liveLocationReceiver { delivered += it }) val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) @@ -79,7 +79,7 @@ class LiveLocationSharingCoordinatorTest { nowMillis = { nowMillis }, ) - coordinator.register(A_SESSION_ID) { location -> delivered += location } + coordinator.register(A_SESSION_ID, liveLocationReceiver { delivered += it }) val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) val secondLocation = Location(lat = 4.0, lon = 5.0, accuracy = 6f) @@ -101,7 +101,7 @@ class LiveLocationSharingCoordinatorTest { nowMillis = { nowMillis }, ) - coordinator.register(A_SESSION_ID) { location -> delivered += location } + coordinator.register(A_SESSION_ID, liveLocationReceiver { delivered += it }) val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) val secondLocation = Location(lat = 4.0, lon = 5.0, accuracy = 6f) @@ -113,3 +113,10 @@ class LiveLocationSharingCoordinatorTest { assertThat(delivered).containsExactly(firstLocation, secondLocation).inOrder() } } + +private fun liveLocationReceiver( + onLocation: suspend (Location) -> Unit = {}, +) = object : LiveLocationReceiver { + override suspend fun onLocationUpdate(location: Location) = onLocation(location) + override suspend fun onUnrecoverableError() = Unit +} From be0eb003bf876bd27cca12bd3f6e368ea3370d82 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:16:50 +0200 Subject: [PATCH 0581/1083] Update dependency org.maplibre.gl:android-sdk to v13.2.0 (#6930) 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 05530df227..46109a4a01 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -212,7 +212,7 @@ vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil3", version.ref = "telephoto" } telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" } statemachine = "com.freeletics.flowredux:compose:1.2.2" -maplibre = "org.maplibre.gl:android-sdk:13.1.0" +maplibre = "org.maplibre.gl:android-sdk:13.2.0" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.0" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" From 1aef3860c277a55de7e2248b83d713902be394ac Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 2 Jun 2026 15:22:04 +0200 Subject: [PATCH 0582/1083] [Media bottom sheet] Improve design, and hide Share and Download when rendered from the MediaViewer. Closes #6907 --- .../impl/details/MediaBottomSheetState.kt | 1 + .../MediaBottomSheetStateDetailsProvider.kt | 5 ++ .../impl/details/MediaDetailsBottomSheet.kt | 66 +++++++++---------- .../impl/gallery/MediaGalleryPresenter.kt | 1 + .../impl/viewer/MediaViewerPresenter.kt | 1 + .../impl/viewer/MediaViewerView.kt | 2 + .../details/MediaDetailsBottomSheetTest.kt | 30 +++++++-- .../impl/gallery/MediaGalleryPresenterTest.kt | 2 + .../impl/viewer/MediaViewerViewTest.kt | 22 ------- 9 files changed, 70 insertions(+), 60 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt index 722126fac6..245e3a14b8 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetState.kt @@ -16,6 +16,7 @@ sealed interface MediaBottomSheetState { data object Hidden : MediaBottomSheetState data class Details( + val fromGallery: Boolean, val eventId: EventId?, val canDelete: Boolean, val mediaInfo: MediaInfo, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt index 99a6925b9d..7540d49b8a 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaBottomSheetStateDetailsProvider.kt @@ -29,10 +29,14 @@ open class MediaBottomSheetStateDetailsProvider : PreviewParameterProvider @@ -148,11 +118,41 @@ fun MediaDetailsBottomSheet( onOpenWith(state.eventId) } ) + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VisibilityOn())), + headlineContent = { Text(stringResource(CommonStrings.action_view_in_timeline)) }, + onClick = { + onViewInTimeline(state.eventId) + } + ) + if (state.fromGallery) { + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), + headlineContent = { Text(stringResource(CommonStrings.action_share)) }, + onClick = { + onShare(state.eventId) + } + ) + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), + headlineContent = { Text(stringResource(CommonStrings.action_download)) }, + onClick = { + onDownload(state.eventId) + } + ) + } + ListItem( + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Forward())), + headlineContent = { Text(stringResource(CommonStrings.action_forward)) }, + onClick = { + onForward(state.eventId) + } + ) if (state.canDelete) { HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), - headlineContent = { Text(stringResource(CommonStrings.action_delete)) }, + headlineContent = { Text(stringResource(CommonStrings.action_delete_file)) }, style = ListItemStyle.Destructive, onClick = { onDelete(state.eventId) @@ -216,16 +216,14 @@ private fun SenderRow( } @Composable -private fun ColumnScope.Title() { +private fun Title() { Text( modifier = Modifier - .align(Alignment.CenterHorizontally) .padding(top = 16.dp, bottom = 8.dp, start = 16.dp, end = 16.dp) .semantics { heading() }, text = stringResource(R.string.screen_media_details_title), - textAlign = TextAlign.Center, style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textPrimary, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index 2c2fb31020..25e27330b4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -129,6 +129,7 @@ class MediaGalleryPresenter( } is MediaGalleryEvent.OpenInfo -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.Details( + fromGallery = true, eventId = event.mediaItem.eventId(), canDelete = when (event.mediaItem.mediaInfo().senderId) { null -> false 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 296f20ef4c..eec99468f7 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 @@ -145,6 +145,7 @@ class MediaViewerPresenter( } is MediaViewerEvent.OpenInfo -> coroutineScope.launch { mediaBottomSheetState = MediaBottomSheetState.Details( + fromGallery = false, eventId = event.data.eventId, canDelete = when (event.data.mediaInfo.senderId) { null -> false diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 3a7c006593..09206a318d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -277,6 +277,7 @@ fun MediaViewerView( state.eventSink(MediaViewerEvent.ViewInTimeline(it)) }, onShare = { + // Note: share action is not rendered when the bottom sheet is opened from the media viewer (currentData as? MediaViewerPageData.MediaViewerData)?.let { state.eventSink(MediaViewerEvent.Share(currentData)) } @@ -285,6 +286,7 @@ fun MediaViewerView( state.eventSink(MediaViewerEvent.Forward(it)) }, onDownload = { + // Note: download action is not rendered when the bottom sheet is opened from the media viewer (currentData as? MediaViewerPageData.MediaViewerData)?.let { state.eventSink(MediaViewerEvent.SaveOnDisk(currentData)) } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt index 5b0f105aea..c6e317a853 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheetTest.kt @@ -45,7 +45,9 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on Share invokes expected callback`() = runAndroidComposeUiTest { - val state = aMediaBottomSheetStateDetails() + val state = aMediaBottomSheetStateDetails( + fromGallery = true, + ) ensureCalledOnceWithParam(state.eventId) { callback -> setMediaDetailsBottomSheet( state = state, @@ -55,6 +57,15 @@ class MediaDetailsBottomSheetTest { } } + @Test + @Config(qualifiers = "h1024dp") + fun `item Share is not displayed when opened from the media viewer`() = runAndroidComposeUiTest { + setMediaDetailsBottomSheet( + state = aMediaBottomSheetStateDetails(), + ) + onNodeWithText(activity!!.getString(CommonStrings.action_share)).assertDoesNotExist() + } + @Test @Config(qualifiers = "h1024dp") fun `clicking on Forward invokes expected callback`() = runAndroidComposeUiTest { @@ -71,7 +82,9 @@ class MediaDetailsBottomSheetTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on Download invokes expected callback`() = runAndroidComposeUiTest { - val state = aMediaBottomSheetStateDetails() + val state = aMediaBottomSheetStateDetails( + fromGallery = true, + ) ensureCalledOnceWithParam(state.eventId) { callback -> setMediaDetailsBottomSheet( state = state, @@ -81,6 +94,15 @@ class MediaDetailsBottomSheetTest { } } + @Test + @Config(qualifiers = "h1024dp") + fun `item Download is not displayed when opened from the media viewer`() = runAndroidComposeUiTest { + setMediaDetailsBottomSheet( + state = aMediaBottomSheetStateDetails(), + ) + onNodeWithText(activity!!.getString(CommonStrings.action_download)).assertDoesNotExist() + } + @Config(qualifiers = "h1024dp") @Test fun `clicking on Delete invokes expected callback`() = runAndroidComposeUiTest { @@ -90,8 +112,8 @@ class MediaDetailsBottomSheetTest { state = state, onDelete = callback, ) - onNodeWithText(activity!!.getString(CommonStrings.action_delete)).assertExists() - clickOn(CommonStrings.action_delete) + onNodeWithText(activity!!.getString(CommonStrings.action_delete_file)).assertExists() + clickOn(CommonStrings.action_delete_file) } } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt index 929f2a970e..3ab95f2703 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenterTest.kt @@ -137,6 +137,7 @@ class MediaGalleryPresenterTest { val state = awaitItem() assertThat(state.mediaBottomSheetState).isEqualTo( MediaBottomSheetState.Details( + fromGallery = true, eventId = AN_EVENT_ID, canDelete = canDeleteOwn, mediaInfo = item.mediaInfo, @@ -184,6 +185,7 @@ class MediaGalleryPresenterTest { val state = awaitItem() assertThat(state.mediaBottomSheetState).isEqualTo( MediaBottomSheetState.Details( + fromGallery = true, eventId = AN_EVENT_ID, canDelete = canDeleteOther, mediaInfo = item.mediaInfo, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt index 6521f450f5..092ad65c41 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerViewTest.kt @@ -135,28 +135,6 @@ class MediaViewerViewTest { ) } - @Test - @Config(qualifiers = "h1024dp") - fun `clicking on download emits expected Event`() { - val data = aMediaViewerPageData() - testBottomSheetAction( - data, - CommonStrings.action_download, - MediaViewerEvent.SaveOnDisk(data), - ) - } - - @Test - @Config(qualifiers = "h1024dp") - fun `clicking on share emits expected Event`() { - val data = aMediaViewerPageData() - testBottomSheetAction( - data, - CommonStrings.action_share, - MediaViewerEvent.Share(data), - ) - } - @Config(qualifiers = "h1024dp") @Test fun `clicking on open in emits expected Event`() { From e36115e28a07fb5e0a73e307825bbccebd66a000 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 2 Jun 2026 13:37:23 +0000 Subject: [PATCH 0583/1083] Update screenshots --- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png | 4 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en.png | 3 +++ ...viewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png | 4 ++-- ...viewer.impl.details_MediaDetailsBottomSheet_Night_4_en.png | 3 +++ ...ies.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png | 4 ++-- ...s.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png | 4 ++-- ...mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png | 4 ++-- 14 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en.png diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png index c187b29009..12e89a638f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be6223e16a2b9936164ec4ba659129ceb80ed5746e3376f32559b4942b271502 -size 40656 +oid sha256:3239eba4debc9249ecd75a11f9f96aa543ea0bab3f527a654a5ea58e07b942fb +size 40364 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png index c187b29009..28088c2bcd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be6223e16a2b9936164ec4ba659129ceb80ed5746e3376f32559b4942b271502 -size 40656 +oid sha256:e2c67d25e8e74b9ab7ebcff3d167bc72de2bc2ae7ef827c7785c64b551426eb7 +size 38652 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png index b95ce472ff..8857d18f8d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b57d412a5815756b453d907543bc74b4a154814633d8664a3dcffaa0057c7279 -size 44962 +oid sha256:7c7aebf16d23748e4a0a3a035c6ff1d67277d11fac223e2fb2bf66fdbc13ac99 +size 44576 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png index 69da701004..ca2d61a8ee 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6144f221b9d11c70d15b54321bfbff3d1de1454e6c73be34d7b2e82bd1625a94 -size 30701 +oid sha256:a335f858bbca40a0bdb3bd239fdc3625975d44ddc45bb653815f20acde9ffd0f +size 30710 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en.png new file mode 100644 index 0000000000..493603dc42 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90ed265904cdf988d9b2ef6b5695d5793c48fa9d33d4db8c6f4bf94c3055844d +size 40720 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png index a86d65d8f8..6c803533e5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e3e43f4dbd1bf0e271de57c962b93100720439d608a7d552669ede42141dbc1 -size 39705 +oid sha256:73ee558ceb73554e8ab72797797a3e4fb4ae60bc805d9603cc23a5ec3325ae71 +size 39361 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png index a86d65d8f8..d7166ccf37 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e3e43f4dbd1bf0e271de57c962b93100720439d608a7d552669ede42141dbc1 -size 39705 +oid sha256:16b6c38de0dcb40f5141f06a8957c6a64c406ec45765a38a5a371f873cca676f +size 37330 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png index 782df4dbaa..7f9ac4954f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:086c64f4094cb2e0fda8e415a0d8d89b7dafe67f4d42088eded7abbf45b8de93 -size 44088 +oid sha256:4e37123303553d032b579ce0cdace8c6f2aa6c32b3ccce8ef04abac4c84e16b7 +size 43659 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png index 2534bd5d0c..c4af30aa2a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2898f00a828a69ce9cdd56994d7878f6aae8c5b2ea5d1150df57aa2ebd7e537b -size 29233 +oid sha256:423e92ee408ca6c3ab7c1071245810fcbc2d25a7ce62b3068f1616c933ad008c +size 29216 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en.png new file mode 100644 index 0000000000..e79c1a45fe --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5fd5c4d8d9d2ca9709a2b03d423899ef99738b4ba2e081d9456168605e65e07 +size 39788 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png index 6c70063773..8c9923d1d1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad4bf14c2f6d2d36c978d90c7641fc8b3a9c71062d6b23362eea12c0b7ff24e4 -size 40572 +oid sha256:0c8c1dd110d367173c8a918ff9f94aa4e67e9bcba6d417e8ddd0b6660f6ecf20 +size 40280 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png index 40d55d29a1..5c5cbf2dc5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b44ce089c932019d58e7f1c993f80871352878adf0f5a133a72edce18f5bcb9 -size 39496 +oid sha256:00c97219fdc6377f9f965635b3ed696f3595f6de413528a96ea05d2c4b385c9a +size 39155 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png index 41e45ad002..c45563c143 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e641d1d6604b6c5f489ab38438d9f3b8dcea9802113011200e9ea589c4e2dbee -size 25310 +oid sha256:5a9b7b0c427f40aa8f0a61025fdcfb8093c611e15ef10f22576545a64c6ec35c +size 25286 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png index 40d55d29a1..5c5cbf2dc5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b44ce089c932019d58e7f1c993f80871352878adf0f5a133a72edce18f5bcb9 -size 39496 +oid sha256:00c97219fdc6377f9f965635b3ed696f3595f6de413528a96ea05d2c4b385c9a +size 39155 From 13f9ecca1854a6ac79f26392cb434f03f985f3f0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:57:16 +0000 Subject: [PATCH 0584/1083] Update dependency org.unifiedpush.android:connector to v3.3.3 (#6937) 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 46109a4a01..2ed618ee0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -207,7 +207,7 @@ sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version. sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } sqlcipher = "net.zetetic:sqlcipher-android:4.16.0" sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" -unifiedpush = "org.unifiedpush.android:connector:3.3.2" +unifiedpush = "org.unifiedpush.android:connector:3.3.3" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil3", version.ref = "telephoto" } telephoto_flick = { module = "me.saket.telephoto:flick-android", version.ref = "telephoto" } From 716d6d20b2a99840ea1e6858791b23401845a0ab Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 2 Jun 2026 14:54:51 +0000 Subject: [PATCH 0585/1083] Update screenshots --- ...sages.impl.timeline_TimelineViewMessageShield_Day_0_en.png | 4 ++-- ...ges.impl.timeline_TimelineViewMessageShield_Night_0_en.png | 4 ++-- ...line_TimelineViewWithReadMarkerBothIndicators_Day_0_en.png | 3 +++ ...ne_TimelineViewWithReadMarkerBothIndicators_Night_0_en.png | 3 +++ ...neViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en.png | 3 +++ ...ViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en.png | 3 +++ .../features.messages.impl.timeline_TimelineView_Day_0_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_10_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_11_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_12_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_13_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_14_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_15_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_16_en.png | 4 ++-- ...features.messages.impl.timeline_TimelineView_Day_17_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_1_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_2_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_3_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_4_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_5_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_6_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_7_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_8_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_9_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_0_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_10_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_11_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_12_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_13_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_14_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_15_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_16_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_17_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_1_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_2_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_3_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_4_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_5_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_6_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_7_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_8_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_9_en.png | 4 ++-- .../images/features.messages.impl_MessagesViewA11y_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_0_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_10_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_11_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_2_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_3_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_4_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_5_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_6_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_7_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_8_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_9_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_0_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_10_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_11_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_2_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_3_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_4_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_5_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_6_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_7_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_8_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_9_en.png | 4 ++-- 65 files changed, 134 insertions(+), 122 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png index 85e89d81ba..d8224a523d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1730ce48c314caff6efe29287609dcea9f8cc6eda235a4e1f0a0d210e36e4fe7 -size 37453 +oid sha256:1d3fd3cbe32073e9e58032baacec15591dcd1219d87e17048c7cad709402543d +size 37455 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png index 27da587a71..0ba4ceef7e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78bcce34ea3a2a76333aa8f4e3bfb832507b49038c8e73a34c6ca70735db28bf -size 35828 +oid sha256:8201b2412df88f9850a28129d354bc13f77397dc9156c598b0ae64e962e00653 +size 36134 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Day_0_en.png new file mode 100644 index 0000000000..4a73754a8e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ff35c533fef9ca6ddd0e0f31ae4f4d5673e7e90f6d52d9636bfa62a045d8ebf +size 47952 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Night_0_en.png new file mode 100644 index 0000000000..6df8acbfd3 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbcfc8e7f8fa55d007014f39be61a2d8a5a895ecb51f06d83b4f65c13302ebdd +size 51087 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en.png new file mode 100644 index 0000000000..e5528b303c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:990da337f293792e43768e9aa507581df18fac8b2b9dd01d7ad980e4239bec53 +size 47571 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en.png new file mode 100644 index 0000000000..d6b7840b7b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:092e8d3ae1d219d48e3f696244cc83a53aa6402096ec6b7d817d3a115c6a28ac +size 50750 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_0_en.png index 77f5eb3cf5..5bc0436e67 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6852e8f7ab35f830864a94360450b7d4b78b16ce7cb75f2152757dabddf8868 -size 49599 +oid sha256:4f5ce420b36245b164131386d761cbcd003450a2f8d4789a5d5aa681e69f3a74 +size 48582 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_10_en.png index ce251301d9..5c9f27d993 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:877e252ee1e0c35efef1854bf6c94783add9138148a9e910bc7908ee7228209b -size 88375 +oid sha256:4d856ac57fffa33e24e4bcd518016e356d5e34f6067e3ed228085ed05fdbc09e +size 87739 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_11_en.png index 3907bdf959..5b74b9e857 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e157c0f0f115133f36dee9c1f1647fb8f00813a12783b18fa83c6972e92e037 -size 51116 +oid sha256:a97aa2dda9f95577c260015cc619c520d7cb363ce1f2daa1c790d4976cce43de +size 50098 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_12_en.png index 3ea50dcbe1..64f46855e9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00be45a05243c429344206d132d0fdbc6322c25c3c71dcab61f939070dd015d3 -size 63156 +oid sha256:fccf8ce1c5bb494b8a009390ea6dcaa0c6a17051d5f311f939006141f73a3251 +size 62124 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_13_en.png index b9da99e5c2..4f01516eba 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a19d67b394c682e329bc232b0a36c5015dd73d09931b7e401c5d306f922f026 -size 47404 +oid sha256:7e269908cdd45a3996a1b04b8e477a75703bbf01cede83d773460f64f6f49871 +size 46378 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_14_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_14_en.png index bd22123444..8d904ee1f6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:205d1785959ccc932b6f307bbe8fc86466eeab2be83ce80b265cb54bf75cdfe3 -size 64392 +oid sha256:41adea47d3fdd76cc8dd49c1084b17544078ce3881e6b4e91cccf673efa3bef9 +size 63367 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_15_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_15_en.png index cdd4607e18..4afbf06784 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4384708192ccd7ef69601ba4a37b491d1959f8ec84c3e70ceba148d716347952 -size 54368 +oid sha256:2a22c1ca92e494a08a5641bd8f34c9edd45129b8187af26764c4020c91df400f +size 53373 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_16_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_16_en.png index 32a9dd93d2..7571e9f52b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c3ebe62e38381e25e85c0be666ab6380811d2fbbea58461b917a0af4c6cb4d8 -size 64322 +oid sha256:788d2f17f3dfa8f4f63dc5a6454a4097a23ff984ec0985cf34ed3df146ba60ac +size 63442 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 39bbd406ed..70999d766c 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:6f7e3f1cdaf18d7d529be07cde3bdc9100243780101e73dd53c3d78639775974 -size 66862 +oid sha256:6870f4b12402d309b61277bb6c1c79cf4f7184d364c9275f10679e2f656a9e06 +size 66225 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_1_en.png index 2098c7e796..77e10c4bce 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3d8648d88afa54cc57ae97853e10d3c09e5f7a9e5eb34a1634cdd4fca11b6dd -size 70959 +oid sha256:bd36b89a823c06f75546ecfc55474650931fa9b70700244a1c333a4cad221c4f +size 69970 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png index 414db592da..209a92fcb9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:467e5aee42e9041db2672dc0d37e98fc1090c19207604a31247f3142d845f792 -size 493534 +oid sha256:fc2fa4ca81add0b97d595a3ab69b4b9dd7296a0a92afec5c230d863df34db72d +size 492920 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png index b9723dd5c4..2e4d309b9d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:723238ad84c9925eb0edbbf225b50a03bf29e5671777d9f03eba6b910ee00fcf -size 488705 +oid sha256:28afc0e4146fbb75e7109b0cc3f0beac4dabf2f69c4a9928d2389a6908be312f +size 488121 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png index 193049ba0f..3472c572ef 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80436cf3797f7fe641e3312074d29d5385d09e93cf58927702cd5a2d9bda6a40 -size 65249 +oid sha256:4b7082e677feb1a1b9ddfdbf2f02a6ee214805ce21a17b88de7369f7b41f0ed1 +size 64370 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png index 91a9536188..828857e66c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2928e30fe5c473b93644cced7f8826696b6a8018b10ab96d89152b76c835b006 -size 80674 +oid sha256:9c8148f10a526303a10cb7cb79487c94d53d4ef93fde817d8696fa6cd564ea83 +size 79960 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png index c19f4e5cf7..6f934e18ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bda29daa05fd2ca70ee96e430e887c02d6a05e62accd298b0206dd1c532a77d3 -size 69548 +oid sha256:c565dd13a3d3a40aeabf92c169f1d4afe0b324eb630890287237c5ea16f38071 +size 68671 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png index 0b4707fc0f..884b902c0c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:991669a0939c78b1d1238cdc5f0197e123e5e21229332c53a7e0d65ff5f11ab7 -size 99624 +oid sha256:faafdb864f31d90df887cb689e8166b6a8f09941391af8df6d47ffcf62d2ebbb +size 98965 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_8_en.png index b5a3d74b5c..63a4f0f7e1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bc3aff28b9187e987f4bf41bb81460234e4fbf1f5976de84c5f0126dfd28455 -size 54529 +oid sha256:886b3b82ebfa02b88dfbaf8a4627167ee4c6670fec6b223cf605a253d3fc5e97 +size 53683 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 6ff4840c57..6602c48ce1 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:fbd5652457d495c3c6692c151be27c985cf47e95c8b89af9b6edc8c1b734acc8 -size 371265 +oid sha256:2067bbd6ccf54506b4af07629ce56ad79f9a3edf735e260e71515d111994024a +size 370588 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_0_en.png index a93be896ec..57e72064fd 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c62d43a36212da9b518269767f647493556a5082ccbd1cb3919b608687112405 -size 49392 +oid sha256:358d8aca9d2e08fc55b7afd10f9577462ac5ab1f9abe95523c2f21df12d12240 +size 49449 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_10_en.png index 80dcc6a601..4630a0b1c2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e5dddb25a8a201e5334566c90a252111e0d8a65c9949e4f0b7d3d66b3a4103c -size 83890 +oid sha256:97aa1deaf6f07608e362b4461f2bed084955bf13ec80b0f1ee36ef9f9928c038 +size 83969 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_11_en.png index 7f114a43f2..fccd5d210e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f225e76a780b6a3eccc66c720f710564b82774250a3f229367b12cdb390928a4 -size 50876 +oid sha256:fa3a5b26a6d98948f69598cab12346ecc54edf72d131cafda69f68854e7d2741 +size 50937 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_12_en.png index 161bc26f01..62b3892cd8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed0df44ce25f2a9f7e75d49c48a805f62bbf61f1f63ecee7f29e34f9bcae0e70 -size 61888 +oid sha256:42955e8bed36514ef57a3e53b579041d92c5f37edcd587431a8086fdf99dfca5 +size 61975 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_13_en.png index d74c89c6aa..d0bd1ecf26 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4eeddbe4e53cdf4453db6a7bd0257a52d46cfcac762da73319cf8735aedce481 -size 47422 +oid sha256:83ad6aad137696d06e00aa575d5cb35f96f0d90a61c1eab2a203958da2a73008 +size 47474 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_14_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_14_en.png index 6ddd6f5648..8a8920e572 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:143ae0c737a60e42370c10cdb39c577b91a151fa69079843e740b9edc7c5fc67 -size 63288 +oid sha256:513cb5cca0f8bea0af4c6272faa93c9cc6bb39470a90af807f1f8ca7edd1fd37 +size 63374 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_15_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_15_en.png index 1cff467cbe..ec6ef92b50 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4474b2c524768d2493b7ffd6c05b43f486c595c23f1ea641ba7704fad7181d0f -size 53792 +oid sha256:104638ce62de3f283f4bbc1ee3967816b88d84a6969cfc0cdd3a50f716ad8096 +size 53876 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_16_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_16_en.png index ba24c369e1..9f92d1622e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7e7905c6765db72a06c0dba835e34556377fb014476f0ebb2a68a6b93d05314 -size 64889 +oid sha256:ee37c77bae1dbf13fe3d22650828bcd4b636b9be847ae0bb23ecfed0ce037313 +size 64974 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 e5795401ce..6a1ef10cfe 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:06e2c25d3cbd111b22bd0188e2b1880729e023170c7bed972cdb3c34544ba55e -size 55547 +oid sha256:204bd19f811ab2da4068165b67e2260d0855332877140fd67631a6f9e89c0455 +size 55640 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_1_en.png index 6c57315d3a..0fb34507a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1ebb6edcfa045967fd9d9a2b554b1e2bc1ef0e20680661c0af2d8530348ab72 -size 69388 +oid sha256:3ac772343aad8977a8618d69a50d97ff4d9818eb5869c3fc03e58e43f4b4abc1 +size 69473 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png index c418921834..461d9f4310 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bf788838a204acb53bceba268327e3c2a772447490a597ed4929487716bc6fb -size 486425 +oid sha256:2fb3a106c42c8176321be45a2334b185c59ad7c12e3fa099b4c9ef0b4fc98c3f +size 486526 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png index 6ab414ab0b..ba28533f36 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80e198bd8cf523c785de4a66c4c22cecb22d1040377bdfd66eeed821a4281592 -size 481590 +oid sha256:17a7b359ec376b3fcd4bf4bd60d26a9b0ea5f6319d1da291006c1bf36d3f1b39 +size 481665 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png index e8f46dab8a..08368478be 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08c51bcd425352f667189a6fdf98067322f90f76d506029f3d8db640c943654f -size 64109 +oid sha256:e49aa7b7b5245cc48851ceb9d43e2cfbf4df07e427baf071f81717e0ce454c62 +size 64186 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png index a987d5874c..6190a8ede0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31b76164389481cbe53ea7caa1b1754202314274a0634b8737ad7023bed62a02 -size 79065 +oid sha256:434369f889778088c1612a304a4d7a50de90048eeb0506cd13345567cf0dd0b1 +size 79196 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png index 837304dde2..1ab4e96ddb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9962689d7ea7eedd28c7dbec66244df0321bcf45238b47fb9beac50ee81b4cd -size 68585 +oid sha256:91ab3270af1a376d76ea3457b9e083036ba009a95794fcbddcde62f5a6dbf2b1 +size 68637 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png index 6130f85eed..02d19f3878 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58d5217e29f95074a403572449d54a072d5969852d09c3a1ddacb43949f4a570 -size 97346 +oid sha256:9ea0d765a77d9682e376021a2c1c65b9a6bf00dbe69a0762b8c0abf9d0634880 +size 97456 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_8_en.png index 67777f33f7..e7d088463b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24c430f5d40a0215e5c11348d40d2b9a50cf5bbc6639e5ebdb408004b0f3024c -size 54499 +oid sha256:d02a19a7067b5ab4a6eddfdc50179e0457ff4e40f99746cd384bf5ef528f019b +size 54581 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 825618ae17..6367efddcc 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:75ace43e27a0c8f9786b0494931c3ef5e12d903e7417dddecfb34c9526e74f3c -size 149314 +oid sha256:9a1280605d1890f5e38e1bd3fe953930b36f3d09112318389850382b96a553a9 +size 149392 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png index 631559cabc..b2b3f0b813 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee269e52306e048bbd0a06ea7c56f9080f37f37b00909c3d48a02a3a37bd57bc -size 131800 +oid sha256:02c4892eaa7d27c867266c428374b64e5915ec50ddcdf8b1d532e1cbc6f56462 +size 130436 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png index 9c5932834e..144411969f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0dd30568e628750f922a87c2df1fd7751e9d899b9163253c9f2a0c7b03e4a869 -size 56247 +oid sha256:84415250503d5e586af7b7504aaa915c1e24dec0a3d28446487c474c354e05c9 +size 55534 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png index 157e74f7f0..843adcdff0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc02a7c7b38753d9509b3cb0fb2eb0e29b6d6c79b8471ba4dc7dd5b81b13d15b -size 50892 +oid sha256:446ae29cbb211665f6d91129a7dee0f718b407fcb2a64d3f2c0e962e1cb47af7 +size 50168 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png index a63b53d2c1..adabb6dde5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7fdd2e68114457368c5d19fe117b2d5a86a02ca475925c9fae0269ff92f5144 -size 66312 +oid sha256:9b071ba6e99b68dcc75f5aaed3a879f2e30614c954b88c6dc05e1dfec57f1079 +size 65771 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_2_en.png index f00e72d033..7ce91f4684 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d1a8746f4dc362d7d1caa424b18c09c3d2e14753e8d6599267d472a61e197df -size 59137 +oid sha256:7b749e1260d6ba2b7fef5ae9efd58612f6d67d1788f6c1e5cebc22d58d0fd7b7 +size 58563 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png index c19f70ee0a..479d07ae5f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc8b338c1a56b1b663171e16815b3c8122dab3ec948f3db4b9e790833b3f89a6 -size 55378 +oid sha256:0d4f03ac10bbb676d272dba906e758b25d633a1da1e249fe23ba825f8d2f4901 +size 55298 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png index 3cd7dd274c..c90dc8d08f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2a89e79995050e8b24b459172a7c123cc08c64097d5d735cef8c47f913a3bf4 -size 54080 +oid sha256:e48a364a28a67d7d090faa23ef88b27dbd47f0a2f552857490728cb6952ce08b +size 53454 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png index ae8c29241d..abf8eb7086 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:616deb9421b09e2fa25d6953263fd70a9f687fdfbdf9503bbc35e7a0660ec440 -size 58459 +oid sha256:1e79e1cc59ba62ca8eb99300eb520b05d7ac6d52c077e3010c03b474865b15f4 +size 58374 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png index 4c3689dedd..5d4f5bdaeb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b14de263a1f2356b3e84b2a633b0ed837bd160d04c1ec8eeb8c55176856e59ce -size 48755 +oid sha256:08fb14008b08d86755c3473e7194ef0a39bb73c3f0d48122ca80c6a019ec98eb +size 48676 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png index 767be1a188..2209fcb54f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:970396f75edf55841822286155e73e5f4981c347c7c2ff34e69ff9e4bf0aac9f -size 59343 +oid sha256:bd0de7412503e93c33cf92dde0cff38bb68555ef176080d913320af5e4942e7a +size 58642 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png index e4a14ae551..82ef5e7d6a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39430896a687266d7a60890fdac5dbca6d36c87fe30d07619c9c50e23c3f77be -size 56972 +oid sha256:41c4bd5cd1bcbedd91de0a64967fb3f3e03b5f0937ae1ea1a93a7c4a1b24a4a0 +size 56262 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png index b8d8a2cf4c..281aad62a7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cb21bd5e7d348d1d07ca4b6a360f26a4735cc9760fdd7e3b4b1bcde32da6f08 -size 62655 +oid sha256:85f6f4c64f67faa99b9af65307a0cd3b46a68db52503c9c929375408597995d9 +size 62094 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png index b3c490ad32..89fc6708d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30e13e1b91d681088ceba71f21f668a5d8b8f376cb10832f0289b1b14c1103e4 -size 55569 +oid sha256:89467c5b84d0a15210d4013013598d9994d3005a2299e44583d78355e6718ad8 +size 55538 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png index 74826e1e9e..5f3a619097 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:805245ffe7f4e99a0f5927b89bcaa6ab8eaf7cc603d352b14b8109e76eecbdf2 -size 51742 +oid sha256:19d14e3d779b163053c28e66d3381f0cabe3b540744606e955cd733f9e044089 +size 51713 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png index d2b5044048..b3109663f2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52441a5e250b027ddd40ee32754a63c6206762084f47ecfa7e057e2ac77e78a8 -size 69120 +oid sha256:10bce6df962a5198f019f509b1cdb55e28195587de4b74742ddc29833f1333a4 +size 69216 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_2_en.png index eb13905340..f4ab74029b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f988610da5b4feaa47eb9e5224f9b0d2d47633d9aa8fd45117fff75f5040680 -size 58673 +oid sha256:51a5b682243b969bc2d7d609decb823b0509d240f3ff14ee78319260af76a47f +size 58740 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png index 250279e2f8..b0cd5bc6d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f9e76f5d50ce3e0fa259f0692184564a8a988c2e0ba047595c34a99c04fb8e2 -size 50510 +oid sha256:5e900ff75d02c9db4200e2032444dd7e2f8635973cca3389dd96d7d2bb734061 +size 50757 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png index 6b4cb7360c..486d5da5c6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abf3863e6d5ddc747dfea06a006983345937cd85d0e89b60bc625f4ad16b2691 -size 52906 +oid sha256:e482603e6d03fffb57d4eb135edb6209c748c51b1f07e638a4ccf133b1b87a79 +size 52920 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png index 4f903b55b7..a009d0f584 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e99ae9731e9c75fd025db8f24649d6219941ff3aaf0bd4a67bc2c8d1f204cb3 -size 53516 +oid sha256:478851e9e2e8c80095aa552b98a5d574749200ff49899c9472c913b07459c4b5 +size 53758 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png index ffae0459fc..f82a7a8219 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:539799354ad5b383c308779b1278e879db4542d9d1c870c13a54a0ae927767fb -size 44098 +oid sha256:22ea7fe121a63b35a2c2bb47609e692f8bf2b913871a6baf3d420c04334c6c4a +size 44344 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png index 5e28ba8938..952751a962 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5c6ac53f33fb4338a11358a487c2042304691ecf50f61ca0e7cbb75bc227efc -size 58294 +oid sha256:ed13a2778b8ced86ee41d5460d274b42b714a87f59749e3b26bf75114ef40dd9 +size 58265 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png index 1ad21c4d64..0f7fe2db38 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:289819914863942caad5202131efddd9b880b4af64a36d4b45fb547b5b1ec47f -size 55916 +oid sha256:a576d52b840730334a38046cf8b57993693fc760b4fbdc00376cb48b7268d76e +size 55890 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png index 6e371532de..89065e6bf0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86273e812cbc6245527c3d1f138111ece99375aec0d68728882b656b01687bff -size 64392 +oid sha256:a966c9a1fa4fdd933f4ef9239592e90458a2819ff4a45c857714d2e38c0df5b2 +size 64405 From 748454f34da44414e2215a2be5570d542659d42d Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 2 Jun 2026 13:33:04 -0700 Subject: [PATCH 0586/1083] Add shared PasswordVisibilityToggle design-system component Extract the show/hide password trailing-icon into a reusable PasswordVisibilityToggle so every password field reveals plaintext the same way and announces the same a11y labels. Reuse it from the login and reset-identity password fields. Pure refactor, no behaviour change. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../loginpassword/LoginPasswordView.kt | 15 +++----- .../password/ResetIdentityPasswordView.kt | 16 +++----- .../components/PasswordVisibilityToggle.kt | 37 +++++++++++++++++++ 3 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/PasswordVisibilityToggle.kt diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt index d3641ea749..feb1d3d53a 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt @@ -60,6 +60,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.PasswordVisibilityToggle import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.designsystem.theme.components.TopAppBar @@ -249,16 +250,10 @@ private fun LoginForm( placeholder = stringResource(CommonStrings.common_password), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { - val image = - if (passwordVisible) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() - val description = - if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - Box(Modifier.clickable { passwordVisible = !passwordVisible }) { - Icon( - imageVector = image, - contentDescription = description, - ) - } + PasswordVisibilityToggle( + visible = passwordVisible, + onToggle = { passwordVisible = !passwordVisible }, + ) }, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Password, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt index 8d32433ac5..3bb77ac206 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/reset/password/ResetIdentityPasswordView.kt @@ -8,8 +8,6 @@ package io.element.android.features.securebackup.impl.reset.password -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -32,7 +30,7 @@ import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusN import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button -import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.PasswordVisibilityToggle import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.designsystem.theme.components.TextFieldValidity import io.element.android.libraries.ui.strings.CommonStrings @@ -92,14 +90,10 @@ private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Bool singleLine = true, visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { - val image = - if (showPassword) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() - val description = - if (showPassword) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - - Box(Modifier.clickable { showPassword = !showPassword }) { - Icon(imageVector = image, description) - } + PasswordVisibilityToggle( + visible = showPassword, + onToggle = { showPassword = !showPassword }, + ) }, validity = if (hasError) TextFieldValidity.Invalid else TextFieldValidity.None, supportingText = if (hasError) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/PasswordVisibilityToggle.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/PasswordVisibilityToggle.kt new file mode 100644 index 0000000000..9154ec6292 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/PasswordVisibilityToggle.kt @@ -0,0 +1,37 @@ +/* + * 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.designsystem.theme.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.ui.strings.CommonStrings + +/** + * Show/hide toggle for a password [TextField], intended for its `trailingIcon` slot. + * Shared so every password field reveals plaintext the same way and announces the + * same accessibility labels. + */ +@Composable +fun PasswordVisibilityToggle( + visible: Boolean, + onToggle: () -> Unit, + modifier: Modifier = Modifier, +) { + Box(modifier.clickable(onClick = onToggle)) { + Icon( + imageVector = if (visible) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff(), + contentDescription = stringResource( + if (visible) CommonStrings.a11y_hide_password else CommonStrings.a11y_show_password + ), + ) + } +} From 2931418018d1f6b15cf542361f412ae2e2d74cf8 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 2 Jun 2026 13:33:18 -0700 Subject: [PATCH 0587/1083] Parse custom_recovery_passphrase_settings from Element .well-known Add CustomRecoveryPassphraseRequirements to ElementWellKnown and decode the custom_recovery_passphrase_settings block (currently just min_character_count) from the homeserver's element.json. Invalid specs (missing or non-positive min_character_count) are logged and mapped to null so the setup flow falls back to the generated-key path. Field names match the ESS well-known schema (element-enterprise#261). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../CustomRecoveryPassphraseRequirements.kt | 23 ++++++ .../wellknown/api/ElementWellKnown.kt | 1 + .../impl/InternalElementWellKnown.kt | 18 ++++- .../libraries/wellknown/impl/Mapper.kt | 18 +++++ ...ustomRecoveryPassphraseRequirementsTest.kt | 33 ++++++++ .../DefaultSessionWellknownRetrieverTest.kt | 80 +++++++++++++++++++ .../features/wellknown/test/Fixtures.kt | 9 +++ 7 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirements.kt create mode 100644 libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirementsTest.kt diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirements.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirements.kt new file mode 100644 index 0000000000..dc6241b0a9 --- /dev/null +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirements.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.wellknown.api + +/** + * Server-driven requirements for a user-chosen recovery passphrase. Today the only rule + * is a minimum character count; additional rules can be added here as the well-known + * schema (`custom_recovery_passphrase_settings`) grows. + */ +data class CustomRecoveryPassphraseRequirements( + val minCharacterCount: Int, +) { + /** True when [input] meets every active rule. */ + fun isSatisfiedBy(input: String): Boolean = isSatisfiedBy(input.length) + + /** True when an input of [length] characters meets every active rule. */ + fun isSatisfiedBy(length: Int): Boolean = length >= minCharacterCount +} diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt index 4c1c476c7a..ac050ba94a 100644 --- a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt @@ -15,4 +15,5 @@ data class ElementWellKnown( val brandColor: String?, val notificationSound: String?, val identityProviderAppScheme: String?, + val customRecoveryPassphraseRequirements: CustomRecoveryPassphraseRequirements?, ) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt index 2e2b5de16f..803e498eda 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt @@ -15,7 +15,15 @@ import kotlinx.serialization.Serializable * Example: *
  * {
- *     "registration_helper_url": "https://element.io"
+ *     "registration_helper_url": "https://element.io",
+ *     "enforce_element_pro": true,
+ *     "rageshake_url": "https://example.org/rageshake",
+ *     "brand_color": "#FF0000",
+ *     "notification_sound": "ring.flac",
+ *     "idp_app_scheme": "io.element.app",
+ *     "custom_recovery_passphrase_settings": {
+ *         "min_character_count": 8
+ *     }
  * }
  * 
* . @@ -34,4 +42,12 @@ data class InternalElementWellKnown( val notificationSound: String? = null, @SerialName("idp_app_scheme") val identityProviderAppScheme: String? = null, + @SerialName("custom_recovery_passphrase_settings") + val customRecoveryPassphraseRequirements: InternalCustomRecoveryPassphraseRequirements? = null, +) + +@Serializable +data class InternalCustomRecoveryPassphraseRequirements( + @SerialName("min_character_count") + val minCharacterCount: Int? = null, ) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt index 41ed54d7db..61899578d7 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt @@ -8,7 +8,12 @@ package io.element.android.libraries.wellknown.impl +import io.element.android.libraries.core.log.logger.LoggerTag +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphraseRequirements import io.element.android.libraries.wellknown.api.ElementWellKnown +import timber.log.Timber + +private val loggerTag = LoggerTag("Wellknown") internal fun InternalElementWellKnown.map() = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, @@ -17,4 +22,17 @@ internal fun InternalElementWellKnown.map() = ElementWellKnown( brandColor = brandColor, notificationSound = notificationSound, identityProviderAppScheme = identityProviderAppScheme, + customRecoveryPassphraseRequirements = customRecoveryPassphraseRequirements?.toPublic(), ) + +private fun InternalCustomRecoveryPassphraseRequirements.toPublic(): CustomRecoveryPassphraseRequirements? { + val min = minCharacterCount ?: run { + Timber.tag(loggerTag.value).w("custom_recovery_passphrase_settings missing min_character_count; ignoring spec") + return null + } + if (min <= 0) { + Timber.tag(loggerTag.value).w("custom_recovery_passphrase_settings.min_character_count must be > 0; ignoring spec") + return null + } + return CustomRecoveryPassphraseRequirements(minCharacterCount = min) +} diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirementsTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirementsTest.kt new file mode 100644 index 0000000000..c8f10fe2ca --- /dev/null +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/api/CustomRecoveryPassphraseRequirementsTest.kt @@ -0,0 +1,33 @@ +/* + * 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.wellknown.api + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +class CustomRecoveryPassphraseRequirementsTest { + @Test + fun `empty input never satisfies a positive minimum`() { + assertThat(CustomRecoveryPassphraseRequirements(minCharacterCount = 1).isSatisfiedBy("")).isFalse() + } + + @Test + fun `input shorter than minimum is not satisfied`() { + assertThat(CustomRecoveryPassphraseRequirements(minCharacterCount = 8).isSatisfiedBy("abc")).isFalse() + } + + @Test + fun `input exactly at minimum is satisfied`() { + assertThat(CustomRecoveryPassphraseRequirements(minCharacterCount = 8).isSatisfiedBy("abcdefgh")).isTrue() + } + + @Test + fun `input longer than minimum is satisfied`() { + assertThat(CustomRecoveryPassphraseRequirements(minCharacterCount = 4).isSatisfiedBy("abcdefgh")).isTrue() + } +} diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index cca40e283f..68d4d818c2 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -19,6 +19,7 @@ import io.element.android.libraries.cachestore.api.CacheStore import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphraseRequirements import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.services.toolbox.api.systemclock.SystemClock @@ -51,6 +52,7 @@ class DefaultSessionWellknownRetrieverTest { brandColor = null, notificationSound = null, identityProviderAppScheme = null, + customRecoveryPassphraseRequirements = null, ) ) ) @@ -76,6 +78,7 @@ class DefaultSessionWellknownRetrieverTest { brandColor = "#FF0000", notificationSound = "a_notification_sound.flac", identityProviderAppScheme = "an_app_scheme", + customRecoveryPassphraseRequirements = null, ) ) ) @@ -105,11 +108,86 @@ class DefaultSessionWellknownRetrieverTest { brandColor = null, notificationSound = null, identityProviderAppScheme = null, + customRecoveryPassphraseRequirements = null, ) ) ) } + @Test + fun `get element wellknown with custom recovery passphrase requirements`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.success( + """{ + "custom_recovery_passphrase_settings": { + "min_character_count": 8 + } + }""".trimIndent().toByteArray() + ) + }, + ) + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success( + anElementWellKnown( + customRecoveryPassphraseRequirements = CustomRecoveryPassphraseRequirements(minCharacterCount = 8) + ) + ) + ) + } + + @Test + fun `get element wellknown with custom recovery passphrase requirements missing min character count maps to null`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.success( + """{ + "custom_recovery_passphrase_settings": {} + }""".trimIndent().toByteArray() + ) + }, + ) + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success(anElementWellKnown()) + ) + } + + @Test + fun `get element wellknown with non-positive min character count maps to null`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.success( + """{ + "custom_recovery_passphrase_settings": { + "min_character_count": 0 + } + }""".trimIndent().toByteArray() + ) + }, + ) + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success(anElementWellKnown()) + ) + } + + @Test + fun `get element wellknown with negative min character count maps to null`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.success( + """{ + "custom_recovery_passphrase_settings": { + "min_character_count": -5 + } + }""".trimIndent().toByteArray() + ) + }, + ) + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success(anElementWellKnown()) + ) + } + @Test fun `get element wellknown json error`() = runTest { val sut = createDefaultSessionWellknownRetriever( @@ -157,6 +235,7 @@ class DefaultSessionWellknownRetrieverTest { brandColor = "#FF0000", notificationSound = "a_notification_sound.flac", identityProviderAppScheme = "an_app_scheme", + customRecoveryPassphraseRequirements = null, ) ) ) @@ -210,6 +289,7 @@ class DefaultSessionWellknownRetrieverTest { brandColor = "#FF0000", notificationSound = "a_notification_sound.flac", identityProviderAppScheme = "an_app_scheme", + customRecoveryPassphraseRequirements = null, ) ) ) diff --git a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt index ae7d1c629c..1ed69207ba 100644 --- a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt +++ b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt @@ -8,6 +8,7 @@ package io.element.android.features.wellknown.test +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphraseRequirements import io.element.android.libraries.wellknown.api.ElementWellKnown fun anElementWellKnown( @@ -17,6 +18,7 @@ fun anElementWellKnown( brandColor: String? = null, notificationSound: String? = null, identityProviderAppScheme: String? = null, + customRecoveryPassphraseRequirements: CustomRecoveryPassphraseRequirements? = null, ) = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, enforceElementPro = enforceElementPro, @@ -24,4 +26,11 @@ fun anElementWellKnown( brandColor = brandColor, notificationSound = notificationSound, identityProviderAppScheme = identityProviderAppScheme, + customRecoveryPassphraseRequirements = customRecoveryPassphraseRequirements, +) + +fun aCustomRecoveryPassphraseRequirements( + minCharacterCount: Int = 8, +) = CustomRecoveryPassphraseRequirements( + minCharacterCount = minCharacterCount, ) From 62ac6a3d2f6f6a2fa6c9201fdf54f96386acdc2f Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 2 Jun 2026 13:51:59 -0700 Subject: [PATCH 0588/1083] Add enterprise gate for custom recovery passphrase Add isCustomRecoveryPassphraseEnabled() and estimateCustomRecoveryPassphraseStrength() to EnterpriseService, plus the CustomRecoveryPassphraseStrength result types. FOSS builds return false/null so the feature stays gated off; the enterprise implementation (estimator) lands separately in the enterprise repo. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../api/CustomRecoveryPassphraseStrength.kt | 35 +++++++++++++++++++ .../enterprise/api/EnterpriseService.kt | 16 +++++++++ .../impl/DefaultEnterpriseService.kt | 5 +++ .../enterprise/test/FakeEnterpriseService.kt | 8 +++++ 4 files changed, 64 insertions(+) create mode 100644 features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/CustomRecoveryPassphraseStrength.kt diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/CustomRecoveryPassphraseStrength.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/CustomRecoveryPassphraseStrength.kt new file mode 100644 index 0000000000..ea8b02d93f --- /dev/null +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/CustomRecoveryPassphraseStrength.kt @@ -0,0 +1,35 @@ +/* + * 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.enterprise.api + +/** + * Strength tier surfaced to the user under a custom recovery passphrase field. + * The eight tiers mirror iOS `PasswordStrengthThreshold` 1:1 so both clients label a given + * passphrase identically; each maps to its own label and time-to-crack description in the UI. + */ +enum class CustomRecoveryPassphraseStrength { + Garbage, + Weak, + Moderate, + Okay, + Strong, + VeryStrong, + UltraStrong, + Mega, +} + +/** + * Result of estimating a custom recovery passphrase's strength. The estimation algorithm itself + * is an enterprise capability ([EnterpriseService.estimateCustomRecoveryPassphraseStrength]); FOSS + * builds never produce one. + */ +data class CustomRecoveryPassphraseStrengthResult( + val strength: CustomRecoveryPassphraseStrength, + /** Fill amount for the progress bar. Always in `0f..1f`. */ + val score: Float, +) diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt index 92d8b9b646..ce56a5dc80 100644 --- a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt @@ -41,6 +41,22 @@ interface EnterpriseService { */ fun getNoisyNotificationChannelId(sessionId: SessionId): String? + /** + * Whether the user is allowed to set a custom recovery passphrase. + * Enterprise builds gate this in addition to the homeserver's .well-known `customRecoveryPassphraseRequirements`; + * when false the setup flow falls back to the auto-generated key path even if the homeserver + * advertises a spec. + */ + fun isCustomRecoveryPassphraseEnabled(): Boolean + + /** + * Estimate the strength of a user-typed custom recovery [passphrase]. + * The estimation algorithm is an enterprise capability: FOSS builds return null, so callers + * should treat null as "no indicator to show". Callers are responsible for not calling this with + * an empty passphrase if they want the indicator hidden while the field is empty. + */ + fun estimateCustomRecoveryPassphraseStrength(passphrase: String): CustomRecoveryPassphraseStrengthResult? + companion object { const val ANY_ACCOUNT_PROVIDER = "*" } diff --git a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt index 6e3ed5d3cc..caa2eb291f 100644 --- a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt +++ b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt @@ -13,6 +13,7 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.enterprise.api.BugReportUrl +import io.element.android.features.enterprise.api.CustomRecoveryPassphraseStrengthResult import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.matrix.api.core.SessionId import kotlinx.coroutines.flow.Flow @@ -45,4 +46,8 @@ class DefaultEnterpriseService : EnterpriseService { } override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null + + override fun isCustomRecoveryPassphraseEnabled(): Boolean = false + + override fun estimateCustomRecoveryPassphraseStrength(passphrase: String): CustomRecoveryPassphraseStrengthResult? = null } diff --git a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt index 805c75be6a..fb474a96e5 100644 --- a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt +++ b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt @@ -11,6 +11,7 @@ package io.element.android.features.enterprise.test import androidx.compose.ui.graphics.Color import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.enterprise.api.BugReportUrl +import io.element.android.features.enterprise.api.CustomRecoveryPassphraseStrengthResult import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.tests.testutils.lambda.lambdaError @@ -31,6 +32,8 @@ class FakeEnterpriseService( private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() }, private val tweakMasUrlResult: (String, String) -> String = { _, _ -> lambdaError() }, + private val isCustomRecoveryPassphraseEnabledResult: Boolean = false, + private val estimateCustomRecoveryPassphraseStrengthResult: (String) -> CustomRecoveryPassphraseStrengthResult? = { null }, ) : EnterpriseService { private val brandColorState = MutableStateFlow(initialBrandColor) private val semanticColorsState = MutableStateFlow(initialSemanticColors) @@ -79,4 +82,9 @@ class FakeEnterpriseService( override fun getNoisyNotificationChannelId(sessionId: SessionId): String? { return getNoisyNotificationChannelIdResult(sessionId) } + + override fun isCustomRecoveryPassphraseEnabled(): Boolean = isCustomRecoveryPassphraseEnabledResult + + override fun estimateCustomRecoveryPassphraseStrength(passphrase: String): CustomRecoveryPassphraseStrengthResult? = + estimateCustomRecoveryPassphraseStrengthResult(passphrase) } From 0cb9d2911de86ed5407c3c4965055a91bd197656 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 2 Jun 2026 13:52:08 -0700 Subject: [PATCH 0589/1083] Allow enableRecovery to derive the key from a passphrase enableRecovery now takes an optional passphrase and returns the recovery key as the suspend result (like resetRecoveryKey), avoiding the flow/return-value race. For the passphrase path the SDK-derived base58 key is kept out of the session-scoped progress flow so it is never surfaced to the user; the caller receives it as the return value and is responsible for scrubbing it. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../api/encryption/EncryptionService.kt | 10 ++++++++-- .../impl/encryption/RustEncryptionService.kt | 19 ++++++++++++++----- .../test/encryption/FakeEncryptionService.kt | 9 +++++---- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index 333cfb709b..f82cdc1969 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt @@ -24,9 +24,15 @@ interface EncryptionService { suspend fun enableBackups(): Result /** - * Enable recovery. Observe enableProgressStateFlow to get progress and recovery key. + * Enable recovery and return the SDK-generated recovery key on success. + * Observe [enableRecoveryProgressStateFlow] for in-progress UI updates. + * + * @param waitForBackupsToUpload when true, suspends until existing room keys finish uploading. + * @param passphrase optional user-supplied passphrase. When set, the SDK derives the + * secret-storage key from it instead of a random base58 key; the passphrase can later be + * passed to [recover], and the returned base58 key should not be surfaced to the user. */ - suspend fun enableRecovery(waitForBackupsToUpload: Boolean): Result + suspend fun enableRecovery(waitForBackupsToUpload: Boolean, passphrase: String? = null): Result /** * Change the recovery and return the new recovery key. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index f67b7cb7e1..74f235f9f8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt @@ -131,19 +131,28 @@ class RustEncryptionService( override suspend fun enableRecovery( waitForBackupsToUpload: Boolean, - ): Result = withContext(dispatchers.io) { + passphrase: String?, + ): Result = withContext(dispatchers.io) { runCatchingExceptions { - service.enableRecovery( + // The key arrives as the suspend return value (like resetRecoveryKey), avoiding a + // flow/return-value race; the listener only feeds sub-progress. + enableRecoveryProgressStateFlow.value = EnableRecoveryProgress.Starting + val key = service.enableRecovery( waitForBackupsToUpload = waitForBackupsToUpload, progressListener = object : EnableRecoveryProgressListener { override fun onUpdate(status: RustEnableRecoveryProgress) { enableRecoveryProgressStateFlow.value = enableRecoveryProgressMapper.map(status) } }, - passphrase = null, + passphrase = passphrase, ) - // enableRecovery returns the encryption key, but we read it from the state flow - .let { } + // Pin Done explicitly so observers get a coherent terminal value. For the passphrase + // path the user never sees the SDK base58 key, so keep it out of this session-scoped + // (in-memory) flow entirely; the caller still receives it as the return value and is + // responsible for scrubbing it. The auto-generated path must retain the key here since + // that is how it is surfaced to the user. + enableRecoveryProgressStateFlow.value = EnableRecoveryProgress.Done(if (passphrase != null) "" else key) + key }.mapFailure { it.mapRecoveryException() } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt index 04e3779298..e090319821 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt @@ -28,7 +28,8 @@ class FakeEncryptionService( private val pinUserIdentityResult: (UserId) -> Result = { lambdaError() }, private val withdrawVerificationResult: (UserId) -> Result = { lambdaError() }, private val getUserIdentityResult: (UserId) -> Result = { lambdaError() }, - private val enableRecoveryLambda: (Boolean) -> Result = { lambdaError() }, + private val enableRecoveryLambda: (Boolean, String?) -> Result = { _, _ -> lambdaError() }, + private val resetRecoveryKeyLambda: () -> Result = { Result.success(FAKE_RECOVERY_KEY) }, ) : EncryptionService { private var disableRecoveryFailure: Exception? = null override val backupStateStateFlow: MutableStateFlow = MutableStateFlow(BackupState.UNKNOWN) @@ -90,11 +91,11 @@ class FakeEncryptionService( } override suspend fun resetRecoveryKey(): Result = simulateLongTask { - return Result.success(FAKE_RECOVERY_KEY) + return resetRecoveryKeyLambda() } - override suspend fun enableRecovery(waitForBackupsToUpload: Boolean): Result = simulateLongTask { - return enableRecoveryLambda(waitForBackupsToUpload) + override suspend fun enableRecovery(waitForBackupsToUpload: Boolean, passphrase: String?): Result = simulateLongTask { + return enableRecoveryLambda(waitForBackupsToUpload, passphrase) } fun givenWaitForBackupUploadSteadyStateFlow(flow: Flow) { From db6f4414df4de42c91415f8b91c8493637648a92 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 2 Jun 2026 13:52:21 -0700 Subject: [PATCH 0590/1083] Add custom recovery passphrase setup flow When the homeserver advertises custom_recovery_passphrase_settings (and the enterprise gate is enabled), the secure-backup setup lets the user enter and confirm their own recovery key with a live strength indicator, instead of receiving a generated one. The SDK derives the 4S key from the passphrase and the base58 key is scrubbed everywhere so it is never shown. Falls back to the generated-key flow when no spec is present or the well-known fetch fails. Snapshot PNGs are intentionally left out; the core team regenerates them after the PR is opened. Co-Authored-By: Claude Opus 4.8 (1M context) --- features/securebackup/impl/build.gradle.kts | 3 + .../impl/setup/CustomPassphraseDerivations.kt | 51 ++ .../impl/setup/SecureBackupSetupEvents.kt | 18 + .../impl/setup/SecureBackupSetupPresenter.kt | 206 ++++- .../impl/setup/SecureBackupSetupState.kt | 24 + .../setup/SecureBackupSetupStateMachine.kt | 6 + .../setup/SecureBackupSetupStateProvider.kt | 140 +++- .../impl/setup/SecureBackupSetupView.kt | 378 ++++++++- .../impl/src/main/res/values/temporary.xml | 37 + .../setup/SecureBackupSetupPresenterTest.kt | 758 +++++++++++++++++- .../android/libraries/testtags/TestTags.kt | 2 + 11 files changed, 1552 insertions(+), 71 deletions(-) create mode 100644 features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/CustomPassphraseDerivations.kt create mode 100644 features/securebackup/impl/src/main/res/values/temporary.xml diff --git a/features/securebackup/impl/build.gradle.kts b/features/securebackup/impl/build.gradle.kts index 54d87ef22e..d7dafc3e65 100644 --- a/features/securebackup/impl/build.gradle.kts +++ b/features/securebackup/impl/build.gradle.kts @@ -38,9 +38,12 @@ dependencies { implementation(projects.libraries.oauth.api) implementation(projects.libraries.uiStrings) implementation(projects.libraries.testtags) + implementation(projects.libraries.wellknown.api) api(libs.statemachine) api(projects.features.securebackup.api) testCommonDependencies(libs, true) + testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.wellknown.test) } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/CustomPassphraseDerivations.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/CustomPassphraseDerivations.kt new file mode 100644 index 0000000000..7bf6e5805c --- /dev/null +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/CustomPassphraseDerivations.kt @@ -0,0 +1,51 @@ +/* + * 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.securebackup.impl.setup + +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphraseRequirements + +/** + * Validation flags computed once and shared by the presenter and the preview provider. + * + * Note: passphrase strength is intentionally NOT derived here. The estimation algorithm is an + * enterprise capability ([io.element.android.features.enterprise.api.EnterpriseService.estimateCustomRecoveryPassphraseStrength]); + * the presenter computes it via the injected service and the state provider supplies samples directly. + */ +internal data class CustomPassphraseDerivations( + val meetsMinLength: Boolean, + val mismatch: Boolean, + val canContinueFromEntry: Boolean, + val canSubmitCustomPassphrase: Boolean, +) + +internal fun deriveCustomPassphraseState( + requirements: CustomRecoveryPassphraseRequirements?, + passphrase: String, + confirm: String, + step: CustomEntryStep, + setupState: SetupState, +): CustomPassphraseDerivations { + val meetsMinLength = requirements?.isSatisfiedBy(passphrase) ?: true + val mismatch = confirm.isNotEmpty() && passphrase != confirm + val canContinueFromEntry = requirements != null && + passphrase.isNotEmpty() && + meetsMinLength && + setupState is SetupState.Init + val canSubmit = requirements != null && + passphrase.isNotEmpty() && + passphrase == confirm && + meetsMinLength && + step == CustomEntryStep.Confirm && + setupState is SetupState.Init + return CustomPassphraseDerivations( + meetsMinLength = meetsMinLength, + mismatch = mismatch, + canContinueFromEntry = canContinueFromEntry, + canSubmitCustomPassphrase = canSubmit, + ) +} diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupEvents.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupEvents.kt index f61e65ba61..faf3d618fe 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupEvents.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupEvents.kt @@ -13,4 +13,22 @@ sealed interface SecureBackupSetupEvents { data object RecoveryKeyHasBeenSaved : SecureBackupSetupEvents data object Done : SecureBackupSetupEvents data object DismissDialog : SecureBackupSetupEvents + + /** Update the user-typed custom recovery passphrase. */ + data class UpdateCustomPassphrase(val value: String) : SecureBackupSetupEvents + + /** Update the user-typed confirmation field. */ + data class UpdateCustomPassphraseConfirm(val value: String) : SecureBackupSetupEvents + + /** Advance from the Entry step to the Confirm step. No-op unless the entry passphrase meets requirements. */ + data object ContinueCustomPassphrase : SecureBackupSetupEvents + + /** Step back from Confirm to Entry. Both typed values are preserved. */ + data object BackToCustomEntry : SecureBackupSetupEvents + + /** Submit the custom passphrase to the SDK (only valid when [SecureBackupSetupState.canSubmitCustomPassphrase]). */ + data object SubmitCustomPassphrase : SecureBackupSetupEvents + + /** Abort an in-flight custom submit (back press while creating) and return to the Confirm step. */ + data object CancelCustomPassphraseSubmit : SecureBackupSetupEvents } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt index 9f27bc9566..9145b4a49b 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt @@ -11,6 +11,7 @@ package io.element.android.features.securebackup.impl.setup import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -22,22 +23,33 @@ import com.freeletics.flowredux.compose.rememberStateAndDispatch import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.securebackup.impl.loggerTagSetup import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyUserStory import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyViewState import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress import io.element.android.libraries.matrix.api.encryption.EncryptionService +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphraseRequirements +import io.element.android.libraries.wellknown.api.SessionWellknownRetriever +import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job import kotlinx.coroutines.launch import timber.log.Timber +private data class WellknownStatus( + val loaded: Boolean, + val customRecoveryPassphraseRequirements: CustomRecoveryPassphraseRequirements?, +) + @AssistedInject class SecureBackupSetupPresenter( @Assisted private val isChangeRecoveryKeyUserStory: Boolean, private val stateMachine: SecureBackupSetupStateMachine, private val encryptionService: EncryptionService, + private val sessionWellknownRetriever: SessionWellknownRetriever, + private val enterpriseService: EnterpriseService, ) : Presenter { @AssistedFactory interface Factory { @@ -53,10 +65,81 @@ class SecureBackupSetupPresenter( } var showSaveConfirmationDialog by remember { mutableStateOf(false) } + // Spinner until the well-known fetch settles, so the user can't start the auto-gen path + // while a custom spec is still in flight. The loaded/specs pair flips in one assignment. + val wellknownStatusState = remember { + mutableStateOf(WellknownStatus(loaded = false, customRecoveryPassphraseRequirements = null)) + } + val wellknownLoaded by remember { + derivedStateOf { wellknownStatusState.value.loaded } + } + val customRecoveryPassphraseRequirements by remember { + derivedStateOf { wellknownStatusState.value.customRecoveryPassphraseRequirements } + } + // Not rememberSaveable: the passphrase must never reach the on-disk saved-state bundle. + // Plain String (not a zeroed CharArray): the TextField/event/SDK boundary all copy Strings + // anyway, so we just clear it on success and accept loss on process death. + var customPassphrase by remember { mutableStateOf("") } + var customPassphraseConfirm by remember { mutableStateOf("") } + var customEntryStep by remember { mutableStateOf(CustomEntryStep.Entry) } + // Single-flight guard: a button tap and an IME-Done in the same frame both see + // canSubmit=true and would each launch an enableRecovery coroutine. The state machine + // dedupes UserCreatesKey, but only this flag stops the duplicate SDK call. + var customSubmitInFlight by remember { mutableStateOf(false) } + // Handle to the in-flight custom submit so a back press can abort it (see CancelCustomPassphraseSubmit). + var customSubmitJob by remember { mutableStateOf(null) } + + LaunchedEffect(setupState) { + if (setupState !is SetupState.Creating) { + customSubmitInFlight = false + } + } + + LaunchedEffect(Unit) { + val result = sessionWellknownRetriever.getElementWellKnown() + // Enterprise gate: even if the homeserver advertises a custom spec, only honor it on + // builds where the feature is enabled. FOSS builds always fall back to the auto-gen path. + val specsFromWellknown = (result as? WellknownRetrieverResult.Success)?.data?.customRecoveryPassphraseRequirements + wellknownStatusState.value = WellknownStatus( + loaded = true, + customRecoveryPassphraseRequirements = specsFromWellknown.takeIf { enterpriseService.isCustomRecoveryPassphraseEnabled() }, + ) + } + + // Shared with SecureBackupSetupStateProvider so previews never drift from runtime. + val derivations by remember { + derivedStateOf { + deriveCustomPassphraseState( + requirements = wellknownStatusState.value.customRecoveryPassphraseRequirements, + passphrase = customPassphrase, + confirm = customPassphraseConfirm, + step = customEntryStep, + setupState = setupState, + ) + } + } + + // Strength is an enterprise-only estimation; null while the field is empty or in FOSS builds. + // Only computed on the Entry step, the only place the indicator is rendered. + val customPassphraseStrength by remember { + derivedStateOf { + customPassphrase + .takeIf { customEntryStep == CustomEntryStep.Entry && it.isNotEmpty() } + ?.let { enterpriseService.estimateCustomRecoveryPassphraseStrength(it) } + } + } + + // Nothing to "save" when the user chose the passphrase: auto-skip the Created step. + LaunchedEffect(setupState, customRecoveryPassphraseRequirements) { + if (customRecoveryPassphraseRequirements != null && setupState is SetupState.Created) { + stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.UserSavedKey) + } + } + fun handleEvent(event: SecureBackupSetupEvents) { when (event) { SecureBackupSetupEvents.CreateRecoveryKey -> { - coroutineScope.createOrChangeRecoveryKey(stateAndDispatch) + coroutineScope.createOrChangeRecoveryKey(stateAndDispatch, passphrase = null) } SecureBackupSetupEvents.RecoveryKeyHasBeenSaved -> stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.UserSavedKey) @@ -67,12 +150,51 @@ class SecureBackupSetupPresenter( SecureBackupSetupEvents.Done -> { showSaveConfirmationDialog = true } + is SecureBackupSetupEvents.UpdateCustomPassphrase -> { + customPassphrase = event.value + } + is SecureBackupSetupEvents.UpdateCustomPassphraseConfirm -> { + customPassphraseConfirm = event.value + } + SecureBackupSetupEvents.ContinueCustomPassphrase -> { + if (derivations.canContinueFromEntry) { + customEntryStep = CustomEntryStep.Confirm + } + } + SecureBackupSetupEvents.BackToCustomEntry -> { + customEntryStep = CustomEntryStep.Entry + } + SecureBackupSetupEvents.SubmitCustomPassphrase -> { + if (derivations.canSubmitCustomPassphrase && !customSubmitInFlight) { + customSubmitInFlight = true + customSubmitJob = coroutineScope.createOrChangeRecoveryKey( + stateAndDispatch, + passphrase = customPassphrase, + onSuccess = { + customPassphrase = "" + customPassphraseConfirm = "" + }, + ) + } + } + SecureBackupSetupEvents.CancelCustomPassphraseSubmit -> { + // Abort the SDK call and snap back to Initial. Dispatch the reset first so that + // if the (now cancelled) coroutine still manages to dispatch SdkError/ + // SdkHasCreatedKey, those land in Initial where the state machine ignores them. + customSubmitJob?.cancel() + customSubmitJob = null + customSubmitInFlight = false + stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.UserCancelledCreate) + } } } + val isCustomFlow = customRecoveryPassphraseRequirements != null val recoveryKeyViewState = RecoveryKeyViewState( recoveryKeyUserStory = if (isChangeRecoveryKeyUserStory) RecoveryKeyUserStory.Change else RecoveryKeyUserStory.Setup, - formattedRecoveryKey = setupState.recoveryKey(), + // Custom flow: never surface the SDK base58 key in view state, even during the + // brief Created/CreatedAndSaved auto-skip window. + formattedRecoveryKey = if (isCustomFlow) null else setupState.recoveryKey(), displayTextFieldContents = true, inProgress = setupState is SetupState.Creating, ) @@ -82,6 +204,16 @@ class SecureBackupSetupPresenter( recoveryKeyViewState = recoveryKeyViewState, setupState = setupState, showSaveConfirmationDialog = showSaveConfirmationDialog, + wellknownLoaded = wellknownLoaded, + customRecoveryPassphraseRequirements = customRecoveryPassphraseRequirements, + customEntryStep = customEntryStep, + customPassphrase = customPassphrase, + customPassphraseConfirm = customPassphraseConfirm, + customPassphraseMeetsMinLength = derivations.meetsMinLength, + customPassphraseMismatch = derivations.mismatch, + customPassphraseStrength = customPassphraseStrength, + canContinueFromEntry = derivations.canContinueFromEntry, + canSubmitCustomPassphrase = derivations.canSubmitCustomPassphrase, eventSink = ::handleEvent, ) } @@ -98,47 +230,43 @@ class SecureBackupSetupPresenter( } private fun CoroutineScope.createOrChangeRecoveryKey( - stateAndDispatch: StateAndDispatch + stateAndDispatch: StateAndDispatch, + passphrase: String?, + onSuccess: () -> Unit = {}, ) = launch { stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.UserCreatesKey) - if (isChangeRecoveryKeyUserStory) { + // Custom passphrase → enableRecovery(passphrase): the SDK derives the 4S key from it. + // For the Change flow this rotates in place — the SDK skips backup creation when recovery + // is already enabled (confirmed), so there's no key-backup teardown or room-key re-upload. + val result = if (passphrase != null) { + Timber.tag(loggerTagSetup.value).d("Calling encryptionService.enableRecovery(passphrase=present)") + encryptionService.enableRecovery(waitForBackupsToUpload = false, passphrase = passphrase) + } else if (isChangeRecoveryKeyUserStory) { Timber.tag(loggerTagSetup.value).d("Calling encryptionService.resetRecoveryKey()") - encryptionService.resetRecoveryKey().fold( - onSuccess = { - stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkHasCreatedKey(it)) - }, - onFailure = { - if (it is Exception) { - stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkError(it)) - } - } - ) + encryptionService.resetRecoveryKey() } else { - observeEncryptionService(stateAndDispatch) - Timber.tag(loggerTagSetup.value).d("Calling encryptionService.enableRecovery()") - encryptionService.enableRecovery(waitForBackupsToUpload = false).onFailure { + Timber.tag(loggerTagSetup.value).d("Calling encryptionService.enableRecovery(passphrase=absent)") + encryptionService.enableRecovery(waitForBackupsToUpload = false, passphrase = null) + } + result.fold( + onSuccess = { key -> + // Clear buffers only on success; on failure keep them so the user can retry + // without retyping. + onSuccess() + // Custom flow: scrub the SDK base58 key from the state machine so SetupState + // never carries it. RustEncryptionService likewise keeps it out of + // enableRecoveryProgressStateFlow for the passphrase path, so it is not retained + // anywhere once this local goes out of scope. + val storedKey = if (passphrase != null) "" else key + stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkHasCreatedKey(storedKey)) + }, + onFailure = { Timber.tag(loggerTagSetup.value).e(it, "Failed to enable recovery") - if (it is Exception) { - stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkError(it)) - } + // The state machine only accepts Exception; wrap anything else so a failure + // still leaves the Creating spinner instead of hanging on it. + val exception = it as? Exception ?: RuntimeException(it) + stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkError(exception)) } - } - } - - private fun CoroutineScope.observeEncryptionService( - stateAndDispatch: StateAndDispatch - ) = launch { - encryptionService.enableRecoveryProgressStateFlow.collect { enableRecoveryProgress -> - Timber.tag(loggerTagSetup.value).d("New enableRecoveryProgress: ${enableRecoveryProgress.javaClass.simpleName}") - when (enableRecoveryProgress) { - is EnableRecoveryProgress.Starting, - is EnableRecoveryProgress.CreatingBackup, - is EnableRecoveryProgress.CreatingRecoveryKey, - is EnableRecoveryProgress.BackingUp, - is EnableRecoveryProgress.RoomKeyUploadError -> Unit - is EnableRecoveryProgress.Done -> - stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkHasCreatedKey(enableRecoveryProgress.recoveryKey)) - } - } + ) } } diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupState.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupState.kt index 752b5e4851..0e5b60dab7 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupState.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupState.kt @@ -8,16 +8,40 @@ package io.element.android.features.securebackup.impl.setup +import io.element.android.features.enterprise.api.CustomRecoveryPassphraseStrengthResult import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyViewState +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphraseRequirements data class SecureBackupSetupState( val isChangeRecoveryKeyUserStory: Boolean, val recoveryKeyViewState: RecoveryKeyViewState, val showSaveConfirmationDialog: Boolean, val setupState: SetupState, + /** False while the well-known is still being fetched; the view shows a spinner until true. */ + val wellknownLoaded: Boolean, + /** Non-null when the well-known requires a user-chosen passphrase; hides the generated-key UI. */ + val customRecoveryPassphraseRequirements: CustomRecoveryPassphraseRequirements?, + val customEntryStep: CustomEntryStep, + /** User-typed passphrase. Not persisted to saved-state; cleared after a successful submit. */ + val customPassphrase: String, + /** Confirmation field; same lifetime contract as [customPassphrase]. */ + val customPassphraseConfirm: String, + /** True when [customPassphrase] satisfies the minimum-character-count rule from [customRecoveryPassphraseRequirements]. */ + val customPassphraseMeetsMinLength: Boolean, + val customPassphraseMismatch: Boolean, + /** Null while the Entry-step passphrase is empty; otherwise the latest strength reading rendered below the field. */ + val customPassphraseStrength: CustomRecoveryPassphraseStrengthResult?, + /** True when the Entry-step passphrase is valid enough to advance to the Confirm step. */ + val canContinueFromEntry: Boolean, + val canSubmitCustomPassphrase: Boolean, val eventSink: (SecureBackupSetupEvents) -> Unit ) +enum class CustomEntryStep { + Entry, + Confirm, +} + sealed interface SetupState { data object Init : SetupState data object Creating : SetupState diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupStateMachine.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupStateMachine.kt index 150aeeddc7..62478e3b87 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupStateMachine.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupStateMachine.kt @@ -34,6 +34,9 @@ class SecureBackupSetupStateMachine : FlowReduxStateMachine -> state.override { State.KeyCreated(event.key) } } + on { _: Event.UserCancelledCreate, state: MachineState -> + state.override { State.Initial } + } } inState { on { _: Event.UserSavedKey, state: MachineState -> @@ -64,5 +67,8 @@ class SecureBackupSetupStateMachine : FlowReduxStateMachine { override val values: Sequence get() = sequenceOf( + aSecureBackupSetupState(wellknownLoaded = false), aSecureBackupSetupState(setupState = SetupState.Init), aSecureBackupSetupState(setupState = SetupState.Creating), aSecureBackupSetupState(setupState = SetupState.Created(aFormattedRecoveryKey())), @@ -25,25 +29,141 @@ open class SecureBackupSetupStateProvider : PreviewParameterProvider Unit, modifier: Modifier = Modifier, ) { + // Custom flow auto-skips the "save your key" screen: finish once the SDK accepted it. + LaunchedEffect(state.setupState, state.isCustomEntry()) { + if (state.isCustomEntry() && state.setupState is SetupState.CreatedAndSaved) { + onSuccess() + } + } FlowStepPage( modifier = modifier, - onBackClick = onBackClick.takeIf { state.canGoBack() }, + onBackClick = backClickHandler(state, onBackClick), title = title(state), subTitle = subtitle(state), iconStyle = BigIcon.Style.Default(CompoundIcons.KeySolid()), - buttons = { Buttons(state, onFinish = onSuccess) }, + buttons = { Buttons(state, onFinish = onSuccess, onCancel = onBackClick) }, ) { Content(state = state) } @@ -78,15 +120,45 @@ private fun SecureBackupSetupState.canGoBack(): Boolean { return recoveryKeyViewState.formattedRecoveryKey == null } +private fun SecureBackupSetupState.isCustomEntry(): Boolean = + customRecoveryPassphraseRequirements != null + +private fun backClickHandler( + state: SecureBackupSetupState, + onBackClick: () -> Unit, +): (() -> Unit)? { + if (!state.canGoBack()) return null + if (state.isCustomEntry()) { + // Back while the SDK call is in flight aborts it and returns to the Confirm step + // (typed input preserved) rather than silently flipping the step under the spinner. + if (state.setupState is SetupState.Creating) { + return { state.eventSink.invoke(SecureBackupSetupEvents.CancelCustomPassphraseSubmit) } + } + if (state.customEntryStep == CustomEntryStep.Confirm) { + // In the custom flow, backing out of Confirm returns to Entry (preserve typed input). + return { state.eventSink.invoke(SecureBackupSetupEvents.BackToCustomEntry) } + } + } + return onBackClick +} + @Composable private fun title(state: SecureBackupSetupState): String { + // Hide the heading until the well-known resolves, so it can't flip copy under the user. + if (!state.wellknownLoaded) return "" + // Custom flow has no "save your key" step — use per-step custom titles throughout. + if (state.isCustomEntry()) { + return when (state.customEntryStep) { + CustomEntryStep.Entry -> stringResource(id = R.string.screen_recovery_key_custom_title) + CustomEntryStep.Confirm -> stringResource(id = R.string.screen_recovery_key_custom_confirm_title) + } + } return when (state.setupState) { SetupState.Init, SetupState.Creating, - is SetupState.Error -> if (state.isChangeRecoveryKeyUserStory) { - stringResource(id = R.string.screen_recovery_key_change_title) - } else { - stringResource(id = R.string.screen_recovery_key_setup_title) + is SetupState.Error -> when { + state.isChangeRecoveryKeyUserStory -> stringResource(id = R.string.screen_recovery_key_change_title) + else -> stringResource(id = R.string.screen_recovery_key_setup_title) } is SetupState.Created, is SetupState.CreatedAndSaved -> @@ -95,14 +167,20 @@ private fun title(state: SecureBackupSetupState): String { } @Composable -private fun subtitle(state: SecureBackupSetupState): String { +private fun subtitle(state: SecureBackupSetupState): String? { + if (!state.wellknownLoaded) return null + if (state.isCustomEntry()) { + return when (state.customEntryStep) { + CustomEntryStep.Entry -> stringResource(id = R.string.screen_recovery_key_custom_description) + CustomEntryStep.Confirm -> stringResource(id = R.string.screen_recovery_key_custom_confirm_description) + } + } return when (state.setupState) { SetupState.Init, SetupState.Creating, - is SetupState.Error -> if (state.isChangeRecoveryKeyUserStory) { - stringResource(id = R.string.screen_recovery_key_change_description) - } else { - stringResource(id = R.string.screen_recovery_key_setup_description) + is SetupState.Error -> when { + state.isChangeRecoveryKeyUserStory -> stringResource(id = R.string.screen_recovery_key_change_description) + else -> stringResource(id = R.string.screen_recovery_key_setup_description) } is SetupState.Created, is SetupState.CreatedAndSaved -> @@ -114,6 +192,25 @@ private fun subtitle(state: SecureBackupSetupState): String { private fun Content( state: SecureBackupSetupState, ) { + // Spinner until the well-known resolves, so neither flow renders before we know which applies. + if (!state.wellknownLoaded && state.setupState == SetupState.Init) { + LoadingPlaceholder() + return + } + if (state.isCustomEntry()) { + when (state.setupState) { + SetupState.Init, + is SetupState.Error -> when (state.customEntryStep) { + CustomEntryStep.Entry -> CustomPassphraseEntry(state = state) + CustomEntryStep.Confirm -> CustomPassphraseConfirm(state = state) + } + // Hold the spinner through the auto-skip so the SDK base58 key is never shown/shared. + SetupState.Creating, + is SetupState.Created, + is SetupState.CreatedAndSaved -> LoadingPlaceholder() + } + return + } val context = LocalContext.current val formattedRecoveryKey = state.recoveryKeyViewState.formattedRecoveryKey val toastMessage = stringResource(R.string.screen_recovery_key_copied_to_clipboard) @@ -144,10 +241,269 @@ private fun Content( ) } +@Composable +private fun LoadingPlaceholder() { + val description = stringResource(id = R.string.a11y_recovery_key_loading_specs) + Box( + modifier = Modifier + .fillMaxWidth() + .padding(top = 52.dp) + .semantics { contentDescription = description }, + contentAlignment = Alignment.Center, + ) { + // CircularProgressIndicator applies progressSemantics() internally — no need to add it here. + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + strokeWidth = 2.dp, + ) + } +} + +@Composable +private fun CustomPassphraseEntry(state: SecureBackupSetupState) { + val specs = state.customRecoveryPassphraseRequirements ?: return + var passphraseVisible by rememberSaveable { mutableStateOf(false) } + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 24.dp), + ) { + TextField( + modifier = Modifier + .fillMaxWidth() + .testTag(TestTags.customRecoveryPassphrase) + .semantics { contentType = ContentType.NewPassword }, + value = state.customPassphrase, + onValueChange = { state.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(it)) }, + label = stringResource(id = CommonStrings.common_recovery_key), + singleLine = true, + visualTransformation = if (passphraseVisible) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + PasswordVisibilityToggle( + visible = passphraseVisible, + onToggle = { passphraseVisible = !passphraseVisible }, + ) + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Password, + imeAction = ImeAction.Done, + ), + keyboardActions = KeyboardActions( + onDone = { + if (state.canContinueFromEntry) { + state.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + } + }, + ), + supportingText = pluralStringResource( + id = R.plurals.screen_recovery_key_custom_requirement_length, + count = specs.minCharacterCount, + specs.minCharacterCount, + ), + ) + // Always render the strength row in the Entry step (matches iOS): an empty field shows the + // "Strength" base label with an empty bar; typing flips it to the per-level label + bar. + Spacer(modifier = Modifier.height(8.dp)) + PassphraseStrengthIndicator( + result = state.customPassphraseStrength, + modifier = Modifier.fillMaxWidth(), + ) + } +} + +@Composable +private fun PassphraseStrengthIndicator( + result: CustomRecoveryPassphraseStrengthResult?, + modifier: Modifier = Modifier, +) { + val label = stringResource( + id = result?.strength?.labelRes() ?: R.string.screen_recovery_key_custom_strength_base, + ) + val hint = result?.strength?.hintRes()?.let { stringResource(id = it) } + val score = result?.score ?: 0f + // Mirror iOS: a zero score (empty field or the Garbage tier) stays neutral; otherwise the + // label and bar share a single colour interpolated along the red→orange→yellow→green gradient. + val color = if (score <= 0f) ElementTheme.colors.textSecondary else passphraseStrengthColor(score) + val announcement = stringResource(id = R.string.a11y_recovery_key_custom_strength_announcement, label) + .let { if (hint != null) "$it. $hint" else it } + Column( + modifier = modifier.semantics(mergeDescendants = true) { + contentDescription = announcement + }, + ) { + Text( + text = label, + color = color, + style = ElementTheme.typography.fontBodySmMedium, + ) + Spacer(modifier = Modifier.height(4.dp)) + LinearProgressIndicator( + progress = { score }, + modifier = Modifier.fillMaxWidth(), + color = color, + ) + if (hint != null) { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = hint, + color = ElementTheme.colors.textSecondary, + style = ElementTheme.typography.fontBodySmRegular, + ) + } + } +} + +private fun CustomRecoveryPassphraseStrength.labelRes(): Int = when (this) { + CustomRecoveryPassphraseStrength.Garbage -> R.string.screen_recovery_key_custom_strength_garbage + CustomRecoveryPassphraseStrength.Weak -> R.string.screen_recovery_key_custom_strength_weak + CustomRecoveryPassphraseStrength.Moderate -> R.string.screen_recovery_key_custom_strength_moderate + CustomRecoveryPassphraseStrength.Okay -> R.string.screen_recovery_key_custom_strength_okay + CustomRecoveryPassphraseStrength.Strong -> R.string.screen_recovery_key_custom_strength_strong + CustomRecoveryPassphraseStrength.VeryStrong -> R.string.screen_recovery_key_custom_strength_very_strong + CustomRecoveryPassphraseStrength.UltraStrong -> R.string.screen_recovery_key_custom_strength_ultra_strong + CustomRecoveryPassphraseStrength.Mega -> R.string.screen_recovery_key_custom_strength_mega +} + +private fun CustomRecoveryPassphraseStrength.hintRes(): Int = when (this) { + CustomRecoveryPassphraseStrength.Garbage -> R.string.screen_recovery_key_custom_strength_hint_garbage + CustomRecoveryPassphraseStrength.Weak -> R.string.screen_recovery_key_custom_strength_hint_weak + CustomRecoveryPassphraseStrength.Moderate -> R.string.screen_recovery_key_custom_strength_hint_moderate + CustomRecoveryPassphraseStrength.Okay -> R.string.screen_recovery_key_custom_strength_hint_okay + CustomRecoveryPassphraseStrength.Strong -> R.string.screen_recovery_key_custom_strength_hint_strong + CustomRecoveryPassphraseStrength.VeryStrong -> R.string.screen_recovery_key_custom_strength_hint_very_strong + CustomRecoveryPassphraseStrength.UltraStrong -> R.string.screen_recovery_key_custom_strength_hint_ultra_strong + CustomRecoveryPassphraseStrength.Mega -> R.string.screen_recovery_key_custom_strength_hint_mega +} + +// Stops mirror iOS PasswordStrengthBar.gradient: Compound red900 / lime700 with the same vivid +// orange & yellow midpoints. Intentionally fixed (not light/dark semantic) so the gradient reads +// identically to iOS in both themes. +private val passphraseStrengthGradientStops = listOf( + 0.25f to Color(0xFFD51928), // Compound red900 + 0.5f to Color(0xFFFF9500), // orange + 0.75f to Color(0xFFFFCC00), // yellow + 1.0f to Color(0xFF54C424), // Compound lime700 +) + +/** Interpolates the strength bar colour along [passphraseStrengthGradientStops] for a 0f..1f score. */ +private fun passphraseStrengthColor(score: Float): Color { + val clamped = score.coerceIn(0f, 1f) + var previousLocation = 0f + var previousColor = passphraseStrengthGradientStops.first().second + for ((location, color) in passphraseStrengthGradientStops) { + if (clamped <= location) { + val span = location - previousLocation + if (span <= 0f) return color + return lerp(previousColor, color, ((clamped - previousLocation) / span).coerceIn(0f, 1f)) + } + previousLocation = location + previousColor = color + } + return previousColor +} + +@Composable +private fun CustomPassphraseConfirm(state: SecureBackupSetupState) { + var passphraseVisible by rememberSaveable { mutableStateOf(false) } + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 24.dp), + ) { + TextField( + modifier = Modifier + .fillMaxWidth() + .testTag(TestTags.customRecoveryPassphraseConfirm) + .semantics { contentType = ContentType.NewPassword }, + value = state.customPassphraseConfirm, + onValueChange = { state.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(it)) }, + label = stringResource(id = CommonStrings.common_recovery_key), + singleLine = true, + visualTransformation = if (passphraseVisible) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + PasswordVisibilityToggle( + visible = passphraseVisible, + onToggle = { passphraseVisible = !passphraseVisible }, + ) + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Password, + imeAction = ImeAction.Done, + ), + keyboardActions = KeyboardActions( + onDone = { + if (state.canSubmitCustomPassphrase) { + state.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + } + }, + ), + validity = if (state.customPassphraseMismatch) TextFieldValidity.Invalid else TextFieldValidity.None, + supportingText = if (state.customPassphraseMismatch) { + stringResource(id = R.string.screen_recovery_key_custom_mismatch) + } else { + null + }, + ) + } +} + @Composable private fun ColumnScope.Buttons( state: SecureBackupSetupState, onFinish: () -> Unit, + onCancel: () -> Unit, +) { + // No buttons until the well-known resolves; Content shows a spinner meanwhile. + if (!state.wellknownLoaded && state.setupState == SetupState.Init) return + if (state.isCustomEntry()) { + CustomButtons(state = state, onCancel = onCancel) + } else { + AutoGenButtons(state = state, onFinish = onFinish) + } +} + +@Composable +private fun ColumnScope.CustomButtons( + state: SecureBackupSetupState, + onCancel: () -> Unit, +) { + // No save/share controls in the custom flow — they'd leak the base58 key during Created. + when (state.setupState) { + SetupState.Creating, + is SetupState.Created, + is SetupState.CreatedAndSaved -> return + SetupState.Init, + is SetupState.Error -> Unit + } + when (state.customEntryStep) { + CustomEntryStep.Entry -> { + Button( + text = stringResource(id = CommonStrings.action_continue), + enabled = state.canContinueFromEntry, + modifier = Modifier.fillMaxWidth(), + onClick = { state.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) }, + ) + TextButton( + text = stringResource(id = CommonStrings.action_cancel), + modifier = Modifier.fillMaxWidth(), + onClick = onCancel, + ) + } + CustomEntryStep.Confirm -> { + Button( + text = stringResource(id = R.string.screen_recovery_key_custom_finish_action), + enabled = state.canSubmitCustomPassphrase, + modifier = Modifier.fillMaxWidth(), + onClick = { state.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) }, + ) + } + } +} + +@Composable +private fun ColumnScope.AutoGenButtons( + state: SecureBackupSetupState, + onFinish: () -> Unit, ) { val context = LocalContext.current val chooserTitle = stringResource(id = R.string.screen_recovery_key_save_action) diff --git a/features/securebackup/impl/src/main/res/values/temporary.xml b/features/securebackup/impl/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..3edbd84d73 --- /dev/null +++ b/features/securebackup/impl/src/main/res/values/temporary.xml @@ -0,0 +1,37 @@ + + + Enter a custom recovery key + Choose a recovery key that you can memorize. + Confirm your recovery key + Enter your recovery key again. + The recovery key you entered doesn\'t match + + Minimum %1$d character + Minimum %1$d characters + + Finish setup + Strength + Garbage + Weak + Moderate + Okay + Strong + Very strong + Super strong + Ideal + Cracking would take roughly milliseconds. + Cracking would take roughly minutes to months. + Cracking would take roughly years. + Cracking would take roughly hundreds of years. + Cracking would take roughly billions of years. + Cracking would take roughly trillions of years. + Cracking would take roughly quadrillions of years. + Cracking would take roughly quintillions of years. + Loading recovery key requirements + Passphrase strength: %1$s + diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenterTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenterTest.kt index a3cf920d82..6ca716bcd6 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenterTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenterTest.kt @@ -6,23 +6,37 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) + package io.element.android.features.securebackup.impl.setup import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.api.CustomRecoveryPassphraseStrength +import io.element.android.features.enterprise.api.CustomRecoveryPassphraseStrengthResult +import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyUserStory import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyViewState -import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress +import io.element.android.features.wellknown.test.FakeSessionWellknownRetriever +import io.element.android.features.wellknown.test.aCustomRecoveryPassphraseRequirements +import io.element.android.features.wellknown.test.anElementWellKnown import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.test.A_RECOVERY_KEY import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService +import io.element.android.libraries.wellknown.api.SessionWellknownRetriever +import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +@Suppress("LargeClass") class SecureBackupSetupPresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -33,11 +47,16 @@ class SecureBackupSetupPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = awaitItem() - assertThat(initialState.isChangeRecoveryKeyUserStory).isFalse() - assertThat(initialState.setupState).isEqualTo(SetupState.Init) - assertThat(initialState.showSaveConfirmationDialog).isFalse() - assertThat(initialState.recoveryKeyViewState).isEqualTo( + val preFetch = awaitItem() + assertThat(preFetch.wellknownLoaded).isFalse() + assertThat(preFetch.setupState).isEqualTo(SetupState.Init) + + val loaded = awaitItem() + assertThat(loaded.wellknownLoaded).isTrue() + assertThat(loaded.isChangeRecoveryKeyUserStory).isFalse() + assertThat(loaded.setupState).isEqualTo(SetupState.Init) + assertThat(loaded.showSaveConfirmationDialog).isFalse() + assertThat(loaded.recoveryKeyViewState).isEqualTo( RecoveryKeyViewState( recoveryKeyUserStory = RecoveryKeyUserStory.Setup, formattedRecoveryKey = null, @@ -50,14 +69,17 @@ class SecureBackupSetupPresenterTest { @Test fun `present - create recovery key and save it`() = runTest { - val encryptionService = FakeEncryptionService() + val encryptionService = FakeEncryptionService( + enableRecoveryLambda = { _, _ -> Result.success(A_RECOVERY_KEY) }, + ) val presenter = createSecureBackupSetupPresenter( encryptionService = encryptionService ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = awaitItem() + awaitItem() // pre-fetch + val initialState = awaitItem() // post-fetch, wellknownLoaded=true initialState.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey) val creatingState = awaitItem() assertThat(creatingState.setupState).isEqualTo(SetupState.Creating) @@ -69,7 +91,6 @@ class SecureBackupSetupPresenterTest { inProgress = true, ) ) - encryptionService.emitEnableRecoveryProgress(EnableRecoveryProgress.Done(A_RECOVERY_KEY)) val createdState = awaitItem() assertThat(createdState.setupState).isEqualTo(SetupState.Created(A_RECOVERY_KEY)) assertThat(createdState.recoveryKeyViewState).isEqualTo( @@ -100,7 +121,9 @@ class SecureBackupSetupPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { + awaitItem() // pre-fetch val initialState = awaitItem() + assertThat(initialState.wellknownLoaded).isTrue() assertThat(initialState.isChangeRecoveryKeyUserStory).isTrue() assertThat(initialState.setupState).isEqualTo(SetupState.Init) assertThat(initialState.recoveryKeyViewState).isEqualTo( @@ -117,7 +140,7 @@ class SecureBackupSetupPresenterTest { @Test fun `present - handle errors`() = runTest { val encryptionService = FakeEncryptionService( - enableRecoveryLambda = { Result.failure(IllegalStateException("Test error")) } + enableRecoveryLambda = { _, _ -> Result.failure(IllegalStateException("Test error")) } ) val presenter = createSecureBackupSetupPresenter( isChangeRecoveryKeyUserStory = false, @@ -126,6 +149,7 @@ class SecureBackupSetupPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { + awaitItem() // pre-fetch val initialState = awaitItem() assertThat(initialState.isChangeRecoveryKeyUserStory).isFalse() assertThat(initialState.setupState).isEqualTo(SetupState.Init) @@ -152,6 +176,7 @@ class SecureBackupSetupPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { + awaitItem() // pre-fetch val initialState = awaitItem() initialState.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey) val creatingState = awaitItem() @@ -186,16 +211,727 @@ class SecureBackupSetupPresenterTest { } } + @Test + fun `present - wellknownLoaded flips false to true exactly once after fetch resolves`() = runTest { + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val preFetch = awaitItem() + assertThat(preFetch.wellknownLoaded).isFalse() + assertThat(preFetch.customRecoveryPassphraseRequirements).isNull() + + val loaded = awaitItem() + assertThat(loaded.wellknownLoaded).isTrue() + assertThat(loaded.customRecoveryPassphraseRequirements).isNotNull() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec absent leaves customRecoveryPassphraseRequirements null and uses generated-key path`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = null)) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val preFetch = awaitItem() + assertThat(preFetch.wellknownLoaded).isFalse() + val loaded = awaitItem() + assertThat(loaded.wellknownLoaded).isTrue() + assertThat(loaded.customRecoveryPassphraseRequirements).isNull() + assertThat(loaded.canSubmitCustomPassphrase).isFalse() + loaded.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey) + awaitItem() // creating + advanceUntilIdle() + enableRecoveryLambda.assertions().isCalledOnce() + .with(value(false), value(null)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec present surfaces validation errors and blocks continue`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial, pre-fetch + val withSpec = awaitItem() + assertThat(withSpec.customRecoveryPassphraseRequirements).isNotNull() + assertThat(withSpec.customEntryStep).isEqualTo(CustomEntryStep.Entry) + assertThat(withSpec.canContinueFromEntry).isFalse() + assertThat(withSpec.canSubmitCustomPassphrase).isFalse() + + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase("abc")) + val afterShortInput = awaitItem() + assertThat(afterShortInput.customPassphrase).isEqualTo("abc") + assertThat(afterShortInput.customPassphraseMeetsMinLength).isFalse() + assertThat(afterShortInput.canContinueFromEntry).isFalse() + + // Continue is a no-op when entry is invalid: step stays Entry. + afterShortInput.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + expectNoEvents() + enableRecoveryLambda.assertions().isNeverCalled() + } + } + + @Test + fun `present - custom spec strength is null while empty and delegates to the enterprise estimator once user types`() = runTest { + // The estimation algorithm lives in the enterprise module; here we only verify the presenter + // suppresses the indicator while the field is empty and otherwise forwards the service result. + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + enterpriseService = FakeEnterpriseService( + isCustomRecoveryPassphraseEnabledResult = true, + estimateCustomRecoveryPassphraseStrengthResult = { passphrase -> + if (passphrase.length > 5) { + CustomRecoveryPassphraseStrengthResult(CustomRecoveryPassphraseStrength.Strong, score = 0.9f) + } else { + CustomRecoveryPassphraseStrengthResult(CustomRecoveryPassphraseStrength.Weak, score = 0.1f) + } + }, + ), + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + // Field is empty → indicator suppressed (the estimator is never consulted). + assertThat(withSpec.customPassphraseStrength).isNull() + + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase("abc")) + val afterShort = awaitItem() + assertThat(afterShort.customPassphraseStrength?.strength) + .isEqualTo(CustomRecoveryPassphraseStrength.Weak) + + afterShort.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase("Abcdefg1!@#xyz")) + val afterStrong = awaitItem() + assertThat(afterStrong.customPassphraseStrength?.strength) + .isEqualTo(CustomRecoveryPassphraseStrength.Strong) + + // Clearing the field brings the indicator back to null. + afterStrong.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase("")) + val cleared = awaitItem() + assertThat(cleared.customPassphraseStrength).isNull() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec ContinueCustomPassphrase advances Entry to Confirm when valid`() = runTest { + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial + val withSpec = awaitItem() + assertThat(withSpec.customEntryStep).isEqualTo(CustomEntryStep.Entry) + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + val typed = awaitItem() + assertThat(typed.canContinueFromEntry).isTrue() + + typed.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val advanced = awaitItem() + assertThat(advanced.customEntryStep).isEqualTo(CustomEntryStep.Confirm) + assertThat(advanced.customPassphrase).isEqualTo(valid) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec BackToCustomEntry returns to Entry preserving both fields`() = runTest { + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + assertThat(onConfirm.customEntryStep).isEqualTo(CustomEntryStep.Confirm) + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + awaitItem() + + onConfirm.eventSink.invoke(SecureBackupSetupEvents.BackToCustomEntry) + val backOnEntry = awaitItem() + assertThat(backOnEntry.customEntryStep).isEqualTo(CustomEntryStep.Entry) + assertThat(backOnEntry.customPassphrase).isEqualTo(valid) + assertThat(backOnEntry.customPassphraseConfirm).isEqualTo(valid) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec SubmitCustomPassphrase from Entry step is a no-op`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + val typed = awaitItem() + // Both fields contain matching content via a stale path: simulate by also setting confirm + // while still on the Entry step (e.g., previously typed). Submit must still be gated. + typed.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val bothTyped = awaitItem() + assertThat(bothTyped.customEntryStep).isEqualTo(CustomEntryStep.Entry) + assertThat(bothTyped.canSubmitCustomPassphrase).isFalse() + + bothTyped.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + expectNoEvents() + enableRecoveryLambda.assertions().isNeverCalled() + } + } + + @Test + fun `present - custom spec present submit with valid input forwards passphrase to SDK`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + val afterKey = awaitItem() + afterKey.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + assertThat(onConfirm.customEntryStep).isEqualTo(CustomEntryStep.Confirm) + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + awaitItem() // creating + advanceUntilIdle() + enableRecoveryLambda.assertions().isCalledOnce() + .with(value(false), value(valid)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec error retains typed passphrase and Confirm step across DismissDialog`() = runTest { + val encryptionService = FakeEncryptionService( + enableRecoveryLambda = { _, _ -> Result.failure(IllegalStateException("boom")) }, + ) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + awaitItem() // creating + val errored = awaitItem() + assertThat(errored.setupState).isInstanceOf(SetupState.Error::class.java) + + errored.eventSink.invoke(SecureBackupSetupEvents.DismissDialog) + val afterDismiss = awaitItem() + assertThat(afterDismiss.setupState).isEqualTo(SetupState.Init) + assertThat(afterDismiss.customPassphrase).isEqualTo(valid) + assertThat(afterDismiss.customPassphraseConfirm).isEqualTo(valid) + assertThat(afterDismiss.customEntryStep).isEqualTo(CustomEntryStep.Confirm) + assertThat(afterDismiss.canSubmitCustomPassphrase).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec submit success auto-advances to CreatedAndSaved without manual save`() = runTest { + val encryptionService = FakeEncryptionService( + enableRecoveryLambda = { _, _ -> Result.success(A_RECOVERY_KEY) }, + ) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + awaitItem() // creating + advanceUntilIdle() + + // The presenter's auto-skip LaunchedEffect should have advanced state machine past + // Created without requiring a manual RecoveryKeyHasBeenSaved event. The terminal + // state observed is CreatedAndSaved. + val finalState = expectMostRecentItem() + assertThat(finalState.setupState).isInstanceOf(SetupState.CreatedAndSaved::class.java) + // The SDK-derived base58 key must not leak through the recoveryKeyViewState in + // the custom-passphrase flow. + assertThat(finalState.recoveryKeyViewState.formattedRecoveryKey).isNull() + // The state machine's KeyCreatedAndSaved variant carries a key too — confirm + // the presenter scrubbed it before dispatching SdkHasCreatedKey, so observers + // of setupState don't see the SDK-generated base58 key either. + assertThat(finalState.setupState).isEqualTo(SetupState.CreatedAndSaved(formattedRecoveryKey = "")) + assertThat(finalState.setupState.recoveryKey()).isEqualTo("") + // Typed passphrase is cleared once the SDK call returns successfully. + assertThat(finalState.customPassphrase).isEmpty() + assertThat(finalState.customPassphraseConfirm).isEmpty() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - enterprise feature disabled suppresses spec and forces auto-gen path`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + enterpriseService = FakeEnterpriseService(isCustomRecoveryPassphraseEnabledResult = false), + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val loaded = awaitItem() + assertThat(loaded.wellknownLoaded).isTrue() + // Even though the homeserver advertised a spec, the enterprise gate suppresses it. + assertThat(loaded.customRecoveryPassphraseRequirements).isNull() + assertThat(loaded.canSubmitCustomPassphrase).isFalse() + loaded.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey) + awaitItem() // creating + advanceUntilIdle() + enableRecoveryLambda.assertions().isCalledOnce() + .with(value(false), value(null)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - well-known fetch failure falls back to generated-key path`() = runTest { + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Error(IllegalStateException("boom")) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val preFetch = awaitItem() + assertThat(preFetch.wellknownLoaded).isFalse() + val loaded = awaitItem() + assertThat(loaded.wellknownLoaded).isTrue() + assertThat(loaded.customRecoveryPassphraseRequirements).isNull() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - change + custom spec absent uses resetRecoveryKey path`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + isChangeRecoveryKeyUserStory = true, + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = null)) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val loaded = awaitItem() + assertThat(loaded.customRecoveryPassphraseRequirements).isNull() + loaded.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey) + awaitItem() // creating + val createdState = awaitItem() + assertThat(createdState.setupState).isEqualTo(SetupState.Created(FakeEncryptionService.FAKE_RECOVERY_KEY)) + enableRecoveryLambda.assertions().isNeverCalled() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - change + custom spec present surfaces validation errors and blocks continue`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + isChangeRecoveryKeyUserStory = true, + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial, pre-fetch + val withSpec = awaitItem() + assertThat(withSpec.customRecoveryPassphraseRequirements).isNotNull() + assertThat(withSpec.canContinueFromEntry).isFalse() + + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase("abc")) + val afterShortInput = awaitItem() + assertThat(afterShortInput.customPassphrase).isEqualTo("abc") + assertThat(afterShortInput.customPassphraseMeetsMinLength).isFalse() + assertThat(afterShortInput.canContinueFromEntry).isFalse() + + afterShortInput.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + expectNoEvents() + enableRecoveryLambda.assertions().isNeverCalled() + } + } + + @Test + fun `present - change + custom spec present submit with valid input forwards passphrase to enableRecovery`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + isChangeRecoveryKeyUserStory = true, + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // initial + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + val afterKey = awaitItem() + afterKey.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + awaitItem() // creating + advanceUntilIdle() + enableRecoveryLambda.assertions().isCalledOnce() + .with(value(false), value(valid)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - change + well-known fetch failure falls back to resetRecoveryKey path`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + isChangeRecoveryKeyUserStory = true, + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Error(IllegalStateException("boom")) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val loaded = awaitItem() + assertThat(loaded.customRecoveryPassphraseRequirements).isNull() + loaded.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey) + awaitItem() // creating + val createdState = awaitItem() + assertThat(createdState.setupState).isEqualTo(SetupState.Created(FakeEncryptionService.FAKE_RECOVERY_KEY)) + enableRecoveryLambda.assertions().isNeverCalled() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec Confirm mismatch clears once user edits to match`() = runTest { + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + assertThat(onConfirm.customPassphraseMismatch).isFalse() + + // Typing a different value flips mismatch=true and blocks submit. + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm("differen")) + val mismatched = awaitItem() + assertThat(mismatched.customPassphraseMismatch).isTrue() + assertThat(mismatched.canSubmitCustomPassphrase).isFalse() + + // Editing the confirm field to match clears the mismatch and re-enables submit. + mismatched.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val matched = awaitItem() + assertThat(matched.customPassphraseMismatch).isFalse() + assertThat(matched.canSubmitCustomPassphrase).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec rapid double-submit invokes the SDK only once`() = runTest { + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + // Two synchronous submits dispatched from the same snapshot (e.g., button + IME-Done + // racing). The presenter's in-flight guard must drop the second one before it + // launches a second enableRecovery coroutine. + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + advanceUntilIdle() + enableRecoveryLambda.assertions().isCalledOnce() + .with(value(false), value(valid)) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - change + custom spec submit routes to enableRecovery and never resetRecoveryKey`() = runTest { + // Guards the custom-passphrase Change path against silently dropping the passphrase: + // the user's passphrase reaches the SDK only via enableRecovery(passphrase); the + // passphrase-less resetRecoveryKey() path must never be taken here. A true end-to-end + // check that the 4S key actually rotates needs the real SDK + homeserver and lives + // outside this JVM suite. + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val resetRecoveryKeyLambda = lambdaRecorder> { Result.success(FakeEncryptionService.FAKE_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService( + enableRecoveryLambda = enableRecoveryLambda, + resetRecoveryKeyLambda = resetRecoveryKeyLambda, + ) + val presenter = createSecureBackupSetupPresenter( + isChangeRecoveryKeyUserStory = true, + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + awaitItem() // creating + advanceUntilIdle() + enableRecoveryLambda.assertions().isCalledOnce() + .with(value(false), value(valid)) + resetRecoveryKeyLambda.assertions().isNeverCalled() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - custom spec cancel while creating aborts the SDK call and returns to Confirm with input preserved`() = runTest { + // simulateLongTask suspends on delay(1) before invoking the lambda, so cancelling before + // advancing virtual time guarantees the SDK call never runs. + val enableRecoveryLambda = lambdaRecorder> { _, _ -> Result.success(A_RECOVERY_KEY) } + val encryptionService = FakeEncryptionService(enableRecoveryLambda = enableRecoveryLambda) + val presenter = createSecureBackupSetupPresenter( + encryptionService = encryptionService, + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + awaitItem() + withSpec.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + onConfirm.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphraseConfirm(valid)) + val ready = awaitItem() + assertThat(ready.canSubmitCustomPassphrase).isTrue() + + ready.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) + val creating = awaitItem() + assertThat(creating.setupState).isEqualTo(SetupState.Creating) + + creating.eventSink.invoke(SecureBackupSetupEvents.CancelCustomPassphraseSubmit) + val cancelled = awaitItem() + assertThat(cancelled.setupState).isEqualTo(SetupState.Init) + assertThat(cancelled.customEntryStep).isEqualTo(CustomEntryStep.Confirm) + assertThat(cancelled.customPassphrase).isEqualTo(valid) + assertThat(cancelled.customPassphraseConfirm).isEqualTo(valid) + assertThat(cancelled.canSubmitCustomPassphrase).isTrue() + + // The cancelled coroutine never reached the SDK, and no zombie success/error followed. + advanceUntilIdle() + enableRecoveryLambda.assertions().isNeverCalled() + expectNoEvents() + } + } + + @Test + fun `present - custom spec strength indicator is suppressed on the Confirm step`() = runTest { + val presenter = createSecureBackupSetupPresenter( + sessionWellknownRetriever = FakeSessionWellknownRetriever { + WellknownRetrieverResult.Success(anElementWellKnown(customRecoveryPassphraseRequirements = aCustomRecoveryPassphraseRequirements())) + }, + enterpriseService = FakeEnterpriseService( + isCustomRecoveryPassphraseEnabledResult = true, + estimateCustomRecoveryPassphraseStrengthResult = { + CustomRecoveryPassphraseStrengthResult(CustomRecoveryPassphraseStrength.Strong, score = 0.9f) + }, + ), + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem() // pre-fetch + val withSpec = awaitItem() + + val valid = "Ab12!@cd" + withSpec.eventSink.invoke(SecureBackupSetupEvents.UpdateCustomPassphrase(valid)) + val onEntry = awaitItem() + // Entry step: the estimator result is surfaced. + assertThat(onEntry.customPassphraseStrength?.strength).isEqualTo(CustomRecoveryPassphraseStrength.Strong) + + onEntry.eventSink.invoke(SecureBackupSetupEvents.ContinueCustomPassphrase) + val onConfirm = awaitItem() + // Confirm step: indicator is not rendered, so the presenter stops computing it. + assertThat(onConfirm.customEntryStep).isEqualTo(CustomEntryStep.Confirm) + assertThat(onConfirm.customPassphraseStrength).isNull() + cancelAndIgnoreRemainingEvents() + } + } + private fun createSecureBackupSetupPresenter( isChangeRecoveryKeyUserStory: Boolean = false, encryptionService: EncryptionService = FakeEncryptionService( - enableRecoveryLambda = { Result.success(Unit) }, + enableRecoveryLambda = { _, _ -> Result.success(A_RECOVERY_KEY) }, ), + sessionWellknownRetriever: SessionWellknownRetriever = FakeSessionWellknownRetriever(), + enterpriseService: EnterpriseService = FakeEnterpriseService(isCustomRecoveryPassphraseEnabledResult = true), ): SecureBackupSetupPresenter { return SecureBackupSetupPresenter( isChangeRecoveryKeyUserStory = isChangeRecoveryKeyUserStory, stateMachine = SecureBackupSetupStateMachine(), encryptionService = encryptionService, + sessionWellknownRetriever = sessionWellknownRetriever, + enterpriseService = enterpriseService, ) } } diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index 4b3a0d6ffa..593560936e 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -29,6 +29,8 @@ object TestTags { * Verification screen. */ val recoveryKey = TestTag("verification-recovery_key") + val customRecoveryPassphrase = TestTag("verification-custom_recovery_passphrase") + val customRecoveryPassphraseConfirm = TestTag("verification-custom_recovery_passphrase_confirm") /** * Sign out screen. From a6ca2105584ae6e4b769f37a69cfd244d44fe985 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:23:21 +0000 Subject: [PATCH 0591/1083] Update dependency com.posthog:posthog-android to v3.47.0 --- 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 2ed618ee0e..aeb1bce8a7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -226,7 +226,7 @@ haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics -posthog = "com.posthog:posthog-android:3.43.0" +posthog = "com.posthog:posthog-android:3.47.0" sentry = "io.sentry:sentry-android:8.41.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" From 3fc48787b80393cab46319eaf05cc4a277d72238 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 2 Jun 2026 15:01:17 -0700 Subject: [PATCH 0592/1083] Add missing PasswordVisibilityToggle extraction areas --- .../logout/impl/AccountDeactivationView.kt | 14 +++++--------- .../impl/setup/views/RecoveryKeyView.kt | 16 +++++----------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index 352efdfb92..c942d2df72 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -8,7 +8,6 @@ package io.element.android.features.logout.impl -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -60,6 +59,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.PasswordVisibilityToggle import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextField @@ -280,14 +280,10 @@ private fun Content( placeholder = stringResource(CommonStrings.common_password), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { - val image = - if (passwordVisible) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() - val description = - if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - - Box(modifier = Modifier.clickable { passwordVisible = !passwordVisible }) { - Icon(imageVector = image, description) - } + PasswordVisibilityToggle( + visible = passwordVisible, + onToggle = { passwordVisible = !passwordVisible }, + ) }, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Password, diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt index 198891473c..8055709f20 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/views/RecoveryKeyView.kt @@ -9,7 +9,6 @@ package io.element.android.features.securebackup.impl.setup.views import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -50,6 +49,7 @@ 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.PasswordVisibilityToggle import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.testtags.TestTags @@ -223,16 +223,10 @@ private fun RecoveryKeyFormContent( ), placeholder = stringResource(id = R.string.screen_recovery_key_confirm_key_placeholder), trailingIcon = { - val image = - if (state.displayTextFieldContents) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() - val description = - if (state.displayTextFieldContents) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) - Box(Modifier.clickable { toggleRecoveryKeyVisibility(!state.displayTextFieldContents) }) { - Icon( - imageVector = image, - contentDescription = description, - ) - } + PasswordVisibilityToggle( + visible = state.displayTextFieldContents, + onToggle = { toggleRecoveryKeyVisibility(!state.displayTextFieldContents) }, + ) }, ) } From ea529261da915bd7d51187d6f1d90247558a46a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 09:23:40 +0200 Subject: [PATCH 0593/1083] Update kotlin to v2.3.9 (#6946) 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 2ed618ee0e..f0123733fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ android_gradle_plugin = "8.13.2" # When updating this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.3.21" kotlinpoet = "2.3.0" -ksp = "2.3.8" +ksp = "2.3.9" firebaseAppDistribution = "5.2.1" # AndroidX From 1a73ab00941426e2c91ff65058456210729e3f13 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 3 Jun 2026 09:58:00 +0200 Subject: [PATCH 0594/1083] Import compound token from release 10.2.1 https://github.com/element-hq/compound-design-tokens/releases/tag/v10.2.1 (#6942) * Sync compound tokens https://github.com/element-hq/compound-design-tokens/releases/tag/v10.2.1 * Update screenshots --------- Co-authored-by: ElementBot --- .../screenshots/Compound Icons - Dark.png | 4 +- .../screenshots/Compound Icons - Light.png | 4 +- .../screenshots/Compound Icons - Rtl.png | 4 +- .../Compound Vector Icons - Dark.png | 4 +- .../Compound Vector Icons - Light.png | 4 +- .../compound/src/main/assets/theme.iife.js | 2 +- .../tokens/generated/CompoundIcons.kt | 45 +++++++++++++++++++ .../tokens/generated/SemanticColors.kt | 2 + .../tokens/generated/SemanticColorsDark.kt | 1 + .../tokens/generated/SemanticColorsDarkHc.kt | 1 + .../tokens/generated/SemanticColorsLight.kt | 1 + .../tokens/generated/SemanticColorsLightHc.kt | 1 + .../res/drawable/ic_compound_collapse_all.xml | 9 ++++ .../main/res/drawable/ic_compound_crop.xml | 12 +++++ .../res/drawable/ic_compound_expand_all.xml | 9 ++++ .../drawable/ic_compound_flip_horizontal.xml | 9 ++++ .../drawable/ic_compound_flip_vertical.xml | 9 ++++ .../main/res/drawable/ic_compound_save.xml | 9 ++++ .../res/drawable/ic_compound_save_solid.xml | 9 ++++ .../main/res/drawable/ic_compound_unsave.xml | 13 ++++++ ...tem.theme.components_AllIcons_Icons_en.png | 4 +- 21 files changed, 143 insertions(+), 13 deletions(-) create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_collapse_all.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_crop.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_expand_all.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_flip_horizontal.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_flip_vertical.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_save.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_save_solid.xml create mode 100644 libraries/compound/src/main/res/drawable/ic_compound_unsave.xml diff --git a/libraries/compound/screenshots/Compound Icons - Dark.png b/libraries/compound/screenshots/Compound Icons - Dark.png index 2e3fd0d04d..1209b824be 100644 --- a/libraries/compound/screenshots/Compound Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7901fea2f578c8ed796160c9c08f417c61f4fb21580f958844fdf0cb794adf8a -size 239731 +oid sha256:f7511b9256afc6d001b53576959e69549683ab4cb81b49031aeda027d14178aa +size 245703 diff --git a/libraries/compound/screenshots/Compound Icons - Light.png b/libraries/compound/screenshots/Compound Icons - Light.png index 6e1bfc80cd..58ba1591ed 100644 --- a/libraries/compound/screenshots/Compound Icons - Light.png +++ b/libraries/compound/screenshots/Compound Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:245f012d419817f6557d92a71729b3b70092f24f0eba37f2f1fc431ad27592be -size 252969 +oid sha256:83a12b138543be1e17da8aa562bd95d1de18c0093da50d9a14196f905584bf7c +size 258948 diff --git a/libraries/compound/screenshots/Compound Icons - Rtl.png b/libraries/compound/screenshots/Compound Icons - Rtl.png index aa1b5d93a7..06daf04971 100644 --- a/libraries/compound/screenshots/Compound Icons - Rtl.png +++ b/libraries/compound/screenshots/Compound Icons - Rtl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d15c52b21cc279d306fa187cd0c318820109b5ec66270e6447e1b02e800eeba -size 254206 +oid sha256:73b37a7cd34f2ffe285011f67c2b38ed5399cbea40b3115c6c5115536f2902f2 +size 260171 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Dark.png b/libraries/compound/screenshots/Compound Vector Icons - Dark.png index a01fbf18b4..5c95b36a89 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85ef188fa3a27e42f4beafc899c1f3e7e8bcfad980ed76af6a03f76d70d6a511 -size 93807 +oid sha256:49a9372bea521e4ee948bbd4f7616310c411ee46f84ffd562d9b35bc9bfeb4d9 +size 97239 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Light.png b/libraries/compound/screenshots/Compound Vector Icons - Light.png index e227f1579c..38764691f4 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Light.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6e38386e95dc0c50384f06fca122ce14851ceff8ffc7865e394c1b4fccc5db6 -size 100555 +oid sha256:add37e4d84f03a33caf1079eaa99631682f5ef6418096629f96433520e519b20 +size 103742 diff --git a/libraries/compound/src/main/assets/theme.iife.js b/libraries/compound/src/main/assets/theme.iife.js index e7205e4f81..02fd99637a 100644 --- a/libraries/compound/src/main/assets/theme.iife.js +++ b/libraries/compound/src/main/assets/theme.iife.js @@ -1 +1 @@ -var CompoundTheme=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),c=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},l=(e,r,i)=>(i=e==null?{}:t(a(e)),c(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),{min:u,max:d}=Math,f=(e,t=0,n=1)=>u(d(t,e),n),p=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=f(e[t],0,255)):t===3&&(e[t]=f(e[t],0,1));return e},m={};for(let e of[`Boolean`,`Number`,`String`,`Function`,`Array`,`Date`,`RegExp`,`Undefined`,`Null`])m[`[object ${e}]`]=e.toLowerCase();function h(e){return m[Object.prototype.toString.call(e)]||`object`}var g=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):h(e[0])==`object`&&t?t.split(``).filter(t=>e[0][t]!==void 0).map(t=>e[0][t]):e[0].slice(0),_=e=>{if(e.length<2)return null;let t=e.length-1;return h(e[t])==`string`?e[t].toLowerCase():null},{PI:v,min:y,max:b}=Math,x=e=>Math.round(e*100)/100,S=e=>Math.round(e*100)/100,C=v*2,w=v/3,T=v/180,ee=180/v;function E(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}var D={format:{},autodetect:[]},O=class{constructor(...e){let t=this;if(h(e[0])===`object`&&e[0].constructor&&e[0].constructor===this.constructor)return e[0];let n=_(e),r=!1;if(!n){r=!0,D.sorted||=(D.autodetect=D.autodetect.sort((e,t)=>t.p-e.p),!0);for(let t of D.autodetect)if(n=t.test(...e),n)break}if(D.format[n])t._rgb=p(D.format[n].apply(null,r?e:e.slice(0,-1)));else throw Error(`unknown format: `+e);t._rgb.length===3&&t._rgb.push(1)}toString(){return h(this.hex)==`function`?this.hex():`[${this._rgb.join(`,`)}]`}},te=`3.2.0`,k=(...e)=>new O(...e);k.version=te;var A={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,laserlemon:`#ffff54`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrod:`#fafad2`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,maroon2:`#7f0000`,maroon3:`#b03060`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,purple2:`#7f007f`,purple3:`#a020f0`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`},ne=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,re=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,ie=e=>{if(e.match(ne)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);let t=parseInt(e,16);return[t>>16,t>>8&255,t&255,1]}if(e.match(re)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);let t=parseInt(e,16);return[t>>24&255,t>>16&255,t>>8&255,Math.round((t&255)/255*100)/100]}throw Error(`unknown hex color: ${e}`)},{round:ae}=Math,oe=(...e)=>{let[t,n,r,i]=g(e,`rgba`),a=_(e)||`auto`;i===void 0&&(i=1),a===`auto`&&(a=i<1?`rgba`:`rgb`),t=ae(t),n=ae(n),r=ae(r);let o=`000000`+(t<<16|n<<8|r).toString(16);o=o.substr(o.length-6);let s=`0`+ae(i*255).toString(16);switch(s=s.substr(s.length-2),a.toLowerCase()){case`rgba`:return`#${o}${s}`;case`argb`:return`#${s}${o}`;default:return`#${o}`}};O.prototype.name=function(){let e=oe(this._rgb,`rgb`);for(let t of Object.keys(A))if(A[t]===e)return t.toLowerCase();return e},D.format.named=e=>{if(e=e.toLowerCase(),A[e])return ie(A[e]);throw Error(`unknown color name: `+e)},D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&A[e.toLowerCase()])return`named`}}),O.prototype.alpha=function(e,t=!1){return e!==void 0&&h(e)===`number`?t?(this._rgb[3]=e,this):new O([this._rgb[0],this._rgb[1],this._rgb[2],e],`rgb`):this._rgb[3]},O.prototype.clipped=function(){return this._rgb._clipped||!1};var j={Kn:18,labWhitePoint:`d65`,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},se=new Map([[`a`,[1.0985,.35585]],[`b`,[1.0985,.35585]],[`c`,[.98074,1.18232]],[`d50`,[.96422,.82521]],[`d55`,[.95682,.92149]],[`d65`,[.95047,1.08883]],[`e`,[1,1,1]],[`f2`,[.99186,.67393]],[`f7`,[.95041,1.08747]],[`f11`,[1.00962,.6435]],[`icc`,[.96422,.82521]]]);function M(e){let t=se.get(String(e).toLowerCase());if(!t)throw Error(`unknown Lab illuminant `+e);j.labWhitePoint=e,j.Xn=t[0],j.Zn=t[1]}function ce(){return j.labWhitePoint}var N=(...e)=>{e=g(e,`lab`);let[t,n,r]=e,[i,a,o]=le(t,n,r),[s,c,l]=de(i,a,o);return[s,c,l,e.length>3?e[3]:1]},le=(e,t,n)=>{let{kE:r,kK:i,kKE:a,Xn:o,Yn:s,Zn:c}=j,l=(e+16)/116,u=.002*t+l,d=l-.005*n,f=u*u*u,p=d*d*d,m=f>r?f:(116*u-16)/i,h=e>a?((e+16)/116)**3:e/i,g=p>r?p:(116*d-16)/i;return[m*o,h*s,g*c]},ue=e=>{let t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*e**(1/2.4)-.055)*t},de=(e,t,n)=>{let{MtxAdaptMa:r,MtxAdaptMaI:i,MtxXYZ2RGB:a,RefWhiteRGB:o,Xn:s,Yn:c,Zn:l}=j,u=s*r.m00+c*r.m10+l*r.m20,d=s*r.m01+c*r.m11+l*r.m21,f=s*r.m02+c*r.m12+l*r.m22,p=o.X*r.m00+o.Y*r.m10+o.Z*r.m20,m=o.X*r.m01+o.Y*r.m11+o.Z*r.m21,h=o.X*r.m02+o.Y*r.m12+o.Z*r.m22,g=(e*r.m00+t*r.m10+n*r.m20)*(p/u),_=(e*r.m01+t*r.m11+n*r.m21)*(m/d),v=(e*r.m02+t*r.m12+n*r.m22)*(h/f),y=g*i.m00+_*i.m10+v*i.m20,b=g*i.m01+_*i.m11+v*i.m21,x=g*i.m02+_*i.m12+v*i.m22,S=ue(y*a.m00+b*a.m10+x*a.m20),C=ue(y*a.m01+b*a.m11+x*a.m21),w=ue(y*a.m02+b*a.m12+x*a.m22);return[S*255,C*255,w*255]},fe=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=he(t,n,r),[c,l,u]=pe(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function pe(e,t,n){let{Xn:r,Yn:i,Zn:a,kE:o,kK:s}=j,c=e/r,l=t/i,u=n/a,d=c>o?c**(1/3):(s*c+16)/116,f=l>o?l**(1/3):(s*l+16)/116,p=u>o?u**(1/3):(s*u+16)/116;return[116*f-16,500*(d-f),200*(f-p)]}function me(e){let t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:((e+.055)/1.055)**2.4)*t}var he=(e,t,n)=>{e=me(e/255),t=me(t/255),n=me(n/255);let{MtxRGB2XYZ:r,MtxAdaptMa:i,MtxAdaptMaI:a,Xn:o,Yn:s,Zn:c,As:l,Bs:u,Cs:d}=j,f=e*r.m00+t*r.m10+n*r.m20,p=e*r.m01+t*r.m11+n*r.m21,m=e*r.m02+t*r.m12+n*r.m22,h=o*i.m00+s*i.m10+c*i.m20,g=o*i.m01+s*i.m11+c*i.m21,_=o*i.m02+s*i.m12+c*i.m22,v=f*i.m00+p*i.m10+m*i.m20,y=f*i.m01+p*i.m11+m*i.m21,b=f*i.m02+p*i.m12+m*i.m22;return v*=h/l,y*=g/u,b*=_/d,f=v*a.m00+y*a.m10+b*a.m20,p=v*a.m01+y*a.m11+b*a.m21,m=v*a.m02+y*a.m12+b*a.m22,[f,p,m]};O.prototype.lab=function(){return fe(this._rgb)},Object.assign(k,{lab:(...e)=>new O(...e,`lab`),getLabWhitePoint:ce,setLabWhitePoint:M}),D.format.lab=N,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`lab`),h(e)===`array`&&e.length===3)return`lab`}}),O.prototype.darken=function(e=1){let t=this,n=t.lab();return n[0]-=j.Kn*e,new O(n,`lab`).alpha(t.alpha(),!0)},O.prototype.brighten=function(e=1){return this.darken(-e)},O.prototype.darker=O.prototype.darken,O.prototype.brighter=O.prototype.brighten,O.prototype.get=function(e){let[t,n]=e.split(`.`),r=this[t]();if(n){let e=t.indexOf(n)-(t.substr(0,2)===`ok`?2:0);if(e>-1)return r[e];throw Error(`unknown channel ${n} in mode ${t}`)}else return r};var{pow:ge}=Math,_e=1e-7,ve=20;O.prototype.luminance=function(e,t=`rgb`){if(e!==void 0&&h(e)===`number`){if(e===0)return new O([0,0,0,this._rgb[3]],`rgb`);if(e===1)return new O([255,255,255,this._rgb[3]],`rgb`);let n=this.luminance(),r=ve,i=(n,a)=>{let o=n.interpolate(a,.5,t),s=o.luminance();return Math.abs(e-s)<_e||!r--?o:s>e?i(n,o):i(o,a)};return new O([...(n>e?i(new O([0,0,0]),this):i(this,new O([255,255,255]))).rgb(),this._rgb[3]])}return ye(...this._rgb.slice(0,3))};var ye=(e,t,n)=>(e=be(e),t=be(t),n=be(n),.2126*e+.7152*t+.0722*n),be=e=>(e/=255,e<=.03928?e/12.92:ge((e+.055)/1.055,2.4)),P={},F=(e,t,n=.5,...r)=>{let i=r[0]||`lrgb`;if(!P[i]&&!r.length&&(i=Object.keys(P)[0]),!P[i])throw Error(`interpolation mode ${i} is not defined`);return h(e)!==`object`&&(e=new O(e)),h(t)!==`object`&&(t=new O(t)),P[i](e,t,n).alpha(e.alpha()+n*(t.alpha()-e.alpha()))};O.prototype.mix=O.prototype.interpolate=function(e,t=.5,...n){return F(this,e,t,...n)},O.prototype.premultiply=function(e=!1){let t=this._rgb,n=t[3];return e?(this._rgb=[t[0]*n,t[1]*n,t[2]*n,n],this):new O([t[0]*n,t[1]*n,t[2]*n,n],`rgb`)};var{sin:xe,cos:Se}=Math,Ce=(...e)=>{let[t,n,r]=g(e,`lch`);return isNaN(r)&&(r=0),r*=T,[t,Se(r)*n,xe(r)*n]},we=(...e)=>{e=g(e,`lch`);let[t,n,r]=e,[i,a,o]=Ce(t,n,r),[s,c,l]=N(i,a,o);return[s,c,l,e.length>3?e[3]:1]},Te=(...e)=>we(...E(g(e,`hcl`))),{sqrt:Ee,atan2:De,round:Oe}=Math,ke=(...e)=>{let[t,n,r]=g(e,`lab`),i=Ee(n*n+r*r),a=(De(r,n)*ee+360)%360;return Oe(i*1e4)===0&&(a=NaN),[t,i,a]},Ae=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=fe(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};O.prototype.lch=function(){return Ae(this._rgb)},O.prototype.hcl=function(){return E(Ae(this._rgb))},Object.assign(k,{lch:(...e)=>new O(...e,`lch`),hcl:(...e)=>new O(...e,`hcl`)}),D.format.lch=we,D.format.hcl=Te,[`lch`,`hcl`].forEach(e=>D.autodetect.push({p:2,test:(...t)=>{if(t=g(t,e),h(t)===`array`&&t.length===3)return e}})),O.prototype.saturate=function(e=1){let t=this,n=t.lch();return n[1]+=j.Kn*e,n[1]<0&&(n[1]=0),new O(n,`lch`).alpha(t.alpha(),!0)},O.prototype.desaturate=function(e=1){return this.saturate(-e)},O.prototype.set=function(e,t,n=!1){let[r,i]=e.split(`.`),a=this[r]();if(i){let e=r.indexOf(i)-(r.substr(0,2)===`ok`?2:0);if(e>-1){if(h(t)==`string`)switch(t.charAt(0)){case`+`:a[e]+=+t;break;case`-`:a[e]+=+t;break;case`*`:a[e]*=+t.substr(1);break;case`/`:a[e]/=+t.substr(1);break;default:a[e]=+t}else if(h(t)===`number`)a[e]=t;else throw Error(`unsupported value for Color.set`);let i=new O(a,r);return n?(this._rgb=i._rgb,this):i}throw Error(`unknown channel ${i} in mode ${r}`)}else return a},O.prototype.tint=function(e=.5,...t){return F(this,`white`,e,...t)},O.prototype.shade=function(e=.5,...t){return F(this,`black`,e,...t)},P.rgb=(e,t,n)=>{let r=e._rgb,i=t._rgb;return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`rgb`)};var{sqrt:je,pow:Me}=Math;P.lrgb=(e,t,n)=>{let[r,i,a]=e._rgb,[o,s,c]=t._rgb;return new O(je(Me(r,2)*(1-n)+Me(o,2)*n),je(Me(i,2)*(1-n)+Me(s,2)*n),je(Me(a,2)*(1-n)+Me(c,2)*n),`rgb`)},P.lab=(e,t,n)=>{let r=e.lab(),i=t.lab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`lab`)};var Ne=(e,t,n,r)=>{let i,a;r===`hsl`?(i=e.hsl(),a=t.hsl()):r===`hsv`?(i=e.hsv(),a=t.hsv()):r===`hcg`?(i=e.hcg(),a=t.hcg()):r===`hsi`?(i=e.hsi(),a=t.hsi()):r===`lch`||r===`hcl`?(r=`hcl`,i=e.hcl(),a=t.hcl()):r===`oklch`&&(i=e.oklch().reverse(),a=t.oklch().reverse());let o,s,c,l,u,d;(r.substr(0,1)===`h`||r===`oklch`)&&([o,c,u]=i,[s,l,d]=a);let f,p,m,h;return!isNaN(o)&&!isNaN(s)?(h=s>o&&s-o>180?s-(o+360):s180?s+360-o:s-o,p=o+n*h):isNaN(o)?isNaN(s)?p=NaN:(p=s,(u==1||u==0)&&r!=`hsv`&&(f=l)):(p=o,(d==1||d==0)&&r!=`hsv`&&(f=c)),f===void 0&&(f=c+n*(l-c)),m=u+n*(d-u),r===`oklch`?new O([m,f,p],r):new O([p,f,m],r)},Pe=(e,t,n)=>Ne(e,t,n,`lch`);P.lch=Pe,P.hcl=Pe;var Fe=e=>{if(h(e)==`number`&&e>=0&&e<=16777215)return[e>>16,e>>8&255,e&255,1];throw Error(`unknown num color: `+e)},Ie=(...e)=>{let[t,n,r]=g(e,`rgb`);return(t<<16)+(n<<8)+r};O.prototype.num=function(){return Ie(this._rgb)},Object.assign(k,{num:(...e)=>new O(...e,`num`)}),D.format.num=Fe,D.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&h(e[0])===`number`&&e[0]>=0&&e[0]<=16777215)return`num`}}),P.num=(e,t,n)=>{let r=e.num();return new O(r+n*(t.num()-r),`num`)};var{floor:Le}=Math,Re=(...e)=>{e=g(e,`hcg`);let[t,n,r]=e,i,a,o;r*=255;let s=n*255;if(n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Le(t),c=t-e,l=r*(1-n),u=l+s*(1-c),d=l+s*c,f=l+s;switch(e){case 0:[i,a,o]=[f,d,l];break;case 1:[i,a,o]=[u,f,l];break;case 2:[i,a,o]=[l,f,d];break;case 3:[i,a,o]=[l,u,f];break;case 4:[i,a,o]=[d,l,f];break;case 5:[i,a,o]=[f,l,u];break}}return[i,a,o,e.length>3?e[3]:1]},ze=(...e)=>{let[t,n,r]=g(e,`rgb`),i=y(t,n,r),a=b(t,n,r),o=a-i,s=o*100/255,c=i/(255-o)*100,l;return o===0?l=NaN:(t===a&&(l=(n-r)/o),n===a&&(l=2+(r-t)/o),r===a&&(l=4+(t-n)/o),l*=60,l<0&&(l+=360)),[l,s,c]};O.prototype.hcg=function(){return ze(this._rgb)},k.hcg=(...e)=>new O(...e,`hcg`),D.format.hcg=Re,D.autodetect.push({p:1,test:(...e)=>{if(e=g(e,`hcg`),h(e)===`array`&&e.length===3)return`hcg`}}),P.hcg=(e,t,n)=>Ne(e,t,n,`hcg`);var{cos:Be}=Math,Ve=(...e)=>{e=g(e,`hsi`);let[t,n,r]=e,i,a,o;return isNaN(t)&&(t=0),isNaN(n)&&(n=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(o=(1-n)/3,i=(1+n*Be(C*t)/Be(w-C*t))/3,a=1-(o+i)):t<2/3?(t-=1/3,i=(1-n)/3,a=(1+n*Be(C*t)/Be(w-C*t))/3,o=1-(i+a)):(t-=2/3,a=(1-n)/3,o=(1+n*Be(C*t)/Be(w-C*t))/3,i=1-(a+o)),i=f(r*i*3),a=f(r*a*3),o=f(r*o*3),[i*255,a*255,o*255,e.length>3?e[3]:1]},{min:He,sqrt:Ue,acos:We}=Math,Ge=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i,a=He(t,n,r),o=(t+n+r)/3,s=o>0?1-a/o:0;return s===0?i=NaN:(i=(t-n+(t-r))/2,i/=Ue((t-n)*(t-n)+(t-r)*(n-r)),i=We(i),r>n&&(i=C-i),i/=C),[i*360,s,o]};O.prototype.hsi=function(){return Ge(this._rgb)},k.hsi=(...e)=>new O(...e,`hsi`),D.format.hsi=Ve,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsi`),h(e)===`array`&&e.length===3)return`hsi`}}),P.hsi=(e,t,n)=>Ne(e,t,n,`hsi`);var Ke=(...e)=>{e=g(e,`hsl`);let[t,n,r]=e,i,a,o;if(n===0)i=a=o=r*255;else{let e=[0,0,0],s=[0,0,0],c=r<.5?r*(1+n):r+n-r*n,l=2*r-c,u=t/360;e[0]=u+1/3,e[1]=u,e[2]=u-1/3;for(let t=0;t<3;t++)e[t]<0&&(e[t]+=1),e[t]>1&&--e[t],6*e[t]<1?s[t]=l+(c-l)*6*e[t]:2*e[t]<1?s[t]=c:3*e[t]<2?s[t]=l+(c-l)*(2/3-e[t])*6:s[t]=l;[i,a,o]=[s[0]*255,s[1]*255,s[2]*255]}return e.length>3?[i,a,o,e[3]]:[i,a,o,1]},qe=(...e)=>{e=g(e,`rgba`);let[t,n,r]=e;t/=255,n/=255,r/=255;let i=y(t,n,r),a=b(t,n,r),o=(a+i)/2,s,c;return a===i?(s=0,c=NaN):s=o<.5?(a-i)/(a+i):(a-i)/(2-a-i),t==a?c=(n-r)/(a-i):n==a?c=2+(r-t)/(a-i):r==a&&(c=4+(t-n)/(a-i)),c*=60,c<0&&(c+=360),e.length>3&&e[3]!==void 0?[c,s,o,e[3]]:[c,s,o]};O.prototype.hsl=function(){return qe(this._rgb)},k.hsl=(...e)=>new O(...e,`hsl`),D.format.hsl=Ke,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsl`),h(e)===`array`&&e.length===3)return`hsl`}}),P.hsl=(e,t,n)=>Ne(e,t,n,`hsl`);var{floor:Je}=Math,Ye=(...e)=>{e=g(e,`hsv`);let[t,n,r]=e,i,a,o;if(r*=255,n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Je(t),s=t-e,c=r*(1-n),l=r*(1-n*s),u=r*(1-n*(1-s));switch(e){case 0:[i,a,o]=[r,u,c];break;case 1:[i,a,o]=[l,r,c];break;case 2:[i,a,o]=[c,r,u];break;case 3:[i,a,o]=[c,l,r];break;case 4:[i,a,o]=[u,c,r];break;case 5:[i,a,o]=[r,c,l];break}}return[i,a,o,e.length>3?e[3]:1]},{min:Xe,max:Ze}=Math,Qe=(...e)=>{e=g(e,`rgb`);let[t,n,r]=e,i=Xe(t,n,r),a=Ze(t,n,r),o=a-i,s,c,l;return l=a/255,a===0?(s=NaN,c=0):(c=o/a,t===a&&(s=(n-r)/o),n===a&&(s=2+(r-t)/o),r===a&&(s=4+(t-n)/o),s*=60,s<0&&(s+=360)),[s,c,l]};O.prototype.hsv=function(){return Qe(this._rgb)},k.hsv=(...e)=>new O(...e,`hsv`),D.format.hsv=Ye,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsv`),h(e)===`array`&&e.length===3)return`hsv`}}),P.hsv=(e,t,n)=>Ne(e,t,n,`hsv`);function $e(e,t){let n=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(e=>[e]));let r=t[0].length,i=t[0].map((e,n)=>t.map(e=>e[n])),a=e.map(e=>i.map(t=>Array.isArray(e)?e.reduce((e,n,r)=>e+n*(t[r]||0),0):t.reduce((t,n)=>t+n*e,0)));return n===1&&(a=a[0]),r===1?a.map(e=>e[0]):a}var et=(...e)=>{e=g(e,`lab`);let[t,n,r,...i]=e,[a,o,s]=tt([t,n,r]),[c,l,u]=de(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function tt(e){return $e([[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],$e([[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],e).map(e=>e**3))}var nt=(...e)=>{let[t,n,r,...i]=g(e,`rgb`);return[...rt(he(t,n,r)),...i.length>0&&i[0]<1?[i[0]]:[]]};function rt(e){return $e([[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],$e([[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],e).map(e=>Math.cbrt(e)))}O.prototype.oklab=function(){return nt(this._rgb)},Object.assign(k,{oklab:(...e)=>new O(...e,`oklab`)}),D.format.oklab=et,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklab`),h(e)===`array`&&e.length===3)return`oklab`}}),P.oklab=(e,t,n)=>{let r=e.oklab(),i=t.oklab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`oklab`)},P.oklch=(e,t,n)=>Ne(e,t,n,`oklch`);var{pow:it,sqrt:at,PI:ot,cos:st,sin:ct,atan2:lt}=Math,ut=(e,t=`lrgb`,n=null)=>{let r=e.length;n||=Array.from(Array(r)).map(()=>1);let i=r/n.reduce(function(e,t){return e+t});if(n.forEach((e,t)=>{n[t]*=i}),e=e.map(e=>new O(e)),t===`lrgb`)return dt(e,n);let a=e.shift(),o=a.get(t),s=[],c=0,l=0;for(let e=0;e{let i=e.get(t);u+=e.alpha()*n[r+1];for(let e=0;e=360;)t-=360;o[e]=t}else o[e]=o[e]/s[e];return u/=r,new O(o,t).alpha(u>.99999?1:u,!0)},dt=(e,t)=>{let n=e.length,r=[0,0,0,0];for(let i=0;i.9999999&&(r[3]=1),new O(p(r))},{pow:ft}=Math;function pt(e){let t=`rgb`,n=k(`#ccc`),r=0,i=[0,1],a=[0,1],o=[],s=[0,0],c=!1,l=[],u=!1,d=0,p=1,m=!1,g={},_=!0,v=1,y=function(e){if(e||=[`#fff`,`#000`],e&&h(e)===`string`&&k.brewer&&k.brewer[e.toLowerCase()]&&(e=k.brewer[e.toLowerCase()]),h(e)===`array`){e.length===1&&(e=[e[0],e[0]]),e=e.slice(0);for(let t=0;t=c[n];)n++;return n-1}return 0},x=e=>e,S=e=>e,C=function(e,r){let i,a;if(r??=!1,isNaN(e)||e===null)return n;a=r?e:c&&c.length>2?b(e)/(c.length-2):p===d?1:(e-d)/(p-d),a=S(a),r||(a=x(a)),v!==1&&(a=ft(a,v)),a=s[0]+a*(1-s[0]-s[1]),a=f(a,0,1);let u=Math.floor(a*1e4);if(_&&g[u])i=g[u];else{if(h(l)===`array`)for(let e=0;e=n&&e===o.length-1){i=l[e];break}if(a>n&&ag={};y(e);let T=function(e){let t=k(C(e));return u&&t[u]?t[u]():t};return T.classes=function(e){if(e!=null){if(h(e)===`array`)c=e,i=[e[0],e[e.length-1]];else{let t=k.analyze(i);c=e===0?[t.min,t.max]:k.limits(t,`e`,e)}return T}return c},T.domain=function(e){if(!arguments.length)return a;a=e.slice(0),d=e[0],p=e[e.length-1],o=[];let t=l.length;if(e.length===t&&d!==p)for(let t of Array.from(e))o.push((t-d)/(p-d));else{for(let e=0;e2){let t=e.map((t,n)=>n/(e.length-1)),n=e.map(e=>(e-d)/(p-d));n.every((e,n)=>t[n]===e)||(S=e=>{if(e<=0||e>=1)return e;let r=0;for(;e>=n[r+1];)r++;let i=(e-n[r])/(n[r+1]-n[r]);return t[r]+i*(t[r+1]-t[r])})}}return i=[d,p],T},T.mode=function(e){return arguments.length?(t=e,w(),T):t},T.range=function(e,t){return y(e,t),T},T.out=function(e){return u=e,T},T.spread=function(e){return arguments.length?(r=e,T):r},T.correctLightness=function(e){return e??=!0,m=e,w(),x=m?function(e){let t=C(0,!0).lab()[0],n=C(1,!0).lab()[0],r=t>n,i=C(e,!0).lab()[0],a=t+(n-t)*e,o=i-a,s=0,c=1,l=20;for(;Math.abs(o)>.01&&l-- >0;)(function(){return r&&(o*=-1),o<0?(s=e,e+=(c-e)*.5):(c=e,e+=(s-e)*.5),i=C(e,!0).lab()[0],o=i-a})();return e}:e=>e,T},T.padding=function(e){return e==null?s:(h(e)===`number`&&(e=[e,e]),s=e,T)},T.colors=function(t,n){arguments.length<2&&(n=`hex`);let r=[];if(arguments.length===0)r=l.slice(0);else if(t===1)r=[T(.5)];else if(t>1){let e=i[0],n=i[1]-e;r=mt(0,t,!1).map(r=>T(e+r/(t-1)*n))}else{e=[];let t=[];if(c&&c.length>2)for(let e=1,n=c.length,r=1<=n;r?en;r?e++:e--)t.push((c[e-1]+c[e])*.5);else t=i;r=t.map(e=>T(e))}return k[n]&&(r=r.map(e=>e[n]())),r},T.cache=function(e){return e==null?_:(_=e,T)},T.gamma=function(e){return e==null?v:(v=e,T)},T.nodata=function(e){return e==null?n:(n=k(e),T)},T}function mt(e,t,n){let r=[],i=ea;i?t++:t--)r.push(t);return r}var ht=function(e){let t=[1,1];for(let n=1;nnew O(e)),e.length===2)[n,r]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>n[t]+e*(r[t]-n[t])),`lab`)};else if(e.length===3)[n,r,i]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*n[t]+2*(1-e)*e*r[t]+e*e*i[t]),`lab`)};else if(e.length===4){let a;[n,r,i,a]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*(1-e)*n[t]+3*(1-e)*(1-e)*e*r[t]+3*(1-e)*e*e*i[t]+e*e*e*a[t]),`lab`)}}else if(e.length>=5){let n,r,i;n=e.map(e=>e.lab()),i=e.length-1,r=ht(i),t=function(e){let t=1-e;return new O([0,1,2].map(a=>n.reduce((n,o,s)=>n+r[s]*t**(i-s)*e**s*o[a],0)),`lab`)}}else throw RangeError(`No point in running bezier with only one color.`);return t},_t=e=>{let t=gt(e);return t.scale=()=>pt(t),t},{round:vt}=Math;O.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(vt)},O.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,n)=>n<3?e===!1?t:vt(t):t)},Object.assign(k,{rgb:(...e)=>new O(...e,`rgb`)}),D.format.rgb=(...e)=>{let t=g(e,`rgba`);return t[3]===void 0&&(t[3]=1),t},D.autodetect.push({p:3,test:(...e)=>{if(e=g(e,`rgba`),h(e)===`array`&&(e.length===3||e.length===4&&h(e[3])==`number`&&e[3]>=0&&e[3]<=1))return`rgb`}});var I=(e,t,n)=>{if(!I[n])throw Error(`unknown blend mode `+n);return I[n](e,t)},L=e=>(t,n)=>{let r=k(n).rgb(),i=k(t).rgb();return k.rgb(e(r,i))},R=e=>(t,n)=>{let r=[];return r[0]=e(t[0],n[0]),r[1]=e(t[1],n[1]),r[2]=e(t[2],n[2]),r};I.normal=L(R(e=>e)),I.multiply=L(R((e,t)=>e*t/255)),I.screen=L(R((e,t)=>255*(1-(1-e/255)*(1-t/255)))),I.overlay=L(R((e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)))),I.darken=L(R((e,t)=>e>t?t:e)),I.lighten=L(R((e,t)=>e>t?e:t)),I.dodge=L(R((e,t)=>e===255?255:(e=t/255*255/(1-e/255),e>255?255:e))),I.burn=L(R((e,t)=>255*(1-(1-t/255)/(e/255))));var{pow:yt,sin:bt,cos:xt}=Math;function St(e=300,t=-1.5,n=1,r=1,i=[0,1]){let a=0,o;h(i)===`array`?o=i[1]-i[0]:(o=0,i=[i,i]);let s=function(s){let c=C*((e+120)/360+t*s),l=yt(i[0]+o*s,r),u=(a===0?n:n[0]+s*a)*l*(1-l)/2,d=xt(c),f=bt(c),m=l+u*(-.14861*d+1.78277*f),h=l+u*(-.29227*d-.90649*f),g=l+1.97294*d*u;return k(p([m*255,h*255,g*255,1]))};return s.start=function(t){return t==null?e:(e=t,s)},s.rotations=function(e){return e==null?t:(t=e,s)},s.gamma=function(e){return e==null?r:(r=e,s)},s.hue=function(e){return e==null?n:(n=e,h(n)===`array`?(a=n[1]-n[0],a===0&&(n=n[1])):a=0,s)},s.lightness=function(e){return e==null?i:(h(e)===`array`?(i=e,o=e[1]-e[0]):(i=[e,e],o=0),s)},s.scale=()=>k.scale(s),s.hue(n),s}var Ct=`0123456789abcdef`,{floor:wt,random:Tt}=Math,Et=(e=Tt)=>{let t=`#`;for(let n=0;n<6;n++)t+=Ct.charAt(wt(e()*16));return new O(t,`hex`)},{log:Dt,pow:Ot,floor:kt,abs:At}=Math;function jt(e,t=null){let n={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return h(e)===`object`&&(e=Object.values(e)),e.forEach(e=>{t&&h(e)===`object`&&(e=e[t]),e!=null&&!isNaN(e)&&(n.values.push(e),n.sum+=e,en.max&&(n.max=e),n.count+=1)}),n.domain=[n.min,n.max],n.limits=(e,t)=>Mt(n,e,t),n}function Mt(e,t=`equal`,n=7){h(e)==`array`&&(e=jt(e));let{min:r,max:i}=e,a=e.values.sort((e,t)=>e-t);if(n===1)return[r,i];let o=[];if(t.substr(0,1)===`c`&&(o.push(r),o.push(i)),t.substr(0,1)===`e`){o.push(r);for(let e=1;e 0`);let e=Math.LOG10E*Dt(r),t=Math.LOG10E*Dt(i);o.push(r);for(let r=1;r200&&(l=!1)}let f={};for(let e=0;ee-t),o.push(p[0]);for(let e=1;e{e=new O(e),t=new O(t);let n=e.luminance(),r=t.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)},Pt=.027,Ft=5e-4,It=.1,Lt=1.14,Rt=.022,zt=1.414,Bt=(e,t)=>{e=new O(e),t=new O(t),e.alpha()<1&&(e=F(t,e,e.alpha(),`rgb`));let n=Vt(...e.rgb()),r=Vt(...t.rgb()),i=n>=Rt?n:n+(Rt-n)**+zt,a=r>=Rt?r:r+(Rt-r)**+zt,o=a**.56-i**.57,s=a**.65-i**.62,c=Math.abs(a-i)0?c-Pt:c+Pt)*100};function Vt(e,t,n){return .2126729*(e/255)**2.4+.7151522*(t/255)**2.4+.072175*(n/255)**2.4}var{sqrt:z,pow:B,min:Ht,max:Ut,atan2:Wt,abs:Gt,cos:Kt,sin:qt,exp:Jt,PI:Yt}=Math;function Xt(e,t,n=1,r=1,i=1){var a=function(e){return 360*e/(2*Yt)},o=function(e){return 2*Yt*e/360};e=new O(e),t=new O(t);let[s,c,l]=Array.from(e.lab()),[u,d,f]=Array.from(t.lab()),p=(s+u)/2,m=(z(B(c,2)+B(l,2))+z(B(d,2)+B(f,2)))/2,h=.5*(1-z(B(m,7)/(B(m,7)+B(25,7)))),g=c*(1+h),_=d*(1+h),v=z(B(g,2)+B(l,2)),y=z(B(_,2)+B(f,2)),b=(v+y)/2,x=a(Wt(l,g)),S=a(Wt(f,_)),C=x>=0?x:x+360,w=S>=0?S:S+360,T=Gt(C-w)>180?(C+w+360)/2:(C+w)/2,ee=1-.17*Kt(o(T-30))+.24*Kt(o(2*T))+.32*Kt(o(3*T+6))-.2*Kt(o(4*T-63)),E=w-C;E=Gt(E)<=180?E:w<=C?E+360:E-360,E=2*z(v*y)*qt(o(E)/2);let D=u-s,te=y-v,k=1+.015*B(p-50,2)/z(20+B(p-50,2)),A=1+.045*b,ne=1+.015*b*ee,re=30*Jt(-B((T-275)/25,2)),ie=-(2*z(B(b,7)/(B(b,7)+B(25,7))))*qt(2*o(re));return Ut(0,Ht(100,z(B(D/(n*k),2)+B(te/(r*A),2)+B(E/(i*ne),2)+ie*(te/(r*A))*(E/(i*ne)))))}function Zt(e,t,n=`lab`){e=new O(e),t=new O(t);let r=e.get(n),i=t.get(n),a=0;for(let e in r){let t=(r[e]||0)-(i[e]||0);a+=t*t}return Math.sqrt(a)}var Qt=(...e)=>{try{return new O(...e),!0}catch{return!1}},$t={cool(){return pt([k.hsl(180,1,.9),k.hsl(250,.7,.4)])},hot(){return pt([`#000`,`#f00`,`#ff0`,`#fff`],[0,.25,.75,1]).mode(`rgb`)}},en={OrRd:[`#fff7ec`,`#fee8c8`,`#fdd49e`,`#fdbb84`,`#fc8d59`,`#ef6548`,`#d7301f`,`#b30000`,`#7f0000`],PuBu:[`#fff7fb`,`#ece7f2`,`#d0d1e6`,`#a6bddb`,`#74a9cf`,`#3690c0`,`#0570b0`,`#045a8d`,`#023858`],BuPu:[`#f7fcfd`,`#e0ecf4`,`#bfd3e6`,`#9ebcda`,`#8c96c6`,`#8c6bb1`,`#88419d`,`#810f7c`,`#4d004b`],Oranges:[`#fff5eb`,`#fee6ce`,`#fdd0a2`,`#fdae6b`,`#fd8d3c`,`#f16913`,`#d94801`,`#a63603`,`#7f2704`],BuGn:[`#f7fcfd`,`#e5f5f9`,`#ccece6`,`#99d8c9`,`#66c2a4`,`#41ae76`,`#238b45`,`#006d2c`,`#00441b`],YlOrBr:[`#ffffe5`,`#fff7bc`,`#fee391`,`#fec44f`,`#fe9929`,`#ec7014`,`#cc4c02`,`#993404`,`#662506`],YlGn:[`#ffffe5`,`#f7fcb9`,`#d9f0a3`,`#addd8e`,`#78c679`,`#41ab5d`,`#238443`,`#006837`,`#004529`],Reds:[`#fff5f0`,`#fee0d2`,`#fcbba1`,`#fc9272`,`#fb6a4a`,`#ef3b2c`,`#cb181d`,`#a50f15`,`#67000d`],RdPu:[`#fff7f3`,`#fde0dd`,`#fcc5c0`,`#fa9fb5`,`#f768a1`,`#dd3497`,`#ae017e`,`#7a0177`,`#49006a`],Greens:[`#f7fcf5`,`#e5f5e0`,`#c7e9c0`,`#a1d99b`,`#74c476`,`#41ab5d`,`#238b45`,`#006d2c`,`#00441b`],YlGnBu:[`#ffffd9`,`#edf8b1`,`#c7e9b4`,`#7fcdbb`,`#41b6c4`,`#1d91c0`,`#225ea8`,`#253494`,`#081d58`],Purples:[`#fcfbfd`,`#efedf5`,`#dadaeb`,`#bcbddc`,`#9e9ac8`,`#807dba`,`#6a51a3`,`#54278f`,`#3f007d`],GnBu:[`#f7fcf0`,`#e0f3db`,`#ccebc5`,`#a8ddb5`,`#7bccc4`,`#4eb3d3`,`#2b8cbe`,`#0868ac`,`#084081`],Greys:[`#ffffff`,`#f0f0f0`,`#d9d9d9`,`#bdbdbd`,`#969696`,`#737373`,`#525252`,`#252525`,`#000000`],YlOrRd:[`#ffffcc`,`#ffeda0`,`#fed976`,`#feb24c`,`#fd8d3c`,`#fc4e2a`,`#e31a1c`,`#bd0026`,`#800026`],PuRd:[`#f7f4f9`,`#e7e1ef`,`#d4b9da`,`#c994c7`,`#df65b0`,`#e7298a`,`#ce1256`,`#980043`,`#67001f`],Blues:[`#f7fbff`,`#deebf7`,`#c6dbef`,`#9ecae1`,`#6baed6`,`#4292c6`,`#2171b5`,`#08519c`,`#08306b`],PuBuGn:[`#fff7fb`,`#ece2f0`,`#d0d1e6`,`#a6bddb`,`#67a9cf`,`#3690c0`,`#02818a`,`#016c59`,`#014636`],Viridis:[`#440154`,`#482777`,`#3f4a8a`,`#31678e`,`#26838f`,`#1f9d8a`,`#6cce5a`,`#b6de2b`,`#fee825`],Spectral:[`#9e0142`,`#d53e4f`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#e6f598`,`#abdda4`,`#66c2a5`,`#3288bd`,`#5e4fa2`],RdYlGn:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#d9ef8b`,`#a6d96a`,`#66bd63`,`#1a9850`,`#006837`],RdBu:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#f7f7f7`,`#d1e5f0`,`#92c5de`,`#4393c3`,`#2166ac`,`#053061`],PiYG:[`#8e0152`,`#c51b7d`,`#de77ae`,`#f1b6da`,`#fde0ef`,`#f7f7f7`,`#e6f5d0`,`#b8e186`,`#7fbc41`,`#4d9221`,`#276419`],PRGn:[`#40004b`,`#762a83`,`#9970ab`,`#c2a5cf`,`#e7d4e8`,`#f7f7f7`,`#d9f0d3`,`#a6dba0`,`#5aae61`,`#1b7837`,`#00441b`],RdYlBu:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee090`,`#ffffbf`,`#e0f3f8`,`#abd9e9`,`#74add1`,`#4575b4`,`#313695`],BrBG:[`#543005`,`#8c510a`,`#bf812d`,`#dfc27d`,`#f6e8c3`,`#f5f5f5`,`#c7eae5`,`#80cdc1`,`#35978f`,`#01665e`,`#003c30`],RdGy:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#ffffff`,`#e0e0e0`,`#bababa`,`#878787`,`#4d4d4d`,`#1a1a1a`],PuOr:[`#7f3b08`,`#b35806`,`#e08214`,`#fdb863`,`#fee0b6`,`#f7f7f7`,`#d8daeb`,`#b2abd2`,`#8073ac`,`#542788`,`#2d004b`],Set2:[`#66c2a5`,`#fc8d62`,`#8da0cb`,`#e78ac3`,`#a6d854`,`#ffd92f`,`#e5c494`,`#b3b3b3`],Accent:[`#7fc97f`,`#beaed4`,`#fdc086`,`#ffff99`,`#386cb0`,`#f0027f`,`#bf5b17`,`#666666`],Set1:[`#e41a1c`,`#377eb8`,`#4daf4a`,`#984ea3`,`#ff7f00`,`#ffff33`,`#a65628`,`#f781bf`,`#999999`],Set3:[`#8dd3c7`,`#ffffb3`,`#bebada`,`#fb8072`,`#80b1d3`,`#fdb462`,`#b3de69`,`#fccde5`,`#d9d9d9`,`#bc80bd`,`#ccebc5`,`#ffed6f`],Dark2:[`#1b9e77`,`#d95f02`,`#7570b3`,`#e7298a`,`#66a61e`,`#e6ab02`,`#a6761d`,`#666666`],Paired:[`#a6cee3`,`#1f78b4`,`#b2df8a`,`#33a02c`,`#fb9a99`,`#e31a1c`,`#fdbf6f`,`#ff7f00`,`#cab2d6`,`#6a3d9a`,`#ffff99`,`#b15928`],Pastel2:[`#b3e2cd`,`#fdcdac`,`#cbd5e8`,`#f4cae4`,`#e6f5c9`,`#fff2ae`,`#f1e2cc`,`#cccccc`],Pastel1:[`#fbb4ae`,`#b3cde3`,`#ccebc5`,`#decbe4`,`#fed9a6`,`#ffffcc`,`#e5d8bd`,`#fddaec`,`#f2f2f2`]},tn=Object.keys(en),nn=new Map(tn.map(e=>[e.toLowerCase(),e])),rn=typeof Proxy==`function`?new Proxy(en,{get(e,t){let n=t.toLowerCase();if(nn.has(n))return e[nn.get(n)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tn)}}):en,an=(...e)=>{e=g(e,`cmyk`);let[t,n,r,i]=e,a=e.length>4?e[4]:1;return i===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-i),n>=1?0:255*(1-n)*(1-i),r>=1?0:255*(1-r)*(1-i),a]},{max:on}=Math,sn=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i=1-on(t,on(n,r)),a=i<1?1/(1-i):0;return[(1-t-i)*a,(1-n-i)*a,(1-r-i)*a,i]};O.prototype.cmyk=function(){return sn(this._rgb)},Object.assign(k,{cmyk:(...e)=>new O(...e,`cmyk`)}),D.format.cmyk=an,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`cmyk`),h(e)===`array`&&e.length===4)return`cmyk`}});var cn=(...e)=>{let t=g(e,`hsla`),n=_(e)||`lsa`;return t[0]=x(t[0]||0)+`deg`,t[1]=x(t[1]*100)+`%`,t[2]=x(t[2]*100)+`%`,n===`hsla`||t.length>3&&t[3]<1?(t[3]=`/ `+(t.length>3?t[3]:1),n=`hsla`):t.length=3,`${n.substr(0,3)}(${t.join(` `)})`},ln=(...e)=>{let t=g(e,`lab`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=x(t[2]),n===`laba`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(` `)})`},un=(...e)=>{let t=g(e,`lch`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,n===`lcha`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(` `)})`},dn=(...e)=>{let t=g(e,`lab`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=S(t[2]),t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(` `)})`},fn=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=nt(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},pn=(...e)=>{let t=g(e,`lch`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(` `)})`},{round:mn}=Math,hn=(...e)=>{let t=g(e,`rgba`),n=_(e)||`rgb`;if(n.substr(0,3)===`hsl`)return cn(qe(t),n);if(n.substr(0,3)===`lab`){let e=ce();M(`d50`);let r=ln(fe(t),n);return M(e),r}if(n.substr(0,3)===`lch`){let e=ce();M(`d50`);let r=un(Ae(t),n);return M(e),r}return n.substr(0,5)===`oklab`?dn(nt(t)):n.substr(0,5)===`oklch`?pn(fn(t)):(t[0]=mn(t[0]),t[1]=mn(t[1]),t[2]=mn(t[2]),(n===`rgba`||t.length>3&&t[3]<1)&&(t[3]=`/ `+(t.length>3?t[3]:1),n=`rgba`),`${n.substr(0,3)}(${t.slice(0,n===`rgb`?3:4).join(` `)})`)},gn=(...e)=>{e=g(e,`lch`);let[t,n,r,...i]=e,[a,o,s]=Ce(t,n,r),[c,l,u]=et(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},V=`((?:-?\\d+)|(?:-?\\d+(?:\\.\\d+)?)%|none)`,H=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%?)|none)`,_n=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%)|none)`,U=`\\s*`,vn=`\\s+`,yn=`\\s*,\\s*`,bn=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:deg)?)|none)`,xn=`\\s*(?:\\/\\s*((?:[01]|[01]?\\.\\d+)|\\d+(?:\\.\\d+)?%))?`,Sn=RegExp(`^rgba?\\(`+U+[V,V,V].join(vn)+xn+`\\)$`),Cn=RegExp(`^rgb\\(`+U+[V,V,V].join(yn)+U+`\\)$`),wn=RegExp(`^rgba\\(`+U+[V,V,V,H].join(yn)+U+`\\)$`),Tn=RegExp(`^hsla?\\(`+U+[bn,_n,_n].join(vn)+xn+`\\)$`),En=RegExp(`^hsl?\\(`+U+[bn,_n,_n].join(yn)+U+`\\)$`),Dn=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,On=RegExp(`^lab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),kn=RegExp(`^lch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),An=RegExp(`^oklab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),jn=RegExp(`^oklch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),{round:Mn}=Math,Nn=e=>e.map((e,t)=>t<=2?f(Mn(e),0,255):e),W=(e,t=0,n=100,r=!1)=>(typeof e==`string`&&e.endsWith(`%`)&&(e=parseFloat(e.substring(0,e.length-1))/100,e=r?t+(e+1)*.5*(n-t):t+e*(n-t)),+e),G=(e,t)=>e===`none`?t:e,Pn=e=>{if(e=e.toLowerCase().trim(),e===`transparent`)return[0,0,0,0];let t;if(D.format.named)try{return D.format.named(e)}catch{}if((t=e.match(Sn))||(t=e.match(Cn))){let e=t.slice(1,4);for(let t=0;t<3;t++)e[t]=+W(G(e[t],0),0,255);e=Nn(e);let n=t[4]===void 0?1:+W(t[4],0,1);return e[3]=n,e}if(t=e.match(wn)){let e=t.slice(1,5);for(let t=0;t<4;t++)e[t]=+W(e[t],0,255);return e}if((t=e.match(Tn))||(t=e.match(En))){let e=t.slice(1,4);e[0]=+G(e[0].replace(`deg`,``),0),e[1]=W(G(e[1],0),0,100)*.01,e[2]=W(G(e[2],0),0,100)*.01;let n=Nn(Ke(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(Dn)){let e=t.slice(1,4);e[1]*=.01,e[2]*=.01;let n=Ke(e);for(let e=0;e<3;e++)n[e]=Mn(n[e]);return n[3]=+t[4],n}if(t=e.match(On)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,100),e[1]=W(G(e[1],0),-125,125,!0),e[2]=W(G(e[2],0),-125,125,!0);let n=ce();M(`d50`);let r=Nn(N(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(kn)){let e=t.slice(1,4);e[0]=W(e[0],0,100),e[1]=W(G(e[1],0),0,150,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=ce();M(`d50`);let r=Nn(we(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(An)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),-.4,.4,!0),e[2]=W(G(e[2],0),-.4,.4,!0);let n=Nn(et(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(jn)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),0,.4,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=Nn(gn(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}};Pn.test=e=>Sn.test(e)||Tn.test(e)||On.test(e)||kn.test(e)||An.test(e)||jn.test(e)||Cn.test(e)||wn.test(e)||En.test(e)||Dn.test(e)||e===`transparent`,O.prototype.css=function(e){return hn(this._rgb,e)},k.css=(...e)=>new O(...e,`css`),D.format.css=Pn,D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&Pn.test(e))return`css`}}),D.format.gl=(...e)=>{let t=g(e,`rgba`);return t[0]*=255,t[1]*=255,t[2]*=255,t},k.gl=(...e)=>new O(...e,`gl`),O.prototype.gl=function(){let e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},O.prototype.hex=function(e){return oe(this._rgb,e)},k.hex=(...e)=>new O(...e,`hex`),D.format.hex=ie,D.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return`hex`}});var{log:Fn}=Math,In=e=>{let t=e/100,n,r,i;return t<66?(n=255,r=t<6?0:-155.25485562709179-.44596950469579133*(r=t-2)+104.49216199393888*Fn(r),i=t<20?0:-254.76935184120902+.8274096064007395*(i=t-10)+115.67994401066147*Fn(i)):(n=351.97690566805693+.114206453784165*(n=t-55)-40.25366309332127*Fn(n),r=325.4494125711974+.07943456536662342*(r=t-50)-28.0852963507957*Fn(r),i=255),[n,r,i,1]},{round:Ln}=Math,Rn=(...e)=>{let t=g(e,`rgb`),n=t[0],r=t[2],i=1e3,a=4e4,o;for(;a-i>.4;){o=(a+i)*.5;let e=In(o);e[2]/e[0]>=r/n?a=o:i=o}return Ln(o)};O.prototype.temp=O.prototype.kelvin=O.prototype.temperature=function(){return Rn(this._rgb)};var zn=(...e)=>new O(...e,`temp`);Object.assign(k,{temp:zn,kelvin:zn,temperature:zn}),D.format.temp=D.format.kelvin=D.format.temperature=In,O.prototype.oklch=function(){return fn(this._rgb)},Object.assign(k,{oklch:(...e)=>new O(...e,`oklch`)}),D.format.oklch=gn,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklch`),h(e)===`array`&&e.length===3)return`oklch`}}),Object.assign(k,{analyze:jt,average:ut,bezier:_t,blend:I,brewer:rn,Color:O,colors:A,contrast:Nt,contrastAPCA:Bt,cubehelix:St,deltaE:Xt,distance:Zt,input:D,interpolate:F,limits:Mt,mix:F,random:Et,scale:pt,scales:$t,valid:Qt});var K=k,q=class e{constructor(){this.hex=`#000000`,this.rgb_r=0,this.rgb_g=0,this.rgb_b=0,this.xyz_x=0,this.xyz_y=0,this.xyz_z=0,this.luv_l=0,this.luv_u=0,this.luv_v=0,this.lch_l=0,this.lch_c=0,this.lch_h=0,this.hsluv_h=0,this.hsluv_s=0,this.hsluv_l=0,this.hpluv_h=0,this.hpluv_p=0,this.hpluv_l=0,this.r0s=0,this.r0i=0,this.r1s=0,this.r1i=0,this.g0s=0,this.g0i=0,this.g1s=0,this.g1i=0,this.b0s=0,this.b0i=0,this.b1s=0,this.b1i=0}static fromLinear(e){return e<=.0031308?12.92*e:1.055*e**(1/2.4)-.055}static toLinear(e){return e>.04045?((e+.055)/1.055)**2.4:e/12.92}static yToL(t){return t<=e.epsilon?t/e.refY*e.kappa:116*(t/e.refY)**(1/3)-16}static lToY(t){return t<=8?e.refY*t/e.kappa:e.refY*((t+16)/116)**3}static rgbChannelToHex(t){let n=Math.round(t*255),r=n%16,i=(n-r)/16|0;return e.hexChars.charAt(i)+e.hexChars.charAt(r)}static hexToRgbChannel(t,n){let r=e.hexChars.indexOf(t.charAt(n)),i=e.hexChars.indexOf(t.charAt(n+1));return(r*16+i)/255}static distanceFromOriginAngle(e,t,n){let r=t/(Math.sin(n)-e*Math.cos(n));return r<0?1/0:r}static distanceFromOrigin(e,t){return Math.abs(t)/Math.sqrt(e**2+1)}static min6(e,t,n,r,i,a){return Math.min(e,Math.min(t,Math.min(n,Math.min(r,Math.min(i,a)))))}rgbToHex(){this.hex=`#`,this.hex+=e.rgbChannelToHex(this.rgb_r),this.hex+=e.rgbChannelToHex(this.rgb_g),this.hex+=e.rgbChannelToHex(this.rgb_b)}hexToRgb(){this.hex=this.hex.toLowerCase(),this.rgb_r=e.hexToRgbChannel(this.hex,1),this.rgb_g=e.hexToRgbChannel(this.hex,3),this.rgb_b=e.hexToRgbChannel(this.hex,5)}xyzToRgb(){this.rgb_r=e.fromLinear(e.m_r0*this.xyz_x+e.m_r1*this.xyz_y+e.m_r2*this.xyz_z),this.rgb_g=e.fromLinear(e.m_g0*this.xyz_x+e.m_g1*this.xyz_y+e.m_g2*this.xyz_z),this.rgb_b=e.fromLinear(e.m_b0*this.xyz_x+e.m_b1*this.xyz_y+e.m_b2*this.xyz_z)}rgbToXyz(){let t=e.toLinear(this.rgb_r),n=e.toLinear(this.rgb_g),r=e.toLinear(this.rgb_b);this.xyz_x=.41239079926595*t+.35758433938387*n+.18048078840183*r,this.xyz_y=.21263900587151*t+.71516867876775*n+.072192315360733*r,this.xyz_z=.019330818715591*t+.11919477979462*n+.95053215224966*r}xyzToLuv(){let t=this.xyz_x+15*this.xyz_y+3*this.xyz_z,n=4*this.xyz_x,r=9*this.xyz_y;t===0?(n=NaN,r=NaN):(n/=t,r/=t),this.luv_l=e.yToL(this.xyz_y),this.luv_l===0?(this.luv_u=0,this.luv_v=0):(this.luv_u=13*this.luv_l*(n-e.refU),this.luv_v=13*this.luv_l*(r-e.refV))}luvToXyz(){if(this.luv_l===0){this.xyz_x=0,this.xyz_y=0,this.xyz_z=0;return}let t=this.luv_u/(13*this.luv_l)+e.refU,n=this.luv_v/(13*this.luv_l)+e.refV;this.xyz_y=e.lToY(this.luv_l),this.xyz_x=0-9*this.xyz_y*t/((t-4)*n-t*n),this.xyz_z=(9*this.xyz_y-15*n*this.xyz_y-n*this.xyz_x)/(3*n)}luvToLch(){this.lch_l=this.luv_l,this.lch_c=Math.sqrt(this.luv_u*this.luv_u+this.luv_v*this.luv_v),this.lch_c<1e-8?this.lch_h=0:(this.lch_h=Math.atan2(this.luv_v,this.luv_u)*180/Math.PI,this.lch_h<0&&(this.lch_h=360+this.lch_h))}lchToLuv(){let e=this.lch_h/180*Math.PI;this.luv_l=this.lch_l,this.luv_u=Math.cos(e)*this.lch_c,this.luv_v=Math.sin(e)*this.lch_c}calculateBoundingLines(t){let n=(t+16)**3/1560896,r=n>e.epsilon?n:t/e.kappa,i=r*(284517*e.m_r0-94839*e.m_r2),a=r*(838422*e.m_r2+769860*e.m_r1+731718*e.m_r0),o=r*(632260*e.m_r2-126452*e.m_r1),s=r*(284517*e.m_g0-94839*e.m_g2),c=r*(838422*e.m_g2+769860*e.m_g1+731718*e.m_g0),l=r*(632260*e.m_g2-126452*e.m_g1),u=r*(284517*e.m_b0-94839*e.m_b2),d=r*(838422*e.m_b2+769860*e.m_b1+731718*e.m_b0),f=r*(632260*e.m_b2-126452*e.m_b1);this.r0s=i/o,this.r0i=a*t/o,this.r1s=i/(o+126452),this.r1i=(a-769860)*t/(o+126452),this.g0s=s/l,this.g0i=c*t/l,this.g1s=s/(l+126452),this.g1i=(c-769860)*t/(l+126452),this.b0s=u/f,this.b0i=d*t/f,this.b1s=u/(f+126452),this.b1i=(d-769860)*t/(f+126452)}calcMaxChromaHpluv(){let t=e.distanceFromOrigin(this.r0s,this.r0i),n=e.distanceFromOrigin(this.r1s,this.r1i),r=e.distanceFromOrigin(this.g0s,this.g0i),i=e.distanceFromOrigin(this.g1s,this.g1i),a=e.distanceFromOrigin(this.b0s,this.b0i),o=e.distanceFromOrigin(this.b1s,this.b1i);return e.min6(t,n,r,i,a,o)}calcMaxChromaHsluv(t){let n=t/360*Math.PI*2,r=e.distanceFromOriginAngle(this.r0s,this.r0i,n),i=e.distanceFromOriginAngle(this.r1s,this.r1i,n),a=e.distanceFromOriginAngle(this.g0s,this.g0i,n),o=e.distanceFromOriginAngle(this.g1s,this.g1i,n),s=e.distanceFromOriginAngle(this.b0s,this.b0i,n),c=e.distanceFromOriginAngle(this.b1s,this.b1i,n);return e.min6(r,i,a,o,s,c)}hsluvToLch(){this.hsluv_l>99.9999999?(this.lch_l=100,this.lch_c=0):this.hsluv_l<1e-8?(this.lch_l=0,this.lch_c=0):(this.lch_l=this.hsluv_l,this.calculateBoundingLines(this.hsluv_l),this.lch_c=this.calcMaxChromaHsluv(this.hsluv_h)/100*this.hsluv_s),this.lch_h=this.hsluv_h}lchToHsluv(){if(this.lch_l>99.9999999)this.hsluv_s=0,this.hsluv_l=100;else if(this.lch_l<1e-8)this.hsluv_s=0,this.hsluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHsluv(this.lch_h);this.hsluv_s=this.lch_c/e*100,this.hsluv_l=this.lch_l}this.hsluv_h=this.lch_h}hpluvToLch(){this.hpluv_l>99.9999999?(this.lch_l=100,this.lch_c=0):this.hpluv_l<1e-8?(this.lch_l=0,this.lch_c=0):(this.lch_l=this.hpluv_l,this.calculateBoundingLines(this.hpluv_l),this.lch_c=this.calcMaxChromaHpluv()/100*this.hpluv_p),this.lch_h=this.hpluv_h}lchToHpluv(){if(this.lch_l>99.9999999)this.hpluv_p=0,this.hpluv_l=100;else if(this.lch_l<1e-8)this.hpluv_p=0,this.hpluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHpluv();this.hpluv_p=this.lch_c/e*100,this.hpluv_l=this.lch_l}this.hpluv_h=this.lch_h}hsluvToRgb(){this.hsluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hpluvToRgb(){this.hpluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hsluvToHex(){this.hsluvToRgb(),this.rgbToHex()}hpluvToHex(){this.hpluvToRgb(),this.rgbToHex()}rgbToHsluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHsluv()}rgbToHpluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHpluv()}hexToHsluv(){this.hexToRgb(),this.rgbToHsluv()}hexToHpluv(){this.hexToRgb(),this.rgbToHpluv()}};q.hexChars=`0123456789abcdef`,q.refY=1,q.refU=.19783000664283,q.refV=.46831999493879,q.kappa=903.2962962,q.epsilon=.0088564516,q.m_r0=3.240969941904521,q.m_r1=-1.537383177570093,q.m_r2=-.498610760293,q.m_g0=-.96924363628087,q.m_g1=1.87596750150772,q.m_g2=.041555057407175,q.m_b0=.055630079696993,q.m_b1=-.20397695888897,q.m_b2=1.056971514242878;var Bn=s(((e,t)=>{function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=n})),Vn=s(((e,t)=>{var n=Bn(),r,i;function a(){for(var e in i=[`toString`,`toLocaleString`,`valueOf`,`hasOwnProperty`,`isPrototypeOf`,`propertyIsEnumerable`,`constructor`],r=!0,{toString:null})r=!1}function o(e,t,o){var c,l=0;for(c in r??a(),e)if(s(t,e,c,o)===!1)break;if(r)for(var u=e.constructor,d=!!u&&e===u.prototype;(c=i[l++])&&!((c!==`constructor`||!d&&n(e,c))&&e[c]!==Object.prototype[c]&&s(t,e,c,o)===!1););}function s(e,t,n,r){return e.call(r,t[n],n,t)}t.exports=o})),Hn=s(((e,t)=>{var n=Vn();function r(e){var t=[];return n(e,function(e,n){typeof e==`function`&&t.push(n)}),t.sort()}t.exports=r})),Un=s(((e,t)=>{function n(e,t,n){var r=e.length;t=t==null?0:t<0?Math.max(r+t,0):Math.min(t,r),n=n==null?r:n<0?Math.max(r+n,0):Math.min(n,r);for(var i=[];t{var n=Un();function r(e,t,r){var i=n(arguments,2);return function(){return e.apply(t,i.concat(n(arguments)))}}t.exports=r})),Gn=s(((e,t)=>{function n(e,t,n){if(e!=null)for(var r=-1,i=e.length;++r{var n=Hn(),r=Wn(),i=Gn(),a=Un();function o(e,t){i(arguments.length>1?a(arguments,1):n(e),function(t){e[t]=r(e[t],e)})}t.exports=o})),J=s(((e,t)=>{var n=Bn(),r=Vn();function i(e,t,i){r(e,function(r,a){if(n(e,a))return t.call(i,e[a],a,e)})}t.exports=i})),qn=s(((e,t)=>{function n(e){return e}t.exports=n})),Jn=s(((e,t)=>{function n(e){return function(t){return t[e]}}t.exports=n})),Yn=s(((e,t)=>{var n=/^\[object (.*)\]$/,r=Object.prototype.toString,i;function a(e){return e===null?`Null`:e===i?`Undefined`:n.exec(r.call(e))[1]}t.exports=a})),Xn=s(((e,t)=>{var n=Yn();function r(e,t){return n(e)===t}t.exports=r})),Zn=s(((e,t)=>{var n=Xn();t.exports=Array.isArray||function(e){return n(e,`Array`)}})),Qn=s(((e,t)=>{var n=J(),r=Zn();function i(e,t){for(var n=-1,r=e.length;++n{var n=qn(),r=Jn(),i=Qn();function a(e,t){if(e==null)return n;switch(typeof e){case`function`:return t===void 0?e:function(n,r,i){return e.call(t,n,r,i)};case`object`:return function(t){return i(t,e)};case`string`:case`number`:return r(e)}}t.exports=a})),$n=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!1;return n(e,function(n,r){if(t(n,r,e))return a=!0,!1}),a}t.exports=i})),er=s(((e,t)=>{var n=$n();function r(e,t){return n(e,function(e){return e===t})}t.exports=r})),tr=s(((e,t)=>{function n(e){return!!e&&typeof e==`object`&&e.constructor===Object}t.exports=n})),nr=s(((e,t)=>{var n=J(),r=tr();function i(e,t){for(var a=0,o=arguments.length,s;++a{var n=J(),r=tr();function i(e,t){for(var r=0,i=arguments.length,o;++r{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!0;return n(e,function(n,r){if(!t(n,r,e))return a=!1,!1}),a}t.exports=i})),ar=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Object`)}t.exports=r})),or=s(((e,t)=>{function n(e,t){return e===t?e!==0||1/e==1/t:e!==e&&t!==t}t.exports=n})),sr=s(((e,t)=>{var n=Bn(),r=ir(),i=ar(),a=or();function o(e){return function(t,r){return n(this,r)&&e(t,this[r])}}function s(e,t){return n(this,t)}function c(e,t,n){return n||=a,!i(e)||!i(t)?n(e,t):r(e,o(n),t)&&r(t,s,e)}t.exports=c})),cr=s(((e,t)=>{var n=Gn(),r=Un(),i=J();function a(e,t){return n(r(arguments,1),function(t){i(t,function(t,n){e[n]??(e[n]=t)})}),e}t.exports=a})),lr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){t(e,n,r)&&(a[n]=e)}),a}t.exports=i})),ur=s(((e,t)=>{var n=$n(),r=Y();function i(e,t,i){t=r(t,i);var a;return n(e,function(e,n,r){if(t(e,n,r))return a=e,!0}),a}t.exports=i})),dr=s(((e,t)=>{var n=J(),r=tr();function i(e,t,a,o){return n(e,function(e,n){var s=a?a+`.`+n:n;o!==0&&r(e)?i(e,t,s,o-1):t[s]=e}),t}function a(e,t){return e==null?{}:(t??=-1,i(e,{},``,t))}t.exports=a})),fr=s(((e,t)=>{function n(e){switch(typeof e){case`string`:case`number`:case`boolean`:return!0}return e==null}t.exports=n})),pr=s(((e,t)=>{fr();function n(e,t){for(var n=t.split(`.`),r=n.pop();t=n.shift();)if(e=e[t],e==null)return;return e[r]}t.exports=n})),mr=s(((e,t)=>{var n=pr(),r;function i(e,t){return n(e,t)!==r}t.exports=i})),hr=s(((e,t)=>{var n=J();t.exports=Object.keys||function(e){var t=[];return n(e,function(e,n){t.push(n)}),t}})),gr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){a[n]=t(e,n,r)}),a}t.exports=i})),_r=s(((e,t)=>{var n=J();function r(e,t){var r=!0;return n(t,function(t,n){if(e[n]!==t)return r=!1}),r}t.exports=r})),vr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return 1/0;if(e.length&&!t)return Math.max.apply(Math,e);t=n(t,r);for(var i,a=-1/0,o,s,c=-1,l=e.length;++ca&&(a=s,i=o);return i}t.exports=r})),yr=s(((e,t)=>{var n=J();function r(e){var t=[];return n(e,function(e,n){t.push(e)}),t}t.exports=r})),br=s(((e,t)=>{var n=vr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),xr=s(((e,t)=>{var n=J();function r(e,t){for(var r=0,a=arguments.length,o;++r{var n=Yn(),r=tr(),i=xr();function a(e){switch(n(e)){case`Object`:return o(e);case`Array`:return l(e);case`RegExp`:return s(e);case`Date`:return c(e);default:return e}}function o(e){return r(e)?i({},e):e}function s(e){var t=``;return t+=e.multiline?`m`:``,t+=e.global?`g`:``,t+=e.ignoreCase?`i`:``,new RegExp(e.source,t)}function c(e){return new Date(+e)}function l(e){return e.slice()}t.exports=a})),Cr=s(((e,t)=>{var n=Sr(),r=J(),i=Yn(),a=tr();function o(e,t){switch(i(e)){case`Object`:return s(e,t);case`Array`:return c(e,t);default:return n(e)}}function s(e,t){if(a(e)){var n={};return r(e,function(e,n){this[n]=o(e,t)},n),n}else if(t)return t(e);else return e}function c(e,t){for(var n=[],r=-1,i=e.length;++r{var n=Bn(),r=Cr(),i=ar();function a(){for(var e=1,t,o,s,c=r(arguments[0]);s=arguments[e++];)for(t in s)n(s,t)&&(o=s[t],i(o)&&i(c[t])?c[t]=a(c[t],o):c[t]=r(o));return c}t.exports=a})),Tr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return-1/0;if(e.length&&!t)return Math.min.apply(Math,e);t=n(t,r);for(var i,a=1/0,o,s,c=-1,l=e.length;++c{var n=Tr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),Dr=s(((e,t)=>{var n=Gn();function r(e,t){return t&&n(t.split(`.`),function(t){e[t]||(e[t]={}),e=e[t]}),e}t.exports=r})),Or=s(((e,t)=>{function n(e,t,n){if(n||=0,e==null)return-1;for(var r=e.length,i=n<0?r+n:n;i{var n=Or();function r(e,t){return n(e,t)!==-1}t.exports=r})),Ar=s(((e,t)=>{var n=Un(),r=kr();function i(e,t){var i=typeof arguments[1]==`string`?n(arguments,1):arguments[1],a={};for(var o in e)e.hasOwnProperty(o)&&!r(i,o)&&(a[o]=e[o]);return a}t.exports=i})),jr=s(((e,t)=>{var n=Un();function r(e,t){for(var r=typeof arguments[1]==`string`?n(arguments,1):arguments[1],i={},a=0,o;o=r[a++];)i[o]=e[o];return i}t.exports=r})),Mr=s(((e,t)=>{var n=gr(),r=Jn();function i(e,t){return n(e,r(t))}t.exports=i})),Nr=s(((e,t)=>{var n=J();function r(e){var t=0;return n(e,function(){t++}),t}t.exports=r})),Pr=s(((e,t)=>{var n=J(),r=Nr();function i(e,t,i,a){var o=arguments.length>2;if(!r(e)&&!o)throw Error(`reduce of empty object with no initial value`);return n(e,function(e,n,r){o?i=t.call(a,i,e,n,r):(i=e,o=!0)}),i}t.exports=i})),Fr=s(((e,t)=>{var n=lr(),r=Y();function i(e,t,i){return t=r(t,i),n(e,function(e,n,r){return!t(e,n,r)},i)}t.exports=i})),Ir=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Function`)}t.exports=r})),Lr=s(((e,t)=>{var n=Ir();function r(e,t){var r=e[t];if(r!==void 0)return n(r)?r.call(e):r}t.exports=r})),Rr=s(((e,t)=>{var n=Dr();function r(e,t,r){var i=/^(.+)\.(.+)$/.exec(t);i?n(e,i[1])[i[2]]=r:e[t]=r}t.exports=r})),zr=s(((e,t)=>{var n=mr();function r(e,t){if(n(e,t)){for(var r=t.split(`.`),i=r.pop();t=r.shift();)e=e[t];return delete e[i]}else return!0}t.exports=r})),Br=s(((e,t)=>{t.exports={bindAll:Kn(),contains:er(),deepFillIn:nr(),deepMatches:Qn(),deepMixIn:rr(),equals:sr(),every:ir(),fillIn:cr(),filter:lr(),find:ur(),flatten:dr(),forIn:Vn(),forOwn:J(),functions:Hn(),get:pr(),has:mr(),hasOwn:Bn(),keys:hr(),map:gr(),matches:_r(),max:br(),merge:wr(),min:Er(),mixIn:xr(),namespace:Dr(),omit:Ar(),pick:jr(),pluck:Mr(),reduce:Pr(),reject:Fr(),result:Lr(),set:Rr(),size:Nr(),some:$n(),unset:zr(),values:yr()}})),Vr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.default=(0,Br().map)({A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},function(e){return[100*(e.x/e.y),100,100*(1-e.x-e.y)/e.y]}),t.exports=e.default})),Hr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=Math,r=n.pow,i=n.sign,a=n.abs,o={decode:function(e){return e<=.04045?e/12.92:r((e+.055)/1.055,2.4)},encode:function(e){return e<=.0031308?12.92*e:1.055*r(e,1/2.4)-.055}},s={encode:function(e){return e<.001953125?16*e:r(e,1/1.8)},decode:function(e){return e<16*.001953125?e/16:r(e,1.8)}};function c(e){return{decode:function(t){return i(t)*r(a(t),e)},encode:function(t){return i(t)*r(a(t),1/e)}}}e.default={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:o},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:c(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:c(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:s}},t.exports=e.default})),Ur=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});function t(e){return[[e[0][0],e[1][0],e[2][0]],[e[0][1],e[1][1],e[2][1]],[e[0][2],e[1][2],e[2][2]]]}function n(e){return e[0][0]*(e[2][2]*e[1][1]-e[2][1]*e[1][2])+e[1][0]*(e[2][1]*e[0][2]-e[2][2]*e[0][1])+e[2][0]*(e[1][2]*e[0][1]-e[1][1]*e[0][2])}function r(e){var t=1/n(e);return[[(e[2][2]*e[1][1]-e[2][1]*e[1][2])*t,(e[2][1]*e[0][2]-e[2][2]*e[0][1])*t,(e[1][2]*e[0][1]-e[1][1]*e[0][2])*t],[(e[2][0]*e[1][2]-e[2][2]*e[1][0])*t,(e[2][2]*e[0][0]-e[2][0]*e[0][2])*t,(e[1][0]*e[0][2]-e[1][2]*e[0][0])*t],[(e[2][1]*e[1][0]-e[2][0]*e[1][1])*t,(e[2][0]*e[0][1]-e[2][1]*e[0][0])*t,(e[1][1]*e[0][0]-e[1][0]*e[0][1])*t]]}function i(e,t){return[e[0][0]*t[0]+e[0][1]*t[1]+e[0][2]*t[2],e[1][0]*t[0]+e[1][1]*t[1]+e[1][2]*t[2],e[2][0]*t[0]+e[2][1]*t[1]+e[2][2]*t[2]]}function a(e,t){return[[e[0][0]*t[0],e[0][1]*t[1],e[0][2]*t[2]],[e[1][0]*t[0],e[1][1]*t[1],e[1][2]*t[2]],[e[2][0]*t[0],e[2][1]*t[1],e[2][2]*t[2]]]}function o(e,t){return[[e[0][0]*t[0][0]+e[0][1]*t[1][0]+e[0][2]*t[2][0],e[0][0]*t[0][1]+e[0][1]*t[1][1]+e[0][2]*t[2][1],e[0][0]*t[0][2]+e[0][1]*t[1][2]+e[0][2]*t[2][2]],[e[1][0]*t[0][0]+e[1][1]*t[1][0]+e[1][2]*t[2][0],e[1][0]*t[0][1]+e[1][1]*t[1][1]+e[1][2]*t[2][1],e[1][0]*t[0][2]+e[1][1]*t[1][2]+e[1][2]*t[2][2]],[e[2][0]*t[0][0]+e[2][1]*t[1][0]+e[2][2]*t[2][0],e[2][0]*t[0][1]+e[2][1]*t[1][1]+e[2][2]*t[2][1],e[2][0]*t[0][2]+e[2][1]*t[1][2]+e[2][2]*t[2][2]]]}e.transpose=t,e.determinant=n,e.inverse=r,e.multiply=i,e.scalar=a,e.product=o})),Wr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.PI;function n(e){for(var n=e*180/t;n<0;)n+=360;for(;n>360;)n-=360;return n}function r(e){for(var n=t*e/180;n<0;)n+=2*t;for(;n>2*t;)n-=2*t;return n}e.fromRadian=n,e.toRadian=r})),Gr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.round;function n(e){return e[0]==`#`&&(e=e.slice(1)),e.length<6&&(e=e.split(``).map(function(e){return e+e}).join(``)),e.match(/../g).map(function(e){return parseInt(e,16)/255})}function r(e){return`#`+e.map(function(e){return e=t(255*e).toString(16),e.length<2&&(e=`0`+e),e}).join(``)}e.fromHex=n,e.toHex=r})),Kr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=o(Ur()),r=a(Vr()),i=a(Hr());function a(e){return e&&e.__esModule?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function s(){var e=arguments.length<=0||arguments[0]===void 0?i.default.sRGB:arguments[0],t=arguments.length<=1||arguments[1]===void 0?r.default.D65:arguments[1],a=[e.r,e.g,e.b],o=n.transpose(a.map(function(e){return[e.x/e.y,1,(1-e.x-e.y)/e.y]})),s=e.gamma,c=n.multiply(n.inverse(o),t),l=n.scalar(o,c),u=n.inverse(l);return{fromRgb:function(e){return n.multiply(l,e.map(s.decode))},toRgb:function(e){return n.multiply(u,e).map(s.encode)}}}e.default=s,t.exports=e.default})),qr=s(((e,t)=>{t.exports={illuminant:Vr(),workspace:Hr(),matrix:Ur(),degree:Wr(),rgb:Gr(),xyz:Kr()}})),Jr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.cfs=e.distance=e.lerp=e.corLerp=void 0;var t=Br();function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ti/2&&(e>t?t+=i:e+=i),((1-n)*e+n*t)%(i||1/0)}function u(e,t,n){var r={};for(var i in e)r[i]=l(e[i],t[i],n,i);return r}function d(e,t){var n=0;for(var r in e)n+=o(e[r]-t[r],2);return s(n)}function f(e){return t.merge.apply(void 0,r(e.split(``).map(function(e){return n({},e,!0)})))}e.corLerp=l,e.lerp=u,e.distance=d,e.cfs=f})),Yr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=Jr();function a(e,t){var a=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],o=-a,s=1+a,c=Math,l=c.min,u=c.max,d=n([`000`,`fff`].map(function(n){return t.fromXyz(e.fromRgb(r.rgb.fromHex(n)))}),2),f=d[0],p=d[1];function m(n){var r=e.toRgb(t.toXyz(n));return[r.map(function(e){return e>=o&&e<=s}).reduce(function(e,t){return e&&t},!0),r]}function h(e,t){for(var r=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,i.distance)(e,t)>r;){var a=(0,i.lerp)(e,t,.5);n(m(a),1)[0]?e=a:t=a}return e}function g(e){return(0,i.lerp)(f,p,e)}function _(e){return e.map(function(e){return u(o,l(s,e))})}return{contains:m,limit:h,spine:g,crop:_}}e.default=a,t.exports=e.default})),Xr=s((e=>{var t=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0}),e.toNotation=e.fromNotation=e.toHue=e.fromHue=void 0;var n=Jr(),r=Math.floor,i=[{s:`R`,h:20.14,e:.8,H:0},{s:`Y`,h:90,e:.7,H:100},{s:`G`,h:164.25,e:1,H:200},{s:`B`,h:237.53,e:1.2,H:300},{s:`R`,h:380.14,e:.8,H:400}],a=i.map(function(e){return e.s}).slice(0,-1).join(``);function o(e){e50){var o=[n,t];t=o[0],n=o[1],i=100-i}return i<1?a[t]:a[t]+i.toFixed()+a[n]}e.fromHue=o,e.toHue=s,e.fromNotation=l,e.toNotation=u})),Zr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=s(Xr()),a=Jr(),o=Br();function s(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var c=Math,l=c.pow,u=c.sqrt,d=c.exp,f=c.abs,p=c.sign,m=Math,h=m.sin,g=m.cos,_=m.atan2,v={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},y=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],b=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],x=y,S=r.matrix.inverse(y),C=r.matrix.product(b,r.matrix.inverse(y)),w=r.matrix.product(y,r.matrix.inverse(b)),T={whitePoint:r.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ee=(0,a.cfs)(`QJMCshH`),E=(0,a.cfs)(`JCh`);function D(){var e=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],t=arguments.length<=1||arguments[1]===void 0?ee:arguments[1];e=(0,o.merge)(T,e);var a=e.whitePoint,s=e.adaptingLuminance,c=e.backgroundLuminance,m=v[e.surroundType],b=m.F,D=m.c,O=m.N_c,te=a[1],k=1/(5*s+1),A=.2*l(k,4)*5*s+.1*l(1-l(k,4),2)*l(5*s,1/3),ne=c/te,re=.725*l(1/ne,.2),ie=re,ae=1.48+u(ne),oe=e.discounting?1:b*(1-1/3.6*d(-(s+42)/92)),j=n(r.matrix.multiply(y,a).map(function(e){return oe*te/e+1-oe}),3),se=j[0],M=j[1],ce=j[2],N=pe(de(le(a)));function le(e){var t=n(r.matrix.multiply(x,e),3),i=t[0],a=t[1],o=t[2];return[se*i,M*a,ce*o]}function ue(e){var t=n(e,3),i=t[0],a=t[1],o=t[2];return r.matrix.multiply(S,[i/se,a/M,o/ce])}function de(e){return r.matrix.multiply(C,e).map(function(e){var t=l(A*f(e)/100,.42);return p(e)*400*t/(27.13+t)+.1})}function fe(e){return r.matrix.multiply(w,e.map(function(e){var t=e-.1;return p(t)*100/A*l(27.13*f(t)/(400-f(t)),1/.42)}))}function pe(e){var t=n(e,3),r=t[0],i=t[1],a=t[2];return(r*2+i+a/20-.305)*re}function me(e){return 4/D*u(e/100)*(N+4)*l(A,.25)}function he(e){return 6.25*l(D*e/((N+4)*l(A,.25)),2)}function ge(e){return e*l(A,.25)}function _e(e,t){return l(e/100,2)*t/l(A,.25)}function ve(e){return e/l(A,.25)}function ye(e,t){return 100*u(e/t)}function be(e,t){var n=t.Q,r=t.J,a=t.M,o=t.C,s=t.s,c=t.h,l=t.H,u={};return e.J&&(u.J=isNaN(r)?he(n):r),e.C&&(isNaN(o)?isNaN(a)?(n=isNaN(n)?me(r):n,u.C=_e(s,n)):u.C=ve(a):u.C=t.C),e.h&&(u.h=isNaN(c)?i.toHue(l):c),e.Q&&(u.Q=isNaN(n)?me(r):n),e.M&&(u.M=isNaN(a)?ge(o):a),e.s&&(isNaN(s)?(n=isNaN(n)?me(r):n,a=isNaN(a)?ge(o):a,u.s=ye(a,n)):u.s=s),e.H&&(u.H=isNaN(l)?i.fromHue(c):l),u}function P(e){var i=de(le(e)),a=n(i,3),o=a[0],s=a[1],c=a[2],d=o-s*12/11+c/11,f=(o+s-2*c)/9,p=_(f,d),m=r.degree.fromRadian(p),h=1/4*(g(p+2)+3.8),v=100*l(pe(i)/N,D*ae);return be(t,{J:v,C:l(5e4/13*O*ie*h*u(d*d+f*f)/(o+s+21/20*c),.9)*u(v/100)*l(1.64-l(.29,ne),.73),h:m})}function F(e){var t=be(E,e),n=t.J,i=t.C,a=t.h,o=r.degree.toRadian(a),s=l(i/(u(n/100)*l(1.64-l(.29,ne),.73)),10/9),c=1/4*(g(o+2)+3.8),d=N*l(n/100,1/D/ae),p=5e4/13*O*ie*c/s,m=d/re+.305,_=m*61/20*460/1403,v=61/20*220/1403,y=21/20*6300/1403-27/1403,b=h(o),x=g(o),S,C;return s===0||isNaN(s)?S=C=0:f(b)>=f(x)?(C=_/(p/b+v*x/b+y),S=C*x/b):(S=_/(p/x+v+y*b/x),C=S*b/x),ue(fe([20/61*m+451/1403*S+288/1403*C,20/61*m-891/1403*S-261/1403*C,20/61*m-220/1403*S-6300/1403*C]))}return{fromXyz:P,toXyz:F,fillOut:be}}e.default=D,t.exports=e.default})),Qr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=qr(),r=Math,i=r.sqrt,a=r.pow,o=r.exp,s=r.log,c=r.cos,l=r.sin,u=r.atan2,d={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function f(){var e=d[arguments.length<=0||arguments[0]===void 0?`UCS`:arguments[0]],t=e.K_L,r=e.c_1,f=e.c_2;function p(e){var t=e.J,i=e.M,a=e.h,o=n.degree.toRadian(a),u=(1+100*r)*t/(1+r*t),d=1/f*s(1+f*i);return{J_p:u,a_p:d*c(o),b_p:d*l(o)}}function m(e){var t=e.J_p,s=e.a_p,c=e.b_p,l=-t/(r*t-100*r-1),d=(o(f*i(a(s,2)+a(c,2)))-1)/f,p=u(c,s);return{J:l,M:d,h:n.degree.fromRadian(p)}}function h(e,n){return i(a((e.J_p-n.J_p)/t,2)+a(e.a_p-n.a_p,2)+a(e.b_p-n.b_p,2))}return{fromCam:p,toCam:m,distance:h}}e.default=f,t.exports=e.default})),$r=s(((e,t)=>{var n=Jr(),r=Yr(),i=Zr(),a=Qr(),o=Xr();t.exports={gamut:r,cfs:n.cfs,lerp:n.lerp,cam:i,ucs:a,hq:o}})),ei=l(qr(),1),ti=l($r(),1);function ni(e){let t=new q;return t.rgb_r=e[0],t.rgb_g=e[1],t.rgb_b=e[2],t.rgbToHsluv(),[t.hsluv_h,t.hsluv_s,t.hsluv_l]}function ri(e){let t=new q;return t.hsluv_h=e[0],t.hsluv_s=e[1],t.hsluv_l=e[2],t.hsluvToRgb(),[t.rgb_r,t.rgb_g,t.rgb_b]}var ii=ti.default.cam({whitePoint:ei.default.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ti.default.cfs(`JCh`)),ai=ei.default.xyz(ei.default.workspace.sRGB,ei.default.illuminant.D65),oi=e=>ai.toRgb(ii.toXyz({J:e[0],C:e[1],h:e[2]})),si=e=>{let t=ii.fromXyz(ai.fromRgb(e));return[t.J,t.C,t.h]},[ci,li]=(()=>{let e={k_l:1,c1:.007,c2:.0228},t=Math.PI,n=64/t/5,r=1/(5*n+1),i=.2*r**4*(5*n)+.1*(1-r**4)**2*(5*n)**(1/3);return[n=>{let[r,a,o]=n,s=a*i**.25,c=(1+100*e.c1)*r/(1+e.c1*r);c/=e.k_l;let l=1/e.c2*Math.log(1+e.c2*s),u=l*Math.cos(t/180*o),d=l*Math.sin(t/180*o);return[c,u,d]},n=>{let[r,a,o]=n,s=Math.sqrt(a*a+o*o),c=(Math.exp(s*e.c2)-1)/e.c2,l=(180/t*Math.atan2(o,a)+360)%360,u=c/i**.25;return[r/(1+e.c1*(100-r)),u,l]}]})(),ui=e=>oi(li(e)),di=e=>ci(si(e)),fi=console;fi.color=(e,t=``)=>{let n=K(e).luminance();fi.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?`#000`:`#fff`}`)},fi.ramp=(e,t=1)=>{fi.log(`%c `,`font-size: 1px;line-height: 16px;background: ${K.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};var pi=(e,t,n,r,i,a,o=.1)=>{if(e===n||t===r)return!0;let s=(r-t)/(n-e),c=(a+i/s-t+s*e)/(s+1/s),l=a+i/s-c/s;return(i-c)**2+(a-l)**2{let i=(t[0]+n[0])/2,a=e(i);return pi(...t,...n,i,a,r)?null:[i,a]},hi=(e,t,n,r=.1)=>{let i=(n-t)/10,a=[];for(let r=t;rMath.round(e*10**t)/10**t,_i=(e,t=1,n=90,r=.005)=>{let i=hi(t=>e(t).gl()[0],0,t,r),a=hi(t=>e(t).gl()[1],0,t,r),o=hi(t=>e(t).gl()[2],0,t,r);return`linear-gradient(${n}deg, ${Array.from(new Set([...i.map(e=>gi(e[0])),...a.map(e=>gi(e[0])),...o.map(e=>gi(e[0]))].sort((e,t)=>e-t))).map(t=>`${e(t).hex()} ${gi(t*100)}%`).join()});`},vi=e=>{e.Color.prototype.jch=function(){return si(this._rgb.slice(0,3).map(e=>e/255))},e.jch=(...t)=>new e.Color(...oi(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.jab=function(){return di(this._rgb.slice(0,3).map(e=>e/255))},e.jab=(...t)=>new e.Color(...ui(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.hsluv=function(){return ni(this._rgb.slice(0,3).map(e=>e/255))},e.hsluv=(...t)=>new e.Color(...ri(t).map(e=>Math.floor(e*255)),`rgb`);let t=e.interpolate,n={jch:si,jab:di,hsluv:ni},r=(e,t,n)=>(Math.abs(e-t)>360/2&&(e>t?t+=360:e+=360),((1-n)*e+n*t)%360);e.interpolate=(i,a,o=.5,s=`lrgb`)=>{if(n[s]){typeof i!=`object`&&(i=new e.Color(i)),typeof a!=`object`&&(a=new e.Color(a));let t=n[s](i.gl()),c=n[s](a.gl()),l=Number.isNaN(i.hsl()[0]),u=Number.isNaN(a.hsl()[0]),d,f,p;switch(s){case`hsluv`:t[1]<1e-10&&(t[0]=c[0]),t[1]===0&&(t[1]=c[1]),c[1]<1e-10&&(c[0]=t[0]),c[1]===0&&(c[1]=t[1]),d=r(t[0],c[0],o),f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o;break;case`jch`:l&&(t[2]=c[2]),u&&(c[2]=t[2]),d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=r(t[2],c[2],o);break;default:d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o}return e[s](d,f,p).alpha(i.alpha()+o*(a.alpha()-i.alpha()))}return t(i,a,o,s)},e.getCSSGradient=_i},X={mainTRC:2.4,get mainTRCencode(){return 1/this.mainTRC},sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1,mFactor:1.9468554433171,get mFactInv(){return 1/this.mFactor},mOffsetIn:.0387393816571401,mExpAdj:.283343396420869,get mExp(){return this.mExpAdj/this.blkClmp},mOffsetOut:.312865795870758};function yi(e,t,n=-1){let r=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)r[1])return 0;let i=0,a=0,o=`BoW`;return e=e>X.blkThrs?e:e+(X.blkThrs-e)**+X.blkClmp,t=t>X.blkThrs?t:t+(X.blkThrs-t)**+X.blkClmp,Math.abs(t-e)e?(i=(t**+X.normBG-e**+X.normTXT)*X.scaleBoW,a=i-X.loClip?0:i+X.loWoBoffset),n<0?a*100:n==0?Math.round(Math.abs(a)*100)+``+o+``:Number.isInteger(n)?(a*100).toFixed(n):0)}function bi(e=[0,0,0]){function t(e){return(e/255)**X.mainTRC}return X.sRco*t(e[0])+X.sGco*t(e[1])+X.sBco*t(e[2])}var xi=(e,t,n,r,i,a,o,s,c)=>{let l=1-c,u=l*l,d=u*l,f=c*c*c;return{x:d*e+u*3*c*n+l*3*c*c*i+f*o,y:d*t+u*3*c*r+l*3*c*c*a+f*s}},Si=(e,t)=>{let n=[],r={x:+e[0],y:+e[1]};for(let i=0,a=e.length;a-2*!t>i;i+=2){let o=[{x:+e[i-2],y:+e[i-1]},{x:+e[i],y:+e[i+1]},{x:+e[i+2],y:+e[i+3]},{x:+e[i+4],y:+e[i+5]}];t?i?a-4===i?o[3]={x:+e[0],y:+e[1]}:a-2===i&&(o[2]={x:+e[0],y:+e[1]},o[3]={x:+e[2],y:+e[3]}):o[0]={x:+e[a-2],y:+e[a-1]}:a-4===i?o[3]=o[2]:i||(o[0]={x:+e[i],y:+e[i+1]}),n.push([r.x,r.y,(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y]),r=o[2]}return n},Ci=(e,t,n,r,i,a,o,s)=>{let c=e,l=t,u=0;for(let d=1;d<5;d++){let{x:f,y:p}=xi(e,t,n,r,i,a,o,s,d/5);u+=Math.hypot(f-c,p-l),c=f,l=p}return u+=Math.hypot(o-c,s-l),u},wi=(e,t,n,r,i,a,o,s)=>{let c=Math.floor(Ci(e,t,n,r,i,a,o,s)*.75),l=[],u=0;for(let d=0;d<=c;d++){let f=xi(e,t,n,r,i,a,o,s,d/c),p=Math.round(f.x);if(l[p]=f.y,p-u>1){let e=l[u],t=l[p];for(let n=u+1;nl[Math.round(e)]||null},Ti={CAM02:`jab`,CAM02p:`jch`,HEX:`hex`,HSL:`hsl`,HSLuv:`hsluv`,HSV:`hsv`,LAB:`lab`,LCH:`lch`,RGB:`rgb`,OKLAB:`oklab`,OKLCH:`oklch`};function Z(e,t=0){let n=10**t;return Math.round(e*n)/n}function Ei(e,t){let n;return n=e>1?(e-1)*t+1:e<-1?(e+1)*t-1:1,Z(n,2)}function Di(e){return K(String(e)).jch()}function Oi(e){return K(String(e)).hsluv()}function ki(e,t,n){let r=[[],[],[]];if(e.forEach((e,n)=>r.forEach((r,i)=>r.push(t[n],e[i]))),n===`hcl`){let e=r[1];for(let t=1;t{let t=[];for(let n=1;n{e[t]=e[n]}),t.length=0;break}if(t.length){let n=K(`#ccc`).jch()[2];t.forEach(t=>{e[t]=n})}t.length=0;for(let n=e.length-1;n>0;n-=2)if(Number.isNaN(e[n]))t.push(n);else{t.forEach(t=>{e[t]=e[n]});break}for(let t=1;tSi(e).map(e=>wi(...e)));return e=>{let t=i.map(t=>{for(let n=0;nr*t**e+i}function ji({swatches:e,colorKeys:t,colorspace:n,colorSpace:r=n??`LAB`,shift:i=1,fullScale:a=!0,smooth:o=!1,distributeLightness:s=`linear`,sortColor:c=!0,asFun:l=!1}={}){n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead.");let u=Ti[r];if(!u)throw Error(`Colorspace “${r}” not supported`);if(!t)throw Error(`Colorkeys missing: returned “${t}”`);let d;if(a)d=t.map(t=>e-e*(K(t).jch()[0]/100)).sort((e,t)=>e-t).concat(e),d.unshift(0);else{let n=t.map(e=>K(e).jch()[0]/100),r=Math.min(...n),i=Math.max(...n);d=n.map(t=>t===0||isNaN((t-r)/(i-r))?0:e-(t-r)/(i-r)*e).sort((e,t)=>e-t)}let f=Ai(i,[1,e],[1,e]);if(f=d.map(e=>Math.max(0,f(e))),d=f,s===`polynomial`){let t=e=>Math.sqrt(Math.sqrt((e**2.25+e**4)/2));d=f.map(t=>t/e).map(n=>t(n)*e)}let p=t.map((e,t)=>({colorKeys:Di(e),index:t})).sort((e,t)=>t.colorKeys[0]-e.colorKeys[0]).map(e=>t[e.index]),m=[],h;if(a){let e=u===`lch`?K.lch(...K(`#fff`).lch()):`#ffffff`,t=u===`lch`?K.lch(...K(`#000`).lch()):`#000000`;m=[e,...p,t]}else m=c?p:t;let g;if(o){let t=m;if(m=m.map(e=>K(String(e))[u]()),u===`hcl`&&m.forEach(e=>{e[1]=Number.isNaN(e[1])?0:e[1]}),u===`jch`)for(let e=0;eh(t))}else h=K.scale(m.map(e=>typeof e==`object`&&e.constructor===K.Color?e:String(e))).domain(d).mode(u);return l?h:(!o||o===!1?h.colors(e):g).filter(e=>e!=null)}function Mi(e,t){let n=[],r={};return Object.keys(e).forEach(n=>{r[e[n][t]]=e[n]}),Object.keys(r).forEach(e=>n.push(r[e])),n}function Ni(e){return Number.isNaN(e)?0:e}function Pi(e,t,n=!1){if(!e)throw Error(`Cannot convert color value of “${e}”`);if(!Ti[t])throw Error(`Cannot convert to colorspace “${t}”`);let r=Ti[t],i=K(String(e))[r]();if(t===`HSL`&&i.pop(),t===`HEX`){if(n){let t=K(String(e)).rgb();return{r:t[0],g:t[1],b:t[2]}}return i}let a={},o=i.map(Ni);o=o.map((e,t)=>{let i=Z(e),o=t;r===`hsluv`&&(o+=2);let s=r.charAt(o);return r===`jch`&&s===`c`&&(s=`C`),a[s===`j`?`J`:s]=i,r in{lab:1,lch:1,jab:1,jch:1}?n||(s===`l`||s===`j`)&&(i+=`%`):r!==`hsluv`&&(s===`s`||s===`l`||s===`v`)&&(a[s]=Z(e,2),n||(i=Z(e*100),i+=`%`)),i});let s=`${r}(${o.join(`, `)})`;return n?a:s}function Fi(e,t,n){let r=[e,t,n].map(e=>(e/=255,e<=.03928?e/12.92:((e+.055)/1.055)**2.4));return r[0]*.2126+r[1]*.7152+r[2]*.0722}function Ii(e,t,n,r=`wcag2`){if(n===void 0){let e=K.rgb(...t).hsluv()[2];n=Z(e/100,2)}if(r===`wcag2`){let r=Fi(e[0],e[1],e[2]),i=Fi(t[0],t[1],t[2]),a=(r+.05)/(i+.05),o=(i+.05)/(r+.05);return n<.5?a>=1?a:-o:a<1?o:a===1?a:-a}else if(r===`wcag3`)return n<.5?yi(bi(e),bi(t))*-1:yi(bi(e),bi(t));else throw Error(`Contrast calculation method ${r} unsupported; use 'wcag2' or 'wcag3'`)}function Li(e,t){if(!e)throw Error(`Array undefined`);if(!Array.isArray(e))throw Error(`Passed object is not an array`);let n=t===`wcag2`?0:1;return Math.min(...e.filter(e=>e>=n))}function Ri(e,t){if(!e)throw Error(`Ratios undefined`);e=e.sort((e,t)=>e-t);let n=Li(e,t),r=e.indexOf(n),i=[],a=e.slice(0,r),o=e.slice(r,e.length);for(let e=0;ee-t),i}var zi=(e,t,n,r,i)=>{let a=3e3,o=ji({swatches:a,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),s={},c=e=>{if(s[e])return s[e];let r=Ii(K(o(e)).rgb(),t,n,i);return s[e]=r,r},l=e=>{let t=c(0).01&&o;)o--,n/=2,iu.push(o(l(+e)))),u},Q=class{constructor({name:e,colorKeys:t,colorspace:n,colorSpace:r=n??`RGB`,ratios:i,smooth:a=!1,output:o=`HEX`,saturation:s=100}){if(n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),this._name=e,this._colorKeys=t,this._modifiedKeys=t,this._colorspace=r,this._ratios=i,this._smooth=a,this._output=o,this._saturation=s,!this._name)throw Error(`Color missing name`);if(!this._colorKeys)throw Error(`Color Keys are undefined`);if(!Ti[this._colorspace])throw Error(`Colorspace “${r}” not supported`);if(!Ti[this._output])throw Error(`Output “${this._output}” not supported`);for(let e=0;e{let n=K(`${t}`).oklch(),r=n[1]*(this._saturation/100),i=K.oklch(n[0],r,n[2]),a=K.rgb(i).hex();e.push(a)}),this._modifiedKeys=e,this._generateColorScale()}_generateColorScale(){this._colorScale=ji({swatches:3e3,colorKeys:this._modifiedKeys,colorSpace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}},Bi=class extends Q{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){Q.prototype._generateColorScale.call(this);let e=ji({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});e.push(...this.colorKeys);let t=Mi(e.map((e,t)=>({value:Math.round(Oi(e)[2]),index:t})),`value`).map(t=>e[t.index]);return t.length>=101&&(t.length=100,t.push(`#ffffff`)),this._backgroundColorScale=t.map(e=>Pi(e,this._output)),this._backgroundColorScale}},Vi=class{constructor({colors:e,backgroundColor:t,lightness:n,contrast:r=1,saturation:i=100,output:a=`HEX`,formula:o=`wcag2`}){if(this._output=a,this._colors=e,this._lightness=n,this._saturation=i,this._formula=o,this._setBackgroundColor(t),this._setBackgroundColorValue(),this._contrast=r,!this._colors)throw Error(`No colors are defined`);if(!this._backgroundColor)throw Error(`Background color is undefined`);if(e.forEach(e=>{if(!e.ratios)throw Error(`Color ${e.name}'s ratios are undefined`)}),!Ti[this._output])throw Error(`Output “${a}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(e){this._formula=e,this._findContrastColors()}get formula(){return this._formula}set contrast(e){this._contrast=e,this._findContrastColors()}get contrast(){return this._contrast}set lightness(e){this._lightness=e,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(e){this._saturation=e,this._updateColorSaturation(e),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(e){this._setBackgroundColor(e),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(e){this._colors=e,this._findContrastColors()}get colors(){return this._colors}set addColor(e){this._colors.push(e),this._findContrastColors()}set removeColor(e){this._colors=this._colors.filter(t=>t.name!==e.name),this._findContrastColors()}set updateColor(e){if(Array.isArray(e))for(let t=0;tn.name===e[t].color);n=n[0];let r=this._colors.indexOf(n),i=this._colors.filter(n=>n.name!==e[t].color);e[t].name&&(n.name=e[t].name),e[t].colorKeys&&(n.colorKeys=e[t].colorKeys),e[t].ratios&&(n.ratios=e[t].ratios),(e[t].colorSpace!==void 0||e[t].colorspace!==void 0)&&(e[t].colorspace!==void 0&&e[t].colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),n.colorSpace=e[t].colorSpace??e[t].colorspace),e[t].smooth&&(n.smooth=e[t].smooth),n._generateColorScale(),i.splice(r,0,n),this._colors=i}else{let t=this._colors.filter(t=>t.name===e.color);t=t[0];let n=this._colors.indexOf(t),r=this._colors.filter(t=>t.name!==e.color);e.name&&(t.name=e.name),e.colorKeys&&(t.colorKeys=e.colorKeys),e.ratios&&(t.ratios=e.ratios),(e.colorSpace!==void 0||e.colorspace!==void 0)&&(e.colorspace!==void 0&&e.colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),t.colorSpace=e.colorSpace??e.colorspace),e.smooth&&(t.smooth=e.smooth),t._generateColorScale(),r.splice(n,0,t),this._colors=r}this._findContrastColors()}set output(e){this._output=e,this._colors.forEach(e=>{e.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(e){if(typeof e==`string`){let t=new Bi({name:`background`,colorKeys:[e],output:`RGB`}),n=Z(K(String(e)).hsluv()[2]);this._backgroundColor=t,this._lightness=n,this._backgroundColorValue=t[this._lightness]}else{e.output=`RGB`;let t=e.backgroundColorScale[this._lightness];this._backgroundColor=e,this._backgroundColorValue=t}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(e){this._colors.map(t=>{t.saturation=e})}_findContrastColors(){let e=K(String(this._backgroundColorValue)).rgb(),t=this._lightness/100,n={background:Pi(this._backgroundColorValue,this._output)},r=[],i=[],a={...n};return r.push(n),this._colors.map(n=>{if(n.ratios!==void 0){let o,s=[],c={name:n.name,values:s},l;Array.isArray(n.ratios)?l=n.ratios:Array.isArray(n.ratios)||(o=Object.keys(n.ratios),l=Object.values(n.ratios)),l=l.map(e=>Ei(+e,this._contrast));let u=zi(n,e,t,l,this._formula).map(e=>Pi(e,this._output));for(let e=0;e{let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},Wi=(e,t,n)=>{let r=e/255,i=t/255,a=n/255,o=Math.min(r,i,a),s=Math.max(r,i,a),c=s-o,l=0,u=0,d=0;return l=c===0?0:s===r?(i-a)/c%6:s===i?(a-r)/c+2:(r-i)/c+4,l=Math.round(l*60),l<0&&(l+=360),d=(s+o)/2,u=c===0?0:c/(1-Math.abs(2*d-1)),u=+(u*100).toFixed(1),d=+(d*100).toFixed(1),[l,u,Math.round(d)]},Gi=(e,t,n,r)=>{let i=n/100,a=t*Math.min(i,1-i)/100,o=t=>{let n=(t+e/30)%12,r=i-a*Math.max(Math.min(n-3,9-n,1),-1);return Math.round(255*r).toString(16).padStart(2,`0`).toUpperCase()},s=o(0),c=o(8),l=o(4),u=((e,t,n)=>Math.min(Math.max(e,t),n))(r,0,1);return`#${s}${c}${l}${Math.round(u*255).toString(16).padStart(2,`0`).toUpperCase()}`},Ki=(e,t,n=1)=>{let r=Ui(e),i=Ui(t===`white`?`#FFFFFF`:t===`black`?`#000000`:t),a=r.map((e,t)=>[(e-i[t])/(255-i[t]),(e-i[t])/(0-i[t])]),o=Hi(Math.max(...a.flat().filter(e=>/^-?\d+\.?\d*$/.test(e)))),s=r.map((e,t)=>Math.round((e-i[t]+i[t]*o)/o));if(s.includes(NaN)){let e=Wi(r[0],r[1],r[2]);return{h:e[0],s:Math.round(e[1]*n),l:e[2],a:1}}let c=Wi(s[0],s[1],s[2]);return{h:c[0],s:Math.round(c[1]*n),l:c[2],a:o}},qi={backgroundColor:`gray`,colorSpace:`OKLCH`,colorSmoothing:!1,formula:`wcag2`,output:`HEX`,colors:{gray:[$(215,20,90),$(215,8,50),$(215,6,25)],red:[$(358,100,58),$(350,100,30)],orange:[$(32,100,48),$(12,100,30)],yellow:[$(50,100,50),$(25,100,20)],lime:[$(100,68,50),$(115,86,25)],green:[$(163,87,42),$(168,100,25)],cyan:[$(185,80,45),$(200,98,35)],blue:[$(212,98,46),$(222,95,25)],purple:[$(258,94,64),$(265,100,35)],fuchsia:[$(295,56,50),$(285,80,25)],pink:[$(334,90,50),$(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function $(e,t,n){return K.hsl(e,t/100,n/100).hex()}function Ji(e,t){let n=e.colorSpace,r=e.colorSmoothing,i=e.themes[t].ratios,a=new Bi({name:`gray`,colorKeys:e.colors.gray,colorspace:n,ratios:i,smooth:r}),o=new Q({name:`blue`,colorKeys:e.colors.blue,colorspace:n,ratios:i,smooth:r}),s=new Q({name:`cyan`,colorKeys:e.colors.cyan,colorspace:n,ratios:i,smooth:r}),c=new Q({name:`fuchsia`,colorKeys:e.colors.fuchsia,colorspace:n,ratios:i,smooth:r}),l=new Q({name:`green`,colorKeys:e.colors.green,colorspace:n,ratios:i,smooth:r}),u=new Q({name:`lime`,colorKeys:e.colors.lime,colorspace:n,ratios:i,smooth:r}),d=new Q({name:`orange`,colorKeys:e.colors.orange,colorspace:n,ratios:i,smooth:r}),f=new Q({name:`pink`,colorKeys:e.colors.pink,colorspace:n,ratios:i,smooth:r}),p=new Q({name:`purple`,colorKeys:e.colors.purple,colorspace:n,ratios:i,smooth:r}),m={gray:a,red:new Q({name:`red`,colorKeys:e.colors.red,colorspace:n,ratios:i,smooth:r}),orange:d,yellow:new Q({name:`yellow`,colorKeys:e.colors.yellow,colorspace:n,ratios:i,smooth:r}),lime:u,green:l,cyan:s,blue:o,purple:p,fuchsia:c,pink:f};return e.colors.custom&&(m.custom=new Q({name:`custom`,colorKeys:e.colors.custom,colorspace:n,ratios:i,smooth:r})),new Vi({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function Yi(e){let t={};for(let n of Object.keys(e.themes))t[n]=Ji(e,n);return t}function Xi(e){qi.colors.custom=[e];let t=Yi(qi);return Object.fromEntries(Object.entries(t).map(([e,t])=>{let n=t.find(e=>e&&e.name===`custom`),r=Object.fromEntries(n.values.map(({name:e,value:t})=>[e,t]));for(let[e,n]of Object.entries(r)){let i=Ki(n,t[0].background);r[`alpha${e.charAt(0).toUpperCase()+e.slice(1)}`]=Gi(i.h,i.s,i.l,i.a)}return[e,r]}))}return e.generateCustomColors=Xi,e.generateThemesJson=Yi,e.hslToHex=$,e.leonardoConfig=qi,e})({}); \ No newline at end of file +var CompoundTheme=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},l=(e,r,i)=>(i=e==null?{}:t(a(e)),c(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),{min:u,max:d}=Math,f=(e,t=0,n=1)=>u(d(t,e),n),p=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=f(e[t],0,255)):t===3&&(e[t]=f(e[t],0,1));return e},m={};for(let e of[`Boolean`,`Number`,`String`,`Function`,`Array`,`Date`,`RegExp`,`Undefined`,`Null`])m[`[object ${e}]`]=e.toLowerCase();function h(e){return m[Object.prototype.toString.call(e)]||`object`}var g=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):h(e[0])==`object`&&t?t.split(``).filter(t=>e[0][t]!==void 0).map(t=>e[0][t]):e[0].slice(0),_=e=>{if(e.length<2)return null;let t=e.length-1;return h(e[t])==`string`?e[t].toLowerCase():null},{PI:v,min:y,max:b}=Math,x=e=>Math.round(e*100)/100,S=e=>Math.round(e*100)/100,C=v*2,w=v/3,T=v/180,ee=180/v;function E(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}var D={format:{},autodetect:[]},O=class{constructor(...e){let t=this;if(h(e[0])===`object`&&e[0].constructor&&e[0].constructor===this.constructor)return e[0];let n=_(e),r=!1;if(!n){r=!0,D.sorted||=(D.autodetect=D.autodetect.sort((e,t)=>t.p-e.p),!0);for(let t of D.autodetect)if(n=t.test(...e),n)break}if(D.format[n])t._rgb=p(D.format[n].apply(null,r?e:e.slice(0,-1)));else throw Error(`unknown format: `+e);t._rgb.length===3&&t._rgb.push(1)}toString(){return h(this.hex)==`function`?this.hex():`[${this._rgb.join(`,`)}]`}},te=`3.2.0`,k=(...e)=>new O(...e);k.version=te;var A={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,laserlemon:`#ffff54`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrod:`#fafad2`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,maroon2:`#7f0000`,maroon3:`#b03060`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,purple2:`#7f007f`,purple3:`#a020f0`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`},ne=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,re=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,ie=e=>{if(e.match(ne)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);let t=parseInt(e,16);return[t>>16,t>>8&255,t&255,1]}if(e.match(re)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);let t=parseInt(e,16);return[t>>24&255,t>>16&255,t>>8&255,Math.round((t&255)/255*100)/100]}throw Error(`unknown hex color: ${e}`)},{round:ae}=Math,oe=(...e)=>{let[t,n,r,i]=g(e,`rgba`),a=_(e)||`auto`;i===void 0&&(i=1),a===`auto`&&(a=i<1?`rgba`:`rgb`),t=ae(t),n=ae(n),r=ae(r);let o=`000000`+(t<<16|n<<8|r).toString(16);o=o.substr(o.length-6);let s=`0`+ae(i*255).toString(16);switch(s=s.substr(s.length-2),a.toLowerCase()){case`rgba`:return`#${o}${s}`;case`argb`:return`#${s}${o}`;default:return`#${o}`}};O.prototype.name=function(){let e=oe(this._rgb,`rgb`);for(let t of Object.keys(A))if(A[t]===e)return t.toLowerCase();return e},D.format.named=e=>{if(e=e.toLowerCase(),A[e])return ie(A[e]);throw Error(`unknown color name: `+e)},D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&A[e.toLowerCase()])return`named`}}),O.prototype.alpha=function(e,t=!1){return e!==void 0&&h(e)===`number`?t?(this._rgb[3]=e,this):new O([this._rgb[0],this._rgb[1],this._rgb[2],e],`rgb`):this._rgb[3]},O.prototype.clipped=function(){return this._rgb._clipped||!1};var j={Kn:18,labWhitePoint:`d65`,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},se=new Map([[`a`,[1.0985,.35585]],[`b`,[1.0985,.35585]],[`c`,[.98074,1.18232]],[`d50`,[.96422,.82521]],[`d55`,[.95682,.92149]],[`d65`,[.95047,1.08883]],[`e`,[1,1,1]],[`f2`,[.99186,.67393]],[`f7`,[.95041,1.08747]],[`f11`,[1.00962,.6435]],[`icc`,[.96422,.82521]]]);function M(e){let t=se.get(String(e).toLowerCase());if(!t)throw Error(`unknown Lab illuminant `+e);j.labWhitePoint=e,j.Xn=t[0],j.Zn=t[1]}function ce(){return j.labWhitePoint}var N=(...e)=>{e=g(e,`lab`);let[t,n,r]=e,[i,a,o]=le(t,n,r),[s,c,l]=de(i,a,o);return[s,c,l,e.length>3?e[3]:1]},le=(e,t,n)=>{let{kE:r,kK:i,kKE:a,Xn:o,Yn:s,Zn:c}=j,l=(e+16)/116,u=.002*t+l,d=l-.005*n,f=u*u*u,p=d*d*d,m=f>r?f:(116*u-16)/i,h=e>a?((e+16)/116)**3:e/i,g=p>r?p:(116*d-16)/i;return[m*o,h*s,g*c]},ue=e=>{let t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*e**(1/2.4)-.055)*t},de=(e,t,n)=>{let{MtxAdaptMa:r,MtxAdaptMaI:i,MtxXYZ2RGB:a,RefWhiteRGB:o,Xn:s,Yn:c,Zn:l}=j,u=s*r.m00+c*r.m10+l*r.m20,d=s*r.m01+c*r.m11+l*r.m21,f=s*r.m02+c*r.m12+l*r.m22,p=o.X*r.m00+o.Y*r.m10+o.Z*r.m20,m=o.X*r.m01+o.Y*r.m11+o.Z*r.m21,h=o.X*r.m02+o.Y*r.m12+o.Z*r.m22,g=(e*r.m00+t*r.m10+n*r.m20)*(p/u),_=(e*r.m01+t*r.m11+n*r.m21)*(m/d),v=(e*r.m02+t*r.m12+n*r.m22)*(h/f),y=g*i.m00+_*i.m10+v*i.m20,b=g*i.m01+_*i.m11+v*i.m21,x=g*i.m02+_*i.m12+v*i.m22,S=ue(y*a.m00+b*a.m10+x*a.m20),C=ue(y*a.m01+b*a.m11+x*a.m21),w=ue(y*a.m02+b*a.m12+x*a.m22);return[S*255,C*255,w*255]},fe=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=he(t,n,r),[c,l,u]=pe(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function pe(e,t,n){let{Xn:r,Yn:i,Zn:a,kE:o,kK:s}=j,c=e/r,l=t/i,u=n/a,d=c>o?c**(1/3):(s*c+16)/116,f=l>o?l**(1/3):(s*l+16)/116,p=u>o?u**(1/3):(s*u+16)/116;return[116*f-16,500*(d-f),200*(f-p)]}function me(e){let t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:((e+.055)/1.055)**2.4)*t}var he=(e,t,n)=>{e=me(e/255),t=me(t/255),n=me(n/255);let{MtxRGB2XYZ:r,MtxAdaptMa:i,MtxAdaptMaI:a,Xn:o,Yn:s,Zn:c,As:l,Bs:u,Cs:d}=j,f=e*r.m00+t*r.m10+n*r.m20,p=e*r.m01+t*r.m11+n*r.m21,m=e*r.m02+t*r.m12+n*r.m22,h=o*i.m00+s*i.m10+c*i.m20,g=o*i.m01+s*i.m11+c*i.m21,_=o*i.m02+s*i.m12+c*i.m22,v=f*i.m00+p*i.m10+m*i.m20,y=f*i.m01+p*i.m11+m*i.m21,b=f*i.m02+p*i.m12+m*i.m22;return v*=h/l,y*=g/u,b*=_/d,f=v*a.m00+y*a.m10+b*a.m20,p=v*a.m01+y*a.m11+b*a.m21,m=v*a.m02+y*a.m12+b*a.m22,[f,p,m]};O.prototype.lab=function(){return fe(this._rgb)},Object.assign(k,{lab:(...e)=>new O(...e,`lab`),getLabWhitePoint:ce,setLabWhitePoint:M}),D.format.lab=N,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`lab`),h(e)===`array`&&e.length===3)return`lab`}}),O.prototype.darken=function(e=1){let t=this,n=t.lab();return n[0]-=j.Kn*e,new O(n,`lab`).alpha(t.alpha(),!0)},O.prototype.brighten=function(e=1){return this.darken(-e)},O.prototype.darker=O.prototype.darken,O.prototype.brighter=O.prototype.brighten,O.prototype.get=function(e){let[t,n]=e.split(`.`),r=this[t]();if(n){let e=t.indexOf(n)-(t.substr(0,2)===`ok`?2:0);if(e>-1)return r[e];throw Error(`unknown channel ${n} in mode ${t}`)}else return r};var{pow:ge}=Math,_e=1e-7,ve=20;O.prototype.luminance=function(e,t=`rgb`){if(e!==void 0&&h(e)===`number`){if(e===0)return new O([0,0,0,this._rgb[3]],`rgb`);if(e===1)return new O([255,255,255,this._rgb[3]],`rgb`);let n=this.luminance(),r=ve,i=(n,a)=>{let o=n.interpolate(a,.5,t),s=o.luminance();return Math.abs(e-s)<_e||!r--?o:s>e?i(n,o):i(o,a)};return new O([...(n>e?i(new O([0,0,0]),this):i(this,new O([255,255,255]))).rgb(),this._rgb[3]])}return ye(...this._rgb.slice(0,3))};var ye=(e,t,n)=>(e=be(e),t=be(t),n=be(n),.2126*e+.7152*t+.0722*n),be=e=>(e/=255,e<=.03928?e/12.92:ge((e+.055)/1.055,2.4)),P={},F=(e,t,n=.5,...r)=>{let i=r[0]||`lrgb`;if(!P[i]&&!r.length&&(i=Object.keys(P)[0]),!P[i])throw Error(`interpolation mode ${i} is not defined`);return h(e)!==`object`&&(e=new O(e)),h(t)!==`object`&&(t=new O(t)),P[i](e,t,n).alpha(e.alpha()+n*(t.alpha()-e.alpha()))};O.prototype.mix=O.prototype.interpolate=function(e,t=.5,...n){return F(this,e,t,...n)},O.prototype.premultiply=function(e=!1){let t=this._rgb,n=t[3];return e?(this._rgb=[t[0]*n,t[1]*n,t[2]*n,n],this):new O([t[0]*n,t[1]*n,t[2]*n,n],`rgb`)};var{sin:xe,cos:Se}=Math,Ce=(...e)=>{let[t,n,r]=g(e,`lch`);return isNaN(r)&&(r=0),r*=T,[t,Se(r)*n,xe(r)*n]},we=(...e)=>{e=g(e,`lch`);let[t,n,r]=e,[i,a,o]=Ce(t,n,r),[s,c,l]=N(i,a,o);return[s,c,l,e.length>3?e[3]:1]},Te=(...e)=>we(...E(g(e,`hcl`))),{sqrt:Ee,atan2:De,round:Oe}=Math,ke=(...e)=>{let[t,n,r]=g(e,`lab`),i=Ee(n*n+r*r),a=(De(r,n)*ee+360)%360;return Oe(i*1e4)===0&&(a=NaN),[t,i,a]},Ae=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=fe(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};O.prototype.lch=function(){return Ae(this._rgb)},O.prototype.hcl=function(){return E(Ae(this._rgb))},Object.assign(k,{lch:(...e)=>new O(...e,`lch`),hcl:(...e)=>new O(...e,`hcl`)}),D.format.lch=we,D.format.hcl=Te,[`lch`,`hcl`].forEach(e=>D.autodetect.push({p:2,test:(...t)=>{if(t=g(t,e),h(t)===`array`&&t.length===3)return e}})),O.prototype.saturate=function(e=1){let t=this,n=t.lch();return n[1]+=j.Kn*e,n[1]<0&&(n[1]=0),new O(n,`lch`).alpha(t.alpha(),!0)},O.prototype.desaturate=function(e=1){return this.saturate(-e)},O.prototype.set=function(e,t,n=!1){let[r,i]=e.split(`.`),a=this[r]();if(i){let e=r.indexOf(i)-(r.substr(0,2)===`ok`?2:0);if(e>-1){if(h(t)==`string`)switch(t.charAt(0)){case`+`:a[e]+=+t;break;case`-`:a[e]+=+t;break;case`*`:a[e]*=+t.substr(1);break;case`/`:a[e]/=+t.substr(1);break;default:a[e]=+t}else if(h(t)===`number`)a[e]=t;else throw Error(`unsupported value for Color.set`);let i=new O(a,r);return n?(this._rgb=i._rgb,this):i}throw Error(`unknown channel ${i} in mode ${r}`)}else return a},O.prototype.tint=function(e=.5,...t){return F(this,`white`,e,...t)},O.prototype.shade=function(e=.5,...t){return F(this,`black`,e,...t)},P.rgb=(e,t,n)=>{let r=e._rgb,i=t._rgb;return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`rgb`)};var{sqrt:je,pow:Me}=Math;P.lrgb=(e,t,n)=>{let[r,i,a]=e._rgb,[o,s,c]=t._rgb;return new O(je(Me(r,2)*(1-n)+Me(o,2)*n),je(Me(i,2)*(1-n)+Me(s,2)*n),je(Me(a,2)*(1-n)+Me(c,2)*n),`rgb`)},P.lab=(e,t,n)=>{let r=e.lab(),i=t.lab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`lab`)};var Ne=(e,t,n,r)=>{let i,a;r===`hsl`?(i=e.hsl(),a=t.hsl()):r===`hsv`?(i=e.hsv(),a=t.hsv()):r===`hcg`?(i=e.hcg(),a=t.hcg()):r===`hsi`?(i=e.hsi(),a=t.hsi()):r===`lch`||r===`hcl`?(r=`hcl`,i=e.hcl(),a=t.hcl()):r===`oklch`&&(i=e.oklch().reverse(),a=t.oklch().reverse());let o,s,c,l,u,d;(r.substr(0,1)===`h`||r===`oklch`)&&([o,c,u]=i,[s,l,d]=a);let f,p,m,h;return!isNaN(o)&&!isNaN(s)?(h=s>o&&s-o>180?s-(o+360):s180?s+360-o:s-o,p=o+n*h):isNaN(o)?isNaN(s)?p=NaN:(p=s,(u==1||u==0)&&r!=`hsv`&&(f=l)):(p=o,(d==1||d==0)&&r!=`hsv`&&(f=c)),f===void 0&&(f=c+n*(l-c)),m=u+n*(d-u),r===`oklch`?new O([m,f,p],r):new O([p,f,m],r)},Pe=(e,t,n)=>Ne(e,t,n,`lch`);P.lch=Pe,P.hcl=Pe;var Fe=e=>{if(h(e)==`number`&&e>=0&&e<=16777215)return[e>>16,e>>8&255,e&255,1];throw Error(`unknown num color: `+e)},Ie=(...e)=>{let[t,n,r]=g(e,`rgb`);return(t<<16)+(n<<8)+r};O.prototype.num=function(){return Ie(this._rgb)},Object.assign(k,{num:(...e)=>new O(...e,`num`)}),D.format.num=Fe,D.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&h(e[0])===`number`&&e[0]>=0&&e[0]<=16777215)return`num`}}),P.num=(e,t,n)=>{let r=e.num();return new O(r+n*(t.num()-r),`num`)};var{floor:Le}=Math,Re=(...e)=>{e=g(e,`hcg`);let[t,n,r]=e,i,a,o;r*=255;let s=n*255;if(n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Le(t),c=t-e,l=r*(1-n),u=l+s*(1-c),d=l+s*c,f=l+s;switch(e){case 0:[i,a,o]=[f,d,l];break;case 1:[i,a,o]=[u,f,l];break;case 2:[i,a,o]=[l,f,d];break;case 3:[i,a,o]=[l,u,f];break;case 4:[i,a,o]=[d,l,f];break;case 5:[i,a,o]=[f,l,u];break}}return[i,a,o,e.length>3?e[3]:1]},ze=(...e)=>{let[t,n,r]=g(e,`rgb`),i=y(t,n,r),a=b(t,n,r),o=a-i,s=o*100/255,c=i/(255-o)*100,l;return o===0?l=NaN:(t===a&&(l=(n-r)/o),n===a&&(l=2+(r-t)/o),r===a&&(l=4+(t-n)/o),l*=60,l<0&&(l+=360)),[l,s,c]};O.prototype.hcg=function(){return ze(this._rgb)},k.hcg=(...e)=>new O(...e,`hcg`),D.format.hcg=Re,D.autodetect.push({p:1,test:(...e)=>{if(e=g(e,`hcg`),h(e)===`array`&&e.length===3)return`hcg`}}),P.hcg=(e,t,n)=>Ne(e,t,n,`hcg`);var{cos:Be}=Math,Ve=(...e)=>{e=g(e,`hsi`);let[t,n,r]=e,i,a,o;return isNaN(t)&&(t=0),isNaN(n)&&(n=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(o=(1-n)/3,i=(1+n*Be(C*t)/Be(w-C*t))/3,a=1-(o+i)):t<2/3?(t-=1/3,i=(1-n)/3,a=(1+n*Be(C*t)/Be(w-C*t))/3,o=1-(i+a)):(t-=2/3,a=(1-n)/3,o=(1+n*Be(C*t)/Be(w-C*t))/3,i=1-(a+o)),i=f(r*i*3),a=f(r*a*3),o=f(r*o*3),[i*255,a*255,o*255,e.length>3?e[3]:1]},{min:He,sqrt:Ue,acos:We}=Math,Ge=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i,a=He(t,n,r),o=(t+n+r)/3,s=o>0?1-a/o:0;return s===0?i=NaN:(i=(t-n+(t-r))/2,i/=Ue((t-n)*(t-n)+(t-r)*(n-r)),i=We(i),r>n&&(i=C-i),i/=C),[i*360,s,o]};O.prototype.hsi=function(){return Ge(this._rgb)},k.hsi=(...e)=>new O(...e,`hsi`),D.format.hsi=Ve,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsi`),h(e)===`array`&&e.length===3)return`hsi`}}),P.hsi=(e,t,n)=>Ne(e,t,n,`hsi`);var Ke=(...e)=>{e=g(e,`hsl`);let[t,n,r]=e,i,a,o;if(n===0)i=a=o=r*255;else{let e=[0,0,0],s=[0,0,0],c=r<.5?r*(1+n):r+n-r*n,l=2*r-c,u=t/360;e[0]=u+1/3,e[1]=u,e[2]=u-1/3;for(let t=0;t<3;t++)e[t]<0&&(e[t]+=1),e[t]>1&&--e[t],6*e[t]<1?s[t]=l+(c-l)*6*e[t]:2*e[t]<1?s[t]=c:3*e[t]<2?s[t]=l+(c-l)*(2/3-e[t])*6:s[t]=l;[i,a,o]=[s[0]*255,s[1]*255,s[2]*255]}return e.length>3?[i,a,o,e[3]]:[i,a,o,1]},qe=(...e)=>{e=g(e,`rgba`);let[t,n,r]=e;t/=255,n/=255,r/=255;let i=y(t,n,r),a=b(t,n,r),o=(a+i)/2,s,c;return a===i?(s=0,c=NaN):s=o<.5?(a-i)/(a+i):(a-i)/(2-a-i),t==a?c=(n-r)/(a-i):n==a?c=2+(r-t)/(a-i):r==a&&(c=4+(t-n)/(a-i)),c*=60,c<0&&(c+=360),e.length>3&&e[3]!==void 0?[c,s,o,e[3]]:[c,s,o]};O.prototype.hsl=function(){return qe(this._rgb)},k.hsl=(...e)=>new O(...e,`hsl`),D.format.hsl=Ke,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsl`),h(e)===`array`&&e.length===3)return`hsl`}}),P.hsl=(e,t,n)=>Ne(e,t,n,`hsl`);var{floor:Je}=Math,Ye=(...e)=>{e=g(e,`hsv`);let[t,n,r]=e,i,a,o;if(r*=255,n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Je(t),s=t-e,c=r*(1-n),l=r*(1-n*s),u=r*(1-n*(1-s));switch(e){case 0:[i,a,o]=[r,u,c];break;case 1:[i,a,o]=[l,r,c];break;case 2:[i,a,o]=[c,r,u];break;case 3:[i,a,o]=[c,l,r];break;case 4:[i,a,o]=[u,c,r];break;case 5:[i,a,o]=[r,c,l];break}}return[i,a,o,e.length>3?e[3]:1]},{min:Xe,max:Ze}=Math,Qe=(...e)=>{e=g(e,`rgb`);let[t,n,r]=e,i=Xe(t,n,r),a=Ze(t,n,r),o=a-i,s,c,l;return l=a/255,a===0?(s=NaN,c=0):(c=o/a,t===a&&(s=(n-r)/o),n===a&&(s=2+(r-t)/o),r===a&&(s=4+(t-n)/o),s*=60,s<0&&(s+=360)),[s,c,l]};O.prototype.hsv=function(){return Qe(this._rgb)},k.hsv=(...e)=>new O(...e,`hsv`),D.format.hsv=Ye,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsv`),h(e)===`array`&&e.length===3)return`hsv`}}),P.hsv=(e,t,n)=>Ne(e,t,n,`hsv`);function $e(e,t){let n=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(e=>[e]));let r=t[0].length,i=t[0].map((e,n)=>t.map(e=>e[n])),a=e.map(e=>i.map(t=>Array.isArray(e)?e.reduce((e,n,r)=>e+n*(t[r]||0),0):t.reduce((t,n)=>t+n*e,0)));return n===1&&(a=a[0]),r===1?a.map(e=>e[0]):a}var et=(...e)=>{e=g(e,`lab`);let[t,n,r,...i]=e,[a,o,s]=tt([t,n,r]),[c,l,u]=de(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function tt(e){return $e([[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],$e([[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],e).map(e=>e**3))}var nt=(...e)=>{let[t,n,r,...i]=g(e,`rgb`);return[...rt(he(t,n,r)),...i.length>0&&i[0]<1?[i[0]]:[]]};function rt(e){return $e([[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],$e([[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],e).map(e=>Math.cbrt(e)))}O.prototype.oklab=function(){return nt(this._rgb)},Object.assign(k,{oklab:(...e)=>new O(...e,`oklab`)}),D.format.oklab=et,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklab`),h(e)===`array`&&e.length===3)return`oklab`}}),P.oklab=(e,t,n)=>{let r=e.oklab(),i=t.oklab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`oklab`)},P.oklch=(e,t,n)=>Ne(e,t,n,`oklch`);var{pow:it,sqrt:at,PI:ot,cos:st,sin:ct,atan2:lt}=Math,ut=(e,t=`lrgb`,n=null)=>{let r=e.length;n||=Array.from(Array(r)).map(()=>1);let i=r/n.reduce(function(e,t){return e+t});if(n.forEach((e,t)=>{n[t]*=i}),e=e.map(e=>new O(e)),t===`lrgb`)return dt(e,n);let a=e.shift(),o=a.get(t),s=[],c=0,l=0;for(let e=0;e{let i=e.get(t);u+=e.alpha()*n[r+1];for(let e=0;e=360;)t-=360;o[e]=t}else o[e]=o[e]/s[e];return u/=r,new O(o,t).alpha(u>.99999?1:u,!0)},dt=(e,t)=>{let n=e.length,r=[0,0,0,0];for(let i=0;i.9999999&&(r[3]=1),new O(p(r))},{pow:ft}=Math;function pt(e){let t=`rgb`,n=k(`#ccc`),r=0,i=[0,1],a=[0,1],o=[],s=[0,0],c=!1,l=[],u=!1,d=0,p=1,m=!1,g={},_=!0,v=1,y=function(e){if(e||=[`#fff`,`#000`],e&&h(e)===`string`&&k.brewer&&k.brewer[e.toLowerCase()]&&(e=k.brewer[e.toLowerCase()]),h(e)===`array`){e.length===1&&(e=[e[0],e[0]]),e=e.slice(0);for(let t=0;t=c[n];)n++;return n-1}return 0},x=e=>e,S=e=>e,C=function(e,r){let i,a;if(r??=!1,isNaN(e)||e===null)return n;a=r?e:c&&c.length>2?b(e)/(c.length-2):p===d?1:(e-d)/(p-d),a=S(a),r||(a=x(a)),v!==1&&(a=ft(a,v)),a=s[0]+a*(1-s[0]-s[1]),a=f(a,0,1);let u=Math.floor(a*1e4);if(_&&g[u])i=g[u];else{if(h(l)===`array`)for(let e=0;e=n&&e===o.length-1){i=l[e];break}if(a>n&&ag={};y(e);let T=function(e){let t=k(C(e));return u&&t[u]?t[u]():t};return T.classes=function(e){if(e!=null){if(h(e)===`array`)c=e,i=[e[0],e[e.length-1]];else{let t=k.analyze(i);c=e===0?[t.min,t.max]:k.limits(t,`e`,e)}return T}return c},T.domain=function(e){if(!arguments.length)return a;a=e.slice(0),d=e[0],p=e[e.length-1],o=[];let t=l.length;if(e.length===t&&d!==p)for(let t of Array.from(e))o.push((t-d)/(p-d));else{for(let e=0;e2){let t=e.map((t,n)=>n/(e.length-1)),n=e.map(e=>(e-d)/(p-d));n.every((e,n)=>t[n]===e)||(S=e=>{if(e<=0||e>=1)return e;let r=0;for(;e>=n[r+1];)r++;let i=(e-n[r])/(n[r+1]-n[r]);return t[r]+i*(t[r+1]-t[r])})}}return i=[d,p],T},T.mode=function(e){return arguments.length?(t=e,w(),T):t},T.range=function(e,t){return y(e,t),T},T.out=function(e){return u=e,T},T.spread=function(e){return arguments.length?(r=e,T):r},T.correctLightness=function(e){return e??=!0,m=e,w(),x=m?function(e){let t=C(0,!0).lab()[0],n=C(1,!0).lab()[0],r=t>n,i=C(e,!0).lab()[0],a=t+(n-t)*e,o=i-a,s=0,c=1,l=20;for(;Math.abs(o)>.01&&l-- >0;)(function(){return r&&(o*=-1),o<0?(s=e,e+=(c-e)*.5):(c=e,e+=(s-e)*.5),i=C(e,!0).lab()[0],o=i-a})();return e}:e=>e,T},T.padding=function(e){return e==null?s:(h(e)===`number`&&(e=[e,e]),s=e,T)},T.colors=function(t,n){arguments.length<2&&(n=`hex`);let r=[];if(arguments.length===0)r=l.slice(0);else if(t===1)r=[T(.5)];else if(t>1){let e=i[0],n=i[1]-e;r=mt(0,t,!1).map(r=>T(e+r/(t-1)*n))}else{e=[];let t=[];if(c&&c.length>2)for(let e=1,n=c.length,r=1<=n;r?en;r?e++:e--)t.push((c[e-1]+c[e])*.5);else t=i;r=t.map(e=>T(e))}return k[n]&&(r=r.map(e=>e[n]())),r},T.cache=function(e){return e==null?_:(_=e,T)},T.gamma=function(e){return e==null?v:(v=e,T)},T.nodata=function(e){return e==null?n:(n=k(e),T)},T}function mt(e,t,n){let r=[],i=ea;i?t++:t--)r.push(t);return r}var ht=function(e){let t=[1,1];for(let n=1;nnew O(e)),e.length===2)[n,r]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>n[t]+e*(r[t]-n[t])),`lab`)};else if(e.length===3)[n,r,i]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*n[t]+2*(1-e)*e*r[t]+e*e*i[t]),`lab`)};else if(e.length===4){let a;[n,r,i,a]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*(1-e)*n[t]+3*(1-e)*(1-e)*e*r[t]+3*(1-e)*e*e*i[t]+e*e*e*a[t]),`lab`)}}else if(e.length>=5){let n,r,i;n=e.map(e=>e.lab()),i=e.length-1,r=ht(i),t=function(e){let t=1-e;return new O([0,1,2].map(a=>n.reduce((n,o,s)=>n+r[s]*t**(i-s)*e**s*o[a],0)),`lab`)}}else throw RangeError(`No point in running bezier with only one color.`);return t},_t=e=>{let t=gt(e);return t.scale=()=>pt(t),t},{round:vt}=Math;O.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(vt)},O.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,n)=>n<3?e===!1?t:vt(t):t)},Object.assign(k,{rgb:(...e)=>new O(...e,`rgb`)}),D.format.rgb=(...e)=>{let t=g(e,`rgba`);return t[3]===void 0&&(t[3]=1),t},D.autodetect.push({p:3,test:(...e)=>{if(e=g(e,`rgba`),h(e)===`array`&&(e.length===3||e.length===4&&h(e[3])==`number`&&e[3]>=0&&e[3]<=1))return`rgb`}});var I=(e,t,n)=>{if(!I[n])throw Error(`unknown blend mode `+n);return I[n](e,t)},L=e=>(t,n)=>{let r=k(n).rgb(),i=k(t).rgb();return k.rgb(e(r,i))},R=e=>(t,n)=>{let r=[];return r[0]=e(t[0],n[0]),r[1]=e(t[1],n[1]),r[2]=e(t[2],n[2]),r};I.normal=L(R(e=>e)),I.multiply=L(R((e,t)=>e*t/255)),I.screen=L(R((e,t)=>255*(1-(1-e/255)*(1-t/255)))),I.overlay=L(R((e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)))),I.darken=L(R((e,t)=>e>t?t:e)),I.lighten=L(R((e,t)=>e>t?e:t)),I.dodge=L(R((e,t)=>e===255?255:(e=t/255*255/(1-e/255),e>255?255:e))),I.burn=L(R((e,t)=>255*(1-(1-t/255)/(e/255))));var{pow:yt,sin:bt,cos:xt}=Math;function St(e=300,t=-1.5,n=1,r=1,i=[0,1]){let a=0,o;h(i)===`array`?o=i[1]-i[0]:(o=0,i=[i,i]);let s=function(s){let c=C*((e+120)/360+t*s),l=yt(i[0]+o*s,r),u=(a===0?n:n[0]+s*a)*l*(1-l)/2,d=xt(c),f=bt(c),m=l+u*(-.14861*d+1.78277*f),h=l+u*(-.29227*d-.90649*f),g=l+1.97294*d*u;return k(p([m*255,h*255,g*255,1]))};return s.start=function(t){return t==null?e:(e=t,s)},s.rotations=function(e){return e==null?t:(t=e,s)},s.gamma=function(e){return e==null?r:(r=e,s)},s.hue=function(e){return e==null?n:(n=e,h(n)===`array`?(a=n[1]-n[0],a===0&&(n=n[1])):a=0,s)},s.lightness=function(e){return e==null?i:(h(e)===`array`?(i=e,o=e[1]-e[0]):(i=[e,e],o=0),s)},s.scale=()=>k.scale(s),s.hue(n),s}var Ct=`0123456789abcdef`,{floor:wt,random:Tt}=Math,Et=(e=Tt)=>{let t=`#`;for(let n=0;n<6;n++)t+=Ct.charAt(wt(e()*16));return new O(t,`hex`)},{log:Dt,pow:Ot,floor:kt,abs:At}=Math;function jt(e,t=null){let n={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return h(e)===`object`&&(e=Object.values(e)),e.forEach(e=>{t&&h(e)===`object`&&(e=e[t]),e!=null&&!isNaN(e)&&(n.values.push(e),n.sum+=e,en.max&&(n.max=e),n.count+=1)}),n.domain=[n.min,n.max],n.limits=(e,t)=>Mt(n,e,t),n}function Mt(e,t=`equal`,n=7){h(e)==`array`&&(e=jt(e));let{min:r,max:i}=e,a=e.values.sort((e,t)=>e-t);if(n===1)return[r,i];let o=[];if(t.substr(0,1)===`c`&&(o.push(r),o.push(i)),t.substr(0,1)===`e`){o.push(r);for(let e=1;e 0`);let e=Math.LOG10E*Dt(r),t=Math.LOG10E*Dt(i);o.push(r);for(let r=1;r200&&(l=!1)}let f={};for(let e=0;ee-t),o.push(p[0]);for(let e=1;e{e=new O(e),t=new O(t);let n=e.luminance(),r=t.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)},Pt=.027,Ft=5e-4,It=.1,Lt=1.14,Rt=.022,zt=1.414,Bt=(e,t)=>{e=new O(e),t=new O(t),e.alpha()<1&&(e=F(t,e,e.alpha(),`rgb`));let n=Vt(...e.rgb()),r=Vt(...t.rgb()),i=n>=Rt?n:n+(Rt-n)**+zt,a=r>=Rt?r:r+(Rt-r)**+zt,o=a**.56-i**.57,s=a**.65-i**.62,c=Math.abs(a-i)0?c-Pt:c+Pt)*100};function Vt(e,t,n){return .2126729*(e/255)**2.4+.7151522*(t/255)**2.4+.072175*(n/255)**2.4}var{sqrt:z,pow:B,min:Ht,max:Ut,atan2:Wt,abs:Gt,cos:Kt,sin:qt,exp:Jt,PI:Yt}=Math;function Xt(e,t,n=1,r=1,i=1){var a=function(e){return 360*e/(2*Yt)},o=function(e){return 2*Yt*e/360};e=new O(e),t=new O(t);let[s,c,l]=Array.from(e.lab()),[u,d,f]=Array.from(t.lab()),p=(s+u)/2,m=(z(B(c,2)+B(l,2))+z(B(d,2)+B(f,2)))/2,h=.5*(1-z(B(m,7)/(B(m,7)+B(25,7)))),g=c*(1+h),_=d*(1+h),v=z(B(g,2)+B(l,2)),y=z(B(_,2)+B(f,2)),b=(v+y)/2,x=a(Wt(l,g)),S=a(Wt(f,_)),C=x>=0?x:x+360,w=S>=0?S:S+360,T=Gt(C-w)>180?(C+w+360)/2:(C+w)/2,ee=1-.17*Kt(o(T-30))+.24*Kt(o(2*T))+.32*Kt(o(3*T+6))-.2*Kt(o(4*T-63)),E=w-C;E=Gt(E)<=180?E:w<=C?E+360:E-360,E=2*z(v*y)*qt(o(E)/2);let D=u-s,te=y-v,k=1+.015*B(p-50,2)/z(20+B(p-50,2)),A=1+.045*b,ne=1+.015*b*ee,re=30*Jt(-B((T-275)/25,2)),ie=-(2*z(B(b,7)/(B(b,7)+B(25,7))))*qt(2*o(re));return Ut(0,Ht(100,z(B(D/(n*k),2)+B(te/(r*A),2)+B(E/(i*ne),2)+ie*(te/(r*A))*(E/(i*ne)))))}function Zt(e,t,n=`lab`){e=new O(e),t=new O(t);let r=e.get(n),i=t.get(n),a=0;for(let e in r){let t=(r[e]||0)-(i[e]||0);a+=t*t}return Math.sqrt(a)}var Qt=(...e)=>{try{return new O(...e),!0}catch{return!1}},$t={cool(){return pt([k.hsl(180,1,.9),k.hsl(250,.7,.4)])},hot(){return pt([`#000`,`#f00`,`#ff0`,`#fff`],[0,.25,.75,1]).mode(`rgb`)}},en={OrRd:[`#fff7ec`,`#fee8c8`,`#fdd49e`,`#fdbb84`,`#fc8d59`,`#ef6548`,`#d7301f`,`#b30000`,`#7f0000`],PuBu:[`#fff7fb`,`#ece7f2`,`#d0d1e6`,`#a6bddb`,`#74a9cf`,`#3690c0`,`#0570b0`,`#045a8d`,`#023858`],BuPu:[`#f7fcfd`,`#e0ecf4`,`#bfd3e6`,`#9ebcda`,`#8c96c6`,`#8c6bb1`,`#88419d`,`#810f7c`,`#4d004b`],Oranges:[`#fff5eb`,`#fee6ce`,`#fdd0a2`,`#fdae6b`,`#fd8d3c`,`#f16913`,`#d94801`,`#a63603`,`#7f2704`],BuGn:[`#f7fcfd`,`#e5f5f9`,`#ccece6`,`#99d8c9`,`#66c2a4`,`#41ae76`,`#238b45`,`#006d2c`,`#00441b`],YlOrBr:[`#ffffe5`,`#fff7bc`,`#fee391`,`#fec44f`,`#fe9929`,`#ec7014`,`#cc4c02`,`#993404`,`#662506`],YlGn:[`#ffffe5`,`#f7fcb9`,`#d9f0a3`,`#addd8e`,`#78c679`,`#41ab5d`,`#238443`,`#006837`,`#004529`],Reds:[`#fff5f0`,`#fee0d2`,`#fcbba1`,`#fc9272`,`#fb6a4a`,`#ef3b2c`,`#cb181d`,`#a50f15`,`#67000d`],RdPu:[`#fff7f3`,`#fde0dd`,`#fcc5c0`,`#fa9fb5`,`#f768a1`,`#dd3497`,`#ae017e`,`#7a0177`,`#49006a`],Greens:[`#f7fcf5`,`#e5f5e0`,`#c7e9c0`,`#a1d99b`,`#74c476`,`#41ab5d`,`#238b45`,`#006d2c`,`#00441b`],YlGnBu:[`#ffffd9`,`#edf8b1`,`#c7e9b4`,`#7fcdbb`,`#41b6c4`,`#1d91c0`,`#225ea8`,`#253494`,`#081d58`],Purples:[`#fcfbfd`,`#efedf5`,`#dadaeb`,`#bcbddc`,`#9e9ac8`,`#807dba`,`#6a51a3`,`#54278f`,`#3f007d`],GnBu:[`#f7fcf0`,`#e0f3db`,`#ccebc5`,`#a8ddb5`,`#7bccc4`,`#4eb3d3`,`#2b8cbe`,`#0868ac`,`#084081`],Greys:[`#ffffff`,`#f0f0f0`,`#d9d9d9`,`#bdbdbd`,`#969696`,`#737373`,`#525252`,`#252525`,`#000000`],YlOrRd:[`#ffffcc`,`#ffeda0`,`#fed976`,`#feb24c`,`#fd8d3c`,`#fc4e2a`,`#e31a1c`,`#bd0026`,`#800026`],PuRd:[`#f7f4f9`,`#e7e1ef`,`#d4b9da`,`#c994c7`,`#df65b0`,`#e7298a`,`#ce1256`,`#980043`,`#67001f`],Blues:[`#f7fbff`,`#deebf7`,`#c6dbef`,`#9ecae1`,`#6baed6`,`#4292c6`,`#2171b5`,`#08519c`,`#08306b`],PuBuGn:[`#fff7fb`,`#ece2f0`,`#d0d1e6`,`#a6bddb`,`#67a9cf`,`#3690c0`,`#02818a`,`#016c59`,`#014636`],Viridis:[`#440154`,`#482777`,`#3f4a8a`,`#31678e`,`#26838f`,`#1f9d8a`,`#6cce5a`,`#b6de2b`,`#fee825`],Spectral:[`#9e0142`,`#d53e4f`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#e6f598`,`#abdda4`,`#66c2a5`,`#3288bd`,`#5e4fa2`],RdYlGn:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#d9ef8b`,`#a6d96a`,`#66bd63`,`#1a9850`,`#006837`],RdBu:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#f7f7f7`,`#d1e5f0`,`#92c5de`,`#4393c3`,`#2166ac`,`#053061`],PiYG:[`#8e0152`,`#c51b7d`,`#de77ae`,`#f1b6da`,`#fde0ef`,`#f7f7f7`,`#e6f5d0`,`#b8e186`,`#7fbc41`,`#4d9221`,`#276419`],PRGn:[`#40004b`,`#762a83`,`#9970ab`,`#c2a5cf`,`#e7d4e8`,`#f7f7f7`,`#d9f0d3`,`#a6dba0`,`#5aae61`,`#1b7837`,`#00441b`],RdYlBu:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee090`,`#ffffbf`,`#e0f3f8`,`#abd9e9`,`#74add1`,`#4575b4`,`#313695`],BrBG:[`#543005`,`#8c510a`,`#bf812d`,`#dfc27d`,`#f6e8c3`,`#f5f5f5`,`#c7eae5`,`#80cdc1`,`#35978f`,`#01665e`,`#003c30`],RdGy:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#ffffff`,`#e0e0e0`,`#bababa`,`#878787`,`#4d4d4d`,`#1a1a1a`],PuOr:[`#7f3b08`,`#b35806`,`#e08214`,`#fdb863`,`#fee0b6`,`#f7f7f7`,`#d8daeb`,`#b2abd2`,`#8073ac`,`#542788`,`#2d004b`],Set2:[`#66c2a5`,`#fc8d62`,`#8da0cb`,`#e78ac3`,`#a6d854`,`#ffd92f`,`#e5c494`,`#b3b3b3`],Accent:[`#7fc97f`,`#beaed4`,`#fdc086`,`#ffff99`,`#386cb0`,`#f0027f`,`#bf5b17`,`#666666`],Set1:[`#e41a1c`,`#377eb8`,`#4daf4a`,`#984ea3`,`#ff7f00`,`#ffff33`,`#a65628`,`#f781bf`,`#999999`],Set3:[`#8dd3c7`,`#ffffb3`,`#bebada`,`#fb8072`,`#80b1d3`,`#fdb462`,`#b3de69`,`#fccde5`,`#d9d9d9`,`#bc80bd`,`#ccebc5`,`#ffed6f`],Dark2:[`#1b9e77`,`#d95f02`,`#7570b3`,`#e7298a`,`#66a61e`,`#e6ab02`,`#a6761d`,`#666666`],Paired:[`#a6cee3`,`#1f78b4`,`#b2df8a`,`#33a02c`,`#fb9a99`,`#e31a1c`,`#fdbf6f`,`#ff7f00`,`#cab2d6`,`#6a3d9a`,`#ffff99`,`#b15928`],Pastel2:[`#b3e2cd`,`#fdcdac`,`#cbd5e8`,`#f4cae4`,`#e6f5c9`,`#fff2ae`,`#f1e2cc`,`#cccccc`],Pastel1:[`#fbb4ae`,`#b3cde3`,`#ccebc5`,`#decbe4`,`#fed9a6`,`#ffffcc`,`#e5d8bd`,`#fddaec`,`#f2f2f2`]},tn=Object.keys(en),nn=new Map(tn.map(e=>[e.toLowerCase(),e])),rn=typeof Proxy==`function`?new Proxy(en,{get(e,t){let n=t.toLowerCase();if(nn.has(n))return e[nn.get(n)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tn)}}):en,an=(...e)=>{e=g(e,`cmyk`);let[t,n,r,i]=e,a=e.length>4?e[4]:1;return i===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-i),n>=1?0:255*(1-n)*(1-i),r>=1?0:255*(1-r)*(1-i),a]},{max:on}=Math,sn=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i=1-on(t,on(n,r)),a=i<1?1/(1-i):0;return[(1-t-i)*a,(1-n-i)*a,(1-r-i)*a,i]};O.prototype.cmyk=function(){return sn(this._rgb)},Object.assign(k,{cmyk:(...e)=>new O(...e,`cmyk`)}),D.format.cmyk=an,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`cmyk`),h(e)===`array`&&e.length===4)return`cmyk`}});var cn=(...e)=>{let t=g(e,`hsla`),n=_(e)||`lsa`;return t[0]=x(t[0]||0)+`deg`,t[1]=x(t[1]*100)+`%`,t[2]=x(t[2]*100)+`%`,n===`hsla`||t.length>3&&t[3]<1?(t[3]=`/ `+(t.length>3?t[3]:1),n=`hsla`):t.length=3,`${n.substr(0,3)}(${t.join(` `)})`},ln=(...e)=>{let t=g(e,`lab`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=x(t[2]),n===`laba`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(` `)})`},un=(...e)=>{let t=g(e,`lch`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,n===`lcha`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(` `)})`},dn=(...e)=>{let t=g(e,`lab`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=S(t[2]),t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(` `)})`},fn=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=nt(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},pn=(...e)=>{let t=g(e,`lch`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(` `)})`},{round:mn}=Math,hn=(...e)=>{let t=g(e,`rgba`),n=_(e)||`rgb`;if(n.substr(0,3)===`hsl`)return cn(qe(t),n);if(n.substr(0,3)===`lab`){let e=ce();M(`d50`);let r=ln(fe(t),n);return M(e),r}if(n.substr(0,3)===`lch`){let e=ce();M(`d50`);let r=un(Ae(t),n);return M(e),r}return n.substr(0,5)===`oklab`?dn(nt(t)):n.substr(0,5)===`oklch`?pn(fn(t)):(t[0]=mn(t[0]),t[1]=mn(t[1]),t[2]=mn(t[2]),(n===`rgba`||t.length>3&&t[3]<1)&&(t[3]=`/ `+(t.length>3?t[3]:1),n=`rgba`),`${n.substr(0,3)}(${t.slice(0,n===`rgb`?3:4).join(` `)})`)},gn=(...e)=>{e=g(e,`lch`);let[t,n,r,...i]=e,[a,o,s]=Ce(t,n,r),[c,l,u]=et(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},V=`((?:-?\\d+)|(?:-?\\d+(?:\\.\\d+)?)%|none)`,H=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%?)|none)`,_n=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%)|none)`,U=`\\s*`,vn=`\\s+`,yn=`\\s*,\\s*`,bn=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:deg)?)|none)`,xn=`\\s*(?:\\/\\s*((?:[01]|[01]?\\.\\d+)|\\d+(?:\\.\\d+)?%))?`,Sn=RegExp(`^rgba?\\(`+U+[V,V,V].join(vn)+xn+`\\)$`),Cn=RegExp(`^rgb\\(`+U+[V,V,V].join(yn)+U+`\\)$`),wn=RegExp(`^rgba\\(`+U+[V,V,V,H].join(yn)+U+`\\)$`),Tn=RegExp(`^hsla?\\(`+U+[bn,_n,_n].join(vn)+xn+`\\)$`),En=RegExp(`^hsl?\\(`+U+[bn,_n,_n].join(yn)+U+`\\)$`),Dn=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,On=RegExp(`^lab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),kn=RegExp(`^lch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),An=RegExp(`^oklab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),jn=RegExp(`^oklch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),{round:Mn}=Math,Nn=e=>e.map((e,t)=>t<=2?f(Mn(e),0,255):e),W=(e,t=0,n=100,r=!1)=>(typeof e==`string`&&e.endsWith(`%`)&&(e=parseFloat(e.substring(0,e.length-1))/100,e=r?t+(e+1)*.5*(n-t):t+e*(n-t)),+e),G=(e,t)=>e===`none`?t:e,Pn=e=>{if(e=e.toLowerCase().trim(),e===`transparent`)return[0,0,0,0];let t;if(D.format.named)try{return D.format.named(e)}catch{}if((t=e.match(Sn))||(t=e.match(Cn))){let e=t.slice(1,4);for(let t=0;t<3;t++)e[t]=+W(G(e[t],0),0,255);e=Nn(e);let n=t[4]===void 0?1:+W(t[4],0,1);return e[3]=n,e}if(t=e.match(wn)){let e=t.slice(1,5);for(let t=0;t<4;t++)e[t]=+W(e[t],0,255);return e}if((t=e.match(Tn))||(t=e.match(En))){let e=t.slice(1,4);e[0]=+G(e[0].replace(`deg`,``),0),e[1]=W(G(e[1],0),0,100)*.01,e[2]=W(G(e[2],0),0,100)*.01;let n=Nn(Ke(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(Dn)){let e=t.slice(1,4);e[1]*=.01,e[2]*=.01;let n=Ke(e);for(let e=0;e<3;e++)n[e]=Mn(n[e]);return n[3]=+t[4],n}if(t=e.match(On)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,100),e[1]=W(G(e[1],0),-125,125,!0),e[2]=W(G(e[2],0),-125,125,!0);let n=ce();M(`d50`);let r=Nn(N(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(kn)){let e=t.slice(1,4);e[0]=W(e[0],0,100),e[1]=W(G(e[1],0),0,150,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=ce();M(`d50`);let r=Nn(we(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(An)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),-.4,.4,!0),e[2]=W(G(e[2],0),-.4,.4,!0);let n=Nn(et(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(jn)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),0,.4,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=Nn(gn(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}};Pn.test=e=>Sn.test(e)||Tn.test(e)||On.test(e)||kn.test(e)||An.test(e)||jn.test(e)||Cn.test(e)||wn.test(e)||En.test(e)||Dn.test(e)||e===`transparent`,O.prototype.css=function(e){return hn(this._rgb,e)},k.css=(...e)=>new O(...e,`css`),D.format.css=Pn,D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&Pn.test(e))return`css`}}),D.format.gl=(...e)=>{let t=g(e,`rgba`);return t[0]*=255,t[1]*=255,t[2]*=255,t},k.gl=(...e)=>new O(...e,`gl`),O.prototype.gl=function(){let e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},O.prototype.hex=function(e){return oe(this._rgb,e)},k.hex=(...e)=>new O(...e,`hex`),D.format.hex=ie,D.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return`hex`}});var{log:Fn}=Math,In=e=>{let t=e/100,n,r,i;return t<66?(n=255,r=t<6?0:-155.25485562709179-.44596950469579133*(r=t-2)+104.49216199393888*Fn(r),i=t<20?0:-254.76935184120902+.8274096064007395*(i=t-10)+115.67994401066147*Fn(i)):(n=351.97690566805693+.114206453784165*(n=t-55)-40.25366309332127*Fn(n),r=325.4494125711974+.07943456536662342*(r=t-50)-28.0852963507957*Fn(r),i=255),[n,r,i,1]},{round:Ln}=Math,Rn=(...e)=>{let t=g(e,`rgb`),n=t[0],r=t[2],i=1e3,a=4e4,o;for(;a-i>.4;){o=(a+i)*.5;let e=In(o);e[2]/e[0]>=r/n?a=o:i=o}return Ln(o)};O.prototype.temp=O.prototype.kelvin=O.prototype.temperature=function(){return Rn(this._rgb)};var zn=(...e)=>new O(...e,`temp`);Object.assign(k,{temp:zn,kelvin:zn,temperature:zn}),D.format.temp=D.format.kelvin=D.format.temperature=In,O.prototype.oklch=function(){return fn(this._rgb)},Object.assign(k,{oklch:(...e)=>new O(...e,`oklch`)}),D.format.oklch=gn,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklch`),h(e)===`array`&&e.length===3)return`oklch`}}),Object.assign(k,{analyze:jt,average:ut,bezier:_t,blend:I,brewer:rn,Color:O,colors:A,contrast:Nt,contrastAPCA:Bt,cubehelix:St,deltaE:Xt,distance:Zt,input:D,interpolate:F,limits:Mt,mix:F,random:Et,scale:pt,scales:$t,valid:Qt});var K=k,q=class e{constructor(){this.hex=`#000000`,this.rgb_r=0,this.rgb_g=0,this.rgb_b=0,this.xyz_x=0,this.xyz_y=0,this.xyz_z=0,this.luv_l=0,this.luv_u=0,this.luv_v=0,this.lch_l=0,this.lch_c=0,this.lch_h=0,this.hsluv_h=0,this.hsluv_s=0,this.hsluv_l=0,this.hpluv_h=0,this.hpluv_p=0,this.hpluv_l=0,this.r0s=0,this.r0i=0,this.r1s=0,this.r1i=0,this.g0s=0,this.g0i=0,this.g1s=0,this.g1i=0,this.b0s=0,this.b0i=0,this.b1s=0,this.b1i=0}static fromLinear(e){return e<=.0031308?12.92*e:1.055*e**(1/2.4)-.055}static toLinear(e){return e>.04045?((e+.055)/1.055)**2.4:e/12.92}static yToL(t){return t<=e.epsilon?t/e.refY*e.kappa:116*(t/e.refY)**(1/3)-16}static lToY(t){return t<=8?e.refY*t/e.kappa:e.refY*((t+16)/116)**3}static rgbChannelToHex(t){let n=Math.round(t*255),r=n%16,i=(n-r)/16|0;return e.hexChars.charAt(i)+e.hexChars.charAt(r)}static hexToRgbChannel(t,n){let r=e.hexChars.indexOf(t.charAt(n)),i=e.hexChars.indexOf(t.charAt(n+1));return(r*16+i)/255}static distanceFromOriginAngle(e,t,n){let r=t/(Math.sin(n)-e*Math.cos(n));return r<0?1/0:r}static distanceFromOrigin(e,t){return Math.abs(t)/Math.sqrt(e**2+1)}static min6(e,t,n,r,i,a){return Math.min(e,Math.min(t,Math.min(n,Math.min(r,Math.min(i,a)))))}rgbToHex(){this.hex=`#`,this.hex+=e.rgbChannelToHex(this.rgb_r),this.hex+=e.rgbChannelToHex(this.rgb_g),this.hex+=e.rgbChannelToHex(this.rgb_b)}hexToRgb(){this.hex=this.hex.toLowerCase(),this.rgb_r=e.hexToRgbChannel(this.hex,1),this.rgb_g=e.hexToRgbChannel(this.hex,3),this.rgb_b=e.hexToRgbChannel(this.hex,5)}xyzToRgb(){this.rgb_r=e.fromLinear(e.m_r0*this.xyz_x+e.m_r1*this.xyz_y+e.m_r2*this.xyz_z),this.rgb_g=e.fromLinear(e.m_g0*this.xyz_x+e.m_g1*this.xyz_y+e.m_g2*this.xyz_z),this.rgb_b=e.fromLinear(e.m_b0*this.xyz_x+e.m_b1*this.xyz_y+e.m_b2*this.xyz_z)}rgbToXyz(){let t=e.toLinear(this.rgb_r),n=e.toLinear(this.rgb_g),r=e.toLinear(this.rgb_b);this.xyz_x=.41239079926595*t+.35758433938387*n+.18048078840183*r,this.xyz_y=.21263900587151*t+.71516867876775*n+.072192315360733*r,this.xyz_z=.019330818715591*t+.11919477979462*n+.95053215224966*r}xyzToLuv(){let t=this.xyz_x+15*this.xyz_y+3*this.xyz_z,n=4*this.xyz_x,r=9*this.xyz_y;t===0?(n=NaN,r=NaN):(n/=t,r/=t),this.luv_l=e.yToL(this.xyz_y),this.luv_l===0?(this.luv_u=0,this.luv_v=0):(this.luv_u=13*this.luv_l*(n-e.refU),this.luv_v=13*this.luv_l*(r-e.refV))}luvToXyz(){if(this.luv_l===0){this.xyz_x=0,this.xyz_y=0,this.xyz_z=0;return}let t=this.luv_u/(13*this.luv_l)+e.refU,n=this.luv_v/(13*this.luv_l)+e.refV;this.xyz_y=e.lToY(this.luv_l),this.xyz_x=0-9*this.xyz_y*t/((t-4)*n-t*n),this.xyz_z=(9*this.xyz_y-15*n*this.xyz_y-n*this.xyz_x)/(3*n)}luvToLch(){if(this.lch_l=this.luv_l,this.lch_c=Math.sqrt(this.luv_u*this.luv_u+this.luv_v*this.luv_v),this.lch_c<1e-8)this.lch_h=0;else{let e=Math.atan2(this.luv_v,this.luv_u);this.lch_h=e*180/Math.PI,this.lch_h<0&&(this.lch_h=360+this.lch_h)}}lchToLuv(){let e=this.lch_h/180*Math.PI;this.luv_l=this.lch_l,this.luv_u=Math.cos(e)*this.lch_c,this.luv_v=Math.sin(e)*this.lch_c}calculateBoundingLines(t){let n=(t+16)**3/1560896,r=n>e.epsilon?n:t/e.kappa,i=r*(284517*e.m_r0-94839*e.m_r2),a=r*(838422*e.m_r2+769860*e.m_r1+731718*e.m_r0),o=r*(632260*e.m_r2-126452*e.m_r1),s=r*(284517*e.m_g0-94839*e.m_g2),c=r*(838422*e.m_g2+769860*e.m_g1+731718*e.m_g0),l=r*(632260*e.m_g2-126452*e.m_g1),u=r*(284517*e.m_b0-94839*e.m_b2),d=r*(838422*e.m_b2+769860*e.m_b1+731718*e.m_b0),f=r*(632260*e.m_b2-126452*e.m_b1);this.r0s=i/o,this.r0i=a*t/o,this.r1s=i/(o+126452),this.r1i=(a-769860)*t/(o+126452),this.g0s=s/l,this.g0i=c*t/l,this.g1s=s/(l+126452),this.g1i=(c-769860)*t/(l+126452),this.b0s=u/f,this.b0i=d*t/f,this.b1s=u/(f+126452),this.b1i=(d-769860)*t/(f+126452)}calcMaxChromaHpluv(){let t=e.distanceFromOrigin(this.r0s,this.r0i),n=e.distanceFromOrigin(this.r1s,this.r1i),r=e.distanceFromOrigin(this.g0s,this.g0i),i=e.distanceFromOrigin(this.g1s,this.g1i),a=e.distanceFromOrigin(this.b0s,this.b0i),o=e.distanceFromOrigin(this.b1s,this.b1i);return e.min6(t,n,r,i,a,o)}calcMaxChromaHsluv(t){let n=t/360*Math.PI*2,r=e.distanceFromOriginAngle(this.r0s,this.r0i,n),i=e.distanceFromOriginAngle(this.r1s,this.r1i,n),a=e.distanceFromOriginAngle(this.g0s,this.g0i,n),o=e.distanceFromOriginAngle(this.g1s,this.g1i,n),s=e.distanceFromOriginAngle(this.b0s,this.b0i,n),c=e.distanceFromOriginAngle(this.b1s,this.b1i,n);return e.min6(r,i,a,o,s,c)}hsluvToLch(){if(this.hsluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hsluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hsluv_l,this.calculateBoundingLines(this.hsluv_l);let e=this.calcMaxChromaHsluv(this.hsluv_h);this.lch_c=e/100*this.hsluv_s}this.lch_h=this.hsluv_h}lchToHsluv(){if(this.lch_l>99.9999999)this.hsluv_s=0,this.hsluv_l=100;else if(this.lch_l<1e-8)this.hsluv_s=0,this.hsluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHsluv(this.lch_h);this.hsluv_s=this.lch_c/e*100,this.hsluv_l=this.lch_l}this.hsluv_h=this.lch_h}hpluvToLch(){if(this.hpluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hpluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hpluv_l,this.calculateBoundingLines(this.hpluv_l);let e=this.calcMaxChromaHpluv();this.lch_c=e/100*this.hpluv_p}this.lch_h=this.hpluv_h}lchToHpluv(){if(this.lch_l>99.9999999)this.hpluv_p=0,this.hpluv_l=100;else if(this.lch_l<1e-8)this.hpluv_p=0,this.hpluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHpluv();this.hpluv_p=this.lch_c/e*100,this.hpluv_l=this.lch_l}this.hpluv_h=this.lch_h}hsluvToRgb(){this.hsluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hpluvToRgb(){this.hpluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hsluvToHex(){this.hsluvToRgb(),this.rgbToHex()}hpluvToHex(){this.hpluvToRgb(),this.rgbToHex()}rgbToHsluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHsluv()}rgbToHpluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHpluv()}hexToHsluv(){this.hexToRgb(),this.rgbToHsluv()}hexToHpluv(){this.hexToRgb(),this.rgbToHpluv()}};q.hexChars=`0123456789abcdef`,q.refY=1,q.refU=.19783000664283,q.refV=.46831999493879,q.kappa=903.2962962,q.epsilon=.0088564516,q.m_r0=3.240969941904521,q.m_r1=-1.537383177570093,q.m_r2=-.498610760293,q.m_g0=-.96924363628087,q.m_g1=1.87596750150772,q.m_g2=.041555057407175,q.m_b0=.055630079696993,q.m_b1=-.20397695888897,q.m_b2=1.056971514242878;var Bn=s(((e,t)=>{function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=n})),Vn=s(((e,t)=>{var n=Bn(),r,i;function a(){for(var e in i=[`toString`,`toLocaleString`,`valueOf`,`hasOwnProperty`,`isPrototypeOf`,`propertyIsEnumerable`,`constructor`],r=!0,{toString:null})r=!1}function o(e,t,o){var c,l=0;for(c in r??a(),e)if(s(t,e,c,o)===!1)break;if(r)for(var u=e.constructor,d=!!u&&e===u.prototype;(c=i[l++])&&!((c!==`constructor`||!d&&n(e,c))&&e[c]!==Object.prototype[c]&&s(t,e,c,o)===!1););}function s(e,t,n,r){return e.call(r,t[n],n,t)}t.exports=o})),Hn=s(((e,t)=>{var n=Vn();function r(e){var t=[];return n(e,function(e,n){typeof e==`function`&&t.push(n)}),t.sort()}t.exports=r})),Un=s(((e,t)=>{function n(e,t,n){var r=e.length;t=t==null?0:t<0?Math.max(r+t,0):Math.min(t,r),n=n==null?r:n<0?Math.max(r+n,0):Math.min(n,r);for(var i=[];t{var n=Un();function r(e,t,r){var i=n(arguments,2);return function(){return e.apply(t,i.concat(n(arguments)))}}t.exports=r})),Gn=s(((e,t)=>{function n(e,t,n){if(e!=null)for(var r=-1,i=e.length;++r{var n=Hn(),r=Wn(),i=Gn(),a=Un();function o(e,t){i(arguments.length>1?a(arguments,1):n(e),function(t){e[t]=r(e[t],e)})}t.exports=o})),J=s(((e,t)=>{var n=Bn(),r=Vn();function i(e,t,i){r(e,function(r,a){if(n(e,a))return t.call(i,e[a],a,e)})}t.exports=i})),qn=s(((e,t)=>{function n(e){return e}t.exports=n})),Jn=s(((e,t)=>{function n(e){return function(t){return t[e]}}t.exports=n})),Yn=s(((e,t)=>{var n=/^\[object (.*)\]$/,r=Object.prototype.toString,i;function a(e){return e===null?`Null`:e===i?`Undefined`:n.exec(r.call(e))[1]}t.exports=a})),Xn=s(((e,t)=>{var n=Yn();function r(e,t){return n(e)===t}t.exports=r})),Zn=s(((e,t)=>{var n=Xn();t.exports=Array.isArray||function(e){return n(e,`Array`)}})),Qn=s(((e,t)=>{var n=J(),r=Zn();function i(e,t){for(var n=-1,r=e.length;++n{var n=qn(),r=Jn(),i=Qn();function a(e,t){if(e==null)return n;switch(typeof e){case`function`:return t===void 0?e:function(n,r,i){return e.call(t,n,r,i)};case`object`:return function(t){return i(t,e)};case`string`:case`number`:return r(e)}}t.exports=a})),$n=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!1;return n(e,function(n,r){if(t(n,r,e))return a=!0,!1}),a}t.exports=i})),er=s(((e,t)=>{var n=$n();function r(e,t){return n(e,function(e){return e===t})}t.exports=r})),tr=s(((e,t)=>{function n(e){return!!e&&typeof e==`object`&&e.constructor===Object}t.exports=n})),nr=s(((e,t)=>{var n=J(),r=tr();function i(e,t){for(var a=0,o=arguments.length,s;++a{var n=J(),r=tr();function i(e,t){for(var r=0,i=arguments.length,o;++r{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!0;return n(e,function(n,r){if(!t(n,r,e))return a=!1,!1}),a}t.exports=i})),ar=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Object`)}t.exports=r})),or=s(((e,t)=>{function n(e,t){return e===t?e!==0||1/e==1/t:e!==e&&t!==t}t.exports=n})),sr=s(((e,t)=>{var n=Bn(),r=ir(),i=ar(),a=or();function o(e){return function(t,r){return n(this,r)&&e(t,this[r])}}function s(e,t){return n(this,t)}function c(e,t,n){return n||=a,!i(e)||!i(t)?n(e,t):r(e,o(n),t)&&r(t,s,e)}t.exports=c})),cr=s(((e,t)=>{var n=Gn(),r=Un(),i=J();function a(e,t){return n(r(arguments,1),function(t){i(t,function(t,n){e[n]??(e[n]=t)})}),e}t.exports=a})),lr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){t(e,n,r)&&(a[n]=e)}),a}t.exports=i})),ur=s(((e,t)=>{var n=$n(),r=Y();function i(e,t,i){t=r(t,i);var a;return n(e,function(e,n,r){if(t(e,n,r))return a=e,!0}),a}t.exports=i})),dr=s(((e,t)=>{var n=J(),r=tr();function i(e,t,a,o){return n(e,function(e,n){var s=a?a+`.`+n:n;o!==0&&r(e)?i(e,t,s,o-1):t[s]=e}),t}function a(e,t){return e==null?{}:(t??=-1,i(e,{},``,t))}t.exports=a})),fr=s(((e,t)=>{function n(e){switch(typeof e){case`string`:case`number`:case`boolean`:return!0}return e==null}t.exports=n})),pr=s(((e,t)=>{fr();function n(e,t){for(var n=t.split(`.`),r=n.pop();t=n.shift();)if(e=e[t],e==null)return;return e[r]}t.exports=n})),mr=s(((e,t)=>{var n=pr(),r;function i(e,t){return n(e,t)!==r}t.exports=i})),hr=s(((e,t)=>{var n=J();t.exports=Object.keys||function(e){var t=[];return n(e,function(e,n){t.push(n)}),t}})),gr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){a[n]=t(e,n,r)}),a}t.exports=i})),_r=s(((e,t)=>{var n=J();function r(e,t){var r=!0;return n(t,function(t,n){if(e[n]!==t)return r=!1}),r}t.exports=r})),vr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return 1/0;if(e.length&&!t)return Math.max.apply(Math,e);t=n(t,r);for(var i,a=-1/0,o,s,c=-1,l=e.length;++ca&&(a=s,i=o);return i}t.exports=r})),yr=s(((e,t)=>{var n=J();function r(e){var t=[];return n(e,function(e,n){t.push(e)}),t}t.exports=r})),br=s(((e,t)=>{var n=vr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),xr=s(((e,t)=>{var n=J();function r(e,t){for(var r=0,a=arguments.length,o;++r{var n=Yn(),r=tr(),i=xr();function a(e){switch(n(e)){case`Object`:return o(e);case`Array`:return l(e);case`RegExp`:return s(e);case`Date`:return c(e);default:return e}}function o(e){return r(e)?i({},e):e}function s(e){var t=``;return t+=e.multiline?`m`:``,t+=e.global?`g`:``,t+=e.ignoreCase?`i`:``,new RegExp(e.source,t)}function c(e){return new Date(+e)}function l(e){return e.slice()}t.exports=a})),Cr=s(((e,t)=>{var n=Sr(),r=J(),i=Yn(),a=tr();function o(e,t){switch(i(e)){case`Object`:return s(e,t);case`Array`:return c(e,t);default:return n(e)}}function s(e,t){if(a(e)){var n={};return r(e,function(e,n){this[n]=o(e,t)},n),n}else if(t)return t(e);else return e}function c(e,t){for(var n=[],r=-1,i=e.length;++r{var n=Bn(),r=Cr(),i=ar();function a(){for(var e=1,t,o,s,c=r(arguments[0]);s=arguments[e++];)for(t in s)n(s,t)&&(o=s[t],i(o)&&i(c[t])?c[t]=a(c[t],o):c[t]=r(o));return c}t.exports=a})),Tr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return-1/0;if(e.length&&!t)return Math.min.apply(Math,e);t=n(t,r);for(var i,a=1/0,o,s,c=-1,l=e.length;++c{var n=Tr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),Dr=s(((e,t)=>{var n=Gn();function r(e,t){return t&&n(t.split(`.`),function(t){e[t]||(e[t]={}),e=e[t]}),e}t.exports=r})),Or=s(((e,t)=>{function n(e,t,n){if(n||=0,e==null)return-1;for(var r=e.length,i=n<0?r+n:n;i{var n=Or();function r(e,t){return n(e,t)!==-1}t.exports=r})),Ar=s(((e,t)=>{var n=Un(),r=kr();function i(e,t){var i=typeof arguments[1]==`string`?n(arguments,1):arguments[1],a={};for(var o in e)e.hasOwnProperty(o)&&!r(i,o)&&(a[o]=e[o]);return a}t.exports=i})),jr=s(((e,t)=>{var n=Un();function r(e,t){for(var r=typeof arguments[1]==`string`?n(arguments,1):arguments[1],i={},a=0,o;o=r[a++];)i[o]=e[o];return i}t.exports=r})),Mr=s(((e,t)=>{var n=gr(),r=Jn();function i(e,t){return n(e,r(t))}t.exports=i})),Nr=s(((e,t)=>{var n=J();function r(e){var t=0;return n(e,function(){t++}),t}t.exports=r})),Pr=s(((e,t)=>{var n=J(),r=Nr();function i(e,t,i,a){var o=arguments.length>2;if(!r(e)&&!o)throw Error(`reduce of empty object with no initial value`);return n(e,function(e,n,r){o?i=t.call(a,i,e,n,r):(i=e,o=!0)}),i}t.exports=i})),Fr=s(((e,t)=>{var n=lr(),r=Y();function i(e,t,i){return t=r(t,i),n(e,function(e,n,r){return!t(e,n,r)},i)}t.exports=i})),Ir=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Function`)}t.exports=r})),Lr=s(((e,t)=>{var n=Ir();function r(e,t){var r=e[t];if(r!==void 0)return n(r)?r.call(e):r}t.exports=r})),Rr=s(((e,t)=>{var n=Dr();function r(e,t,r){var i=/^(.+)\.(.+)$/.exec(t);i?n(e,i[1])[i[2]]=r:e[t]=r}t.exports=r})),zr=s(((e,t)=>{var n=mr();function r(e,t){if(n(e,t)){for(var r=t.split(`.`),i=r.pop();t=r.shift();)e=e[t];return delete e[i]}else return!0}t.exports=r})),Br=s(((e,t)=>{t.exports={bindAll:Kn(),contains:er(),deepFillIn:nr(),deepMatches:Qn(),deepMixIn:rr(),equals:sr(),every:ir(),fillIn:cr(),filter:lr(),find:ur(),flatten:dr(),forIn:Vn(),forOwn:J(),functions:Hn(),get:pr(),has:mr(),hasOwn:Bn(),keys:hr(),map:gr(),matches:_r(),max:br(),merge:wr(),min:Er(),mixIn:xr(),namespace:Dr(),omit:Ar(),pick:jr(),pluck:Mr(),reduce:Pr(),reject:Fr(),result:Lr(),set:Rr(),size:Nr(),some:$n(),unset:zr(),values:yr()}})),Vr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.default=(0,Br().map)({A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},function(e){return[100*(e.x/e.y),100,100*(1-e.x-e.y)/e.y]}),t.exports=e.default})),Hr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=Math,r=n.pow,i=n.sign,a=n.abs,o={decode:function(e){return e<=.04045?e/12.92:r((e+.055)/1.055,2.4)},encode:function(e){return e<=.0031308?12.92*e:1.055*r(e,1/2.4)-.055}},s={encode:function(e){return e<.001953125?16*e:r(e,1/1.8)},decode:function(e){return e<16*.001953125?e/16:r(e,1.8)}};function c(e){return{decode:function(t){return i(t)*r(a(t),e)},encode:function(t){return i(t)*r(a(t),1/e)}}}e.default={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:o},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:c(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:c(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:s}},t.exports=e.default})),Ur=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});function t(e){return[[e[0][0],e[1][0],e[2][0]],[e[0][1],e[1][1],e[2][1]],[e[0][2],e[1][2],e[2][2]]]}function n(e){return e[0][0]*(e[2][2]*e[1][1]-e[2][1]*e[1][2])+e[1][0]*(e[2][1]*e[0][2]-e[2][2]*e[0][1])+e[2][0]*(e[1][2]*e[0][1]-e[1][1]*e[0][2])}function r(e){var t=1/n(e);return[[(e[2][2]*e[1][1]-e[2][1]*e[1][2])*t,(e[2][1]*e[0][2]-e[2][2]*e[0][1])*t,(e[1][2]*e[0][1]-e[1][1]*e[0][2])*t],[(e[2][0]*e[1][2]-e[2][2]*e[1][0])*t,(e[2][2]*e[0][0]-e[2][0]*e[0][2])*t,(e[1][0]*e[0][2]-e[1][2]*e[0][0])*t],[(e[2][1]*e[1][0]-e[2][0]*e[1][1])*t,(e[2][0]*e[0][1]-e[2][1]*e[0][0])*t,(e[1][1]*e[0][0]-e[1][0]*e[0][1])*t]]}function i(e,t){return[e[0][0]*t[0]+e[0][1]*t[1]+e[0][2]*t[2],e[1][0]*t[0]+e[1][1]*t[1]+e[1][2]*t[2],e[2][0]*t[0]+e[2][1]*t[1]+e[2][2]*t[2]]}function a(e,t){return[[e[0][0]*t[0],e[0][1]*t[1],e[0][2]*t[2]],[e[1][0]*t[0],e[1][1]*t[1],e[1][2]*t[2]],[e[2][0]*t[0],e[2][1]*t[1],e[2][2]*t[2]]]}function o(e,t){return[[e[0][0]*t[0][0]+e[0][1]*t[1][0]+e[0][2]*t[2][0],e[0][0]*t[0][1]+e[0][1]*t[1][1]+e[0][2]*t[2][1],e[0][0]*t[0][2]+e[0][1]*t[1][2]+e[0][2]*t[2][2]],[e[1][0]*t[0][0]+e[1][1]*t[1][0]+e[1][2]*t[2][0],e[1][0]*t[0][1]+e[1][1]*t[1][1]+e[1][2]*t[2][1],e[1][0]*t[0][2]+e[1][1]*t[1][2]+e[1][2]*t[2][2]],[e[2][0]*t[0][0]+e[2][1]*t[1][0]+e[2][2]*t[2][0],e[2][0]*t[0][1]+e[2][1]*t[1][1]+e[2][2]*t[2][1],e[2][0]*t[0][2]+e[2][1]*t[1][2]+e[2][2]*t[2][2]]]}e.transpose=t,e.determinant=n,e.inverse=r,e.multiply=i,e.scalar=a,e.product=o})),Wr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.PI;function n(e){for(var n=e*180/t;n<0;)n+=360;for(;n>360;)n-=360;return n}function r(e){for(var n=t*e/180;n<0;)n+=2*t;for(;n>2*t;)n-=2*t;return n}e.fromRadian=n,e.toRadian=r})),Gr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.round;function n(e){return e[0]==`#`&&(e=e.slice(1)),e.length<6&&(e=e.split(``).map(function(e){return e+e}).join(``)),e.match(/../g).map(function(e){return parseInt(e,16)/255})}function r(e){return`#`+e.map(function(e){return e=t(255*e).toString(16),e.length<2&&(e=`0`+e),e}).join(``)}e.fromHex=n,e.toHex=r})),Kr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=o(Ur()),r=a(Vr()),i=a(Hr());function a(e){return e&&e.__esModule?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function s(){var e=arguments.length<=0||arguments[0]===void 0?i.default.sRGB:arguments[0],t=arguments.length<=1||arguments[1]===void 0?r.default.D65:arguments[1],a=[e.r,e.g,e.b],o=n.transpose(a.map(function(e){return[e.x/e.y,1,(1-e.x-e.y)/e.y]})),s=e.gamma,c=n.multiply(n.inverse(o),t),l=n.scalar(o,c),u=n.inverse(l);return{fromRgb:function(e){return n.multiply(l,e.map(s.decode))},toRgb:function(e){return n.multiply(u,e).map(s.encode)}}}e.default=s,t.exports=e.default})),qr=s(((e,t)=>{t.exports={illuminant:Vr(),workspace:Hr(),matrix:Ur(),degree:Wr(),rgb:Gr(),xyz:Kr()}})),Jr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.cfs=e.distance=e.lerp=e.corLerp=void 0;var t=Br();function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ti/2&&(e>t?t+=i:e+=i),((1-n)*e+n*t)%(i||1/0)}function u(e,t,n){var r={};for(var i in e)r[i]=l(e[i],t[i],n,i);return r}function d(e,t){var n=0;for(var r in e)n+=o(e[r]-t[r],2);return s(n)}function f(e){return t.merge.apply(void 0,r(e.split(``).map(function(e){return n({},e,!0)})))}e.corLerp=l,e.lerp=u,e.distance=d,e.cfs=f})),Yr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=Jr();function a(e,t){var a=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],o=-a,s=1+a,c=Math,l=c.min,u=c.max,d=n([`000`,`fff`].map(function(n){return t.fromXyz(e.fromRgb(r.rgb.fromHex(n)))}),2),f=d[0],p=d[1];function m(n){var r=e.toRgb(t.toXyz(n));return[r.map(function(e){return e>=o&&e<=s}).reduce(function(e,t){return e&&t},!0),r]}function h(e,t){for(var r=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,i.distance)(e,t)>r;){var a=(0,i.lerp)(e,t,.5);n(m(a),1)[0]?e=a:t=a}return e}function g(e){return(0,i.lerp)(f,p,e)}function _(e){return e.map(function(e){return u(o,l(s,e))})}return{contains:m,limit:h,spine:g,crop:_}}e.default=a,t.exports=e.default})),Xr=s((e=>{var t=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0}),e.toNotation=e.fromNotation=e.toHue=e.fromHue=void 0;var n=Jr(),r=Math.floor,i=[{s:`R`,h:20.14,e:.8,H:0},{s:`Y`,h:90,e:.7,H:100},{s:`G`,h:164.25,e:1,H:200},{s:`B`,h:237.53,e:1.2,H:300},{s:`R`,h:380.14,e:.8,H:400}],a=i.map(function(e){return e.s}).slice(0,-1).join(``);function o(e){e50){var o=[n,t];t=o[0],n=o[1],i=100-i}return i<1?a[t]:a[t]+i.toFixed()+a[n]}e.fromHue=o,e.toHue=s,e.fromNotation=l,e.toNotation=u})),Zr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=s(Xr()),a=Jr(),o=Br();function s(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var c=Math,l=c.pow,u=c.sqrt,d=c.exp,f=c.abs,p=c.sign,m=Math,h=m.sin,g=m.cos,_=m.atan2,v={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},y=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],b=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],x=y,S=r.matrix.inverse(y),C=r.matrix.product(b,r.matrix.inverse(y)),w=r.matrix.product(y,r.matrix.inverse(b)),T={whitePoint:r.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ee=(0,a.cfs)(`QJMCshH`),E=(0,a.cfs)(`JCh`);function D(){var e=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],t=arguments.length<=1||arguments[1]===void 0?ee:arguments[1];e=(0,o.merge)(T,e);var a=e.whitePoint,s=e.adaptingLuminance,c=e.backgroundLuminance,m=v[e.surroundType],b=m.F,D=m.c,O=m.N_c,te=a[1],k=1/(5*s+1),A=.2*l(k,4)*5*s+.1*l(1-l(k,4),2)*l(5*s,1/3),ne=c/te,re=.725*l(1/ne,.2),ie=re,ae=1.48+u(ne),oe=e.discounting?1:b*(1-1/3.6*d(-(s+42)/92)),j=n(r.matrix.multiply(y,a).map(function(e){return oe*te/e+1-oe}),3),se=j[0],M=j[1],ce=j[2],N=pe(de(le(a)));function le(e){var t=n(r.matrix.multiply(x,e),3),i=t[0],a=t[1],o=t[2];return[se*i,M*a,ce*o]}function ue(e){var t=n(e,3),i=t[0],a=t[1],o=t[2];return r.matrix.multiply(S,[i/se,a/M,o/ce])}function de(e){return r.matrix.multiply(C,e).map(function(e){var t=l(A*f(e)/100,.42);return p(e)*400*t/(27.13+t)+.1})}function fe(e){return r.matrix.multiply(w,e.map(function(e){var t=e-.1;return p(t)*100/A*l(27.13*f(t)/(400-f(t)),1/.42)}))}function pe(e){var t=n(e,3),r=t[0],i=t[1],a=t[2];return(r*2+i+a/20-.305)*re}function me(e){return 4/D*u(e/100)*(N+4)*l(A,.25)}function he(e){return 6.25*l(D*e/((N+4)*l(A,.25)),2)}function ge(e){return e*l(A,.25)}function _e(e,t){return l(e/100,2)*t/l(A,.25)}function ve(e){return e/l(A,.25)}function ye(e,t){return 100*u(e/t)}function be(e,t){var n=t.Q,r=t.J,a=t.M,o=t.C,s=t.s,c=t.h,l=t.H,u={};return e.J&&(u.J=isNaN(r)?he(n):r),e.C&&(isNaN(o)?isNaN(a)?(n=isNaN(n)?me(r):n,u.C=_e(s,n)):u.C=ve(a):u.C=t.C),e.h&&(u.h=isNaN(c)?i.toHue(l):c),e.Q&&(u.Q=isNaN(n)?me(r):n),e.M&&(u.M=isNaN(a)?ge(o):a),e.s&&(isNaN(s)?(n=isNaN(n)?me(r):n,a=isNaN(a)?ge(o):a,u.s=ye(a,n)):u.s=s),e.H&&(u.H=isNaN(l)?i.fromHue(c):l),u}function P(e){var i=de(le(e)),a=n(i,3),o=a[0],s=a[1],c=a[2],d=o-s*12/11+c/11,f=(o+s-2*c)/9,p=_(f,d),m=r.degree.fromRadian(p),h=1/4*(g(p+2)+3.8),v=100*l(pe(i)/N,D*ae);return be(t,{J:v,C:l(5e4/13*O*ie*h*u(d*d+f*f)/(o+s+21/20*c),.9)*u(v/100)*l(1.64-l(.29,ne),.73),h:m})}function F(e){var t=be(E,e),n=t.J,i=t.C,a=t.h,o=r.degree.toRadian(a),s=l(i/(u(n/100)*l(1.64-l(.29,ne),.73)),10/9),c=1/4*(g(o+2)+3.8),d=N*l(n/100,1/D/ae),p=5e4/13*O*ie*c/s,m=d/re+.305,_=m*61/20*460/1403,v=61/20*220/1403,y=21/20*6300/1403-27/1403,b=h(o),x=g(o),S,C;return s===0||isNaN(s)?S=C=0:f(b)>=f(x)?(C=_/(p/b+v*x/b+y),S=C*x/b):(S=_/(p/x+v+y*b/x),C=S*b/x),ue(fe([20/61*m+451/1403*S+288/1403*C,20/61*m-891/1403*S-261/1403*C,20/61*m-220/1403*S-6300/1403*C]))}return{fromXyz:P,toXyz:F,fillOut:be}}e.default=D,t.exports=e.default})),Qr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=qr(),r=Math,i=r.sqrt,a=r.pow,o=r.exp,s=r.log,c=r.cos,l=r.sin,u=r.atan2,d={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function f(){var e=d[arguments.length<=0||arguments[0]===void 0?`UCS`:arguments[0]],t=e.K_L,r=e.c_1,f=e.c_2;function p(e){var t=e.J,i=e.M,a=e.h,o=n.degree.toRadian(a),u=(1+100*r)*t/(1+r*t),d=1/f*s(1+f*i);return{J_p:u,a_p:d*c(o),b_p:d*l(o)}}function m(e){var t=e.J_p,s=e.a_p,c=e.b_p,l=-t/(r*t-100*r-1),d=(o(f*i(a(s,2)+a(c,2)))-1)/f,p=u(c,s);return{J:l,M:d,h:n.degree.fromRadian(p)}}function h(e,n){return i(a((e.J_p-n.J_p)/t,2)+a(e.a_p-n.a_p,2)+a(e.b_p-n.b_p,2))}return{fromCam:p,toCam:m,distance:h}}e.default=f,t.exports=e.default})),$r=s(((e,t)=>{var n=Jr(),r=Yr(),i=Zr(),a=Qr(),o=Xr();t.exports={gamut:r,cfs:n.cfs,lerp:n.lerp,cam:i,ucs:a,hq:o}})),ei=l(qr(),1),ti=l($r(),1);function ni(e){let t=new q;return t.rgb_r=e[0],t.rgb_g=e[1],t.rgb_b=e[2],t.rgbToHsluv(),[t.hsluv_h,t.hsluv_s,t.hsluv_l]}function ri(e){let t=new q;return t.hsluv_h=e[0],t.hsluv_s=e[1],t.hsluv_l=e[2],t.hsluvToRgb(),[t.rgb_r,t.rgb_g,t.rgb_b]}var ii=ti.default.cam({whitePoint:ei.default.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ti.default.cfs(`JCh`)),ai=ei.default.xyz(ei.default.workspace.sRGB,ei.default.illuminant.D65),oi=e=>ai.toRgb(ii.toXyz({J:e[0],C:e[1],h:e[2]})),si=e=>{let t=ii.fromXyz(ai.fromRgb(e));return[t.J,t.C,t.h]},[ci,li]=(()=>{let e={k_l:1,c1:.007,c2:.0228},t=Math.PI,n=64/t/5,r=1/(5*n+1),i=.2*r**4*(5*n)+.1*(1-r**4)**2*(5*n)**(1/3);return[n=>{let[r,a,o]=n,s=a*i**.25,c=(1+100*e.c1)*r/(1+e.c1*r);c/=e.k_l;let l=1/e.c2*Math.log(1+e.c2*s),u=l*Math.cos(t/180*o),d=l*Math.sin(t/180*o);return[c,u,d]},n=>{let[r,a,o]=n,s=Math.sqrt(a*a+o*o),c=(Math.exp(s*e.c2)-1)/e.c2,l=(180/t*Math.atan2(o,a)+360)%360,u=c/i**.25;return[r/(1+e.c1*(100-r)),u,l]}]})(),ui=e=>oi(li(e)),di=e=>ci(si(e)),fi=console;fi.color=(e,t=``)=>{let n=K(e).luminance();fi.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?`#000`:`#fff`}`)},fi.ramp=(e,t=1)=>{fi.log(`%c `,`font-size: 1px;line-height: 16px;background: ${K.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};var pi=(e,t,n,r,i,a,o=.1)=>{if(e===n||t===r)return!0;let s=(r-t)/(n-e),c=(a+i/s-t+s*e)/(s+1/s),l=a+i/s-c/s;return(i-c)**2+(a-l)**2{let i=(t[0]+n[0])/2,a=e(i);return pi(...t,...n,i,a,r)?null:[i,a]},hi=(e,t,n,r=.1)=>{let i=(n-t)/10,a=[];for(let r=t;rMath.round(e*10**t)/10**t,_i=(e,t=1,n=90,r=.005)=>{let i=hi(t=>e(t).gl()[0],0,t,r),a=hi(t=>e(t).gl()[1],0,t,r),o=hi(t=>e(t).gl()[2],0,t,r);return`linear-gradient(${n}deg, ${Array.from(new Set([...i.map(e=>gi(e[0])),...a.map(e=>gi(e[0])),...o.map(e=>gi(e[0]))].sort((e,t)=>e-t))).map(t=>`${e(t).hex()} ${gi(t*100)}%`).join()});`},vi=e=>{e.Color.prototype.jch=function(){return si(this._rgb.slice(0,3).map(e=>e/255))},e.jch=(...t)=>new e.Color(...oi(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.jab=function(){return di(this._rgb.slice(0,3).map(e=>e/255))},e.jab=(...t)=>new e.Color(...ui(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.hsluv=function(){return ni(this._rgb.slice(0,3).map(e=>e/255))},e.hsluv=(...t)=>new e.Color(...ri(t).map(e=>Math.floor(e*255)),`rgb`);let t=e.interpolate,n={jch:si,jab:di,hsluv:ni},r=(e,t,n)=>(Math.abs(e-t)>360/2&&(e>t?t+=360:e+=360),((1-n)*e+n*t)%360);e.interpolate=(i,a,o=.5,s=`lrgb`)=>{if(n[s]){typeof i!=`object`&&(i=new e.Color(i)),typeof a!=`object`&&(a=new e.Color(a));let t=n[s](i.gl()),c=n[s](a.gl()),l=Number.isNaN(i.hsl()[0]),u=Number.isNaN(a.hsl()[0]),d,f,p;switch(s){case`hsluv`:t[1]<1e-10&&(t[0]=c[0]),t[1]===0&&(t[1]=c[1]),c[1]<1e-10&&(c[0]=t[0]),c[1]===0&&(c[1]=t[1]),d=r(t[0],c[0],o),f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o;break;case`jch`:l&&(t[2]=c[2]),u&&(c[2]=t[2]),d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=r(t[2],c[2],o);break;default:d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o}return e[s](d,f,p).alpha(i.alpha()+o*(a.alpha()-i.alpha()))}return t(i,a,o,s)},e.getCSSGradient=_i},X={mainTRC:2.4,get mainTRCencode(){return 1/this.mainTRC},sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1,mFactor:1.9468554433171,get mFactInv(){return 1/this.mFactor},mOffsetIn:.0387393816571401,mExpAdj:.283343396420869,get mExp(){return this.mExpAdj/this.blkClmp},mOffsetOut:.312865795870758};function yi(e,t,n=-1){let r=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)r[1])return 0;let i=0,a=0,o=`BoW`;return e=e>X.blkThrs?e:e+(X.blkThrs-e)**+X.blkClmp,t=t>X.blkThrs?t:t+(X.blkThrs-t)**+X.blkClmp,Math.abs(t-e)e?(i=(t**+X.normBG-e**+X.normTXT)*X.scaleBoW,a=i-X.loClip?0:i+X.loWoBoffset),n<0?a*100:n==0?Math.round(Math.abs(a)*100)+``+o+``:Number.isInteger(n)?(a*100).toFixed(n):0)}function bi(e=[0,0,0]){function t(e){return(e/255)**X.mainTRC}return X.sRco*t(e[0])+X.sGco*t(e[1])+X.sBco*t(e[2])}var xi=(e,t,n,r,i,a,o,s,c)=>{let l=1-c,u=l*l,d=u*l,f=c*c*c;return{x:d*e+u*3*c*n+l*3*c*c*i+f*o,y:d*t+u*3*c*r+l*3*c*c*a+f*s}},Si=(e,t)=>{let n=[],r={x:+e[0],y:+e[1]};for(let i=0,a=e.length;a-2*!t>i;i+=2){let o=[{x:+e[i-2],y:+e[i-1]},{x:+e[i],y:+e[i+1]},{x:+e[i+2],y:+e[i+3]},{x:+e[i+4],y:+e[i+5]}];t?i?a-4===i?o[3]={x:+e[0],y:+e[1]}:a-2===i&&(o[2]={x:+e[0],y:+e[1]},o[3]={x:+e[2],y:+e[3]}):o[0]={x:+e[a-2],y:+e[a-1]}:a-4===i?o[3]=o[2]:i||(o[0]={x:+e[i],y:+e[i+1]}),n.push([r.x,r.y,(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y]),r=o[2]}return n},Ci=(e,t,n,r,i,a,o,s)=>{let c=e,l=t,u=0;for(let d=1;d<5;d++){let{x:f,y:p}=xi(e,t,n,r,i,a,o,s,d/5);u+=Math.hypot(f-c,p-l),c=f,l=p}return u+=Math.hypot(o-c,s-l),u},wi=(e,t,n,r,i,a,o,s)=>{let c=Math.floor(Ci(e,t,n,r,i,a,o,s)*.75),l=[],u=0;for(let d=0;d<=c;d++){let f=xi(e,t,n,r,i,a,o,s,d/c),p=Math.round(f.x);if(l[p]=f.y,p-u>1){let e=l[u],t=l[p];for(let n=u+1;nl[Math.round(e)]||null},Ti={CAM02:`jab`,CAM02p:`jch`,HEX:`hex`,HSL:`hsl`,HSLuv:`hsluv`,HSV:`hsv`,LAB:`lab`,LCH:`lch`,RGB:`rgb`,OKLAB:`oklab`,OKLCH:`oklch`};function Z(e,t=0){let n=10**t;return Math.round(e*n)/n}function Ei(e,t){let n;return n=e>1?(e-1)*t+1:e<-1?(e+1)*t-1:1,Z(n,2)}function Di(e){return K(String(e)).jch()}function Oi(e){return K(String(e)).hsluv()}function ki(e,t,n){let r=[[],[],[]];if(e.forEach((e,n)=>r.forEach((r,i)=>r.push(t[n],e[i]))),n===`hcl`){let e=r[1];for(let t=1;t{let t=[];for(let n=1;n{e[t]=e[n]}),t.length=0;break}if(t.length){let n=K(`#ccc`).jch()[2];t.forEach(t=>{e[t]=n})}t.length=0;for(let n=e.length-1;n>0;n-=2)if(Number.isNaN(e[n]))t.push(n);else{t.forEach(t=>{e[t]=e[n]});break}for(let t=1;tSi(e).map(e=>wi(...e)));return e=>{let t=i.map(t=>{for(let n=0;nr*t**e+i}function ji({swatches:e,colorKeys:t,colorspace:n,colorSpace:r=n??`LAB`,shift:i=1,fullScale:a=!0,smooth:o=!1,distributeLightness:s=`linear`,sortColor:c=!0,asFun:l=!1}={}){n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead.");let u=Ti[r];if(!u)throw Error(`Colorspace “${r}” not supported`);if(!t)throw Error(`Colorkeys missing: returned “${t}”`);let d;if(a)d=t.map(t=>e-e*(K(t).jch()[0]/100)).sort((e,t)=>e-t).concat(e),d.unshift(0);else{let n=t.map(e=>K(e).jch()[0]/100),r=Math.min(...n),i=Math.max(...n);d=n.map(t=>t===0||isNaN((t-r)/(i-r))?0:e-(t-r)/(i-r)*e).sort((e,t)=>e-t)}let f=Ai(i,[1,e],[1,e]);if(f=d.map(e=>Math.max(0,f(e))),d=f,s===`polynomial`){let t=e=>Math.sqrt(Math.sqrt((e**2.25+e**4)/2));d=f.map(t=>t/e).map(n=>t(n)*e)}let p=t.map((e,t)=>({colorKeys:Di(e),index:t})).sort((e,t)=>t.colorKeys[0]-e.colorKeys[0]).map(e=>t[e.index]),m=[],h;if(a){let e=u===`lch`?K.lch(...K(`#fff`).lch()):`#ffffff`,t=u===`lch`?K.lch(...K(`#000`).lch()):`#000000`;m=[e,...p,t]}else m=c?p:t;let g;if(o){let t=m;if(m=m.map(e=>K(String(e))[u]()),u===`hcl`&&m.forEach(e=>{e[1]=Number.isNaN(e[1])?0:e[1]}),u===`jch`)for(let e=0;eh(t))}else h=K.scale(m.map(e=>typeof e==`object`&&e.constructor===K.Color?e:String(e))).domain(d).mode(u);return l?h:(!o||o===!1?h.colors(e):g).filter(e=>e!=null)}function Mi(e,t){let n=[],r={};return Object.keys(e).forEach(n=>{r[e[n][t]]=e[n]}),Object.keys(r).forEach(e=>n.push(r[e])),n}function Ni(e){return Number.isNaN(e)?0:e}function Pi(e,t,n=!1){if(!e)throw Error(`Cannot convert color value of “${e}”`);if(!Ti[t])throw Error(`Cannot convert to colorspace “${t}”`);let r=Ti[t],i=K(String(e))[r]();if(t===`HSL`&&i.pop(),t===`HEX`){if(n){let t=K(String(e)).rgb();return{r:t[0],g:t[1],b:t[2]}}return i}let a={},o=i.map(Ni);o=o.map((e,t)=>{let i=Z(e),o=t;r===`hsluv`&&(o+=2);let s=r.charAt(o);return r===`jch`&&s===`c`&&(s=`C`),a[s===`j`?`J`:s]=i,r in{lab:1,lch:1,jab:1,jch:1}?n||(s===`l`||s===`j`)&&(i+=`%`):r!==`hsluv`&&(s===`s`||s===`l`||s===`v`)&&(a[s]=Z(e,2),n||(i=Z(e*100),i+=`%`)),i});let s=`${r}(${o.join(`, `)})`;return n?a:s}function Fi(e,t,n){let r=[e,t,n].map(e=>(e/=255,e<=.03928?e/12.92:((e+.055)/1.055)**2.4));return r[0]*.2126+r[1]*.7152+r[2]*.0722}function Ii(e,t,n,r=`wcag2`){if(n===void 0){let e=K.rgb(...t).hsluv()[2];n=Z(e/100,2)}if(r===`wcag2`){let r=Fi(e[0],e[1],e[2]),i=Fi(t[0],t[1],t[2]),a=(r+.05)/(i+.05),o=(i+.05)/(r+.05);return n<.5?a>=1?a:-o:a<1?o:a===1?a:-a}else if(r===`wcag3`)return n<.5?yi(bi(e),bi(t))*-1:yi(bi(e),bi(t));else throw Error(`Contrast calculation method ${r} unsupported; use 'wcag2' or 'wcag3'`)}function Li(e,t){if(!e)throw Error(`Array undefined`);if(!Array.isArray(e))throw Error(`Passed object is not an array`);let n=t===`wcag2`?0:1;return Math.min(...e.filter(e=>e>=n))}function Ri(e,t){if(!e)throw Error(`Ratios undefined`);e=e.sort((e,t)=>e-t);let n=Li(e,t),r=e.indexOf(n),i=[],a=e.slice(0,r),o=e.slice(r,e.length);for(let e=0;ee-t),i}var zi=(e,t,n,r,i)=>{let a=3e3,o=ji({swatches:a,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),s={},c=e=>{if(s[e])return s[e];let r=Ii(K(o(e)).rgb(),t,n,i);return s[e]=r,r},l=e=>{let t=c(0).01&&o;)o--,n/=2,iu.push(o(l(+e)))),u},Q=class{constructor({name:e,colorKeys:t,colorspace:n,colorSpace:r=n??`RGB`,ratios:i,smooth:a=!1,output:o=`HEX`,saturation:s=100}){if(n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),this._name=e,this._colorKeys=t,this._modifiedKeys=t,this._colorspace=r,this._ratios=i,this._smooth=a,this._output=o,this._saturation=s,!this._name)throw Error(`Color missing name`);if(!this._colorKeys)throw Error(`Color Keys are undefined`);if(!Ti[this._colorspace])throw Error(`Colorspace “${r}” not supported`);if(!Ti[this._output])throw Error(`Output “${this._output}” not supported`);for(let e=0;e{let n=K(`${t}`).oklch(),r=n[1]*(this._saturation/100),i=K.oklch(n[0],r,n[2]),a=K.rgb(i).hex();e.push(a)}),this._modifiedKeys=e,this._generateColorScale()}_generateColorScale(){this._colorScale=ji({swatches:3e3,colorKeys:this._modifiedKeys,colorSpace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}},Bi=class extends Q{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){Q.prototype._generateColorScale.call(this);let e=ji({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});e.push(...this.colorKeys);let t=Mi(e.map((e,t)=>({value:Math.round(Oi(e)[2]),index:t})),`value`).map(t=>e[t.index]);return t.length>=101&&(t.length=100,t.push(`#ffffff`)),this._backgroundColorScale=t.map(e=>Pi(e,this._output)),this._backgroundColorScale}},Vi=class{constructor({colors:e,backgroundColor:t,lightness:n,contrast:r=1,saturation:i=100,output:a=`HEX`,formula:o=`wcag2`}){if(this._output=a,this._colors=e,this._lightness=n,this._saturation=i,this._formula=o,this._setBackgroundColor(t),this._setBackgroundColorValue(),this._contrast=r,!this._colors)throw Error(`No colors are defined`);if(!this._backgroundColor)throw Error(`Background color is undefined`);if(e.forEach(e=>{if(!e.ratios)throw Error(`Color ${e.name}'s ratios are undefined`)}),!Ti[this._output])throw Error(`Output “${a}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(e){this._formula=e,this._findContrastColors()}get formula(){return this._formula}set contrast(e){this._contrast=e,this._findContrastColors()}get contrast(){return this._contrast}set lightness(e){this._lightness=e,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(e){this._saturation=e,this._updateColorSaturation(e),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(e){this._setBackgroundColor(e),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(e){this._colors=e,this._findContrastColors()}get colors(){return this._colors}set addColor(e){this._colors.push(e),this._findContrastColors()}set removeColor(e){let t=this._colors.filter(t=>t.name!==e.name);this._colors=t,this._findContrastColors()}set updateColor(e){if(Array.isArray(e))for(let t=0;tn.name===e[t].color);n=n[0];let r=this._colors.indexOf(n),i=this._colors.filter(n=>n.name!==e[t].color);e[t].name&&(n.name=e[t].name),e[t].colorKeys&&(n.colorKeys=e[t].colorKeys),e[t].ratios&&(n.ratios=e[t].ratios),(e[t].colorSpace!==void 0||e[t].colorspace!==void 0)&&(e[t].colorspace!==void 0&&e[t].colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),n.colorSpace=e[t].colorSpace??e[t].colorspace),e[t].smooth&&(n.smooth=e[t].smooth),n._generateColorScale(),i.splice(r,0,n),this._colors=i}else{let t=this._colors.filter(t=>t.name===e.color);t=t[0];let n=this._colors.indexOf(t),r=this._colors.filter(t=>t.name!==e.color);e.name&&(t.name=e.name),e.colorKeys&&(t.colorKeys=e.colorKeys),e.ratios&&(t.ratios=e.ratios),(e.colorSpace!==void 0||e.colorspace!==void 0)&&(e.colorspace!==void 0&&e.colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),t.colorSpace=e.colorSpace??e.colorspace),e.smooth&&(t.smooth=e.smooth),t._generateColorScale(),r.splice(n,0,t),this._colors=r}this._findContrastColors()}set output(e){this._output=e,this._colors.forEach(e=>{e.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(e){if(typeof e==`string`){let t=new Bi({name:`background`,colorKeys:[e],output:`RGB`}),n=Z(K(String(e)).hsluv()[2]);this._backgroundColor=t,this._lightness=n,this._backgroundColorValue=t[this._lightness]}else{e.output=`RGB`;let t=e.backgroundColorScale[this._lightness];this._backgroundColor=e,this._backgroundColorValue=t}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(e){this._colors.map(t=>{t.saturation=e})}_findContrastColors(){let e=K(String(this._backgroundColorValue)).rgb(),t=this._lightness/100,n={background:Pi(this._backgroundColorValue,this._output)},r=[],i=[],a={...n};return r.push(n),this._colors.map(n=>{if(n.ratios!==void 0){let o,s=[],c={name:n.name,values:s},l;Array.isArray(n.ratios)?l=n.ratios:Array.isArray(n.ratios)||(o=Object.keys(n.ratios),l=Object.values(n.ratios)),l=l.map(e=>Ei(+e,this._contrast));let u=zi(n,e,t,l,this._formula).map(e=>Pi(e,this._output));for(let e=0;e{let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},Wi=(e,t,n)=>{let r=e/255,i=t/255,a=n/255,o=Math.min(r,i,a),s=Math.max(r,i,a),c=s-o,l=0,u=0,d=0;return l=c===0?0:s===r?(i-a)/c%6:s===i?(a-r)/c+2:(r-i)/c+4,l=Math.round(l*60),l<0&&(l+=360),d=(s+o)/2,u=c===0?0:c/(1-Math.abs(2*d-1)),u=+(u*100).toFixed(1),d=+(d*100).toFixed(1),[l,u,Math.round(d)]},Gi=(e,t,n,r)=>{let i=n/100,a=t*Math.min(i,1-i)/100,o=t=>{let n=(t+e/30)%12,r=i-a*Math.max(Math.min(n-3,9-n,1),-1);return Math.round(255*r).toString(16).padStart(2,`0`).toUpperCase()},s=o(0),c=o(8),l=o(4),u=((e,t,n)=>Math.min(Math.max(e,t),n))(r,0,1);return`#${s}${c}${l}${Math.round(u*255).toString(16).padStart(2,`0`).toUpperCase()}`},Ki=(e,t,n=1)=>{let r=Ui(e),i=Ui(t===`white`?`#FFFFFF`:t===`black`?`#000000`:t),a=r.map((e,t)=>[(e-i[t])/(255-i[t]),(e-i[t])/(0-i[t])]),o=Hi(Math.max(...a.flat().filter(e=>/^-?\d+\.?\d*$/.test(e)))),s=r.map((e,t)=>Math.round((e-i[t]+i[t]*o)/o));if(s.includes(NaN)){let e=Wi(r[0],r[1],r[2]);return{h:e[0],s:Math.round(e[1]*n),l:e[2],a:1}}let c=Wi(s[0],s[1],s[2]);return{h:c[0],s:Math.round(c[1]*n),l:c[2],a:o}},qi={backgroundColor:`gray`,colorSpace:`OKLCH`,colorSmoothing:!1,formula:`wcag2`,output:`HEX`,colors:{gray:[$(215,20,90),$(215,8,50),$(215,6,25)],red:[$(358,100,58),$(350,100,30)],orange:[$(32,100,48),$(12,100,30)],yellow:[$(50,100,50),$(25,100,20)],lime:[$(100,68,50),$(115,86,25)],green:[$(163,87,42),$(168,100,25)],cyan:[$(185,80,45),$(200,98,35)],blue:[$(212,98,46),$(222,95,25)],purple:[$(258,94,64),$(265,100,35)],fuchsia:[$(295,56,50),$(285,80,25)],pink:[$(334,90,50),$(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function $(e,t,n){return K.hsl(e,t/100,n/100).hex()}function Ji(e,t){let n=e.colorSpace,r=e.colorSmoothing,i=e.themes[t].ratios,a=new Bi({name:`gray`,colorKeys:e.colors.gray,colorspace:n,ratios:i,smooth:r}),o=new Q({name:`blue`,colorKeys:e.colors.blue,colorspace:n,ratios:i,smooth:r}),s=new Q({name:`cyan`,colorKeys:e.colors.cyan,colorspace:n,ratios:i,smooth:r}),c=new Q({name:`fuchsia`,colorKeys:e.colors.fuchsia,colorspace:n,ratios:i,smooth:r}),l=new Q({name:`green`,colorKeys:e.colors.green,colorspace:n,ratios:i,smooth:r}),u=new Q({name:`lime`,colorKeys:e.colors.lime,colorspace:n,ratios:i,smooth:r}),d=new Q({name:`orange`,colorKeys:e.colors.orange,colorspace:n,ratios:i,smooth:r}),f=new Q({name:`pink`,colorKeys:e.colors.pink,colorspace:n,ratios:i,smooth:r}),p=new Q({name:`purple`,colorKeys:e.colors.purple,colorspace:n,ratios:i,smooth:r}),m={gray:a,red:new Q({name:`red`,colorKeys:e.colors.red,colorspace:n,ratios:i,smooth:r}),orange:d,yellow:new Q({name:`yellow`,colorKeys:e.colors.yellow,colorspace:n,ratios:i,smooth:r}),lime:u,green:l,cyan:s,blue:o,purple:p,fuchsia:c,pink:f};return e.colors.custom&&(m.custom=new Q({name:`custom`,colorKeys:e.colors.custom,colorspace:n,ratios:i,smooth:r})),new Vi({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function Yi(e){let t={};for(let n of Object.keys(e.themes))t[n]=Ji(e,n);return t}function Xi(e){qi.colors.custom=[e];let t=Yi(qi);return Object.fromEntries(Object.entries(t).map(([e,t])=>{let n=t.find(e=>e&&e.name===`custom`),r=Object.fromEntries(n.values.map(({name:e,value:t})=>[e,t]));for(let[e,n]of Object.entries(r)){let i=Ki(n,t[0].background);r[`alpha${e.charAt(0).toUpperCase()+e.slice(1)}`]=Gi(i.h,i.s,i.l,i.a)}return[e,r]}))}return e.generateCustomColors=Xi,e.generateThemesJson=Yi,e.hslToHex=$,e.leonardoConfig=qi,e})({}); \ No newline at end of file diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt index 5851a758f0..d8f81dbbbb 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/CompoundIcons.kt @@ -130,6 +130,9 @@ object CompoundIcons { @Composable fun Collapse(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_collapse) } + @Composable fun CollapseAll(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_collapse_all) + } @Composable fun Company(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_company) } @@ -142,6 +145,9 @@ object CompoundIcons { @Composable fun Copy(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_copy) } + @Composable fun Crop(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_crop) + } @Composable fun DarkMode(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_dark_mode) } @@ -202,6 +208,9 @@ object CompoundIcons { @Composable fun Expand(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_expand) } + @Composable fun ExpandAll(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_expand_all) + } @Composable fun Explore(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_explore) } @@ -229,6 +238,15 @@ object CompoundIcons { @Composable fun Filter(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_filter) } + @Composable fun FlipHorizontal(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_flip_horizontal) + } + @Composable fun FlipVertical(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_flip_vertical) + } + @Composable fun Folder(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_folder) + } @Composable fun Forward(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_forward) } @@ -496,6 +514,12 @@ object CompoundIcons { @Composable fun RotateRight(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_rotate_right) } + @Composable fun Save(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_save) + } + @Composable fun SaveSolid(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_save_solid) + } @Composable fun Search(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_search) } @@ -607,6 +631,9 @@ object CompoundIcons { @Composable fun Unpin(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_unpin) } + @Composable fun Unsave(): ImageVector { + return ImageVector.vectorResource(R.drawable.ic_compound_unsave) + } @Composable fun User(): ImageVector { return ImageVector.vectorResource(R.drawable.ic_compound_user) } @@ -735,10 +762,12 @@ object CompoundIcons { CloudSolid(), Code(), Collapse(), + CollapseAll(), Company(), Compose(), Computer(), Copy(), + Crop(), DarkMode(), Delete(), DevicePasskey(), @@ -759,6 +788,7 @@ object CompoundIcons { ErrorSolid(), ExitFullScreen(), Expand(), + ExpandAll(), Explore(), ExportArchive(), Extensions(), @@ -768,6 +798,9 @@ object CompoundIcons { FileError(), Files(), Filter(), + FlipHorizontal(), + FlipVertical(), + Folder(), Forward(), FullScreen(), Grid(), @@ -857,6 +890,8 @@ object CompoundIcons { Room(), RotateLeft(), RotateRight(), + Save(), + SaveSolid(), Search(), Section(), Send(), @@ -894,6 +929,7 @@ object CompoundIcons { Unknown(), UnknownSolid(), Unpin(), + Unsave(), User(), UserAdd(), UserAddSolid(), @@ -963,10 +999,12 @@ object CompoundIcons { R.drawable.ic_compound_cloud_solid, R.drawable.ic_compound_code, R.drawable.ic_compound_collapse, + R.drawable.ic_compound_collapse_all, R.drawable.ic_compound_company, R.drawable.ic_compound_compose, R.drawable.ic_compound_computer, R.drawable.ic_compound_copy, + R.drawable.ic_compound_crop, R.drawable.ic_compound_dark_mode, R.drawable.ic_compound_delete, R.drawable.ic_compound_device_passkey, @@ -987,6 +1025,7 @@ object CompoundIcons { R.drawable.ic_compound_error_solid, R.drawable.ic_compound_exit_full_screen, R.drawable.ic_compound_expand, + R.drawable.ic_compound_expand_all, R.drawable.ic_compound_explore, R.drawable.ic_compound_export_archive, R.drawable.ic_compound_extensions, @@ -996,6 +1035,9 @@ object CompoundIcons { R.drawable.ic_compound_file_error, R.drawable.ic_compound_files, R.drawable.ic_compound_filter, + R.drawable.ic_compound_flip_horizontal, + R.drawable.ic_compound_flip_vertical, + R.drawable.ic_compound_folder, R.drawable.ic_compound_forward, R.drawable.ic_compound_full_screen, R.drawable.ic_compound_grid, @@ -1085,6 +1127,8 @@ object CompoundIcons { R.drawable.ic_compound_room, R.drawable.ic_compound_rotate_left, R.drawable.ic_compound_rotate_right, + R.drawable.ic_compound_save, + R.drawable.ic_compound_save_solid, R.drawable.ic_compound_search, R.drawable.ic_compound_section, R.drawable.ic_compound_send, @@ -1122,6 +1166,7 @@ object CompoundIcons { R.drawable.ic_compound_unknown, R.drawable.ic_compound_unknown_solid, R.drawable.ic_compound_unpin, + R.drawable.ic_compound_unsave, R.drawable.ic_compound_user, R.drawable.ic_compound_user_add, R.drawable.ic_compound_user_add_solid, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt index f5a54bb7be..6bc6c89a63 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt @@ -175,6 +175,8 @@ data class SemanticColors( val iconTertiaryAlpha: Color, /** Used to separate core sections of the UI as well as containers */ val separatorPrimary: Color, + /** Secondary shade for separating sections of components or list items */ + val separatorSecondary: Color, /** Accent text colour for plain actions. */ val textActionAccent: Color, /** Default text colour for plain actions. */ diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt index 35a1234854..e9334de0e7 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDark.kt @@ -103,6 +103,7 @@ val compoundColorsDark = SemanticColors( iconTertiary = DarkColorTokens.colorGray800, iconTertiaryAlpha = DarkColorTokens.colorAlphaGray800, separatorPrimary = DarkColorTokens.colorGray400, + separatorSecondary = DarkColorTokens.colorGray300, textActionAccent = DarkColorTokens.colorGreen900, textActionPrimary = DarkColorTokens.colorGray1400, textBadgeAccent = DarkColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt index 802e3d56b0..a3ef51cff1 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsDarkHc.kt @@ -103,6 +103,7 @@ val compoundColorsHcDark = SemanticColors( iconTertiary = DarkHcColorTokens.colorGray800, iconTertiaryAlpha = DarkHcColorTokens.colorAlphaGray800, separatorPrimary = DarkHcColorTokens.colorGray400, + separatorSecondary = DarkHcColorTokens.colorGray300, textActionAccent = DarkHcColorTokens.colorGreen900, textActionPrimary = DarkHcColorTokens.colorGray1400, textBadgeAccent = DarkHcColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt index 166f9ddafc..75153cb66b 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLight.kt @@ -103,6 +103,7 @@ val compoundColorsLight = SemanticColors( iconTertiary = LightColorTokens.colorGray800, iconTertiaryAlpha = LightColorTokens.colorAlphaGray800, separatorPrimary = LightColorTokens.colorGray400, + separatorSecondary = LightColorTokens.colorGray300, textActionAccent = LightColorTokens.colorGreen900, textActionPrimary = LightColorTokens.colorGray1400, textBadgeAccent = LightColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt index 8914b41bfc..fa40a2e2ab 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColorsLightHc.kt @@ -103,6 +103,7 @@ val compoundColorsHcLight = SemanticColors( iconTertiary = LightHcColorTokens.colorGray800, iconTertiaryAlpha = LightHcColorTokens.colorAlphaGray800, separatorPrimary = LightHcColorTokens.colorGray400, + separatorSecondary = LightHcColorTokens.colorGray300, textActionAccent = LightHcColorTokens.colorGreen900, textActionPrimary = LightHcColorTokens.colorGray1400, textBadgeAccent = LightHcColorTokens.colorGreen1100, diff --git a/libraries/compound/src/main/res/drawable/ic_compound_collapse_all.xml b/libraries/compound/src/main/res/drawable/ic_compound_collapse_all.xml new file mode 100644 index 0000000000..7257b7d2c3 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_collapse_all.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_crop.xml b/libraries/compound/src/main/res/drawable/ic_compound_crop.xml new file mode 100644 index 0000000000..dc9513a239 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_crop.xml @@ -0,0 +1,12 @@ + + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_expand_all.xml b/libraries/compound/src/main/res/drawable/ic_compound_expand_all.xml new file mode 100644 index 0000000000..fcef02880b --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_expand_all.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_flip_horizontal.xml b/libraries/compound/src/main/res/drawable/ic_compound_flip_horizontal.xml new file mode 100644 index 0000000000..90a3a98f44 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_flip_horizontal.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_flip_vertical.xml b/libraries/compound/src/main/res/drawable/ic_compound_flip_vertical.xml new file mode 100644 index 0000000000..430e5eb3fa --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_flip_vertical.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_save.xml b/libraries/compound/src/main/res/drawable/ic_compound_save.xml new file mode 100644 index 0000000000..3bedcc272d --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_save.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_save_solid.xml b/libraries/compound/src/main/res/drawable/ic_compound_save_solid.xml new file mode 100644 index 0000000000..5d453834c7 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_save_solid.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/compound/src/main/res/drawable/ic_compound_unsave.xml b/libraries/compound/src/main/res/drawable/ic_compound_unsave.xml new file mode 100644 index 0000000000..0dfddcfe46 --- /dev/null +++ b/libraries/compound/src/main/res/drawable/ic_compound_unsave.xml @@ -0,0 +1,13 @@ + + + + diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png index 79992a9708..9c80a760b7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30b39281fd597089c94c8ff1680297143989d6da97d6f5b15198be5f92469483 -size 114653 +oid sha256:787bcdf784abedc6858fdab6c7b5dac9e36d42a1047ac0bad181449dbb757585 +size 117936 From a9ecf3c5dcd263e49811ebc2990e66d26b994f99 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 28 May 2026 15:00:03 +0200 Subject: [PATCH 0595/1083] Add flip actions to image edition --- .../preview/AttachmentsPreviewEvent.kt | 2 + .../preview/AttachmentsPreviewPresenter.kt | 12 ++++ .../preview/AttachmentsPreviewView.kt | 2 + .../imageeditor/AttachmentImageEditor.kt | 37 ++++++---- .../imageeditor/AttachmentImageEditorState.kt | 47 ++++++++++-- .../AttachmentImageEditorStateProvider.kt | 10 +++ .../imageeditor/AttachmentImageEditorView.kt | 72 +++++++++++++++---- .../impl/src/main/res/values/localazy.xml | 6 ++ .../AttachmentsPreviewPresenterTest.kt | 35 ++++++++- .../imageeditor/AttachmentImageEditsTest.kt | 33 +++++++++ 10 files changed, 219 insertions(+), 37 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt index a7c64845d1..fb9fddbb48 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt @@ -17,6 +17,8 @@ sealed interface AttachmentsPreviewEvent { data object OpenImageEditor : AttachmentsPreviewEvent data object CloseImageEditor : AttachmentsPreviewEvent data object RotateImageToTheLeft : AttachmentsPreviewEvent + data object FlipImageHorizontally : AttachmentsPreviewEvent + data object FlipImageVertically : AttachmentsPreviewEvent data object ApplyImageEdits : AttachmentsPreviewEvent data object ResetImageEdits : AttachmentsPreviewEvent data class UpdateImageCropRect(val cropRect: NormalizedCropRect) : AttachmentsPreviewEvent diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index cab00d99c1..0f60d7ff0e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -295,6 +295,18 @@ class AttachmentsPreviewPresenter( edits = pendingState.edits.rotateAntiClockwise() ) } + AttachmentsPreviewEvent.FlipImageHorizontally -> { + val pendingState = imageEditorState ?: return + imageEditorState = pendingState.copy( + edits = pendingState.edits.flipHorizontally() + ) + } + AttachmentsPreviewEvent.FlipImageVertically -> { + val pendingState = imageEditorState ?: return + imageEditorState = pendingState.copy( + edits = pendingState.edits.flipVertically() + ) + } AttachmentsPreviewEvent.ResetImageEdits -> { imageEditorState = imageEditorState?.copy( edits = AttachmentImageEdits() diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt index 1714a8b8dc..926106a5ee 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt @@ -136,6 +136,8 @@ fun AttachmentsPreviewView( state.eventSink(AttachmentsPreviewEvent.UpdateImageCropRect(cropRect)) }, onRotateClick = { state.eventSink(AttachmentsPreviewEvent.RotateImageToTheLeft) }, + onFlipHorizontallyClick = { state.eventSink(AttachmentsPreviewEvent.FlipImageHorizontally) }, + onFlipVerticallyClick = { state.eventSink(AttachmentsPreviewEvent.FlipImageVertically) }, onCancelClick = ::postCloseImageEditor, onResetClick = ::postResetImageEditor, onDoneClick = ::postApplyImageEdits, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt index cb66802184..f8d199a74e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditor.kt @@ -87,30 +87,30 @@ class DefaultAttachmentImageEditor( decodedBitmap.recycle() } - val rotatedBitmap = normalizedBitmap.rotateQuarterTurns(edits.rotationQuarterTurns) - if (rotatedBitmap !== normalizedBitmap) { + val transformedBitmap = normalizedBitmap.applyEdits(edits) + if (transformedBitmap !== normalizedBitmap) { normalizedBitmap.recycle() } val cropRect = edits.cropRect.toPixelRect( - imageWidth = rotatedBitmap.width, - imageHeight = rotatedBitmap.height, + imageWidth = transformedBitmap.width, + imageHeight = transformedBitmap.height, ) val isCropUnchanged = cropRect.left == 0 && cropRect.top == 0 && - cropRect.width() == rotatedBitmap.width && cropRect.height() == rotatedBitmap.height + cropRect.width() == transformedBitmap.width && cropRect.height() == transformedBitmap.height val croppedBitmap = if (isCropUnchanged) { - rotatedBitmap + transformedBitmap } else { Bitmap.createBitmap( - rotatedBitmap, + transformedBitmap, cropRect.left, cropRect.top, cropRect.width(), cropRect.height(), ) } - if (croppedBitmap !== rotatedBitmap) { - rotatedBitmap.recycle() + if (croppedBitmap !== transformedBitmap) { + transformedBitmap.recycle() } val editedMediaDir = File(context.cacheDir, EDITED_MEDIA_DIR_NAME).apply { mkdirs() } @@ -141,11 +141,22 @@ internal fun exportedMimeTypeFor(sourceMimeType: String?): String { } } -private fun Bitmap.rotateQuarterTurns(quarterTurns: Int): Bitmap { - val normalizedTurns = (quarterTurns % 4 + 4) % 4 - if (normalizedTurns == 0) return this +private fun Bitmap.applyEdits(edits: AttachmentImageEdits): Bitmap { + val normalizedTurns = (edits.rotationQuarterTurns % 4 + 4) % 4 + if (normalizedTurns == 0 && !edits.isFlippedHorizontally && !edits.isFlippedVertically) { + return this + } + val centerX = width / 2f + val centerY = height / 2f val matrix = Matrix().apply { - postRotate(normalizedTurns * 90f) + val scaleX = if (edits.isFlippedHorizontally) -1f else 1f + val scaleY = if (edits.isFlippedVertically) -1f else 1f + if (scaleX < 0f || scaleY < 0f) { + postScale(scaleX, scaleY, centerX, centerY) + } + if (normalizedTurns != 0) { + postRotate(normalizedTurns * 90f, centerX, centerY) + } } return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt index 3c8af52ce8..b798df2747 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorState.kt @@ -26,6 +26,8 @@ data class AttachmentImageEditorState( data class AttachmentImageEdits( val cropRect: NormalizedCropRect = NormalizedCropRect.default(), val rotationQuarterTurns: Int = 0, + val isFlippedHorizontally: Boolean = false, + val isFlippedVertically: Boolean = false, ) { val normalizedRotationQuarterTurns: Int get() = rotationQuarterTurns % 4 @@ -34,18 +36,32 @@ data class AttachmentImageEdits( get() = normalizedRotationQuarterTurns * 90 val hasChanges: Boolean - get() = cropRect != NormalizedCropRect.default() || normalizedRotationQuarterTurns != 0 + get() = cropRect != NormalizedCropRect.default() || + normalizedRotationQuarterTurns != 0 || + isFlippedHorizontally || + isFlippedVertically fun rotateAntiClockwise(): AttachmentImageEdits { return copy( rotationQuarterTurns = (normalizedRotationQuarterTurns + 3) % 4, // Also update the crop rect to keep the same selected area - cropRect = NormalizedCropRect( - left = cropRect.top, - top = 1f - cropRect.right, - right = cropRect.bottom, - bottom = 1f - cropRect.left, - ) + cropRect = cropRect.rotateAntiClockwise() + ) + } + + fun flipHorizontally(): AttachmentImageEdits { + return copy( + isFlippedHorizontally = !isFlippedHorizontally, + // Also update the crop rect to keep the same selected area + cropRect = cropRect.flipHorizontally(), + ) + } + + fun flipVertically(): AttachmentImageEdits { + return copy( + isFlippedVertically = !isFlippedVertically, + // Also update the crop rect to keep the same selected area + cropRect = cropRect.flipVertically(), ) } } @@ -135,6 +151,23 @@ data class NormalizedCropRect( ) } + fun rotateAntiClockwise() = copy( + left = top, + top = 1f - right, + right = bottom, + bottom = 1f - left, + ) + + fun flipHorizontally() = copy( + left = 1f - right, + right = 1f - left, + ) + + fun flipVertically() = copy( + top = 1f - bottom, + bottom = 1f - top, + ) + companion object { fun default() = NormalizedCropRect( left = DEFAULT_CROP_MARGIN, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt index df4bb5257f..7c542fd1a8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditorStateProvider.kt @@ -75,6 +75,16 @@ open class AttachmentImageEditorStateProvider : PreviewParameterProvider Unit, onRotateClick: () -> Unit, + onFlipHorizontallyClick: () -> Unit, + onFlipVerticallyClick: () -> Unit, onResetClick: () -> Unit, onCancelClick: () -> Unit, onDoneClick: () -> Unit, @@ -101,8 +101,18 @@ fun AttachmentImageEditorView( state.edits.rotationDegrees, state.edits.rotationDegrees, ) - val rotateButtonBackground = ElementTheme.colors.bgCanvasDefault - + val flipHorizontalLabel = stringResource(R.string.screen_image_edition_a11y_flip_image_horizontally) + val flipHorizontalState = if (state.edits.isFlippedHorizontally) { + stringResource(R.string.screen_image_edition_a11y_flip_image_horizontally_state_flipped) + } else { + stringResource(R.string.screen_image_edition_a11y_flip_image_horizontally_state_original) + } + val flipVerticalLabel = stringResource(R.string.screen_image_edition_a11y_flip_image_vertically) + val flipVerticalState = if (state.edits.isFlippedVertically) { + stringResource(R.string.screen_image_edition_a11y_flip_image_vertically_state_flipped) + } else { + stringResource(R.string.screen_image_edition_a11y_flip_image_vertically_state_original) + } Scaffold( modifier = modifier.fillMaxSize(), topBar = { @@ -158,37 +168,57 @@ fun AttachmentImageEditorView( onClick = onResetClick, ) } - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.Center, + Row( + modifier = Modifier.weight(2f), + // Center the content horizontally + horizontalArrangement = Arrangement.Center, ) { + IconButton( + onClick = onFlipHorizontallyClick, + modifier = Modifier + .clearAndSetSemantics { + contentDescription = flipHorizontalLabel + stateDescription = flipHorizontalState + } + ) { + Icon( + imageVector = CompoundIcons.FlipHorizontal(), + contentDescription = null, + ) + } IconButton( onClick = onRotateClick, modifier = Modifier - .background( - color = rotateButtonBackground, - shape = CircleShape, - ) - .border(1.dp, ElementTheme.colors.borderInteractiveSecondary, CircleShape) .clearAndSetSemantics { contentDescription = rotateContentDescription stateDescription = rotationStateDescription } ) { Icon( - modifier = Modifier - .size(22.dp), imageVector = CompoundIcons.RotateLeft(), contentDescription = null, ) } + IconButton( + onClick = onFlipVerticallyClick, + modifier = Modifier + .clearAndSetSemantics { + contentDescription = flipVerticalLabel + stateDescription = flipVerticalState + } + ) { + Icon( + imageVector = CompoundIcons.FlipVertical(), + contentDescription = null, + ) + } } Box( modifier = Modifier.weight(1f), contentAlignment = Alignment.CenterEnd, ) { TextButton( - text = stringResource(CommonStrings.action_done), + text = stringResource(CommonStrings.action_save), onClick = onDoneClick, ) } @@ -204,6 +234,8 @@ private fun BoxScope.CropEditorCanvas( ) { var imageSize by remember(state.localMedia.uri) { mutableStateOf(IntSize.Zero) } val rotationQuarterTurns = state.edits.normalizedRotationQuarterTurns + val flipScaleX = if (state.edits.isFlippedHorizontally) -1f else 1f + val flipScaleY = if (state.edits.isFlippedVertically) -1f else 1f var imageRect by remember { mutableStateOf(Rect.Zero) } @@ -257,6 +289,10 @@ private fun BoxScope.CropEditorCanvas( contentDescription = null, modifier = Modifier .requiredSize(imageLayoutWidthDp, imageLayoutHeightDp) + .graphicsLayer { + scaleX = flipScaleX + scaleY = flipScaleY + } .graphicsLayer { rotationZ = rotationQuarterTurns * 90f }, contentScale = ContentScale.Fit, ) @@ -266,6 +302,10 @@ private fun BoxScope.CropEditorCanvas( contentDescription = stringResource(CommonStrings.common_image), modifier = Modifier .requiredSize(imageLayoutWidthDp, imageLayoutHeightDp) + .graphicsLayer { + scaleX = flipScaleX + scaleY = flipScaleY + } .graphicsLayer { rotationZ = rotationQuarterTurns * 90f }, contentScale = ContentScale.Fit, onState = { painterState -> @@ -642,6 +682,8 @@ internal fun AttachmentImageEditorViewPreview( state = state, onCropRectChange = {}, onRotateClick = {}, + onFlipHorizontallyClick = {}, + onFlipVerticallyClick = {}, onResetClick = {}, onCancelClick = {}, onDoneClick = {}, diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index 908646b048..173a4e78ad 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -16,6 +16,12 @@ "Travel & Places" "Recent emojis" "Symbols" + "Flip image horizontally" + "Flipped horizontally" + "Original" + "Flip image vertically" + "Flipped vertically" + "Original" "Rotate the image to the left" "%1$d degree" diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 140d4f8ea3..817eb740d7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -624,7 +624,11 @@ class AttachmentsPreviewPresenterTest { val croppedState = awaitItem() croppedState.eventSink(AttachmentsPreviewEvent.RotateImageToTheLeft) val rotatedState = awaitItem() - rotatedState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) + rotatedState.eventSink(AttachmentsPreviewEvent.FlipImageHorizontally) + val flippedHorizontallyState = awaitItem() + flippedHorizontallyState.eventSink(AttachmentsPreviewEvent.FlipImageVertically) + val flippedState = awaitItem() + flippedState.eventSink(AttachmentsPreviewEvent.ApplyImageEdits) val appliedState = consumeItemsUntilPredicate { !it.isApplyingImageEdits && it.imageEditorState == null }.last() assertThat((appliedState.attachment as Attachment.Media).localMedia.uri).isEqualTo(editedUri) @@ -638,9 +642,36 @@ class AttachmentsPreviewPresenterTest { right = cropRect.bottom, bottom = 1f - cropRect.left, ) - reopenedState.imageEditorState.edits.cropRect.assertIsSimilarTo(rotatedCropRect) + val flippedCropRect = NormalizedCropRect( + left = 1f - rotatedCropRect.right, + top = 1f - rotatedCropRect.bottom, + right = 1f - rotatedCropRect.left, + bottom = 1f - rotatedCropRect.top, + ) + reopenedState.imageEditorState.edits.cropRect.assertIsSimilarTo(flippedCropRect) assertThat(reopenedState.imageEditorState.edits.rotationQuarterTurns).isEqualTo(3) assertThat(reopenedState.imageEditorState.edits.rotationDegrees).isEqualTo(270) + assertThat(reopenedState.imageEditorState.edits.isFlippedHorizontally).isTrue() + assertThat(reopenedState.imageEditorState.edits.isFlippedVertically).isTrue() + } + } + + @Test + fun `present - image editor flip events update edits`() = runTest { + val presenter = createAttachmentsPreviewPresenter(displayMediaQualitySelectorViews = true) + + presenter.test { + val initialState = awaitItem() + initialState.eventSink(AttachmentsPreviewEvent.OpenImageEditor) + val editorState = consumeItemsUntilPredicate { it.imageEditorState != null }.last() + + editorState.eventSink(AttachmentsPreviewEvent.FlipImageHorizontally) + val flippedHorizontallyState = awaitItem() + assertThat(flippedHorizontallyState.imageEditorState?.edits?.isFlippedHorizontally).isTrue() + + flippedHorizontallyState.eventSink(AttachmentsPreviewEvent.FlipImageVertically) + val flippedState = awaitItem() + assertThat(flippedState.imageEditorState?.edits?.isFlippedVertically).isTrue() } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt index 43c893dd05..eb989967ef 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/preview/imageeditor/AttachmentImageEditsTest.kt @@ -42,4 +42,37 @@ class AttachmentImageEditsTest { assertThat(result.cropRect.bottom).isWithin(0.0001f).of(0.8f) assertThat(result.hasChanges).isTrue() } + + @Test + fun `flip horizontally updates crop and change tracking`() { + val sut = AttachmentImageEdits( + cropRect = NormalizedCropRect( + left = 0.1f, + top = 0.3f, + right = 0.6f, + bottom = 0.9f, + ) + ) + val result = sut.flipHorizontally() + assertThat(result.isFlippedHorizontally).isTrue() + assertThat(result.cropRect.left).isWithin(0.0001f).of(0.4f) + assertThat(result.cropRect.right).isWithin(0.0001f).of(0.9f) + assertThat(result.cropRect.top).isWithin(0.0001f).of(0.3f) + assertThat(result.cropRect.bottom).isWithin(0.0001f).of(0.9f) + assertThat(result.hasChanges).isTrue() + } + + @Test + fun `flip vertical twice resets to default state`() { + val edits = AttachmentImageEdits().flipVertically().flipVertically() + assertThat(edits.isFlippedVertically).isFalse() + assertThat(edits.hasChanges).isFalse() + } + + @Test + fun `flip horizontally twice resets to default state`() { + val edits = AttachmentImageEdits().flipHorizontally().flipHorizontally() + assertThat(edits.isFlippedVertically).isFalse() + assertThat(edits.hasChanges).isFalse() + } } From 959fd008ea0918d84cc9b1c8c4ebb169e7ae4846 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 3 Jun 2026 09:27:24 +0000 Subject: [PATCH 0596/1083] Update screenshots --- ...nts.preview.imageeditor_AttachmentImageEditorView_0_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_1_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_2_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_3_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_4_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_5_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_6_en.png | 3 +++ ...nts.preview.imageeditor_AttachmentImageEditorView_7_en.png | 3 +++ ...s.impl.attachments.preview_AttachmentsPreviewView_6_en.png | 4 ++-- 9 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png index 3bd0c2ba54..148289d4dd 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51f0b3f7e4bb16728f21055de37b7b2780fd2a1fc65b6bd4564334daeab20763 -size 329042 +oid sha256:b64ae2fd2462ec3b62750084f47ec29c984ef4279a465b926c9d36e23834092e +size 328321 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png index bf0a11f093..21d03570b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5febc6580e4f0bda75a27445157ace7f1acb620c17cba55ca5d2a9330743c1de -size 283397 +oid sha256:864883e9220a4d653d2d6b555ace89c77891a1ade04cd2f49d89c8bb765c6774 +size 282733 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png index 2ae328d7eb..8edee63bc1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34b6dfe4e65612615c3dc87e5f65bd0b160d97527c4a4749b496bf8d48819d96 -size 256641 +oid sha256:de82970da241172b94f822f8792e6fc721dcfc7f0f67e3523962e253e9750884 +size 255933 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png index 553c54a63d..1857dc249d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d99c470fd5134e0a84b284ed32f4c93de01561e630ef32d7c22a4b476bb871b1 -size 277852 +oid sha256:e95d7091485a2e5bb3ca8966c8fa93f21e2e5fd2d939e7582224ebf32c05b619 +size 277160 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png index 6c3a6f4bf6..25a72fa80f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b15a04a861812e3e4dee0a6a30c6afef4ab171c5261d1e5bd5a234bb7296d97 -size 251908 +oid sha256:1ce3085cf45a94e014c9ea79a46d47741fb098853ac81e7531fdbfe32e8d6f5a +size 251213 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png index 530c5e5bb6..f899ad5d43 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c32b4744750b9f18612bded2e292dde151e2bfdd8a69a36c88044f5ca3a76f8e -size 311315 +oid sha256:1ca032575e4ebd75a2ebc5a4cb9f966e48cdfa56f4ff42d6d9309fa3577a1adb +size 310609 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en.png new file mode 100644 index 0000000000..374a59ce84 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:846467c023fb2f6a091c6d350927c2891ddcd164dace189d157a8570339e2d92 +size 282932 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en.png new file mode 100644 index 0000000000..b7cd1d9387 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91472488cf265e9ba62a8b6690fa34ced41ebbf7a4668424c02464086aaf9f9c +size 283181 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png index fbff934ed8..ea4995ba89 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f52a267ee2aa300185191aa3e610787c58d7222bc8e4a7570879d4c5fd37133d -size 328936 +oid sha256:0c6a5c845db0d9ffef0074062cea67134bdabbe91fd1826b2236a0f92e4a6dff +size 328222 From 1863b3aef777ab60842204b0880d448cb02bd5c2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 12:41:54 +0200 Subject: [PATCH 0597/1083] Update dependency org.matrix.rustcomponents:sdk-android to v26.06.3 (#6947) 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 52f1d08862..1af9ef2e2f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -183,7 +183,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.26" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.06.3" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 4812cf9070f05ff3304cb15725efde27819c3915 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:18:43 +0200 Subject: [PATCH 0598/1083] Update dependency com.github.matrix-org:matrix-analytics-events to v0.36.0 (#6939) 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 1af9ef2e2f..9657aaf15d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -229,7 +229,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" posthog = "com.posthog:posthog-android:3.47.0" sentry = "io.sentry:sentry-android:8.41.0" # main branch can be tested replacing the version with main-SNAPSHOT -matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.33.2" +matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.36.0" # Emojibase matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.3" From 2ab780576aed9ae63dc344b9e048fad22444ef4f Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 3 Jun 2026 16:34:06 +0200 Subject: [PATCH 0599/1083] Remove the `FloatingDateBadge` feature flag (#6950) * Remove the `FloatingDateBadge` feature. This is now always enabled. * Update screenshots --------- Co-authored-by: ElementBot --- .../features/messages/impl/timeline/TimelinePresenter.kt | 4 ---- .../features/messages/impl/timeline/TimelineState.kt | 1 - .../messages/impl/timeline/TimelineStateProvider.kt | 2 -- .../features/messages/impl/timeline/TimelineView.kt | 2 +- .../android/libraries/featureflag/api/FeatureFlags.kt | 7 ------- ...atures.messages.impl.timeline_TimelineView_Day_9_en.png | 4 ++-- ...ures.messages.impl.timeline_TimelineView_Night_9_en.png | 4 ++-- 7 files changed, 5 insertions(+), 19 deletions(-) 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 0681a0ff38..0941b5c3f1 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 @@ -148,9 +148,6 @@ class TimelinePresenter( val displayThreadSummaries by produceState(false) { value = featureFlagService.isFeatureEnabled(FeatureFlags.Threads) } - val displayFloatingDateBadge by produceState(false) { - value = featureFlagService.isFeatureEnabled(FeatureFlags.FloatingDateBadge) - } fun handleEvent(event: TimelineEvent) { when (event) { @@ -323,7 +320,6 @@ class TimelinePresenter( messageShieldDialogData = messageShieldDialogData.value, resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, - displayFloatingDateBadge = displayFloatingDateBadge, eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 1869ad6906..03f0083856 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -34,7 +34,6 @@ data class TimelineState( val messageShieldDialogData: MessageShieldData?, val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val displayThreadSummaries: Boolean, - val displayFloatingDateBadge: Boolean, val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 0bf293eca4..3ed50f34a0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -58,7 +58,6 @@ fun aTimelineState( messageShield: MessageShield? = null, resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), displayThreadSummaries: Boolean = false, - displayFloatingDateBadge: Boolean = false, eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId @@ -78,7 +77,6 @@ fun aTimelineState( messageShieldDialogData = messageShield?.let { MessageShieldData(it) }, resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, displayThreadSummaries = displayThreadSummaries, - displayFloatingDateBadge = displayFloatingDateBadge, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 41a828abb4..0791366105 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -213,7 +213,7 @@ fun TimelineView( onFocusEventRender = ::onFocusEventRender, ) - if (state.displayFloatingDateBadge && useReverseLayout) { + if (useReverseLayout) { FloatingDateBadgeOverlay( lazyListState = lazyListState, timelineItems = state.timelineItems, 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 097df99800..ec6aaba3d3 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 @@ -108,13 +108,6 @@ enum class FeatureFlags( defaultValue = { true }, isFinished = false, ), - FloatingDateBadge( - key = "feature.floating_date_badge", - title = "Display sticky date headers in the timeline", - description = "When scrolling, a sticky date badge will be displayed so you can easily know on which date the messages you're seeing were sent.", - defaultValue = { false }, - isFinished = false, - ), SlashCommand( key = "feature.slash_command", title = "Parse slash commands in the message composer", 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 6ff4840c57..7e8f621890 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:fbd5652457d495c3c6692c151be27c985cf47e95c8b89af9b6edc8c1b734acc8 -size 371265 +oid sha256:f90a31ccde2880e01393be2bd36e9554d8087aa52bfe36e29b8514a32fea3dcd +size 752143 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 825618ae17..180c910e51 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:75ace43e27a0c8f9786b0494931c3ef5e12d903e7417dddecfb34c9526e74f3c -size 149314 +oid sha256:a853885aac641afe3fb28f3a1d9ebf6744862f153ea22bc2d511ff957b814a19 +size 747294 From 63ba6d2b18418b2f6ceda7432205cf34d95df670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 3 Jun 2026 16:36:52 +0200 Subject: [PATCH 0600/1083] Try fixing flaky screenshots for location timeline items Replace the `rememberAsyncImagePainter` call when in preview mode with fake values --- .../features/location/api/StaticMapView.kt | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) 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 a61cbe1c24..225032ce6e 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 @@ -8,6 +8,7 @@ package io.element.android.features.location.api +import android.graphics.Bitmap import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints @@ -24,13 +25,17 @@ 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.platform.LocalInspectionMode import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.core.graphics.createBitmap import coil3.Extras +import coil3.asImage import coil3.compose.AsyncImagePainter import coil3.compose.rememberAsyncImagePainter import coil3.request.ImageRequest +import coil3.request.SuccessResult import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.api.internal.StaticMapPlaceholder import io.element.android.features.location.api.internal.StaticMapUrlBuilder @@ -128,32 +133,46 @@ private fun BoxWithConstraintsScope.LoadableMapContent( 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, + val (painter, state) = if (LocalInspectionMode.current) { + val painter = painterResource(R.drawable.blurred_map) + val state = AsyncImagePainter.State.Success( + painter = painter, + result = SuccessResult( + image = createBitmap(1, 1, Bitmap.Config.ALPHA_8).asImage(), + request = ImageRequest.Builder(context).build() + ) + ) + painter to state + } else { + 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() - } - ) + .size(width = constraints.maxWidth, height = constraints.maxHeight) + .apply { + extras.set(Extras.Key("retry_hash"), retryHash).build() + } + .build() + } + ) + + val state by painter.state.collectAsState() + painter to state + } - val state by painter.state.collectAsState() when (state) { is AsyncImagePainter.State.Success -> { Image( From efbe5e43f4a902466fcb1ed0bf5ad2492b6add50 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 3 Jun 2026 14:52:45 +0000 Subject: [PATCH 0601/1083] Update screenshots --- .../images/features.location.api_StaticMapView_Day_0_en.png | 4 ++-- .../images/features.location.api_StaticMapView_Night_0_en.png | 4 ++-- ...ine.components.event_TimelineItemLocationView_Day_0_en.png | 4 ++-- ...ine.components.event_TimelineItemLocationView_Day_1_en.png | 4 ++-- ...ine.components.event_TimelineItemLocationView_Day_3_en.png | 4 ++-- ...e.components.event_TimelineItemLocationView_Night_0_en.png | 4 ++-- ...e.components.event_TimelineItemLocationView_Night_1_en.png | 4 ++-- ...e.components.event_TimelineItemLocationView_Night_3_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_9_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_9_en.png | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) 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 cedf0b1b7c..08d12dee1d 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:56a86695d2c25c94a8e79c27c8f525229cc348201073566909f83a681b37ac30 -size 251329 +oid sha256:96a7cf99e31fcf4264665d5947263819d9fdb0df36500a5e5f670029813e6ea9 +size 169908 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 dea0d3f21c..ee1b34be27 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:0c2b2a7071bd1c21ff706525e2416169507fef364485c651c429baefa15d4c9f -size 104240 +oid sha256:fdb8317be088145c6ac24551a2c330e24f8396744e491f9daecea5144f4fbc66 +size 65342 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 c11e6b978e..ed6e6824ff 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:3daba890afd2533e1746f1ffd0c535674a4a238e4591da2a6bcbe31716d26858 -size 143676 +oid sha256:2c6a096640356f79c0812ef1e75f7e34f2b1cd5c61ea1f1663139192de0d9e5b +size 133923 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 def7635efc..649c8be5bf 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:b9f2f0e8ba6829cb3d83dcc0c6d3ed5a91a0346771f84adb6731ba5fdac01f4d -size 122009 +oid sha256:85bf71d3c04e2992e7557074a119664d4a8608092123a5b8e3acfb06ada6c356 +size 114920 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png index 07613eb447..69f33275b8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f85b9e88dca466b567769291fb69afac535135c3a07f412d6b8203968460519 -size 120940 +oid sha256:9b7bf2e64df1e9ddd57052374be6d6f912a982d51106852b50952d0ac367a5f6 +size 114157 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 b9280ec225..103bc9cde5 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:463a2e544b2806f4082c813ec3ba8c6ce0ad0ebcd8ee32666806757a90c248f5 -size 57131 +oid sha256:2a0493e053d6e49bf8c80f40efb056ab433432cb2abb876d295d1cb7977fdc66 +size 58552 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 f06f86068a..41e2855f01 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:00da192b3b46897c9d50986ecd84e07332cd2b490ebc8f3893a9497e72f18af8 -size 41478 +oid sha256:4b80f58cc648745a64aa6163e1c6d9b7e4c578abab3ba11734228b63b922b95b +size 43823 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png index 4cb5fc6e48..4c0e098731 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c015bae5b3ce8c4447c62a13fb74d855c23b0e41bf0b128a1834d30781c0d1f8 -size 41110 +oid sha256:aaada944746ed97d74bbd358e071d46ba18696fb9ad19be41647159c075a51dd +size 43093 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 7e8f621890..7242fa9889 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:f90a31ccde2880e01393be2bd36e9554d8087aa52bfe36e29b8514a32fea3dcd -size 752143 +oid sha256:9e212eb68de26ca2765e2a67043b2e3bbb3c763884684a89cbba8792f8cb1190 +size 369666 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 180c910e51..f9e7cff264 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:a853885aac641afe3fb28f3a1d9ebf6744862f153ea22bc2d511ff957b814a19 -size 747294 +oid sha256:5db05495db43f14234678b60efe04e7cad6d5d54fdd1e8f9550e0a02b02369bb +size 154516 From 27cdc0fe7dad1f3070eee2cb8d71184de3853f2e Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Wed, 3 Jun 2026 18:08:35 +0300 Subject: [PATCH 0602/1083] Add unread count to the room unread indicator (#6887) * Add unread indicator count * Address review --- .../impl/components/RoomListContentView.kt | 1 + .../home/impl/components/RoomSummaryRow.kt | 14 ++++++++- .../roomlist/RoomListContentStateProvider.kt | 2 ++ .../home/impl/roomlist/RoomListPresenter.kt | 13 ++++++-- .../home/impl/roomlist/RoomListState.kt | 1 + .../impl/roomlist/RoomListPresenterTest.kt | 4 +++ .../designsystem/atomic/atoms/CounterAtom.kt | 10 +++++-- .../atomic/atoms/UnreadIndicatorAtom.kt | 30 ++++++++++++++----- .../libraries/featureflag/api/FeatureFlags.kt | 7 +++++ 9 files changed, 69 insertions(+), 13 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt index dee175a7b1..266b6f5a59 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomListContentView.kt @@ -279,6 +279,7 @@ private fun RoomsViewList( hideInviteAvatars = hideInvitesAvatars, isInviteSeen = room.displayType == RoomSummaryDisplayType.INVITE && state.seenRoomInvites.contains(room.roomId), + showUnreadCount = state.showUnreadCount, onClick = onRoomClick, eventSink = eventSink, ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index 72ecb5046d..934f60aa29 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -75,6 +75,7 @@ internal fun RoomSummaryRow( room: RoomListRoomSummary, hideInviteAvatars: Boolean, isInviteSeen: Boolean, + showUnreadCount: Boolean = false, onClick: (RoomListRoomSummary) -> Unit, eventSink: (RoomListEvent) -> Unit, modifier: Modifier = Modifier, @@ -127,7 +128,7 @@ internal fun RoomSummaryRow( timestamp = room.timestamp, isHighlighted = room.isHighlighted ) - MessagePreviewAndIndicatorRow(room = room) + MessagePreviewAndIndicatorRow(room = room, showUnreadCount = showUnreadCount) } } RoomSummaryDisplayType.KNOCKED -> { @@ -273,6 +274,7 @@ private fun InviteSubtitle( @Composable private fun MessagePreviewAndIndicatorRow( room: RoomListRoomSummary, + showUnreadCount: Boolean, modifier: Modifier = Modifier, ) { Row( @@ -360,8 +362,18 @@ private fun MessagePreviewAndIndicatorRow( } if (room.hasNewContent) { val contentDescription = stringResource(CommonStrings.a11y_notifications_new_messages) + val count = if (showUnreadCount) { + if (room.userDefinedNotificationMode == RoomNotificationMode.MUTE) { + room.numberOfUnreadMessages + } else { + room.numberOfUnreadNotifications + } + } else { + null + } UnreadIndicatorAtom( color = tint, + count = count, contentDescription = contentDescription, ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContentStateProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContentStateProvider.kt index c79e79be73..0ac2b7bf62 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContentStateProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListContentStateProvider.kt @@ -36,6 +36,7 @@ open class RoomListContentStateProvider : PreviewParameterProvider = aRoomListRoomSummaryList(), fullScreenIntentPermissionsState: FullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(), batteryOptimizationState: BatteryOptimizationState = aBatteryOptimizationState(), @@ -43,6 +44,7 @@ internal fun aRoomsContentState( ) = RoomListContentState.Rooms( securityBannerState = securityBannerState, showNewNotificationSoundBanner = showNewNotificationSoundBanner, + showUnreadCount = showUnreadCount, fullScreenIntentPermissionsState = fullScreenIntentPermissionsState, batteryOptimizationState = batteryOptimizationState, summaries = summaries, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt index 2010555cd7..a741da14e9 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt @@ -44,6 +44,8 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -90,6 +92,7 @@ class RoomListPresenter( private val announcementService: AnnouncementService, private val coldStartWatcher: AnalyticsColdStartWatcher, private val spaceFiltersPresenter: Presenter, + private val featureFlagService: FeatureFlagService, ) : Presenter { private val encryptionService = client.encryptionService @@ -165,13 +168,17 @@ class RoomListPresenter( roomListDataSource.updateFilter(allFilters) } + val canReportRoom by produceState(false) { value = client.canReportRoom() } + val showUnreadCount by produceState(false) { + value = featureFlagService.isFeatureEnabled(FeatureFlags.UnreadIndicatorCount) + } + val contentState = roomListContentState( securityBannerDismissed, showNewNotificationSoundBanner, + showUnreadCount, ) - val canReportRoom by produceState(false) { value = client.canReportRoom() } - return RoomListState( contextMenu = contextMenu.value, declineInviteMenu = declineInviteMenu.value, @@ -226,6 +233,7 @@ class RoomListPresenter( private fun roomListContentState( securityBannerDismissed: Boolean, showNewNotificationSoundBanner: Boolean, + showUnreadCount: Boolean, ): RoomListContentState { val roomSummaries by produceState(initialValue = AsyncData.Loading()) { roomListDataSource.roomSummariesFlow.collect { value = AsyncData.Success(it) } @@ -254,6 +262,7 @@ class RoomListPresenter( RoomListContentState.Rooms( securityBannerState = securityBannerState, showNewNotificationSoundBanner = showNewNotificationSoundBanner, + showUnreadCount = showUnreadCount, fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(), batteryOptimizationState = batteryOptimizationPresenter.present(), summaries = roomSummaries.dataOrNull().orEmpty().toImmutableList(), diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt index e0f4943621..c03bd56664 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListState.kt @@ -72,6 +72,7 @@ sealed interface RoomListContentState { val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState, val batteryOptimizationState: BatteryOptimizationState, val showNewNotificationSoundBanner: Boolean, + val showUnreadCount: Boolean, val summaries: ImmutableList, val seenRoomInvites: ImmutableSet, ) : RoomListContentState diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt index 5c2c3e294b..2f3f1c87a5 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt @@ -36,6 +36,8 @@ import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter import io.element.android.libraries.eventformatter.test.FakeRoomLatestEventFormatter +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -669,6 +671,7 @@ class RoomListPresenterTest { appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), announcementService: AnnouncementService = FakeAnnouncementService(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService(), ) = RoomListPresenter( client = client, leaveRoomPresenter = { leaveRoomState }, @@ -697,5 +700,6 @@ class RoomListPresenterTest { seenInvitesStore = seenInvitesStore, announcementService = announcementService, coldStartWatcher = FakeAnalyticsColdStartWatcher(), + featureFlagService = featureFlagService, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/CounterAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/CounterAtom.kt index a051fd4c80..3bbd3c12a7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/CounterAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/CounterAtom.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.dp @@ -37,13 +38,18 @@ private const val MAX_COUNT_STRING = "+$MAX_COUNT" * @param count The number to display. If the number is greater than [MAX_COUNT], the counter will display [MAX_COUNT_STRING]. * If the number is less than 1, the counter will not be displayed. * @param modifier The modifier to apply to this layout. + * @param containerColor The background color of the counter. When null, uses [isCritical] to pick a default. + * @param contentColor The text color inside the counter. When null, uses [textOnSolidPrimary]. * @param textStyle The style to apply to the text inside the counter. * @param isCritical If true, the counter will use a critical color scheme, otherwise it will use an accent color scheme. + * Only used when [containerColor] is null. */ @Composable fun CounterAtom( count: Int, modifier: Modifier = Modifier, + containerColor: Color? = null, + contentColor: Color? = null, textStyle: TextStyle = CounterAtomDefaults.textStyle, isCritical: Boolean = false, ) { @@ -65,7 +71,7 @@ fun CounterAtom( .size(squareSize.toDp() + 1.dp) .clip(CircleShape) .background( - if (isCritical) { + containerColor ?: if (isCritical) { ElementTheme.colors.iconCriticalPrimary } else { ElementTheme.colors.iconAccentPrimary @@ -76,7 +82,7 @@ fun CounterAtom( modifier = Modifier.align(Alignment.Center), text = countAsText, style = textStyle, - color = ElementTheme.colors.textOnSolidPrimary, + color = contentColor ?: ElementTheme.colors.textOnSolidPrimary, ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt index d2db3aec8e..ff49bab06f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/UnreadIndicatorAtom.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.designsystem.atomic.atoms import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.runtime.Composable @@ -29,19 +30,32 @@ import io.element.android.libraries.designsystem.theme.unreadIndicator fun UnreadIndicatorAtom( modifier: Modifier = Modifier, size: Dp = 12.dp, + count: Long? = null, color: Color = ElementTheme.colors.unreadIndicator, isVisible: Boolean = true, contentDescription: String? = null, ) { - Box( - modifier = modifier - .semantics { + when { + !isVisible -> Spacer(modifier = modifier.size(size)) + count != null && count >= 1 -> CounterAtom( + count = count.toInt(), + modifier = modifier.semantics { contentDescription?.let { this.contentDescription = it } - } - .size(size) - .clip(CircleShape) - .background(if (isVisible) color else Color.Transparent) - ) + }, + containerColor = color, + contentColor = ElementTheme.colors.bgCanvasDefault, + textStyle = ElementTheme.typography.fontBodySmMedium, + ) + else -> Box( + modifier = modifier + .semantics { + contentDescription?.let { this.contentDescription = it } + } + .size(size) + .clip(CircleShape) + .background(color), + ) + } } @PreviewsDayNight 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 ec6aaba3d3..0127e41c99 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 @@ -130,4 +130,11 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + UnreadIndicatorCount( + key = "feature.unread_indicator_count", + title = "Unread indicator count", + description = "Show the number of unread messages on the unread indicator in the room list.", + defaultValue = { false }, + isFinished = false, + ), } From 930aa4f1db869f147806a3cd43bb9461b6ae845f Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 3 Jun 2026 21:52:54 +0200 Subject: [PATCH 0603/1083] change: ensure UserLocationState is computed from the Presenters instead of Views --- .../location/impl/common/UserLocationState.kt | 42 --------- .../impl/common/ui/UserLocationPuck.kt | 54 ++++-------- .../DefaultUserLocationStateFactory.kt | 38 +++++++++ .../impl/common/userlocation/Location.kt | 26 ++++++ .../PlatformLocationProvider.kt | 2 +- .../common/userlocation/UserLocationState.kt | 18 ++++ .../UserLocationTrackingEffect.kt} | 36 ++++++-- .../service/LiveLocationSharingService.kt | 2 +- .../impl/share/ShareLocationPresenter.kt | 6 +- .../location/impl/share/ShareLocationState.kt | 3 +- .../impl/share/ShareLocationStateProvider.kt | 14 +-- .../location/impl/share/ShareLocationView.kt | 16 ++-- .../impl/show/ShowLocationPresenter.kt | 85 ++++++++++--------- .../location/impl/show/ShowLocationState.kt | 4 +- .../impl/show/ShowLocationStateProvider.kt | 20 ++--- .../location/impl/show/ShowLocationView.kt | 15 ++-- .../common/FakeUserLocationStateFactory.kt | 18 ++++ .../DefaultShareLocationEntryPointTest.kt | 2 + .../impl/share/ShareLocationPresenterTest.kt | 7 +- .../impl/share/ShareLocationViewTest.kt | 2 - .../show/DefaultShowLocationEntryPointTest.kt | 2 + .../impl/show/ShowLocationPresenterTest.kt | 81 ++++++------------ 22 files changed, 265 insertions(+), 228 deletions(-) delete mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/DefaultUserLocationStateFactory.kt create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/Location.kt rename features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/{ => userlocation}/PlatformLocationProvider.kt (98%) create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationState.kt rename features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/{ui/SimpleLocationTrackingEffect.kt => userlocation/UserLocationTrackingEffect.kt} (60%) create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/FakeUserLocationStateFactory.kt diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt deleted file mode 100644 index 01533a421d..0000000000 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/UserLocationState.kt +++ /dev/null @@ -1,42 +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.features.location.impl.common - -import android.annotation.SuppressLint -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.platform.LocalInspectionMode -import org.maplibre.compose.location.DesiredAccuracy -import org.maplibre.compose.location.Location -import org.maplibre.compose.location.rememberNullLocationProvider -import org.maplibre.spatialk.units.extensions.meters -import kotlin.time.Duration.Companion.seconds - -class UserLocationState(locationState: State) { - val location: Location? by locationState -} - -@SuppressLint("MissingPermission") -@Composable -fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState { - val isPreview = LocalInspectionMode.current - val locationProvider = if (isPreview || !hasLocationPermission) { - rememberNullLocationProvider() - } else { - rememberPlatformLocationProvider( - updateInterval = 5.seconds, - desiredAccuracy = DesiredAccuracy.High, - minDistance = 5.meters, - ) - } - val locationState = locationProvider.location.collectAsState() - return remember { UserLocationState(locationState) } -} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt index 5bcbf6a9b2..074404a4cc 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt @@ -10,9 +10,8 @@ package io.element.android.features.location.impl.common.ui import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.features.location.impl.common.MapDefaults -import io.element.android.features.location.impl.common.UserLocationState import org.maplibre.compose.camera.CameraState +import org.maplibre.compose.location.Location import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationPuckColors import org.maplibre.compose.location.LocationPuckSizes @@ -20,40 +19,23 @@ import org.maplibre.compose.location.LocationPuckSizes @Composable fun UserLocationPuck( cameraState: CameraState, - locationState: UserLocationState, - trackUserLocation: Boolean, + location: Location?, ) { - SimpleLocationTrackingEffect( - locationState = locationState, - enabled = trackUserLocation, - ) { currentLocation -> - val target = currentLocation?.position?.value ?: cameraState.position.target - val newPosition = cameraState.position.copy( - target = target, - // Force pointing to NORTH - bearing = 0.0, - zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM) + LocationPuck( + idPrefix = "user-location", + location = location, + cameraState = cameraState, + accuracyThreshold = Float.POSITIVE_INFINITY, + showBearingAccuracy = false, + showBearing = false, + sizes = LocationPuckSizes( + dotRadius = 8.dp, + dotStrokeWidth = 2.dp, + ), + colors = LocationPuckColors( + dotFillColorCurrentLocation = ElementTheme.colors.iconAccentPrimary, + dotFillColorOldLocation = ElementTheme.colors.iconAccentTertiary, + dotStrokeColor = ElementTheme.colors.bgCanvasDefault, ) - cameraState.animateTo(newPosition) - } - val location = locationState.location - if (location != null) { - LocationPuck( - idPrefix = "user-location", - location = location, - cameraState = cameraState, - accuracyThreshold = Float.POSITIVE_INFINITY, - showBearingAccuracy = false, - showBearing = false, - sizes = LocationPuckSizes( - dotRadius = 8.dp, - dotStrokeWidth = 2.dp, - ), - colors = LocationPuckColors( - dotFillColorCurrentLocation = ElementTheme.colors.iconAccentPrimary, - dotFillColorOldLocation = ElementTheme.colors.iconAccentTertiary, - dotStrokeColor = ElementTheme.colors.bgCanvasDefault, - ) - ) - } + ) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/DefaultUserLocationStateFactory.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/DefaultUserLocationStateFactory.kt new file mode 100644 index 0000000000..01a2b92d4a --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/DefaultUserLocationStateFactory.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common.userlocation + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.di.RoomScope +import org.maplibre.compose.location.DesiredAccuracy +import org.maplibre.compose.location.rememberNullLocationProvider +import org.maplibre.spatialk.units.extensions.meters +import kotlin.time.Duration.Companion.seconds + +@ContributesBinding(RoomScope::class) +class DefaultUserLocationStateFactory : UserLocationState.Factory { + @Composable + override fun create(hasLocationPermission: Boolean): UserLocationState { + val locationProvider = if (!hasLocationPermission) { + rememberNullLocationProvider() + } else { + @SuppressLint("MissingPermission") + rememberPlatformLocationProvider( + updateInterval = 5.seconds, + desiredAccuracy = DesiredAccuracy.High, + minDistance = 5.meters, + ) + } + val location by locationProvider.location.collectAsState() + return UserLocationState(location) + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/Location.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/Location.kt new file mode 100644 index 0000000000..9777e14af5 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/Location.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common.userlocation + +import io.element.android.features.location.api.Location +import org.maplibre.compose.location.PositionWithAccuracy +import org.maplibre.spatialk.geojson.Position +import org.maplibre.spatialk.units.extensions.meters +import kotlin.time.TimeSource +import org.maplibre.compose.location.Location as MapLibreLocation + +fun Location.asMapLibreLocation(): MapLibreLocation { + return MapLibreLocation( + position = PositionWithAccuracy( + value = Position(latitude = lat, longitude = lon), + accuracy = accuracy?.toDouble()?.meters + ), + // Not relevant as not used + timestamp = TimeSource.Monotonic.markNow(), + ) +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/PlatformLocationProvider.kt similarity index 98% rename from features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt rename to features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/PlatformLocationProvider.kt index 7988c73e68..54e6d19cf6 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/PlatformLocationProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/PlatformLocationProvider.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.location.impl.common +package io.element.android.features.location.impl.common.userlocation import android.Manifest import android.annotation.SuppressLint diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationState.kt new file mode 100644 index 0000000000..d9dc2037a6 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationState.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common.userlocation + +import androidx.compose.runtime.Composable +import org.maplibre.compose.location.Location + +data class UserLocationState(val location: Location?) { + fun interface Factory { + @Composable + fun create(hasLocationPermission: Boolean): UserLocationState + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationTrackingEffect.kt similarity index 60% rename from features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt rename to features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationTrackingEffect.kt index cda360be9e..ca6c10b7fa 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/SimpleLocationTrackingEffect.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/userlocation/UserLocationTrackingEffect.kt @@ -5,15 +5,16 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.location.impl.common.ui +package io.element.android.features.location.impl.common.userlocation import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.snapshotFlow -import io.element.android.features.location.impl.common.UserLocationState +import io.element.android.features.location.impl.common.MapDefaults import kotlinx.coroutines.flow.distinctUntilChanged +import org.maplibre.compose.camera.CameraState import org.maplibre.compose.location.Location import kotlin.math.abs @@ -22,16 +23,17 @@ import kotlin.math.abs * TODO remove once https://github.com/maplibre/maplibre-compose/issues/808 is fixed */ @Composable -internal fun SimpleLocationTrackingEffect( +internal fun UserLocationTrackingEffect( locationState: UserLocationState, enabled: Boolean = true, precision: Double = 0.00001, onLocationChange: suspend (Location?) -> Unit, ) { val latestOnLocationChange by rememberUpdatedState(onLocationChange) - LaunchedEffect(locationState, enabled) { + val latestLocationState by rememberUpdatedState(locationState) + LaunchedEffect(enabled) { if (!enabled) return@LaunchedEffect - val locationStateFlow = snapshotFlow { locationState.location } + val locationStateFlow = snapshotFlow { latestLocationState.location } locationStateFlow .distinctUntilChanged { oldLocation, newLocation -> if (oldLocation != null && newLocation != null) { @@ -49,3 +51,27 @@ internal fun SimpleLocationTrackingEffect( } } } + +@Composable +internal fun UserLocationTrackingEffect( + cameraState: CameraState, + locationState: UserLocationState, + enabled: Boolean = true, + precision: Double = 0.00001, +) { + UserLocationTrackingEffect( + locationState = locationState, + enabled = enabled, + precision = precision + ) { location -> + val target = location?.position?.value ?: cameraState.position.target + cameraState.animateTo( + cameraState.position.copy( + target = target, + // Force pointing to NORTH + bearing = 0.0, + zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM) + ) + ) + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt index d682ba0df6..21a0a081d8 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -14,7 +14,7 @@ import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION import android.os.IBinder import androidx.core.app.ServiceCompat import dev.zacsweers.metro.Inject -import io.element.android.features.location.impl.common.PlatformLocationProvider +import io.element.android.features.location.impl.common.userlocation.PlatformLocationProvider import io.element.android.features.location.impl.di.LocationBindings import io.element.android.features.location.impl.live.notification.LiveLocationSharingNotificationCreator import io.element.android.libraries.architecture.bindings diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index 6a769f8958..5b0d7679f7 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -33,6 +33,7 @@ import io.element.android.features.location.impl.common.permissions.PermissionsP import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.location.impl.common.sendLiveLocationPermissions import io.element.android.features.location.impl.common.toDialogState +import io.element.android.features.location.impl.common.userlocation.UserLocationState import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.messages.api.MessageComposerContext import io.element.android.libraries.architecture.AsyncAction @@ -70,6 +71,7 @@ class ShareLocationPresenter( private val durationFormatter: DurationFormatter, private val liveLocationShareManager: ActiveLiveLocationShareManager, private val liveLocationStore: LiveLocationStore, + private val userLocationStateFactory: UserLocationState.Factory, ) : Presenter { @AssistedFactory fun interface Factory { @@ -123,6 +125,8 @@ class ShareLocationPresenter( } } + val userLocationState = userLocationStateFactory.create(permissionsState.isAnyGranted) + LaunchedEffect(permissionsState.permissions) { checkLocationConstraints() } fun handleEvent(event: ShareLocationEvent) { @@ -171,7 +175,7 @@ class ShareLocationPresenter( currentUser = currentUser, dialogState = dialogState, trackUserLocation = trackUserPosition, - hasLocationPermission = permissionsState.isAnyGranted, + userLocationState = userLocationState, canShareLiveLocation = timelineMode.canShareLiveLocation(), appName = appName, startLiveLocationAction = startLiveLocationAction.value, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt index 9e78345bab..fb1b803435 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt @@ -9,6 +9,7 @@ package io.element.android.features.location.impl.share import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.impl.common.userlocation.UserLocationState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.user.MatrixUser @@ -19,7 +20,7 @@ data class ShareLocationState( val currentUser: MatrixUser, val dialogState: Dialog, val trackUserLocation: Boolean, - val hasLocationPermission: Boolean, + val userLocationState: UserLocationState, val appName: String, val canShareLiveLocation: Boolean, val startLiveLocationAction: AsyncAction, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt index e7942b12df..ed8d46afd3 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.location.impl.share import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.impl.common.userlocation.UserLocationState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.UserId @@ -26,43 +27,35 @@ class ShareLocationStateProvider : PreviewParameterProvider aShareLocationState( dialogState = ShareLocationState.Dialog.None, trackUserPosition = false, - hasLocationPermission = false, ), aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionDenied), trackUserPosition = false, - hasLocationPermission = false, ), aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionRationale), trackUserPosition = false, - hasLocationPermission = false, ), aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled), trackUserPosition = false, - hasLocationPermission = true, ), aShareLocationState( dialogState = ShareLocationState.Dialog.None, trackUserPosition = false, - hasLocationPermission = true, ), aShareLocationState( dialogState = ShareLocationState.Dialog.None, trackUserPosition = true, - hasLocationPermission = true, ), aShareLocationState( dialogState = ShareLocationState.Dialog.None, trackUserPosition = true, - hasLocationPermission = true, canShareLiveLocation = true, ), aShareLocationState( dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, trackUserPosition = true, - hasLocationPermission = true, canShareLiveLocation = true, ), aShareLocationState( @@ -74,7 +67,6 @@ class ShareLocationStateProvider : PreviewParameterProvider ) ), trackUserPosition = true, - hasLocationPermission = true, canShareLiveLocation = true, ), aShareLocationState( @@ -88,7 +80,7 @@ fun aShareLocationState( currentUser: MatrixUser = MatrixUser(UserId("@user:matrix.org")), dialogState: ShareLocationState.Dialog = ShareLocationState.Dialog.None, trackUserPosition: Boolean = false, - hasLocationPermission: Boolean = false, + userLocationState: UserLocationState = UserLocationState(null), canShareLiveLocation: Boolean = false, appName: String = APP_NAME, startLiveLocationAction: AsyncAction = AsyncAction.Uninitialized, @@ -99,7 +91,7 @@ fun aShareLocationState( currentUser = currentUser, dialogState = dialogState, trackUserLocation = trackUserPosition, - hasLocationPermission = hasLocationPermission, + userLocationState = userLocationState, canShareLiveLocation = canShareLiveLocation, appName = appName, startLiveLocationAction = startLiveLocationAction, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index da7410f0bb..4760b3597c 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -39,12 +39,11 @@ import io.element.android.features.location.api.Location import io.element.android.features.location.api.internal.centerBottomEdge import io.element.android.features.location.impl.R import io.element.android.features.location.impl.common.MapDefaults -import io.element.android.features.location.impl.common.UserLocationState -import io.element.android.features.location.impl.common.rememberUserLocationState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialog import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold import io.element.android.features.location.impl.common.ui.UserLocationPuck +import io.element.android.features.location.impl.common.userlocation.UserLocationTrackingEffect import io.element.android.features.location.impl.share.ShareLocationEvent.StartLiveLocationShare import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.components.LocationPin @@ -109,7 +108,6 @@ fun ShareLocationView( bottomSheetState = rememberStandardBottomSheetState(initialValue = SheetValue.Expanded) ) val cameraState = rememberCameraState(firstPosition = MapDefaults.defaultCameraPosition) - val userLocationState = rememberUserLocationState(state.hasLocationPermission) LaunchedEffect(cameraState.isCameraMoving) { if (cameraState.moveReason == CameraMoveReason.GESTURE) { @@ -136,15 +134,18 @@ fun ShareLocationView( BottomSheetContent( cameraState = cameraState, state = state, - userLocationState = userLocationState, navigateUp = navigateUp ) }, mapContent = { + UserLocationTrackingEffect( + cameraState = cameraState, + locationState = state.userLocationState, + enabled = state.trackUserLocation, + ) UserLocationPuck( cameraState = cameraState, - locationState = userLocationState, - trackUserLocation = state.trackUserLocation + location = state.userLocationState.location, ) }, overlayContent = { sheetPadding -> @@ -215,11 +216,10 @@ private fun StartLiveLocationActionView( private fun BottomSheetContent( cameraState: CameraState, state: ShareLocationState, - userLocationState: UserLocationState, navigateUp: () -> Unit, ) { Spacer(Modifier.height(20.dp)) - val userLocation = userLocationState.location + val userLocation = state.userLocationState.location if (state.trackUserLocation && userLocation != null) { ShareCurrentLocationItem { state.eventSink( 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 bdb6dd26b8..8ea857c6b9 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 @@ -10,12 +10,14 @@ package io.element.android.features.location.impl.show import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState 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.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory @@ -23,6 +25,7 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.features.location.api.live.isCurrentlySharing import io.element.android.features.location.impl.common.LocationConstraintsCheck import io.element.android.features.location.impl.common.MapDefaults import io.element.android.features.location.impl.common.SendLiveLocationPermissions @@ -33,6 +36,8 @@ import io.element.android.features.location.impl.common.permissions.PermissionsP import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.location.impl.common.toDialogState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.impl.common.userlocation.UserLocationState +import io.element.android.features.location.impl.common.userlocation.asMapLibreLocation import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState @@ -52,8 +57,7 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch -@AssistedInject -class ShowLocationPresenter( +@AssistedInject class ShowLocationPresenter( @Assisted private val mode: ShowLocationMode, permissionsPresenterFactory: PermissionsPresenter.Factory, private val locationActions: LocationActions, @@ -63,9 +67,9 @@ class ShowLocationPresenter( private val client: MatrixClient, private val joinedRoom: JoinedRoom, private val liveLocationShareManager: ActiveLiveLocationShareManager, + private val userLocationStateFactory: UserLocationState.Factory, ) : Presenter { - @AssistedFactory - fun interface Factory { + @AssistedFactory fun interface Factory { fun create(mode: ShowLocationMode): ShowLocationPresenter } @@ -155,55 +159,58 @@ class ShowLocationPresenter( val liveLocationSharesFlow = joinedRoom.subscribeToLiveLocationShares() val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() } combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members -> - 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, - isOwnUser = share.userId == joinedRoom.sessionId - ) - } - .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, + isOwnUser = share.userId == joinedRoom.sessionId + ) + }.toImmutableList() }.collect { value = it } }.value } } - val focusedLocation = when (mode) { - is ShowLocationMode.Static -> locationShares.firstOrNull() - is ShowLocationMode.Live -> locationShares.firstOrNull { it.userId == mode.senderId } + val updatedLocationShares by rememberUpdatedState(locationShares) + val focusedLocation by remember { + derivedStateOf { + when (mode) { + is ShowLocationMode.Static -> updatedLocationShares.firstOrNull() + is ShowLocationMode.Live -> updatedLocationShares.firstOrNull { it.userId == mode.senderId } + } + } } - + val userLocationState = userLocationStateFactory.create(hasLocationPermission = permissionsState.isAnyGranted) return ShowLocationState( customMapStyleUrl = customMapStyleUrl, dialogState = dialogState, locationShares = locationShares, focusedLocation = focusedLocation, - hasLocationPermission = permissionsState.isAnyGranted, isTrackMyLocation = isTrackMyLocation, + userLocationState = userLocationState, isLive = mode is ShowLocationMode.Live, appName = appName, + hideUserLocationPuck = false, 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 478a3bd730..e5ddf589b0 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 @@ -11,6 +11,7 @@ package io.element.android.features.location.impl.show import io.element.android.features.location.api.Location import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.features.location.impl.common.ui.LocationMarkerData +import io.element.android.features.location.impl.common.userlocation.UserLocationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.PinVariant import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -24,9 +25,10 @@ data class ShowLocationState( val dialogState: LocationConstraintsDialogState, val locationShares: ImmutableList, val focusedLocation: LocationShareItem?, - val hasLocationPermission: Boolean, val isTrackMyLocation: Boolean, + val userLocationState: UserLocationState, val appName: String, + val hideUserLocationPuck: Boolean, val eventSink: (ShowLocationEvent) -> Unit, ) { val isSheetDraggable = isLive && locationShares.isNotEmpty() 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 85eacd3ce4..cd7ea108bb 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 @@ -11,6 +11,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.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.impl.common.userlocation.UserLocationState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -33,18 +34,9 @@ class ShowLocationStateProvider : PreviewParameterProvider { ), aShowLocationState( constraintsDialogState = LocationConstraintsDialogState.LocationServiceDisabled, - hasLocationPermission = true, - ), - aShowLocationState( - hasLocationPermission = true, - ), - aShowLocationState( - hasLocationPermission = true, - isTrackMyLocation = true, - ), - aShowLocationState( - customMapStyleUrl = AsyncData.Loading(), ), + aShowLocationState(isTrackMyLocation = true), + aShowLocationState(customMapStyleUrl = AsyncData.Loading()), ) } @@ -56,9 +48,10 @@ fun aShowLocationState( constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None, locationShares: List = listOf(aLocationShareItem(isLive = isLive)), focusedLocation: LocationShareItem? = locationShares.firstOrNull(), - hasLocationPermission: Boolean = false, isTrackMyLocation: Boolean = false, + userLocationState: UserLocationState = UserLocationState(null), appName: String = APP_NAME, + hideUserLocationPuck: Boolean = false, eventSink: (ShowLocationEvent) -> Unit = {}, ): ShowLocationState { return ShowLocationState( @@ -66,8 +59,9 @@ fun aShowLocationState( dialogState = constraintsDialogState, locationShares = locationShares.toImmutableList(), focusedLocation = focusedLocation, - hasLocationPermission = hasLocationPermission, isTrackMyLocation = isTrackMyLocation, + userLocationState = userLocationState, + hideUserLocationPuck = hideUserLocationPuck, appName = appName, isLive = isLive, eventSink = eventSink, 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 ba60a22225..6b1b33014d 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 @@ -37,13 +37,13 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.location.impl.common.MapDefaults -import io.element.android.features.location.impl.common.rememberUserLocationState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialog import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton import io.element.android.features.location.impl.common.ui.LocationPinMarkers import io.element.android.features.location.impl.common.ui.LocationShareRow import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold import io.element.android.features.location.impl.common.ui.UserLocationPuck +import io.element.android.features.location.impl.common.userlocation.UserLocationTrackingEffect import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -91,7 +91,6 @@ fun ShowLocationView( } } - val userLocationState = rememberUserLocationState(state.hasLocationPermission) val scaffoldState = rememberBottomSheetScaffoldState( bottomSheetState = rememberStandardBottomSheetState(SheetValue.Expanded) ) @@ -169,11 +168,17 @@ fun ShowLocationView( } }, mapContent = { - UserLocationPuck( + UserLocationTrackingEffect( cameraState = cameraState, - locationState = userLocationState, - trackUserLocation = state.isTrackMyLocation + locationState = state.userLocationState, + enabled = state.isTrackMyLocation, ) + if (!state.hideUserLocationPuck) { + UserLocationPuck( + cameraState = cameraState, + location = state.userLocationState.location, + ) + } val markers = remember(state.locationShares) { state.locationShares.map { it.toMarkerData() }.toImmutableList() } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/FakeUserLocationStateFactory.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/FakeUserLocationStateFactory.kt new file mode 100644 index 0000000000..f6855c5667 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/FakeUserLocationStateFactory.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common + +import androidx.compose.runtime.Composable +import io.element.android.features.location.impl.common.userlocation.UserLocationState + +class FakeUserLocationStateFactory : UserLocationState.Factory { + @Composable + override fun create(hasLocationPermission: Boolean): UserLocationState { + return UserLocationState(null) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt index 6f20e296d9..49df684666 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt @@ -11,6 +11,7 @@ package io.element.android.features.location.impl.share import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.common.FakeUserLocationStateFactory import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter import io.element.android.features.location.impl.live.LiveLocationStore @@ -56,6 +57,7 @@ class DefaultShareLocationEntryPointTest { preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), sessionId = room.sessionId, ), + userLocationStateFactory = FakeUserLocationStateFactory(), ) }, analyticsService = FakeAnalyticsService(), diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index 5be96a50c5..f9195cd08d 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -21,6 +21,7 @@ import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.Composer import io.element.android.features.location.api.Location import io.element.android.features.location.impl.aPermissionsState +import io.element.android.features.location.impl.common.FakeUserLocationStateFactory import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsEvents @@ -102,6 +103,7 @@ class ShareLocationPresenterTest { durationFormatter = durationFormatter, liveLocationShareManager = liveLocationShareManager, liveLocationStore = liveLocationStore, + userLocationStateFactory = FakeUserLocationStateFactory(), ) @Test @@ -118,7 +120,6 @@ class ShareLocationPresenterTest { val state = awaitFirstItem() assertThat(state.customMapStyleUrl.isLoading()).isFalse() assertThat(state.trackUserLocation).isTrue() - assertThat(state.hasLocationPermission).isTrue() assertThat(state.dialogState).isEqualTo(ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.None)) } } @@ -155,7 +156,6 @@ class ShareLocationPresenterTest { }.test { val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isTrue() - assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.dialogState).isEqualTo(ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.None)) } } @@ -175,7 +175,6 @@ class ShareLocationPresenterTest { }.test { val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isFalse() - assertThat(initialState.hasLocationPermission).isFalse() assertThat(initialState.dialogState).isEqualTo( ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionDenied) ) @@ -195,7 +194,6 @@ class ShareLocationPresenterTest { shareLocationPresenter.test { val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isFalse() - assertThat(initialState.hasLocationPermission).isFalse() assertThat(initialState.dialogState).isEqualTo( ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.PermissionRationale) ) @@ -216,7 +214,6 @@ class ShareLocationPresenterTest { shareLocationPresenter.test { val initialState = awaitFirstItem() assertThat(initialState.trackUserLocation).isFalse() - assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.dialogState).isEqualTo( ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled) ) diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt index 370ccac8ab..d0adf5e6bb 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt @@ -120,7 +120,6 @@ class ShareLocationViewTest { setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled), - hasLocationPermission = true, eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), @@ -135,7 +134,6 @@ class ShareLocationViewTest { setShareLocationView( aShareLocationState( dialogState = ShareLocationState.Dialog.Constraints(LocationConstraintsDialogState.LocationServiceDisabled), - hasLocationPermission = true, eventSink = eventsRecorder ), navigateUp = EnsureNeverCalled(), 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 8f55510128..23b7e9bf4d 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 @@ -14,6 +14,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationEntryPoint import io.element.android.features.location.api.ShowLocationMode +import io.element.android.features.location.impl.common.FakeUserLocationStateFactory import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter import io.element.android.features.location.test.FakeActiveLiveLocationShareManager @@ -51,6 +52,7 @@ class DefaultShowLocationEntryPointTest { joinedRoom = joinedRoom, client = FakeMatrixClient(), liveLocationShareManager = FakeActiveLiveLocationShareManager(), + userLocationStateFactory = FakeUserLocationStateFactory(), ) }, 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 da3cea88f6..da8d766c88 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 @@ -15,6 +15,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.aPermissionsState +import io.element.android.features.location.impl.common.FakeUserLocationStateFactory import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsEvents @@ -41,6 +42,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration.Companion.hours @OptIn(ExperimentalCoroutinesApi::class) class ShowLocationPresenterTest { @@ -76,26 +78,9 @@ class ShowLocationPresenterTest { joinedRoom = joinedRoom, client = client, liveLocationShareManager = liveLocationShareManager, + userLocationStateFactory = FakeUserLocationStateFactory(), ) - @Test - fun `emits initial state with no location permission`() = runTest { - fakePermissionsPresenter.givenState( - aPermissionsState( - permissions = PermissionsState.Permissions.NoneGranted, - shouldShowRationale = false, - ) - ) - - val presenter = createShowLocationPresenter() - presenter.test { - val initialState = awaitItem() - assertThat(initialState.customMapStyleUrl.isLoading()).isTrue() - assertThat(initialState.hasLocationPermission).isFalse() - assertThat(initialState.isTrackMyLocation).isFalse() - } - } - @Test fun `present - non-null customMapStyleUrl`() = runTest { val shareLocationPresenter = createShowLocationPresenter( @@ -112,35 +97,6 @@ class ShowLocationPresenterTest { } } - @Test - fun `emits initial state location permission denied once`() = runTest { - fakePermissionsPresenter.givenState( - aPermissionsState( - permissions = PermissionsState.Permissions.NoneGranted, - shouldShowRationale = true, - ) - ) - - val presenter = createShowLocationPresenter() - presenter.test { - val initialState = awaitItem() - assertThat(initialState.hasLocationPermission).isFalse() - assertThat(initialState.isTrackMyLocation).isFalse() - } - } - - @Test - fun `emits initial state with location permission`() = runTest { - fakePermissionsPresenter.givenState(aPermissionsState(permissions = PermissionsState.Permissions.AllGranted)) - - val presenter = createShowLocationPresenter() - presenter.test { - val initialState = awaitItem() - assertThat(initialState.hasLocationPermission).isTrue() - assertThat(initialState.isTrackMyLocation).isFalse() - } - } - @Test fun `emits initial state with partial location permission`() = runTest { fakePermissionsPresenter.givenState(aPermissionsState(permissions = PermissionsState.Permissions.SomeGranted)) @@ -148,7 +104,6 @@ class ShowLocationPresenterTest { val presenter = createShowLocationPresenter() presenter.test { val initialState = awaitItem() - assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.isTrackMyLocation).isFalse() } } @@ -176,7 +131,6 @@ class ShowLocationPresenterTest { presenter.test { skipItems(1) val initialState = awaitItem() - assertThat(initialState.hasLocationPermission).isTrue() assertThat(initialState.isTrackMyLocation).isFalse() initialState.eventSink(ShowLocationEvent.TrackMyLocation(true)) @@ -184,7 +138,6 @@ class ShowLocationPresenterTest { delay(1) - assertThat(trackMyLocationState.hasLocationPermission).isTrue() assertThat(trackMyLocationState.isTrackMyLocation).isTrue() // Swipe the map to switch mode @@ -192,7 +145,6 @@ class ShowLocationPresenterTest { val trackLocationDisabledState = awaitItem() assertThat(trackLocationDisabledState.dialogState).isEqualTo(LocationConstraintsDialogState.None) assertThat(trackLocationDisabledState.isTrackMyLocation).isFalse() - assertThat(trackLocationDisabledState.hasLocationPermission).isTrue() } } @@ -215,14 +167,12 @@ class ShowLocationPresenterTest { val trackLocationState = awaitItem() assertThat(trackLocationState.dialogState).isEqualTo(LocationConstraintsDialogState.PermissionRationale) assertThat(trackLocationState.isTrackMyLocation).isFalse() - assertThat(trackLocationState.hasLocationPermission).isFalse() // Dismiss the dialog initialState.eventSink(ShowLocationEvent.DismissDialog) val dialogDismissedState = awaitItem() assertThat(dialogDismissedState.dialogState).isEqualTo(LocationConstraintsDialogState.None) assertThat(dialogDismissedState.isTrackMyLocation).isFalse() - assertThat(dialogDismissedState.hasLocationPermission).isFalse() } } @@ -244,7 +194,6 @@ class ShowLocationPresenterTest { val trackLocationState = awaitItem() assertThat(trackLocationState.dialogState).isEqualTo(LocationConstraintsDialogState.PermissionRationale) assertThat(trackLocationState.isTrackMyLocation).isFalse() - assertThat(trackLocationState.hasLocationPermission).isFalse() // Continue the dialog sends permission request to the permissions presenter trackLocationState.eventSink(ShowLocationEvent.RequestPermissions) @@ -271,14 +220,12 @@ class ShowLocationPresenterTest { val trackLocationState = awaitItem() assertThat(trackLocationState.dialogState).isEqualTo(LocationConstraintsDialogState.PermissionDenied) assertThat(trackLocationState.isTrackMyLocation).isFalse() - assertThat(trackLocationState.hasLocationPermission).isFalse() // Dismiss the dialog initialState.eventSink(ShowLocationEvent.DismissDialog) val dialogDismissedState = awaitItem() assertThat(dialogDismissedState.dialogState).isEqualTo(LocationConstraintsDialogState.None) assertThat(dialogDismissedState.isTrackMyLocation).isFalse() - assertThat(dialogDismissedState.hasLocationPermission).isFalse() } } @@ -326,7 +273,6 @@ class ShowLocationPresenterTest { val presenter = createShowLocationPresenter() presenter.test { val initialState = awaitItem() - assertThat(initialState.hasLocationPermission).isTrue() // Try to track location when location services are disabled initialState.eventSink(ShowLocationEvent.TrackMyLocation(true)) @@ -493,4 +439,25 @@ class ShowLocationPresenterTest { assertThat(state.isSheetDraggable).isFalse() } } + + @Test + fun `static mode never hides user location puck`() = runTest { + val presenter = createShowLocationPresenter() + presenter.test { + val state = awaitItem() + assertThat(state.hideUserLocationPuck).isFalse() + } + } + + @Test + fun `live mode does not hide user location puck when not sharing`() = runTest { + val presenter = createShowLocationPresenter( + mode = ShowLocationMode.Live(senderId = A_USER_ID), + ) + presenter.test { + val state = awaitItem() + assertThat(state.hideUserLocationPuck).isFalse() + } + } + } From f800bb5586828822b6917dca38c3637c0aeab576 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 3 Jun 2026 21:54:29 +0200 Subject: [PATCH 0604/1083] change : Hide UserLocaitonPuck when currentlySharing from this device (and follow the marker instead of the puck) --- .../impl/show/ShowLocationPresenter.kt | 12 +++++++-- .../impl/show/ShowLocationPresenterTest.kt | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 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 8ea857c6b9..e21fbb0605 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 @@ -200,7 +200,15 @@ import kotlinx.coroutines.launch } } } - val userLocationState = userLocationStateFactory.create(hasLocationPermission = permissionsState.isAnyGranted) + val isCurrentlySharing by liveLocationShareManager.isCurrentlySharing(roomId = joinedRoom.roomId).collectAsState() + val hideUserLocationPuck = mode is ShowLocationMode.Live && isCurrentlySharing + val userLocationState = if (hideUserLocationPuck) { + // When sharing with this device, use the user LocationShareItem as source of data instead of the device. + val ownLocationShare by remember { derivedStateOf { updatedLocationShares.find { it.isOwnUser }?.location?.asMapLibreLocation() } } + UserLocationState(ownLocationShare) + } else { + userLocationStateFactory.create(hasLocationPermission = permissionsState.isAnyGranted) + } return ShowLocationState( customMapStyleUrl = customMapStyleUrl, dialogState = dialogState, @@ -210,7 +218,7 @@ import kotlinx.coroutines.launch userLocationState = userLocationState, isLive = mode is ShowLocationMode.Live, appName = appName, - hideUserLocationPuck = false, + hideUserLocationPuck = hideUserLocationPuck, eventSink = ::handleEvent, ) } 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 da8d766c88..ab06cc5911 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 @@ -460,4 +460,30 @@ class ShowLocationPresenterTest { } } + @Test + fun `live mode user location state uses own share position when sharing`() = runTest { + val ownLiveLocationShare = aLiveLocationShare() + val fakeRoom = FakeJoinedRoom( + liveLocationSharesFlow = MutableStateFlow(listOf(ownLiveLocationShare)) + ) + val manager = FakeActiveLiveLocationShareManager( + startShareLambda = { _, _ -> Result.success(Unit) } + ) + manager.startShare(fakeRoom.roomId, 1.hours) + + val presenter = createShowLocationPresenter( + mode = ShowLocationMode.Live(senderId = A_USER_ID), + joinedRoom = fakeRoom, + liveLocationShareManager = manager, + ) + val ownLocation = ownLiveLocationShare.lastLocation?.geoUri?.let(Location::fromGeoUri) + presenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.hideUserLocationPuck).isTrue() + val location = requireNotNull(state.userLocationState.location) + assertThat(location.position.value.latitude).isEqualTo(ownLocation?.lat) + assertThat(location.position.value.longitude).isEqualTo(ownLocation?.lon) + } + } } From 1b2bcd8ee548f45742fdfcb3809685ba345c7829 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 3 Jun 2026 20:13:05 +0000 Subject: [PATCH 0605/1083] Update screenshots --- .../features.location.impl.show_ShowLocationView_Day_6_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_7_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_8_en.png | 3 --- ...eatures.location.impl.show_ShowLocationView_Night_6_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_7_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_8_en.png | 3 --- 6 files changed, 8 insertions(+), 14 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png 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 index 46226555db..ceb1513af6 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdf7b194a075902ab9434e272865293535ef39370fbb9cb172b3cf8774850c73 -size 19104 +oid sha256:8988c700db517eef71d7f42c8e21ac819f51c92fb88c0c25cb400be7a5326c22 +size 19228 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 index ceb1513af6..e01e90f7d0 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8988c700db517eef71d7f42c8e21ac819f51c92fb88c0c25cb400be7a5326c22 -size 19228 +oid sha256:dea2fa898a6f9b921eca0931d7380814b31ba858b88c90ba1fbab6332b4c8ebb +size 20722 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png deleted file mode 100644 index e01e90f7d0..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_8_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dea2fa898a6f9b921eca0931d7380814b31ba858b88c90ba1fbab6332b4c8ebb -size 20722 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 index eed60f472d..d3ee3b9e22 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da601c01dd487f9c66f78ada91954398e1dcdf699f1ba4f6d8f7661f7b8cc4b7 -size 18715 +oid sha256:ca86fd5eea8c05a52fee801e1ca61c2e4e205ad9874e06d69b1d1f674585f87b +size 18842 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 index d3ee3b9e22..547e7ba364 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca86fd5eea8c05a52fee801e1ca61c2e4e205ad9874e06d69b1d1f674585f87b -size 18842 +oid sha256:f9f64bc6bb5956459f8943c05bbf0aa6ee9e97e3103713f34d49c013f86376a9 +size 18878 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png deleted file mode 100644 index 547e7ba364..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_8_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f9f64bc6bb5956459f8943c05bbf0aa6ee9e97e3103713f34d49c013f86376a9 -size 18878 From 64c04cefe0d64e40bc29003a508bad4cdd156f21 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 05:12:17 +0000 Subject: [PATCH 0606/1083] Update dependencyAnalysis to v3.14.0 --- 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 9657aaf15d..e4e1a44304 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.12.0" +dependencyAnalysis = "3.14.0" # DI metro = "1.1.1" From 1717cc7370e12fae3cd94fe4b20fca9296ff28ec Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Thu, 4 Jun 2026 08:34:55 +0100 Subject: [PATCH 0607/1083] Fix some string mappings for link new device errors (#6675) * Fix some string mappings for link new device errors * Update snapshots * Add appName * Iterate --------- Co-authored-by: Jorge Martin Espinosa Co-authored-by: Benoit Marty --- .../linknewdevice/impl/screens/error/ErrorView.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt index cc94951dbd..7b830626f6 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/error/ErrorView.kt @@ -73,10 +73,10 @@ fun ErrorView( @Composable private fun titleText(errorScreenType: ErrorScreenType, appName: String) = when (errorScreenType) { - ErrorScreenType.Cancelled -> stringResource(R.string.screen_qr_code_login_error_cancelled_title) + ErrorScreenType.Cancelled -> stringResource(R.string.screen_link_new_device_error_request_cancelled_title) ErrorScreenType.Declined -> stringResource(R.string.screen_qr_code_login_error_declined_title) - ErrorScreenType.Expired -> stringResource(R.string.screen_qr_code_login_error_expired_title) - ErrorScreenType.ProtocolNotSupported -> stringResource(R.string.screen_qr_code_login_error_linking_not_suported_title) + ErrorScreenType.Expired -> stringResource(R.string.screen_link_new_device_error_request_timeout_title) + ErrorScreenType.ProtocolNotSupported -> stringResource(R.string.screen_link_new_device_error_not_supported_title) ErrorScreenType.InsecureChannelDetected -> stringResource(id = R.string.screen_qr_code_login_connection_note_secure_state_title) ErrorScreenType.Mismatch2Digits -> stringResource(id = R.string.screen_link_new_device_wrong_number_title) ErrorScreenType.SlidingSyncNotAvailable -> stringResource(id = R.string.screen_qr_code_login_error_sliding_sync_not_supported_title, appName) @@ -86,10 +86,10 @@ private fun titleText(errorScreenType: ErrorScreenType, appName: String) = when @Composable private fun subtitleText(errorScreenType: ErrorScreenType, appName: String) = when (errorScreenType) { - ErrorScreenType.Cancelled -> stringResource(R.string.screen_qr_code_login_error_cancelled_subtitle) + ErrorScreenType.Cancelled -> stringResource(R.string.screen_link_new_device_error_request_cancelled_subtitle) ErrorScreenType.Declined -> stringResource(R.string.screen_qr_code_login_error_declined_subtitle) - ErrorScreenType.Expired -> stringResource(R.string.screen_qr_code_login_error_expired_subtitle) - ErrorScreenType.ProtocolNotSupported -> stringResource(R.string.screen_qr_code_login_error_linking_not_suported_subtitle, appName) + ErrorScreenType.Expired -> stringResource(R.string.screen_link_new_device_error_request_timeout_subtitle) + ErrorScreenType.ProtocolNotSupported -> stringResource(R.string.screen_link_new_device_error_not_supported_subtitle) ErrorScreenType.Mismatch2Digits -> stringResource(id = R.string.screen_link_new_device_wrong_number_subtitle) ErrorScreenType.InsecureChannelDetected -> stringResource(id = R.string.screen_qr_code_login_connection_note_secure_state_description) ErrorScreenType.SlidingSyncNotAvailable -> stringResource(id = R.string.screen_qr_code_login_error_sliding_sync_not_supported_subtitle, appName) From fdfd5ce72edad97f08da7a8e9f527a003837b94e Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 4 Jun 2026 07:53:12 +0000 Subject: [PATCH 0608/1083] Update screenshots --- ...es.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png | 4 ++-- ....linknewdevice.impl.screens.error_ErrorView_Night_3_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png index 19a824127e..ee619462ec 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d30e200c3e73775ed7081d3fbdc9f8843c5a5bf9e5f1b9ab3535cc6f0ea7f1f6 -size 35946 +oid sha256:17c58ce74a1b198f8659636d180a98152bd66be212f381afd652f615bd847a7f +size 28795 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png index f1f3896ab8..21fe725606 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.error_ErrorView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a78b0677d896de960ce8ce7c5818b1d52004c91917c73c460a605e5e1342554f -size 35129 +oid sha256:5493215960a23d305a2f9f26e39b307c735167583c20ac3fafb1b67e89aa1d12 +size 28124 From 371e69305385209a8a2ee89e8fe6e99b4d926db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 11:06:42 +0200 Subject: [PATCH 0609/1083] Setting version for the release 26.06.0 --- plugins/src/main/kotlin/Versions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 5e9a8694be..69d7791e6b 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -39,13 +39,13 @@ private const val versionYear = 26 * Month of the version on 2 digits. Value must be in [1,12]. * Do not update this value. it is updated by the release script. */ -private const val versionMonth = 5 +private const val versionMonth = 6 /** * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 2 +private const val versionReleaseNumber = 0 object Versions { /** From c3fd5a80b5fc4002216ec75480df3d8b488a7a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 11:09:38 +0200 Subject: [PATCH 0610/1083] Adding fastlane file for version 26.06.0 --- fastlane/metadata/android/en-US/changelogs/202606000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202606000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202606000.txt b/fastlane/metadata/android/en-US/changelogs/202606000.txt new file mode 100644 index 0000000000..6c68999e99 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202606000.txt @@ -0,0 +1,2 @@ +Main changes in this version: added image editing before sending and an option for custom notification sounds, improved start times, several other bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From a91e1fa2ae7a84a6f7daa6cb5d489b39ea818b4f Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 4 Jun 2026 15:08:19 +0200 Subject: [PATCH 0611/1083] Make Vulkan a *not required* feature (#6961) * Make Vulkan a *not required* feature * Add `DeviceHasVulkanSupport` helper to check this on runtime * When trying to open a screen with a map in it, check if vulkan is supported and display a new error dialog in that case * Fix random lint issue * Update screenshots --------- Co-authored-by: ElementBot --- .../home/impl/components/RoomSummaryRow.kt | 4 +- .../api/RenderingMapsNotSupportedDialog.kt | 30 +++++++++ .../impl/src/main/AndroidManifest.xml | 10 ++- .../messages/impl/MessagesFlowNode.kt | 64 ++++++++++++++----- .../impl/DefaultMessagesEntryPointTest.kt | 3 + .../system/DeviceHasVulkanSupport.kt | 31 +++++++++ .../src/main/res/values/localazy.xml | 2 + ...nderingMapsNotSupportedDialog_Day_0_en.png | 3 + ...eringMapsNotSupportedDialog_Night_0_en.png | 3 + 9 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 features/location/api/src/main/kotlin/io/element/android/features/location/api/RenderingMapsNotSupportedDialog.kt create mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/DeviceHasVulkanSupport.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Night_0_en.png diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index 934f60aa29..ba9a204a64 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -75,10 +75,10 @@ internal fun RoomSummaryRow( room: RoomListRoomSummary, hideInviteAvatars: Boolean, isInviteSeen: Boolean, - showUnreadCount: Boolean = false, onClick: (RoomListRoomSummary) -> Unit, - eventSink: (RoomListEvent) -> Unit, modifier: Modifier = Modifier, + showUnreadCount: Boolean = false, + eventSink: (RoomListEvent) -> Unit, ) { Box(modifier = modifier) { when (room.displayType) { diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/RenderingMapsNotSupportedDialog.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/RenderingMapsNotSupportedDialog.kt new file mode 100644 index 0000000000..a4d65763ab --- /dev/null +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/RenderingMapsNotSupportedDialog.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.api + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun RenderingMapsNotSupportedDialog(onSubmit: () -> Unit) { + ErrorDialog( + title = stringResource(CommonStrings.vulkan_not_supported_dialog_title_android), + content = stringResource(CommonStrings.vulkan_not_supported_dialog_content_android), + onSubmit = onSubmit, + ) +} + +@PreviewsDayNight +@Composable +internal fun RenderingMapsNotSupportedDialogPreview() = ElementPreview { + RenderingMapsNotSupportedDialog(onSubmit = {}) +} diff --git a/features/location/impl/src/main/AndroidManifest.xml b/features/location/impl/src/main/AndroidManifest.xml index e92ca68077..e56a13e644 100644 --- a/features/location/impl/src/main/AndroidManifest.xml +++ b/features/location/impl/src/main/AndroidManifest.xml @@ -5,13 +5,21 @@ ~ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. ~ Please see LICENSE files in the repository root for full details. --> - + + + + ( backstack = BackStack( initialElement = plugins.filterIsInstance().first().initialTarget.toNavTarget(), @@ -188,6 +194,8 @@ class MessagesFlowNode( private val callback: MessagesEntryPoint.Callback = callback() + private var displayVulkanNotSupportedError by mutableStateOf(false) + override fun onBuilt() { super.onBuilt() lifecycle.subscribe( @@ -267,7 +275,11 @@ class MessagesFlowNode( } override fun navigateToSendLocation() { - backstack.push(NavTarget.SendLocation(Timeline.Mode.Live)) + if (hasVulkanSupport()) { + backstack.push(NavTarget.SendLocation(Timeline.Mode.Live)) + } else { + displayVulkanNotSupportedError = true + } } override fun navigateToCreatePoll() { @@ -279,7 +291,11 @@ class MessagesFlowNode( } override fun navigateToCurrentLiveLocation() { - backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + if (hasVulkanSupport()) { + backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + } else { + displayVulkanNotSupportedError = true + } } override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { @@ -506,7 +522,11 @@ class MessagesFlowNode( } override fun navigateToSendLocation() { - backstack.push(NavTarget.SendLocation(Timeline.Mode.Thread(navTarget.threadRootId))) + if (hasVulkanSupport()) { + backstack.push(NavTarget.SendLocation(Timeline.Mode.Thread(navTarget.threadRootId))) + } else { + displayVulkanNotSupportedError = true + } } override fun navigateToCreatePoll() { @@ -518,7 +538,11 @@ class MessagesFlowNode( } override fun navigateToCurrentLiveLocation() { - backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + if (hasVulkanSupport()) { + backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + } else { + displayVulkanNotSupportedError = true + } } override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { @@ -607,18 +631,23 @@ class MessagesFlowNode( ) } is TimelineItemLocationContent -> { - 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, - senderName = event.safeSenderName, - senderId = event.senderId, - senderAvatarUrl = event.senderAvatar.url, - timestamp = event.sentTimeMillis, - assetType = event.content.assetType, - ) + if (hasVulkanSupport()) { + 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, + 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 { + displayVulkanNotSupportedError = true + null } - NavTarget.LocationViewer(mode = mode).takeIf { locationService.isServiceAvailable() } } else -> null } @@ -691,6 +720,11 @@ class MessagesFlowNode( @Composable override fun View(modifier: Modifier) { mentionSpanTheme.updateStyles() + + if (displayVulkanNotSupportedError) { + RenderingMapsNotSupportedDialog { displayVulkanNotSupportedError = false } + } + CompositionLocalProvider( LocalMentionSpanUpdater provides mentionSpanUpdater ) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt index dc50fca2c3..9679e23a23 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -23,6 +23,7 @@ import io.element.android.features.messages.api.MessagesEntryPoint import io.element.android.features.messages.impl.pinned.banner.createPinnedEventsTimelineProvider import io.element.android.features.messages.impl.timeline.createTimelineController import io.element.android.features.poll.test.create.FakeCreatePollEntryPoint +import io.element.android.libraries.androidutils.system.DeviceHasVulkanSupport import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -42,6 +43,7 @@ import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.node.TestParentNode import io.element.android.tests.testutils.testCoroutineDispatchers +import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -85,6 +87,7 @@ class DefaultMessagesEntryPointTest { knockRequestsListEntryPoint = FakeKnockRequestsListEntryPoint(), dateFormatter = FakeDateFormatter(), coroutineDispatchers = testCoroutineDispatchers(), + hasVulkanSupport = DeviceHasVulkanSupport(mockk(relaxed = true)) ) } val callback = object : MessagesEntryPoint.Callback { diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/DeviceHasVulkanSupport.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/DeviceHasVulkanSupport.kt new file mode 100644 index 0000000000..e8e5edcca0 --- /dev/null +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/DeviceHasVulkanSupport.kt @@ -0,0 +1,31 @@ +/* + * 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.androidutils.system + +import android.content.Context +import dev.zacsweers.metro.Inject +import io.element.android.libraries.di.annotations.ApplicationContext + +private const val VULKAN_VERSION_1_0 = 0x400003 + +/** + * Checks if the device supports Vulkan 1.0. + * + * This is needed for the location screens that contain maps using MapLibre UI components. + * + * Needed until https://github.com/maplibre/maplibre-native/issues/3079 is resolved and we can automatically choose between OpenGL and Vulkan renderers, + * or no devices support OpenGL anymore. + */ +@Inject +class DeviceHasVulkanSupport( + @ApplicationContext private val context: Context, +) { + operator fun invoke(): Boolean { + return context.packageManager.hasSystemFeature("android.hardware.vulkan.version", VULKAN_VERSION_1_0) + } +} diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 823c0fad72..75b6ab1ee7 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -546,4 +546,6 @@ Are you sure you want to continue?" "You don\'t have access to this message" "Unable to decrypt message" "This message was blocked either because you did not verify your device or because the sender needs to verify your digital identity." + "Your device is too old, a device with Android 8 or newer is required." + "Rendering maps is not supported" diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Day_0_en.png new file mode 100644 index 0000000000..cf35ad0fa8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f64455657f0f8a5ac7eec71ee206721a79b25dacf470d105a0e6497e570204a +size 23954 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Night_0_en.png new file mode 100644 index 0000000000..41cdb80dc8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.api_RenderingMapsNotSupportedDialog_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43bd5f04f170372b120fa2223c632d6a969c45b6d4fe61b161a7109318f9941f +size 22658 From 2552f12370bc1b319ebf2c14a128c90fbb4857d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:20:35 +0000 Subject: [PATCH 0612/1083] Update dependency com.github.matrix-org:matrix-analytics-events to v0.36.1 --- 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 9657aaf15d..0fb49f51bf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -229,7 +229,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" posthog = "com.posthog:posthog-android:3.47.0" sentry = "io.sentry:sentry-android:8.41.0" # main branch can be tested replacing the version with main-SNAPSHOT -matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.36.0" +matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.36.1" # Emojibase matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.5.3" From 092448d5842b98693870f862625727e03f2d291e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 16:13:28 +0200 Subject: [PATCH 0613/1083] Setting version for the release 26.06.1 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 69d7791e6b..f87eed1a40 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 6 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** From 4749ec3112dcf69514d6075f7fc7ffd77f329874 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 3 Jun 2026 16:16:29 +0200 Subject: [PATCH 0614/1083] Replace "Edit" button with Crop icon. --- .../preview/AttachmentsPreviewView.kt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt index 926106a5ee..7a02060ccf 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt @@ -37,6 +37,7 @@ import androidx.compose.ui.tooling.preview.Preview 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.messages.impl.R import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError @@ -57,11 +58,12 @@ import io.element.android.libraries.designsystem.modifiers.niceClickable import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.PreviewsDayNight +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.ListItem import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Switch import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.mediaviewer.api.local.LocalMedia @@ -163,10 +165,14 @@ fun AttachmentsPreviewView( }, actions = { if (state.canEditImage && canShowEditAction) { - TextButton( - stringResource(CommonStrings.action_edit), - onClick = ::postOpenImageEditor - ) + IconButton( + onClick = ::postOpenImageEditor, + ) { + Icon( + imageVector = CompoundIcons.Crop(), + contentDescription = stringResource(CommonStrings.action_edit), + ) + } } } ) From 1592ab9686f53fe5a5f464b8463c05f0d56e3481 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 4 Jun 2026 16:12:44 +0200 Subject: [PATCH 0615/1083] Sync compound tokens https://github.com/element-hq/compound-design-tokens/releases/tag/v10.2.2 --- libraries/compound/src/main/assets/theme.iife.js | 2 +- .../compound/src/main/res/drawable/ic_compound_crop.xml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/compound/src/main/assets/theme.iife.js b/libraries/compound/src/main/assets/theme.iife.js index 02fd99637a..41e18ba6a0 100644 --- a/libraries/compound/src/main/assets/theme.iife.js +++ b/libraries/compound/src/main/assets/theme.iife.js @@ -1 +1 @@ -var CompoundTheme=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},l=(e,r,i)=>(i=e==null?{}:t(a(e)),c(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),{min:u,max:d}=Math,f=(e,t=0,n=1)=>u(d(t,e),n),p=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=f(e[t],0,255)):t===3&&(e[t]=f(e[t],0,1));return e},m={};for(let e of[`Boolean`,`Number`,`String`,`Function`,`Array`,`Date`,`RegExp`,`Undefined`,`Null`])m[`[object ${e}]`]=e.toLowerCase();function h(e){return m[Object.prototype.toString.call(e)]||`object`}var g=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):h(e[0])==`object`&&t?t.split(``).filter(t=>e[0][t]!==void 0).map(t=>e[0][t]):e[0].slice(0),_=e=>{if(e.length<2)return null;let t=e.length-1;return h(e[t])==`string`?e[t].toLowerCase():null},{PI:v,min:y,max:b}=Math,x=e=>Math.round(e*100)/100,S=e=>Math.round(e*100)/100,C=v*2,w=v/3,T=v/180,ee=180/v;function E(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}var D={format:{},autodetect:[]},O=class{constructor(...e){let t=this;if(h(e[0])===`object`&&e[0].constructor&&e[0].constructor===this.constructor)return e[0];let n=_(e),r=!1;if(!n){r=!0,D.sorted||=(D.autodetect=D.autodetect.sort((e,t)=>t.p-e.p),!0);for(let t of D.autodetect)if(n=t.test(...e),n)break}if(D.format[n])t._rgb=p(D.format[n].apply(null,r?e:e.slice(0,-1)));else throw Error(`unknown format: `+e);t._rgb.length===3&&t._rgb.push(1)}toString(){return h(this.hex)==`function`?this.hex():`[${this._rgb.join(`,`)}]`}},te=`3.2.0`,k=(...e)=>new O(...e);k.version=te;var A={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,laserlemon:`#ffff54`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrod:`#fafad2`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,maroon2:`#7f0000`,maroon3:`#b03060`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,purple2:`#7f007f`,purple3:`#a020f0`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`},ne=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,re=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,ie=e=>{if(e.match(ne)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);let t=parseInt(e,16);return[t>>16,t>>8&255,t&255,1]}if(e.match(re)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);let t=parseInt(e,16);return[t>>24&255,t>>16&255,t>>8&255,Math.round((t&255)/255*100)/100]}throw Error(`unknown hex color: ${e}`)},{round:ae}=Math,oe=(...e)=>{let[t,n,r,i]=g(e,`rgba`),a=_(e)||`auto`;i===void 0&&(i=1),a===`auto`&&(a=i<1?`rgba`:`rgb`),t=ae(t),n=ae(n),r=ae(r);let o=`000000`+(t<<16|n<<8|r).toString(16);o=o.substr(o.length-6);let s=`0`+ae(i*255).toString(16);switch(s=s.substr(s.length-2),a.toLowerCase()){case`rgba`:return`#${o}${s}`;case`argb`:return`#${s}${o}`;default:return`#${o}`}};O.prototype.name=function(){let e=oe(this._rgb,`rgb`);for(let t of Object.keys(A))if(A[t]===e)return t.toLowerCase();return e},D.format.named=e=>{if(e=e.toLowerCase(),A[e])return ie(A[e]);throw Error(`unknown color name: `+e)},D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&A[e.toLowerCase()])return`named`}}),O.prototype.alpha=function(e,t=!1){return e!==void 0&&h(e)===`number`?t?(this._rgb[3]=e,this):new O([this._rgb[0],this._rgb[1],this._rgb[2],e],`rgb`):this._rgb[3]},O.prototype.clipped=function(){return this._rgb._clipped||!1};var j={Kn:18,labWhitePoint:`d65`,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},se=new Map([[`a`,[1.0985,.35585]],[`b`,[1.0985,.35585]],[`c`,[.98074,1.18232]],[`d50`,[.96422,.82521]],[`d55`,[.95682,.92149]],[`d65`,[.95047,1.08883]],[`e`,[1,1,1]],[`f2`,[.99186,.67393]],[`f7`,[.95041,1.08747]],[`f11`,[1.00962,.6435]],[`icc`,[.96422,.82521]]]);function M(e){let t=se.get(String(e).toLowerCase());if(!t)throw Error(`unknown Lab illuminant `+e);j.labWhitePoint=e,j.Xn=t[0],j.Zn=t[1]}function ce(){return j.labWhitePoint}var N=(...e)=>{e=g(e,`lab`);let[t,n,r]=e,[i,a,o]=le(t,n,r),[s,c,l]=de(i,a,o);return[s,c,l,e.length>3?e[3]:1]},le=(e,t,n)=>{let{kE:r,kK:i,kKE:a,Xn:o,Yn:s,Zn:c}=j,l=(e+16)/116,u=.002*t+l,d=l-.005*n,f=u*u*u,p=d*d*d,m=f>r?f:(116*u-16)/i,h=e>a?((e+16)/116)**3:e/i,g=p>r?p:(116*d-16)/i;return[m*o,h*s,g*c]},ue=e=>{let t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*e**(1/2.4)-.055)*t},de=(e,t,n)=>{let{MtxAdaptMa:r,MtxAdaptMaI:i,MtxXYZ2RGB:a,RefWhiteRGB:o,Xn:s,Yn:c,Zn:l}=j,u=s*r.m00+c*r.m10+l*r.m20,d=s*r.m01+c*r.m11+l*r.m21,f=s*r.m02+c*r.m12+l*r.m22,p=o.X*r.m00+o.Y*r.m10+o.Z*r.m20,m=o.X*r.m01+o.Y*r.m11+o.Z*r.m21,h=o.X*r.m02+o.Y*r.m12+o.Z*r.m22,g=(e*r.m00+t*r.m10+n*r.m20)*(p/u),_=(e*r.m01+t*r.m11+n*r.m21)*(m/d),v=(e*r.m02+t*r.m12+n*r.m22)*(h/f),y=g*i.m00+_*i.m10+v*i.m20,b=g*i.m01+_*i.m11+v*i.m21,x=g*i.m02+_*i.m12+v*i.m22,S=ue(y*a.m00+b*a.m10+x*a.m20),C=ue(y*a.m01+b*a.m11+x*a.m21),w=ue(y*a.m02+b*a.m12+x*a.m22);return[S*255,C*255,w*255]},fe=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=he(t,n,r),[c,l,u]=pe(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function pe(e,t,n){let{Xn:r,Yn:i,Zn:a,kE:o,kK:s}=j,c=e/r,l=t/i,u=n/a,d=c>o?c**(1/3):(s*c+16)/116,f=l>o?l**(1/3):(s*l+16)/116,p=u>o?u**(1/3):(s*u+16)/116;return[116*f-16,500*(d-f),200*(f-p)]}function me(e){let t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:((e+.055)/1.055)**2.4)*t}var he=(e,t,n)=>{e=me(e/255),t=me(t/255),n=me(n/255);let{MtxRGB2XYZ:r,MtxAdaptMa:i,MtxAdaptMaI:a,Xn:o,Yn:s,Zn:c,As:l,Bs:u,Cs:d}=j,f=e*r.m00+t*r.m10+n*r.m20,p=e*r.m01+t*r.m11+n*r.m21,m=e*r.m02+t*r.m12+n*r.m22,h=o*i.m00+s*i.m10+c*i.m20,g=o*i.m01+s*i.m11+c*i.m21,_=o*i.m02+s*i.m12+c*i.m22,v=f*i.m00+p*i.m10+m*i.m20,y=f*i.m01+p*i.m11+m*i.m21,b=f*i.m02+p*i.m12+m*i.m22;return v*=h/l,y*=g/u,b*=_/d,f=v*a.m00+y*a.m10+b*a.m20,p=v*a.m01+y*a.m11+b*a.m21,m=v*a.m02+y*a.m12+b*a.m22,[f,p,m]};O.prototype.lab=function(){return fe(this._rgb)},Object.assign(k,{lab:(...e)=>new O(...e,`lab`),getLabWhitePoint:ce,setLabWhitePoint:M}),D.format.lab=N,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`lab`),h(e)===`array`&&e.length===3)return`lab`}}),O.prototype.darken=function(e=1){let t=this,n=t.lab();return n[0]-=j.Kn*e,new O(n,`lab`).alpha(t.alpha(),!0)},O.prototype.brighten=function(e=1){return this.darken(-e)},O.prototype.darker=O.prototype.darken,O.prototype.brighter=O.prototype.brighten,O.prototype.get=function(e){let[t,n]=e.split(`.`),r=this[t]();if(n){let e=t.indexOf(n)-(t.substr(0,2)===`ok`?2:0);if(e>-1)return r[e];throw Error(`unknown channel ${n} in mode ${t}`)}else return r};var{pow:ge}=Math,_e=1e-7,ve=20;O.prototype.luminance=function(e,t=`rgb`){if(e!==void 0&&h(e)===`number`){if(e===0)return new O([0,0,0,this._rgb[3]],`rgb`);if(e===1)return new O([255,255,255,this._rgb[3]],`rgb`);let n=this.luminance(),r=ve,i=(n,a)=>{let o=n.interpolate(a,.5,t),s=o.luminance();return Math.abs(e-s)<_e||!r--?o:s>e?i(n,o):i(o,a)};return new O([...(n>e?i(new O([0,0,0]),this):i(this,new O([255,255,255]))).rgb(),this._rgb[3]])}return ye(...this._rgb.slice(0,3))};var ye=(e,t,n)=>(e=be(e),t=be(t),n=be(n),.2126*e+.7152*t+.0722*n),be=e=>(e/=255,e<=.03928?e/12.92:ge((e+.055)/1.055,2.4)),P={},F=(e,t,n=.5,...r)=>{let i=r[0]||`lrgb`;if(!P[i]&&!r.length&&(i=Object.keys(P)[0]),!P[i])throw Error(`interpolation mode ${i} is not defined`);return h(e)!==`object`&&(e=new O(e)),h(t)!==`object`&&(t=new O(t)),P[i](e,t,n).alpha(e.alpha()+n*(t.alpha()-e.alpha()))};O.prototype.mix=O.prototype.interpolate=function(e,t=.5,...n){return F(this,e,t,...n)},O.prototype.premultiply=function(e=!1){let t=this._rgb,n=t[3];return e?(this._rgb=[t[0]*n,t[1]*n,t[2]*n,n],this):new O([t[0]*n,t[1]*n,t[2]*n,n],`rgb`)};var{sin:xe,cos:Se}=Math,Ce=(...e)=>{let[t,n,r]=g(e,`lch`);return isNaN(r)&&(r=0),r*=T,[t,Se(r)*n,xe(r)*n]},we=(...e)=>{e=g(e,`lch`);let[t,n,r]=e,[i,a,o]=Ce(t,n,r),[s,c,l]=N(i,a,o);return[s,c,l,e.length>3?e[3]:1]},Te=(...e)=>we(...E(g(e,`hcl`))),{sqrt:Ee,atan2:De,round:Oe}=Math,ke=(...e)=>{let[t,n,r]=g(e,`lab`),i=Ee(n*n+r*r),a=(De(r,n)*ee+360)%360;return Oe(i*1e4)===0&&(a=NaN),[t,i,a]},Ae=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=fe(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};O.prototype.lch=function(){return Ae(this._rgb)},O.prototype.hcl=function(){return E(Ae(this._rgb))},Object.assign(k,{lch:(...e)=>new O(...e,`lch`),hcl:(...e)=>new O(...e,`hcl`)}),D.format.lch=we,D.format.hcl=Te,[`lch`,`hcl`].forEach(e=>D.autodetect.push({p:2,test:(...t)=>{if(t=g(t,e),h(t)===`array`&&t.length===3)return e}})),O.prototype.saturate=function(e=1){let t=this,n=t.lch();return n[1]+=j.Kn*e,n[1]<0&&(n[1]=0),new O(n,`lch`).alpha(t.alpha(),!0)},O.prototype.desaturate=function(e=1){return this.saturate(-e)},O.prototype.set=function(e,t,n=!1){let[r,i]=e.split(`.`),a=this[r]();if(i){let e=r.indexOf(i)-(r.substr(0,2)===`ok`?2:0);if(e>-1){if(h(t)==`string`)switch(t.charAt(0)){case`+`:a[e]+=+t;break;case`-`:a[e]+=+t;break;case`*`:a[e]*=+t.substr(1);break;case`/`:a[e]/=+t.substr(1);break;default:a[e]=+t}else if(h(t)===`number`)a[e]=t;else throw Error(`unsupported value for Color.set`);let i=new O(a,r);return n?(this._rgb=i._rgb,this):i}throw Error(`unknown channel ${i} in mode ${r}`)}else return a},O.prototype.tint=function(e=.5,...t){return F(this,`white`,e,...t)},O.prototype.shade=function(e=.5,...t){return F(this,`black`,e,...t)},P.rgb=(e,t,n)=>{let r=e._rgb,i=t._rgb;return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`rgb`)};var{sqrt:je,pow:Me}=Math;P.lrgb=(e,t,n)=>{let[r,i,a]=e._rgb,[o,s,c]=t._rgb;return new O(je(Me(r,2)*(1-n)+Me(o,2)*n),je(Me(i,2)*(1-n)+Me(s,2)*n),je(Me(a,2)*(1-n)+Me(c,2)*n),`rgb`)},P.lab=(e,t,n)=>{let r=e.lab(),i=t.lab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`lab`)};var Ne=(e,t,n,r)=>{let i,a;r===`hsl`?(i=e.hsl(),a=t.hsl()):r===`hsv`?(i=e.hsv(),a=t.hsv()):r===`hcg`?(i=e.hcg(),a=t.hcg()):r===`hsi`?(i=e.hsi(),a=t.hsi()):r===`lch`||r===`hcl`?(r=`hcl`,i=e.hcl(),a=t.hcl()):r===`oklch`&&(i=e.oklch().reverse(),a=t.oklch().reverse());let o,s,c,l,u,d;(r.substr(0,1)===`h`||r===`oklch`)&&([o,c,u]=i,[s,l,d]=a);let f,p,m,h;return!isNaN(o)&&!isNaN(s)?(h=s>o&&s-o>180?s-(o+360):s180?s+360-o:s-o,p=o+n*h):isNaN(o)?isNaN(s)?p=NaN:(p=s,(u==1||u==0)&&r!=`hsv`&&(f=l)):(p=o,(d==1||d==0)&&r!=`hsv`&&(f=c)),f===void 0&&(f=c+n*(l-c)),m=u+n*(d-u),r===`oklch`?new O([m,f,p],r):new O([p,f,m],r)},Pe=(e,t,n)=>Ne(e,t,n,`lch`);P.lch=Pe,P.hcl=Pe;var Fe=e=>{if(h(e)==`number`&&e>=0&&e<=16777215)return[e>>16,e>>8&255,e&255,1];throw Error(`unknown num color: `+e)},Ie=(...e)=>{let[t,n,r]=g(e,`rgb`);return(t<<16)+(n<<8)+r};O.prototype.num=function(){return Ie(this._rgb)},Object.assign(k,{num:(...e)=>new O(...e,`num`)}),D.format.num=Fe,D.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&h(e[0])===`number`&&e[0]>=0&&e[0]<=16777215)return`num`}}),P.num=(e,t,n)=>{let r=e.num();return new O(r+n*(t.num()-r),`num`)};var{floor:Le}=Math,Re=(...e)=>{e=g(e,`hcg`);let[t,n,r]=e,i,a,o;r*=255;let s=n*255;if(n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Le(t),c=t-e,l=r*(1-n),u=l+s*(1-c),d=l+s*c,f=l+s;switch(e){case 0:[i,a,o]=[f,d,l];break;case 1:[i,a,o]=[u,f,l];break;case 2:[i,a,o]=[l,f,d];break;case 3:[i,a,o]=[l,u,f];break;case 4:[i,a,o]=[d,l,f];break;case 5:[i,a,o]=[f,l,u];break}}return[i,a,o,e.length>3?e[3]:1]},ze=(...e)=>{let[t,n,r]=g(e,`rgb`),i=y(t,n,r),a=b(t,n,r),o=a-i,s=o*100/255,c=i/(255-o)*100,l;return o===0?l=NaN:(t===a&&(l=(n-r)/o),n===a&&(l=2+(r-t)/o),r===a&&(l=4+(t-n)/o),l*=60,l<0&&(l+=360)),[l,s,c]};O.prototype.hcg=function(){return ze(this._rgb)},k.hcg=(...e)=>new O(...e,`hcg`),D.format.hcg=Re,D.autodetect.push({p:1,test:(...e)=>{if(e=g(e,`hcg`),h(e)===`array`&&e.length===3)return`hcg`}}),P.hcg=(e,t,n)=>Ne(e,t,n,`hcg`);var{cos:Be}=Math,Ve=(...e)=>{e=g(e,`hsi`);let[t,n,r]=e,i,a,o;return isNaN(t)&&(t=0),isNaN(n)&&(n=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(o=(1-n)/3,i=(1+n*Be(C*t)/Be(w-C*t))/3,a=1-(o+i)):t<2/3?(t-=1/3,i=(1-n)/3,a=(1+n*Be(C*t)/Be(w-C*t))/3,o=1-(i+a)):(t-=2/3,a=(1-n)/3,o=(1+n*Be(C*t)/Be(w-C*t))/3,i=1-(a+o)),i=f(r*i*3),a=f(r*a*3),o=f(r*o*3),[i*255,a*255,o*255,e.length>3?e[3]:1]},{min:He,sqrt:Ue,acos:We}=Math,Ge=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i,a=He(t,n,r),o=(t+n+r)/3,s=o>0?1-a/o:0;return s===0?i=NaN:(i=(t-n+(t-r))/2,i/=Ue((t-n)*(t-n)+(t-r)*(n-r)),i=We(i),r>n&&(i=C-i),i/=C),[i*360,s,o]};O.prototype.hsi=function(){return Ge(this._rgb)},k.hsi=(...e)=>new O(...e,`hsi`),D.format.hsi=Ve,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsi`),h(e)===`array`&&e.length===3)return`hsi`}}),P.hsi=(e,t,n)=>Ne(e,t,n,`hsi`);var Ke=(...e)=>{e=g(e,`hsl`);let[t,n,r]=e,i,a,o;if(n===0)i=a=o=r*255;else{let e=[0,0,0],s=[0,0,0],c=r<.5?r*(1+n):r+n-r*n,l=2*r-c,u=t/360;e[0]=u+1/3,e[1]=u,e[2]=u-1/3;for(let t=0;t<3;t++)e[t]<0&&(e[t]+=1),e[t]>1&&--e[t],6*e[t]<1?s[t]=l+(c-l)*6*e[t]:2*e[t]<1?s[t]=c:3*e[t]<2?s[t]=l+(c-l)*(2/3-e[t])*6:s[t]=l;[i,a,o]=[s[0]*255,s[1]*255,s[2]*255]}return e.length>3?[i,a,o,e[3]]:[i,a,o,1]},qe=(...e)=>{e=g(e,`rgba`);let[t,n,r]=e;t/=255,n/=255,r/=255;let i=y(t,n,r),a=b(t,n,r),o=(a+i)/2,s,c;return a===i?(s=0,c=NaN):s=o<.5?(a-i)/(a+i):(a-i)/(2-a-i),t==a?c=(n-r)/(a-i):n==a?c=2+(r-t)/(a-i):r==a&&(c=4+(t-n)/(a-i)),c*=60,c<0&&(c+=360),e.length>3&&e[3]!==void 0?[c,s,o,e[3]]:[c,s,o]};O.prototype.hsl=function(){return qe(this._rgb)},k.hsl=(...e)=>new O(...e,`hsl`),D.format.hsl=Ke,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsl`),h(e)===`array`&&e.length===3)return`hsl`}}),P.hsl=(e,t,n)=>Ne(e,t,n,`hsl`);var{floor:Je}=Math,Ye=(...e)=>{e=g(e,`hsv`);let[t,n,r]=e,i,a,o;if(r*=255,n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Je(t),s=t-e,c=r*(1-n),l=r*(1-n*s),u=r*(1-n*(1-s));switch(e){case 0:[i,a,o]=[r,u,c];break;case 1:[i,a,o]=[l,r,c];break;case 2:[i,a,o]=[c,r,u];break;case 3:[i,a,o]=[c,l,r];break;case 4:[i,a,o]=[u,c,r];break;case 5:[i,a,o]=[r,c,l];break}}return[i,a,o,e.length>3?e[3]:1]},{min:Xe,max:Ze}=Math,Qe=(...e)=>{e=g(e,`rgb`);let[t,n,r]=e,i=Xe(t,n,r),a=Ze(t,n,r),o=a-i,s,c,l;return l=a/255,a===0?(s=NaN,c=0):(c=o/a,t===a&&(s=(n-r)/o),n===a&&(s=2+(r-t)/o),r===a&&(s=4+(t-n)/o),s*=60,s<0&&(s+=360)),[s,c,l]};O.prototype.hsv=function(){return Qe(this._rgb)},k.hsv=(...e)=>new O(...e,`hsv`),D.format.hsv=Ye,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsv`),h(e)===`array`&&e.length===3)return`hsv`}}),P.hsv=(e,t,n)=>Ne(e,t,n,`hsv`);function $e(e,t){let n=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(e=>[e]));let r=t[0].length,i=t[0].map((e,n)=>t.map(e=>e[n])),a=e.map(e=>i.map(t=>Array.isArray(e)?e.reduce((e,n,r)=>e+n*(t[r]||0),0):t.reduce((t,n)=>t+n*e,0)));return n===1&&(a=a[0]),r===1?a.map(e=>e[0]):a}var et=(...e)=>{e=g(e,`lab`);let[t,n,r,...i]=e,[a,o,s]=tt([t,n,r]),[c,l,u]=de(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function tt(e){return $e([[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],$e([[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],e).map(e=>e**3))}var nt=(...e)=>{let[t,n,r,...i]=g(e,`rgb`);return[...rt(he(t,n,r)),...i.length>0&&i[0]<1?[i[0]]:[]]};function rt(e){return $e([[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],$e([[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],e).map(e=>Math.cbrt(e)))}O.prototype.oklab=function(){return nt(this._rgb)},Object.assign(k,{oklab:(...e)=>new O(...e,`oklab`)}),D.format.oklab=et,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklab`),h(e)===`array`&&e.length===3)return`oklab`}}),P.oklab=(e,t,n)=>{let r=e.oklab(),i=t.oklab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`oklab`)},P.oklch=(e,t,n)=>Ne(e,t,n,`oklch`);var{pow:it,sqrt:at,PI:ot,cos:st,sin:ct,atan2:lt}=Math,ut=(e,t=`lrgb`,n=null)=>{let r=e.length;n||=Array.from(Array(r)).map(()=>1);let i=r/n.reduce(function(e,t){return e+t});if(n.forEach((e,t)=>{n[t]*=i}),e=e.map(e=>new O(e)),t===`lrgb`)return dt(e,n);let a=e.shift(),o=a.get(t),s=[],c=0,l=0;for(let e=0;e{let i=e.get(t);u+=e.alpha()*n[r+1];for(let e=0;e=360;)t-=360;o[e]=t}else o[e]=o[e]/s[e];return u/=r,new O(o,t).alpha(u>.99999?1:u,!0)},dt=(e,t)=>{let n=e.length,r=[0,0,0,0];for(let i=0;i.9999999&&(r[3]=1),new O(p(r))},{pow:ft}=Math;function pt(e){let t=`rgb`,n=k(`#ccc`),r=0,i=[0,1],a=[0,1],o=[],s=[0,0],c=!1,l=[],u=!1,d=0,p=1,m=!1,g={},_=!0,v=1,y=function(e){if(e||=[`#fff`,`#000`],e&&h(e)===`string`&&k.brewer&&k.brewer[e.toLowerCase()]&&(e=k.brewer[e.toLowerCase()]),h(e)===`array`){e.length===1&&(e=[e[0],e[0]]),e=e.slice(0);for(let t=0;t=c[n];)n++;return n-1}return 0},x=e=>e,S=e=>e,C=function(e,r){let i,a;if(r??=!1,isNaN(e)||e===null)return n;a=r?e:c&&c.length>2?b(e)/(c.length-2):p===d?1:(e-d)/(p-d),a=S(a),r||(a=x(a)),v!==1&&(a=ft(a,v)),a=s[0]+a*(1-s[0]-s[1]),a=f(a,0,1);let u=Math.floor(a*1e4);if(_&&g[u])i=g[u];else{if(h(l)===`array`)for(let e=0;e=n&&e===o.length-1){i=l[e];break}if(a>n&&ag={};y(e);let T=function(e){let t=k(C(e));return u&&t[u]?t[u]():t};return T.classes=function(e){if(e!=null){if(h(e)===`array`)c=e,i=[e[0],e[e.length-1]];else{let t=k.analyze(i);c=e===0?[t.min,t.max]:k.limits(t,`e`,e)}return T}return c},T.domain=function(e){if(!arguments.length)return a;a=e.slice(0),d=e[0],p=e[e.length-1],o=[];let t=l.length;if(e.length===t&&d!==p)for(let t of Array.from(e))o.push((t-d)/(p-d));else{for(let e=0;e2){let t=e.map((t,n)=>n/(e.length-1)),n=e.map(e=>(e-d)/(p-d));n.every((e,n)=>t[n]===e)||(S=e=>{if(e<=0||e>=1)return e;let r=0;for(;e>=n[r+1];)r++;let i=(e-n[r])/(n[r+1]-n[r]);return t[r]+i*(t[r+1]-t[r])})}}return i=[d,p],T},T.mode=function(e){return arguments.length?(t=e,w(),T):t},T.range=function(e,t){return y(e,t),T},T.out=function(e){return u=e,T},T.spread=function(e){return arguments.length?(r=e,T):r},T.correctLightness=function(e){return e??=!0,m=e,w(),x=m?function(e){let t=C(0,!0).lab()[0],n=C(1,!0).lab()[0],r=t>n,i=C(e,!0).lab()[0],a=t+(n-t)*e,o=i-a,s=0,c=1,l=20;for(;Math.abs(o)>.01&&l-- >0;)(function(){return r&&(o*=-1),o<0?(s=e,e+=(c-e)*.5):(c=e,e+=(s-e)*.5),i=C(e,!0).lab()[0],o=i-a})();return e}:e=>e,T},T.padding=function(e){return e==null?s:(h(e)===`number`&&(e=[e,e]),s=e,T)},T.colors=function(t,n){arguments.length<2&&(n=`hex`);let r=[];if(arguments.length===0)r=l.slice(0);else if(t===1)r=[T(.5)];else if(t>1){let e=i[0],n=i[1]-e;r=mt(0,t,!1).map(r=>T(e+r/(t-1)*n))}else{e=[];let t=[];if(c&&c.length>2)for(let e=1,n=c.length,r=1<=n;r?en;r?e++:e--)t.push((c[e-1]+c[e])*.5);else t=i;r=t.map(e=>T(e))}return k[n]&&(r=r.map(e=>e[n]())),r},T.cache=function(e){return e==null?_:(_=e,T)},T.gamma=function(e){return e==null?v:(v=e,T)},T.nodata=function(e){return e==null?n:(n=k(e),T)},T}function mt(e,t,n){let r=[],i=ea;i?t++:t--)r.push(t);return r}var ht=function(e){let t=[1,1];for(let n=1;nnew O(e)),e.length===2)[n,r]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>n[t]+e*(r[t]-n[t])),`lab`)};else if(e.length===3)[n,r,i]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*n[t]+2*(1-e)*e*r[t]+e*e*i[t]),`lab`)};else if(e.length===4){let a;[n,r,i,a]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*(1-e)*n[t]+3*(1-e)*(1-e)*e*r[t]+3*(1-e)*e*e*i[t]+e*e*e*a[t]),`lab`)}}else if(e.length>=5){let n,r,i;n=e.map(e=>e.lab()),i=e.length-1,r=ht(i),t=function(e){let t=1-e;return new O([0,1,2].map(a=>n.reduce((n,o,s)=>n+r[s]*t**(i-s)*e**s*o[a],0)),`lab`)}}else throw RangeError(`No point in running bezier with only one color.`);return t},_t=e=>{let t=gt(e);return t.scale=()=>pt(t),t},{round:vt}=Math;O.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(vt)},O.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,n)=>n<3?e===!1?t:vt(t):t)},Object.assign(k,{rgb:(...e)=>new O(...e,`rgb`)}),D.format.rgb=(...e)=>{let t=g(e,`rgba`);return t[3]===void 0&&(t[3]=1),t},D.autodetect.push({p:3,test:(...e)=>{if(e=g(e,`rgba`),h(e)===`array`&&(e.length===3||e.length===4&&h(e[3])==`number`&&e[3]>=0&&e[3]<=1))return`rgb`}});var I=(e,t,n)=>{if(!I[n])throw Error(`unknown blend mode `+n);return I[n](e,t)},L=e=>(t,n)=>{let r=k(n).rgb(),i=k(t).rgb();return k.rgb(e(r,i))},R=e=>(t,n)=>{let r=[];return r[0]=e(t[0],n[0]),r[1]=e(t[1],n[1]),r[2]=e(t[2],n[2]),r};I.normal=L(R(e=>e)),I.multiply=L(R((e,t)=>e*t/255)),I.screen=L(R((e,t)=>255*(1-(1-e/255)*(1-t/255)))),I.overlay=L(R((e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)))),I.darken=L(R((e,t)=>e>t?t:e)),I.lighten=L(R((e,t)=>e>t?e:t)),I.dodge=L(R((e,t)=>e===255?255:(e=t/255*255/(1-e/255),e>255?255:e))),I.burn=L(R((e,t)=>255*(1-(1-t/255)/(e/255))));var{pow:yt,sin:bt,cos:xt}=Math;function St(e=300,t=-1.5,n=1,r=1,i=[0,1]){let a=0,o;h(i)===`array`?o=i[1]-i[0]:(o=0,i=[i,i]);let s=function(s){let c=C*((e+120)/360+t*s),l=yt(i[0]+o*s,r),u=(a===0?n:n[0]+s*a)*l*(1-l)/2,d=xt(c),f=bt(c),m=l+u*(-.14861*d+1.78277*f),h=l+u*(-.29227*d-.90649*f),g=l+1.97294*d*u;return k(p([m*255,h*255,g*255,1]))};return s.start=function(t){return t==null?e:(e=t,s)},s.rotations=function(e){return e==null?t:(t=e,s)},s.gamma=function(e){return e==null?r:(r=e,s)},s.hue=function(e){return e==null?n:(n=e,h(n)===`array`?(a=n[1]-n[0],a===0&&(n=n[1])):a=0,s)},s.lightness=function(e){return e==null?i:(h(e)===`array`?(i=e,o=e[1]-e[0]):(i=[e,e],o=0),s)},s.scale=()=>k.scale(s),s.hue(n),s}var Ct=`0123456789abcdef`,{floor:wt,random:Tt}=Math,Et=(e=Tt)=>{let t=`#`;for(let n=0;n<6;n++)t+=Ct.charAt(wt(e()*16));return new O(t,`hex`)},{log:Dt,pow:Ot,floor:kt,abs:At}=Math;function jt(e,t=null){let n={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return h(e)===`object`&&(e=Object.values(e)),e.forEach(e=>{t&&h(e)===`object`&&(e=e[t]),e!=null&&!isNaN(e)&&(n.values.push(e),n.sum+=e,en.max&&(n.max=e),n.count+=1)}),n.domain=[n.min,n.max],n.limits=(e,t)=>Mt(n,e,t),n}function Mt(e,t=`equal`,n=7){h(e)==`array`&&(e=jt(e));let{min:r,max:i}=e,a=e.values.sort((e,t)=>e-t);if(n===1)return[r,i];let o=[];if(t.substr(0,1)===`c`&&(o.push(r),o.push(i)),t.substr(0,1)===`e`){o.push(r);for(let e=1;e 0`);let e=Math.LOG10E*Dt(r),t=Math.LOG10E*Dt(i);o.push(r);for(let r=1;r200&&(l=!1)}let f={};for(let e=0;ee-t),o.push(p[0]);for(let e=1;e{e=new O(e),t=new O(t);let n=e.luminance(),r=t.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)},Pt=.027,Ft=5e-4,It=.1,Lt=1.14,Rt=.022,zt=1.414,Bt=(e,t)=>{e=new O(e),t=new O(t),e.alpha()<1&&(e=F(t,e,e.alpha(),`rgb`));let n=Vt(...e.rgb()),r=Vt(...t.rgb()),i=n>=Rt?n:n+(Rt-n)**+zt,a=r>=Rt?r:r+(Rt-r)**+zt,o=a**.56-i**.57,s=a**.65-i**.62,c=Math.abs(a-i)0?c-Pt:c+Pt)*100};function Vt(e,t,n){return .2126729*(e/255)**2.4+.7151522*(t/255)**2.4+.072175*(n/255)**2.4}var{sqrt:z,pow:B,min:Ht,max:Ut,atan2:Wt,abs:Gt,cos:Kt,sin:qt,exp:Jt,PI:Yt}=Math;function Xt(e,t,n=1,r=1,i=1){var a=function(e){return 360*e/(2*Yt)},o=function(e){return 2*Yt*e/360};e=new O(e),t=new O(t);let[s,c,l]=Array.from(e.lab()),[u,d,f]=Array.from(t.lab()),p=(s+u)/2,m=(z(B(c,2)+B(l,2))+z(B(d,2)+B(f,2)))/2,h=.5*(1-z(B(m,7)/(B(m,7)+B(25,7)))),g=c*(1+h),_=d*(1+h),v=z(B(g,2)+B(l,2)),y=z(B(_,2)+B(f,2)),b=(v+y)/2,x=a(Wt(l,g)),S=a(Wt(f,_)),C=x>=0?x:x+360,w=S>=0?S:S+360,T=Gt(C-w)>180?(C+w+360)/2:(C+w)/2,ee=1-.17*Kt(o(T-30))+.24*Kt(o(2*T))+.32*Kt(o(3*T+6))-.2*Kt(o(4*T-63)),E=w-C;E=Gt(E)<=180?E:w<=C?E+360:E-360,E=2*z(v*y)*qt(o(E)/2);let D=u-s,te=y-v,k=1+.015*B(p-50,2)/z(20+B(p-50,2)),A=1+.045*b,ne=1+.015*b*ee,re=30*Jt(-B((T-275)/25,2)),ie=-(2*z(B(b,7)/(B(b,7)+B(25,7))))*qt(2*o(re));return Ut(0,Ht(100,z(B(D/(n*k),2)+B(te/(r*A),2)+B(E/(i*ne),2)+ie*(te/(r*A))*(E/(i*ne)))))}function Zt(e,t,n=`lab`){e=new O(e),t=new O(t);let r=e.get(n),i=t.get(n),a=0;for(let e in r){let t=(r[e]||0)-(i[e]||0);a+=t*t}return Math.sqrt(a)}var Qt=(...e)=>{try{return new O(...e),!0}catch{return!1}},$t={cool(){return pt([k.hsl(180,1,.9),k.hsl(250,.7,.4)])},hot(){return pt([`#000`,`#f00`,`#ff0`,`#fff`],[0,.25,.75,1]).mode(`rgb`)}},en={OrRd:[`#fff7ec`,`#fee8c8`,`#fdd49e`,`#fdbb84`,`#fc8d59`,`#ef6548`,`#d7301f`,`#b30000`,`#7f0000`],PuBu:[`#fff7fb`,`#ece7f2`,`#d0d1e6`,`#a6bddb`,`#74a9cf`,`#3690c0`,`#0570b0`,`#045a8d`,`#023858`],BuPu:[`#f7fcfd`,`#e0ecf4`,`#bfd3e6`,`#9ebcda`,`#8c96c6`,`#8c6bb1`,`#88419d`,`#810f7c`,`#4d004b`],Oranges:[`#fff5eb`,`#fee6ce`,`#fdd0a2`,`#fdae6b`,`#fd8d3c`,`#f16913`,`#d94801`,`#a63603`,`#7f2704`],BuGn:[`#f7fcfd`,`#e5f5f9`,`#ccece6`,`#99d8c9`,`#66c2a4`,`#41ae76`,`#238b45`,`#006d2c`,`#00441b`],YlOrBr:[`#ffffe5`,`#fff7bc`,`#fee391`,`#fec44f`,`#fe9929`,`#ec7014`,`#cc4c02`,`#993404`,`#662506`],YlGn:[`#ffffe5`,`#f7fcb9`,`#d9f0a3`,`#addd8e`,`#78c679`,`#41ab5d`,`#238443`,`#006837`,`#004529`],Reds:[`#fff5f0`,`#fee0d2`,`#fcbba1`,`#fc9272`,`#fb6a4a`,`#ef3b2c`,`#cb181d`,`#a50f15`,`#67000d`],RdPu:[`#fff7f3`,`#fde0dd`,`#fcc5c0`,`#fa9fb5`,`#f768a1`,`#dd3497`,`#ae017e`,`#7a0177`,`#49006a`],Greens:[`#f7fcf5`,`#e5f5e0`,`#c7e9c0`,`#a1d99b`,`#74c476`,`#41ab5d`,`#238b45`,`#006d2c`,`#00441b`],YlGnBu:[`#ffffd9`,`#edf8b1`,`#c7e9b4`,`#7fcdbb`,`#41b6c4`,`#1d91c0`,`#225ea8`,`#253494`,`#081d58`],Purples:[`#fcfbfd`,`#efedf5`,`#dadaeb`,`#bcbddc`,`#9e9ac8`,`#807dba`,`#6a51a3`,`#54278f`,`#3f007d`],GnBu:[`#f7fcf0`,`#e0f3db`,`#ccebc5`,`#a8ddb5`,`#7bccc4`,`#4eb3d3`,`#2b8cbe`,`#0868ac`,`#084081`],Greys:[`#ffffff`,`#f0f0f0`,`#d9d9d9`,`#bdbdbd`,`#969696`,`#737373`,`#525252`,`#252525`,`#000000`],YlOrRd:[`#ffffcc`,`#ffeda0`,`#fed976`,`#feb24c`,`#fd8d3c`,`#fc4e2a`,`#e31a1c`,`#bd0026`,`#800026`],PuRd:[`#f7f4f9`,`#e7e1ef`,`#d4b9da`,`#c994c7`,`#df65b0`,`#e7298a`,`#ce1256`,`#980043`,`#67001f`],Blues:[`#f7fbff`,`#deebf7`,`#c6dbef`,`#9ecae1`,`#6baed6`,`#4292c6`,`#2171b5`,`#08519c`,`#08306b`],PuBuGn:[`#fff7fb`,`#ece2f0`,`#d0d1e6`,`#a6bddb`,`#67a9cf`,`#3690c0`,`#02818a`,`#016c59`,`#014636`],Viridis:[`#440154`,`#482777`,`#3f4a8a`,`#31678e`,`#26838f`,`#1f9d8a`,`#6cce5a`,`#b6de2b`,`#fee825`],Spectral:[`#9e0142`,`#d53e4f`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#e6f598`,`#abdda4`,`#66c2a5`,`#3288bd`,`#5e4fa2`],RdYlGn:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#d9ef8b`,`#a6d96a`,`#66bd63`,`#1a9850`,`#006837`],RdBu:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#f7f7f7`,`#d1e5f0`,`#92c5de`,`#4393c3`,`#2166ac`,`#053061`],PiYG:[`#8e0152`,`#c51b7d`,`#de77ae`,`#f1b6da`,`#fde0ef`,`#f7f7f7`,`#e6f5d0`,`#b8e186`,`#7fbc41`,`#4d9221`,`#276419`],PRGn:[`#40004b`,`#762a83`,`#9970ab`,`#c2a5cf`,`#e7d4e8`,`#f7f7f7`,`#d9f0d3`,`#a6dba0`,`#5aae61`,`#1b7837`,`#00441b`],RdYlBu:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee090`,`#ffffbf`,`#e0f3f8`,`#abd9e9`,`#74add1`,`#4575b4`,`#313695`],BrBG:[`#543005`,`#8c510a`,`#bf812d`,`#dfc27d`,`#f6e8c3`,`#f5f5f5`,`#c7eae5`,`#80cdc1`,`#35978f`,`#01665e`,`#003c30`],RdGy:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#ffffff`,`#e0e0e0`,`#bababa`,`#878787`,`#4d4d4d`,`#1a1a1a`],PuOr:[`#7f3b08`,`#b35806`,`#e08214`,`#fdb863`,`#fee0b6`,`#f7f7f7`,`#d8daeb`,`#b2abd2`,`#8073ac`,`#542788`,`#2d004b`],Set2:[`#66c2a5`,`#fc8d62`,`#8da0cb`,`#e78ac3`,`#a6d854`,`#ffd92f`,`#e5c494`,`#b3b3b3`],Accent:[`#7fc97f`,`#beaed4`,`#fdc086`,`#ffff99`,`#386cb0`,`#f0027f`,`#bf5b17`,`#666666`],Set1:[`#e41a1c`,`#377eb8`,`#4daf4a`,`#984ea3`,`#ff7f00`,`#ffff33`,`#a65628`,`#f781bf`,`#999999`],Set3:[`#8dd3c7`,`#ffffb3`,`#bebada`,`#fb8072`,`#80b1d3`,`#fdb462`,`#b3de69`,`#fccde5`,`#d9d9d9`,`#bc80bd`,`#ccebc5`,`#ffed6f`],Dark2:[`#1b9e77`,`#d95f02`,`#7570b3`,`#e7298a`,`#66a61e`,`#e6ab02`,`#a6761d`,`#666666`],Paired:[`#a6cee3`,`#1f78b4`,`#b2df8a`,`#33a02c`,`#fb9a99`,`#e31a1c`,`#fdbf6f`,`#ff7f00`,`#cab2d6`,`#6a3d9a`,`#ffff99`,`#b15928`],Pastel2:[`#b3e2cd`,`#fdcdac`,`#cbd5e8`,`#f4cae4`,`#e6f5c9`,`#fff2ae`,`#f1e2cc`,`#cccccc`],Pastel1:[`#fbb4ae`,`#b3cde3`,`#ccebc5`,`#decbe4`,`#fed9a6`,`#ffffcc`,`#e5d8bd`,`#fddaec`,`#f2f2f2`]},tn=Object.keys(en),nn=new Map(tn.map(e=>[e.toLowerCase(),e])),rn=typeof Proxy==`function`?new Proxy(en,{get(e,t){let n=t.toLowerCase();if(nn.has(n))return e[nn.get(n)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tn)}}):en,an=(...e)=>{e=g(e,`cmyk`);let[t,n,r,i]=e,a=e.length>4?e[4]:1;return i===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-i),n>=1?0:255*(1-n)*(1-i),r>=1?0:255*(1-r)*(1-i),a]},{max:on}=Math,sn=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i=1-on(t,on(n,r)),a=i<1?1/(1-i):0;return[(1-t-i)*a,(1-n-i)*a,(1-r-i)*a,i]};O.prototype.cmyk=function(){return sn(this._rgb)},Object.assign(k,{cmyk:(...e)=>new O(...e,`cmyk`)}),D.format.cmyk=an,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`cmyk`),h(e)===`array`&&e.length===4)return`cmyk`}});var cn=(...e)=>{let t=g(e,`hsla`),n=_(e)||`lsa`;return t[0]=x(t[0]||0)+`deg`,t[1]=x(t[1]*100)+`%`,t[2]=x(t[2]*100)+`%`,n===`hsla`||t.length>3&&t[3]<1?(t[3]=`/ `+(t.length>3?t[3]:1),n=`hsla`):t.length=3,`${n.substr(0,3)}(${t.join(` `)})`},ln=(...e)=>{let t=g(e,`lab`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=x(t[2]),n===`laba`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(` `)})`},un=(...e)=>{let t=g(e,`lch`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,n===`lcha`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(` `)})`},dn=(...e)=>{let t=g(e,`lab`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=S(t[2]),t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(` `)})`},fn=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=nt(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},pn=(...e)=>{let t=g(e,`lch`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(` `)})`},{round:mn}=Math,hn=(...e)=>{let t=g(e,`rgba`),n=_(e)||`rgb`;if(n.substr(0,3)===`hsl`)return cn(qe(t),n);if(n.substr(0,3)===`lab`){let e=ce();M(`d50`);let r=ln(fe(t),n);return M(e),r}if(n.substr(0,3)===`lch`){let e=ce();M(`d50`);let r=un(Ae(t),n);return M(e),r}return n.substr(0,5)===`oklab`?dn(nt(t)):n.substr(0,5)===`oklch`?pn(fn(t)):(t[0]=mn(t[0]),t[1]=mn(t[1]),t[2]=mn(t[2]),(n===`rgba`||t.length>3&&t[3]<1)&&(t[3]=`/ `+(t.length>3?t[3]:1),n=`rgba`),`${n.substr(0,3)}(${t.slice(0,n===`rgb`?3:4).join(` `)})`)},gn=(...e)=>{e=g(e,`lch`);let[t,n,r,...i]=e,[a,o,s]=Ce(t,n,r),[c,l,u]=et(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},V=`((?:-?\\d+)|(?:-?\\d+(?:\\.\\d+)?)%|none)`,H=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%?)|none)`,_n=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%)|none)`,U=`\\s*`,vn=`\\s+`,yn=`\\s*,\\s*`,bn=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:deg)?)|none)`,xn=`\\s*(?:\\/\\s*((?:[01]|[01]?\\.\\d+)|\\d+(?:\\.\\d+)?%))?`,Sn=RegExp(`^rgba?\\(`+U+[V,V,V].join(vn)+xn+`\\)$`),Cn=RegExp(`^rgb\\(`+U+[V,V,V].join(yn)+U+`\\)$`),wn=RegExp(`^rgba\\(`+U+[V,V,V,H].join(yn)+U+`\\)$`),Tn=RegExp(`^hsla?\\(`+U+[bn,_n,_n].join(vn)+xn+`\\)$`),En=RegExp(`^hsl?\\(`+U+[bn,_n,_n].join(yn)+U+`\\)$`),Dn=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,On=RegExp(`^lab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),kn=RegExp(`^lch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),An=RegExp(`^oklab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),jn=RegExp(`^oklch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),{round:Mn}=Math,Nn=e=>e.map((e,t)=>t<=2?f(Mn(e),0,255):e),W=(e,t=0,n=100,r=!1)=>(typeof e==`string`&&e.endsWith(`%`)&&(e=parseFloat(e.substring(0,e.length-1))/100,e=r?t+(e+1)*.5*(n-t):t+e*(n-t)),+e),G=(e,t)=>e===`none`?t:e,Pn=e=>{if(e=e.toLowerCase().trim(),e===`transparent`)return[0,0,0,0];let t;if(D.format.named)try{return D.format.named(e)}catch{}if((t=e.match(Sn))||(t=e.match(Cn))){let e=t.slice(1,4);for(let t=0;t<3;t++)e[t]=+W(G(e[t],0),0,255);e=Nn(e);let n=t[4]===void 0?1:+W(t[4],0,1);return e[3]=n,e}if(t=e.match(wn)){let e=t.slice(1,5);for(let t=0;t<4;t++)e[t]=+W(e[t],0,255);return e}if((t=e.match(Tn))||(t=e.match(En))){let e=t.slice(1,4);e[0]=+G(e[0].replace(`deg`,``),0),e[1]=W(G(e[1],0),0,100)*.01,e[2]=W(G(e[2],0),0,100)*.01;let n=Nn(Ke(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(Dn)){let e=t.slice(1,4);e[1]*=.01,e[2]*=.01;let n=Ke(e);for(let e=0;e<3;e++)n[e]=Mn(n[e]);return n[3]=+t[4],n}if(t=e.match(On)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,100),e[1]=W(G(e[1],0),-125,125,!0),e[2]=W(G(e[2],0),-125,125,!0);let n=ce();M(`d50`);let r=Nn(N(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(kn)){let e=t.slice(1,4);e[0]=W(e[0],0,100),e[1]=W(G(e[1],0),0,150,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=ce();M(`d50`);let r=Nn(we(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(An)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),-.4,.4,!0),e[2]=W(G(e[2],0),-.4,.4,!0);let n=Nn(et(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(jn)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),0,.4,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=Nn(gn(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}};Pn.test=e=>Sn.test(e)||Tn.test(e)||On.test(e)||kn.test(e)||An.test(e)||jn.test(e)||Cn.test(e)||wn.test(e)||En.test(e)||Dn.test(e)||e===`transparent`,O.prototype.css=function(e){return hn(this._rgb,e)},k.css=(...e)=>new O(...e,`css`),D.format.css=Pn,D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&Pn.test(e))return`css`}}),D.format.gl=(...e)=>{let t=g(e,`rgba`);return t[0]*=255,t[1]*=255,t[2]*=255,t},k.gl=(...e)=>new O(...e,`gl`),O.prototype.gl=function(){let e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},O.prototype.hex=function(e){return oe(this._rgb,e)},k.hex=(...e)=>new O(...e,`hex`),D.format.hex=ie,D.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return`hex`}});var{log:Fn}=Math,In=e=>{let t=e/100,n,r,i;return t<66?(n=255,r=t<6?0:-155.25485562709179-.44596950469579133*(r=t-2)+104.49216199393888*Fn(r),i=t<20?0:-254.76935184120902+.8274096064007395*(i=t-10)+115.67994401066147*Fn(i)):(n=351.97690566805693+.114206453784165*(n=t-55)-40.25366309332127*Fn(n),r=325.4494125711974+.07943456536662342*(r=t-50)-28.0852963507957*Fn(r),i=255),[n,r,i,1]},{round:Ln}=Math,Rn=(...e)=>{let t=g(e,`rgb`),n=t[0],r=t[2],i=1e3,a=4e4,o;for(;a-i>.4;){o=(a+i)*.5;let e=In(o);e[2]/e[0]>=r/n?a=o:i=o}return Ln(o)};O.prototype.temp=O.prototype.kelvin=O.prototype.temperature=function(){return Rn(this._rgb)};var zn=(...e)=>new O(...e,`temp`);Object.assign(k,{temp:zn,kelvin:zn,temperature:zn}),D.format.temp=D.format.kelvin=D.format.temperature=In,O.prototype.oklch=function(){return fn(this._rgb)},Object.assign(k,{oklch:(...e)=>new O(...e,`oklch`)}),D.format.oklch=gn,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklch`),h(e)===`array`&&e.length===3)return`oklch`}}),Object.assign(k,{analyze:jt,average:ut,bezier:_t,blend:I,brewer:rn,Color:O,colors:A,contrast:Nt,contrastAPCA:Bt,cubehelix:St,deltaE:Xt,distance:Zt,input:D,interpolate:F,limits:Mt,mix:F,random:Et,scale:pt,scales:$t,valid:Qt});var K=k,q=class e{constructor(){this.hex=`#000000`,this.rgb_r=0,this.rgb_g=0,this.rgb_b=0,this.xyz_x=0,this.xyz_y=0,this.xyz_z=0,this.luv_l=0,this.luv_u=0,this.luv_v=0,this.lch_l=0,this.lch_c=0,this.lch_h=0,this.hsluv_h=0,this.hsluv_s=0,this.hsluv_l=0,this.hpluv_h=0,this.hpluv_p=0,this.hpluv_l=0,this.r0s=0,this.r0i=0,this.r1s=0,this.r1i=0,this.g0s=0,this.g0i=0,this.g1s=0,this.g1i=0,this.b0s=0,this.b0i=0,this.b1s=0,this.b1i=0}static fromLinear(e){return e<=.0031308?12.92*e:1.055*e**(1/2.4)-.055}static toLinear(e){return e>.04045?((e+.055)/1.055)**2.4:e/12.92}static yToL(t){return t<=e.epsilon?t/e.refY*e.kappa:116*(t/e.refY)**(1/3)-16}static lToY(t){return t<=8?e.refY*t/e.kappa:e.refY*((t+16)/116)**3}static rgbChannelToHex(t){let n=Math.round(t*255),r=n%16,i=(n-r)/16|0;return e.hexChars.charAt(i)+e.hexChars.charAt(r)}static hexToRgbChannel(t,n){let r=e.hexChars.indexOf(t.charAt(n)),i=e.hexChars.indexOf(t.charAt(n+1));return(r*16+i)/255}static distanceFromOriginAngle(e,t,n){let r=t/(Math.sin(n)-e*Math.cos(n));return r<0?1/0:r}static distanceFromOrigin(e,t){return Math.abs(t)/Math.sqrt(e**2+1)}static min6(e,t,n,r,i,a){return Math.min(e,Math.min(t,Math.min(n,Math.min(r,Math.min(i,a)))))}rgbToHex(){this.hex=`#`,this.hex+=e.rgbChannelToHex(this.rgb_r),this.hex+=e.rgbChannelToHex(this.rgb_g),this.hex+=e.rgbChannelToHex(this.rgb_b)}hexToRgb(){this.hex=this.hex.toLowerCase(),this.rgb_r=e.hexToRgbChannel(this.hex,1),this.rgb_g=e.hexToRgbChannel(this.hex,3),this.rgb_b=e.hexToRgbChannel(this.hex,5)}xyzToRgb(){this.rgb_r=e.fromLinear(e.m_r0*this.xyz_x+e.m_r1*this.xyz_y+e.m_r2*this.xyz_z),this.rgb_g=e.fromLinear(e.m_g0*this.xyz_x+e.m_g1*this.xyz_y+e.m_g2*this.xyz_z),this.rgb_b=e.fromLinear(e.m_b0*this.xyz_x+e.m_b1*this.xyz_y+e.m_b2*this.xyz_z)}rgbToXyz(){let t=e.toLinear(this.rgb_r),n=e.toLinear(this.rgb_g),r=e.toLinear(this.rgb_b);this.xyz_x=.41239079926595*t+.35758433938387*n+.18048078840183*r,this.xyz_y=.21263900587151*t+.71516867876775*n+.072192315360733*r,this.xyz_z=.019330818715591*t+.11919477979462*n+.95053215224966*r}xyzToLuv(){let t=this.xyz_x+15*this.xyz_y+3*this.xyz_z,n=4*this.xyz_x,r=9*this.xyz_y;t===0?(n=NaN,r=NaN):(n/=t,r/=t),this.luv_l=e.yToL(this.xyz_y),this.luv_l===0?(this.luv_u=0,this.luv_v=0):(this.luv_u=13*this.luv_l*(n-e.refU),this.luv_v=13*this.luv_l*(r-e.refV))}luvToXyz(){if(this.luv_l===0){this.xyz_x=0,this.xyz_y=0,this.xyz_z=0;return}let t=this.luv_u/(13*this.luv_l)+e.refU,n=this.luv_v/(13*this.luv_l)+e.refV;this.xyz_y=e.lToY(this.luv_l),this.xyz_x=0-9*this.xyz_y*t/((t-4)*n-t*n),this.xyz_z=(9*this.xyz_y-15*n*this.xyz_y-n*this.xyz_x)/(3*n)}luvToLch(){if(this.lch_l=this.luv_l,this.lch_c=Math.sqrt(this.luv_u*this.luv_u+this.luv_v*this.luv_v),this.lch_c<1e-8)this.lch_h=0;else{let e=Math.atan2(this.luv_v,this.luv_u);this.lch_h=e*180/Math.PI,this.lch_h<0&&(this.lch_h=360+this.lch_h)}}lchToLuv(){let e=this.lch_h/180*Math.PI;this.luv_l=this.lch_l,this.luv_u=Math.cos(e)*this.lch_c,this.luv_v=Math.sin(e)*this.lch_c}calculateBoundingLines(t){let n=(t+16)**3/1560896,r=n>e.epsilon?n:t/e.kappa,i=r*(284517*e.m_r0-94839*e.m_r2),a=r*(838422*e.m_r2+769860*e.m_r1+731718*e.m_r0),o=r*(632260*e.m_r2-126452*e.m_r1),s=r*(284517*e.m_g0-94839*e.m_g2),c=r*(838422*e.m_g2+769860*e.m_g1+731718*e.m_g0),l=r*(632260*e.m_g2-126452*e.m_g1),u=r*(284517*e.m_b0-94839*e.m_b2),d=r*(838422*e.m_b2+769860*e.m_b1+731718*e.m_b0),f=r*(632260*e.m_b2-126452*e.m_b1);this.r0s=i/o,this.r0i=a*t/o,this.r1s=i/(o+126452),this.r1i=(a-769860)*t/(o+126452),this.g0s=s/l,this.g0i=c*t/l,this.g1s=s/(l+126452),this.g1i=(c-769860)*t/(l+126452),this.b0s=u/f,this.b0i=d*t/f,this.b1s=u/(f+126452),this.b1i=(d-769860)*t/(f+126452)}calcMaxChromaHpluv(){let t=e.distanceFromOrigin(this.r0s,this.r0i),n=e.distanceFromOrigin(this.r1s,this.r1i),r=e.distanceFromOrigin(this.g0s,this.g0i),i=e.distanceFromOrigin(this.g1s,this.g1i),a=e.distanceFromOrigin(this.b0s,this.b0i),o=e.distanceFromOrigin(this.b1s,this.b1i);return e.min6(t,n,r,i,a,o)}calcMaxChromaHsluv(t){let n=t/360*Math.PI*2,r=e.distanceFromOriginAngle(this.r0s,this.r0i,n),i=e.distanceFromOriginAngle(this.r1s,this.r1i,n),a=e.distanceFromOriginAngle(this.g0s,this.g0i,n),o=e.distanceFromOriginAngle(this.g1s,this.g1i,n),s=e.distanceFromOriginAngle(this.b0s,this.b0i,n),c=e.distanceFromOriginAngle(this.b1s,this.b1i,n);return e.min6(r,i,a,o,s,c)}hsluvToLch(){if(this.hsluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hsluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hsluv_l,this.calculateBoundingLines(this.hsluv_l);let e=this.calcMaxChromaHsluv(this.hsluv_h);this.lch_c=e/100*this.hsluv_s}this.lch_h=this.hsluv_h}lchToHsluv(){if(this.lch_l>99.9999999)this.hsluv_s=0,this.hsluv_l=100;else if(this.lch_l<1e-8)this.hsluv_s=0,this.hsluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHsluv(this.lch_h);this.hsluv_s=this.lch_c/e*100,this.hsluv_l=this.lch_l}this.hsluv_h=this.lch_h}hpluvToLch(){if(this.hpluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hpluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hpluv_l,this.calculateBoundingLines(this.hpluv_l);let e=this.calcMaxChromaHpluv();this.lch_c=e/100*this.hpluv_p}this.lch_h=this.hpluv_h}lchToHpluv(){if(this.lch_l>99.9999999)this.hpluv_p=0,this.hpluv_l=100;else if(this.lch_l<1e-8)this.hpluv_p=0,this.hpluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHpluv();this.hpluv_p=this.lch_c/e*100,this.hpluv_l=this.lch_l}this.hpluv_h=this.lch_h}hsluvToRgb(){this.hsluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hpluvToRgb(){this.hpluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hsluvToHex(){this.hsluvToRgb(),this.rgbToHex()}hpluvToHex(){this.hpluvToRgb(),this.rgbToHex()}rgbToHsluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHsluv()}rgbToHpluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHpluv()}hexToHsluv(){this.hexToRgb(),this.rgbToHsluv()}hexToHpluv(){this.hexToRgb(),this.rgbToHpluv()}};q.hexChars=`0123456789abcdef`,q.refY=1,q.refU=.19783000664283,q.refV=.46831999493879,q.kappa=903.2962962,q.epsilon=.0088564516,q.m_r0=3.240969941904521,q.m_r1=-1.537383177570093,q.m_r2=-.498610760293,q.m_g0=-.96924363628087,q.m_g1=1.87596750150772,q.m_g2=.041555057407175,q.m_b0=.055630079696993,q.m_b1=-.20397695888897,q.m_b2=1.056971514242878;var Bn=s(((e,t)=>{function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=n})),Vn=s(((e,t)=>{var n=Bn(),r,i;function a(){for(var e in i=[`toString`,`toLocaleString`,`valueOf`,`hasOwnProperty`,`isPrototypeOf`,`propertyIsEnumerable`,`constructor`],r=!0,{toString:null})r=!1}function o(e,t,o){var c,l=0;for(c in r??a(),e)if(s(t,e,c,o)===!1)break;if(r)for(var u=e.constructor,d=!!u&&e===u.prototype;(c=i[l++])&&!((c!==`constructor`||!d&&n(e,c))&&e[c]!==Object.prototype[c]&&s(t,e,c,o)===!1););}function s(e,t,n,r){return e.call(r,t[n],n,t)}t.exports=o})),Hn=s(((e,t)=>{var n=Vn();function r(e){var t=[];return n(e,function(e,n){typeof e==`function`&&t.push(n)}),t.sort()}t.exports=r})),Un=s(((e,t)=>{function n(e,t,n){var r=e.length;t=t==null?0:t<0?Math.max(r+t,0):Math.min(t,r),n=n==null?r:n<0?Math.max(r+n,0):Math.min(n,r);for(var i=[];t{var n=Un();function r(e,t,r){var i=n(arguments,2);return function(){return e.apply(t,i.concat(n(arguments)))}}t.exports=r})),Gn=s(((e,t)=>{function n(e,t,n){if(e!=null)for(var r=-1,i=e.length;++r{var n=Hn(),r=Wn(),i=Gn(),a=Un();function o(e,t){i(arguments.length>1?a(arguments,1):n(e),function(t){e[t]=r(e[t],e)})}t.exports=o})),J=s(((e,t)=>{var n=Bn(),r=Vn();function i(e,t,i){r(e,function(r,a){if(n(e,a))return t.call(i,e[a],a,e)})}t.exports=i})),qn=s(((e,t)=>{function n(e){return e}t.exports=n})),Jn=s(((e,t)=>{function n(e){return function(t){return t[e]}}t.exports=n})),Yn=s(((e,t)=>{var n=/^\[object (.*)\]$/,r=Object.prototype.toString,i;function a(e){return e===null?`Null`:e===i?`Undefined`:n.exec(r.call(e))[1]}t.exports=a})),Xn=s(((e,t)=>{var n=Yn();function r(e,t){return n(e)===t}t.exports=r})),Zn=s(((e,t)=>{var n=Xn();t.exports=Array.isArray||function(e){return n(e,`Array`)}})),Qn=s(((e,t)=>{var n=J(),r=Zn();function i(e,t){for(var n=-1,r=e.length;++n{var n=qn(),r=Jn(),i=Qn();function a(e,t){if(e==null)return n;switch(typeof e){case`function`:return t===void 0?e:function(n,r,i){return e.call(t,n,r,i)};case`object`:return function(t){return i(t,e)};case`string`:case`number`:return r(e)}}t.exports=a})),$n=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!1;return n(e,function(n,r){if(t(n,r,e))return a=!0,!1}),a}t.exports=i})),er=s(((e,t)=>{var n=$n();function r(e,t){return n(e,function(e){return e===t})}t.exports=r})),tr=s(((e,t)=>{function n(e){return!!e&&typeof e==`object`&&e.constructor===Object}t.exports=n})),nr=s(((e,t)=>{var n=J(),r=tr();function i(e,t){for(var a=0,o=arguments.length,s;++a{var n=J(),r=tr();function i(e,t){for(var r=0,i=arguments.length,o;++r{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!0;return n(e,function(n,r){if(!t(n,r,e))return a=!1,!1}),a}t.exports=i})),ar=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Object`)}t.exports=r})),or=s(((e,t)=>{function n(e,t){return e===t?e!==0||1/e==1/t:e!==e&&t!==t}t.exports=n})),sr=s(((e,t)=>{var n=Bn(),r=ir(),i=ar(),a=or();function o(e){return function(t,r){return n(this,r)&&e(t,this[r])}}function s(e,t){return n(this,t)}function c(e,t,n){return n||=a,!i(e)||!i(t)?n(e,t):r(e,o(n),t)&&r(t,s,e)}t.exports=c})),cr=s(((e,t)=>{var n=Gn(),r=Un(),i=J();function a(e,t){return n(r(arguments,1),function(t){i(t,function(t,n){e[n]??(e[n]=t)})}),e}t.exports=a})),lr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){t(e,n,r)&&(a[n]=e)}),a}t.exports=i})),ur=s(((e,t)=>{var n=$n(),r=Y();function i(e,t,i){t=r(t,i);var a;return n(e,function(e,n,r){if(t(e,n,r))return a=e,!0}),a}t.exports=i})),dr=s(((e,t)=>{var n=J(),r=tr();function i(e,t,a,o){return n(e,function(e,n){var s=a?a+`.`+n:n;o!==0&&r(e)?i(e,t,s,o-1):t[s]=e}),t}function a(e,t){return e==null?{}:(t??=-1,i(e,{},``,t))}t.exports=a})),fr=s(((e,t)=>{function n(e){switch(typeof e){case`string`:case`number`:case`boolean`:return!0}return e==null}t.exports=n})),pr=s(((e,t)=>{fr();function n(e,t){for(var n=t.split(`.`),r=n.pop();t=n.shift();)if(e=e[t],e==null)return;return e[r]}t.exports=n})),mr=s(((e,t)=>{var n=pr(),r;function i(e,t){return n(e,t)!==r}t.exports=i})),hr=s(((e,t)=>{var n=J();t.exports=Object.keys||function(e){var t=[];return n(e,function(e,n){t.push(n)}),t}})),gr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){a[n]=t(e,n,r)}),a}t.exports=i})),_r=s(((e,t)=>{var n=J();function r(e,t){var r=!0;return n(t,function(t,n){if(e[n]!==t)return r=!1}),r}t.exports=r})),vr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return 1/0;if(e.length&&!t)return Math.max.apply(Math,e);t=n(t,r);for(var i,a=-1/0,o,s,c=-1,l=e.length;++ca&&(a=s,i=o);return i}t.exports=r})),yr=s(((e,t)=>{var n=J();function r(e){var t=[];return n(e,function(e,n){t.push(e)}),t}t.exports=r})),br=s(((e,t)=>{var n=vr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),xr=s(((e,t)=>{var n=J();function r(e,t){for(var r=0,a=arguments.length,o;++r{var n=Yn(),r=tr(),i=xr();function a(e){switch(n(e)){case`Object`:return o(e);case`Array`:return l(e);case`RegExp`:return s(e);case`Date`:return c(e);default:return e}}function o(e){return r(e)?i({},e):e}function s(e){var t=``;return t+=e.multiline?`m`:``,t+=e.global?`g`:``,t+=e.ignoreCase?`i`:``,new RegExp(e.source,t)}function c(e){return new Date(+e)}function l(e){return e.slice()}t.exports=a})),Cr=s(((e,t)=>{var n=Sr(),r=J(),i=Yn(),a=tr();function o(e,t){switch(i(e)){case`Object`:return s(e,t);case`Array`:return c(e,t);default:return n(e)}}function s(e,t){if(a(e)){var n={};return r(e,function(e,n){this[n]=o(e,t)},n),n}else if(t)return t(e);else return e}function c(e,t){for(var n=[],r=-1,i=e.length;++r{var n=Bn(),r=Cr(),i=ar();function a(){for(var e=1,t,o,s,c=r(arguments[0]);s=arguments[e++];)for(t in s)n(s,t)&&(o=s[t],i(o)&&i(c[t])?c[t]=a(c[t],o):c[t]=r(o));return c}t.exports=a})),Tr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return-1/0;if(e.length&&!t)return Math.min.apply(Math,e);t=n(t,r);for(var i,a=1/0,o,s,c=-1,l=e.length;++c{var n=Tr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),Dr=s(((e,t)=>{var n=Gn();function r(e,t){return t&&n(t.split(`.`),function(t){e[t]||(e[t]={}),e=e[t]}),e}t.exports=r})),Or=s(((e,t)=>{function n(e,t,n){if(n||=0,e==null)return-1;for(var r=e.length,i=n<0?r+n:n;i{var n=Or();function r(e,t){return n(e,t)!==-1}t.exports=r})),Ar=s(((e,t)=>{var n=Un(),r=kr();function i(e,t){var i=typeof arguments[1]==`string`?n(arguments,1):arguments[1],a={};for(var o in e)e.hasOwnProperty(o)&&!r(i,o)&&(a[o]=e[o]);return a}t.exports=i})),jr=s(((e,t)=>{var n=Un();function r(e,t){for(var r=typeof arguments[1]==`string`?n(arguments,1):arguments[1],i={},a=0,o;o=r[a++];)i[o]=e[o];return i}t.exports=r})),Mr=s(((e,t)=>{var n=gr(),r=Jn();function i(e,t){return n(e,r(t))}t.exports=i})),Nr=s(((e,t)=>{var n=J();function r(e){var t=0;return n(e,function(){t++}),t}t.exports=r})),Pr=s(((e,t)=>{var n=J(),r=Nr();function i(e,t,i,a){var o=arguments.length>2;if(!r(e)&&!o)throw Error(`reduce of empty object with no initial value`);return n(e,function(e,n,r){o?i=t.call(a,i,e,n,r):(i=e,o=!0)}),i}t.exports=i})),Fr=s(((e,t)=>{var n=lr(),r=Y();function i(e,t,i){return t=r(t,i),n(e,function(e,n,r){return!t(e,n,r)},i)}t.exports=i})),Ir=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Function`)}t.exports=r})),Lr=s(((e,t)=>{var n=Ir();function r(e,t){var r=e[t];if(r!==void 0)return n(r)?r.call(e):r}t.exports=r})),Rr=s(((e,t)=>{var n=Dr();function r(e,t,r){var i=/^(.+)\.(.+)$/.exec(t);i?n(e,i[1])[i[2]]=r:e[t]=r}t.exports=r})),zr=s(((e,t)=>{var n=mr();function r(e,t){if(n(e,t)){for(var r=t.split(`.`),i=r.pop();t=r.shift();)e=e[t];return delete e[i]}else return!0}t.exports=r})),Br=s(((e,t)=>{t.exports={bindAll:Kn(),contains:er(),deepFillIn:nr(),deepMatches:Qn(),deepMixIn:rr(),equals:sr(),every:ir(),fillIn:cr(),filter:lr(),find:ur(),flatten:dr(),forIn:Vn(),forOwn:J(),functions:Hn(),get:pr(),has:mr(),hasOwn:Bn(),keys:hr(),map:gr(),matches:_r(),max:br(),merge:wr(),min:Er(),mixIn:xr(),namespace:Dr(),omit:Ar(),pick:jr(),pluck:Mr(),reduce:Pr(),reject:Fr(),result:Lr(),set:Rr(),size:Nr(),some:$n(),unset:zr(),values:yr()}})),Vr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.default=(0,Br().map)({A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},function(e){return[100*(e.x/e.y),100,100*(1-e.x-e.y)/e.y]}),t.exports=e.default})),Hr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=Math,r=n.pow,i=n.sign,a=n.abs,o={decode:function(e){return e<=.04045?e/12.92:r((e+.055)/1.055,2.4)},encode:function(e){return e<=.0031308?12.92*e:1.055*r(e,1/2.4)-.055}},s={encode:function(e){return e<.001953125?16*e:r(e,1/1.8)},decode:function(e){return e<16*.001953125?e/16:r(e,1.8)}};function c(e){return{decode:function(t){return i(t)*r(a(t),e)},encode:function(t){return i(t)*r(a(t),1/e)}}}e.default={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:o},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:c(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:c(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:s}},t.exports=e.default})),Ur=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});function t(e){return[[e[0][0],e[1][0],e[2][0]],[e[0][1],e[1][1],e[2][1]],[e[0][2],e[1][2],e[2][2]]]}function n(e){return e[0][0]*(e[2][2]*e[1][1]-e[2][1]*e[1][2])+e[1][0]*(e[2][1]*e[0][2]-e[2][2]*e[0][1])+e[2][0]*(e[1][2]*e[0][1]-e[1][1]*e[0][2])}function r(e){var t=1/n(e);return[[(e[2][2]*e[1][1]-e[2][1]*e[1][2])*t,(e[2][1]*e[0][2]-e[2][2]*e[0][1])*t,(e[1][2]*e[0][1]-e[1][1]*e[0][2])*t],[(e[2][0]*e[1][2]-e[2][2]*e[1][0])*t,(e[2][2]*e[0][0]-e[2][0]*e[0][2])*t,(e[1][0]*e[0][2]-e[1][2]*e[0][0])*t],[(e[2][1]*e[1][0]-e[2][0]*e[1][1])*t,(e[2][0]*e[0][1]-e[2][1]*e[0][0])*t,(e[1][1]*e[0][0]-e[1][0]*e[0][1])*t]]}function i(e,t){return[e[0][0]*t[0]+e[0][1]*t[1]+e[0][2]*t[2],e[1][0]*t[0]+e[1][1]*t[1]+e[1][2]*t[2],e[2][0]*t[0]+e[2][1]*t[1]+e[2][2]*t[2]]}function a(e,t){return[[e[0][0]*t[0],e[0][1]*t[1],e[0][2]*t[2]],[e[1][0]*t[0],e[1][1]*t[1],e[1][2]*t[2]],[e[2][0]*t[0],e[2][1]*t[1],e[2][2]*t[2]]]}function o(e,t){return[[e[0][0]*t[0][0]+e[0][1]*t[1][0]+e[0][2]*t[2][0],e[0][0]*t[0][1]+e[0][1]*t[1][1]+e[0][2]*t[2][1],e[0][0]*t[0][2]+e[0][1]*t[1][2]+e[0][2]*t[2][2]],[e[1][0]*t[0][0]+e[1][1]*t[1][0]+e[1][2]*t[2][0],e[1][0]*t[0][1]+e[1][1]*t[1][1]+e[1][2]*t[2][1],e[1][0]*t[0][2]+e[1][1]*t[1][2]+e[1][2]*t[2][2]],[e[2][0]*t[0][0]+e[2][1]*t[1][0]+e[2][2]*t[2][0],e[2][0]*t[0][1]+e[2][1]*t[1][1]+e[2][2]*t[2][1],e[2][0]*t[0][2]+e[2][1]*t[1][2]+e[2][2]*t[2][2]]]}e.transpose=t,e.determinant=n,e.inverse=r,e.multiply=i,e.scalar=a,e.product=o})),Wr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.PI;function n(e){for(var n=e*180/t;n<0;)n+=360;for(;n>360;)n-=360;return n}function r(e){for(var n=t*e/180;n<0;)n+=2*t;for(;n>2*t;)n-=2*t;return n}e.fromRadian=n,e.toRadian=r})),Gr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0});var t=Math.round;function n(e){return e[0]==`#`&&(e=e.slice(1)),e.length<6&&(e=e.split(``).map(function(e){return e+e}).join(``)),e.match(/../g).map(function(e){return parseInt(e,16)/255})}function r(e){return`#`+e.map(function(e){return e=t(255*e).toString(16),e.length<2&&(e=`0`+e),e}).join(``)}e.fromHex=n,e.toHex=r})),Kr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=o(Ur()),r=a(Vr()),i=a(Hr());function a(e){return e&&e.__esModule?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function s(){var e=arguments.length<=0||arguments[0]===void 0?i.default.sRGB:arguments[0],t=arguments.length<=1||arguments[1]===void 0?r.default.D65:arguments[1],a=[e.r,e.g,e.b],o=n.transpose(a.map(function(e){return[e.x/e.y,1,(1-e.x-e.y)/e.y]})),s=e.gamma,c=n.multiply(n.inverse(o),t),l=n.scalar(o,c),u=n.inverse(l);return{fromRgb:function(e){return n.multiply(l,e.map(s.decode))},toRgb:function(e){return n.multiply(u,e).map(s.encode)}}}e.default=s,t.exports=e.default})),qr=s(((e,t)=>{t.exports={illuminant:Vr(),workspace:Hr(),matrix:Ur(),degree:Wr(),rgb:Gr(),xyz:Kr()}})),Jr=s((e=>{Object.defineProperty(e,`__esModule`,{value:!0}),e.cfs=e.distance=e.lerp=e.corLerp=void 0;var t=Br();function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ti/2&&(e>t?t+=i:e+=i),((1-n)*e+n*t)%(i||1/0)}function u(e,t,n){var r={};for(var i in e)r[i]=l(e[i],t[i],n,i);return r}function d(e,t){var n=0;for(var r in e)n+=o(e[r]-t[r],2);return s(n)}function f(e){return t.merge.apply(void 0,r(e.split(``).map(function(e){return n({},e,!0)})))}e.corLerp=l,e.lerp=u,e.distance=d,e.cfs=f})),Yr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=Jr();function a(e,t){var a=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],o=-a,s=1+a,c=Math,l=c.min,u=c.max,d=n([`000`,`fff`].map(function(n){return t.fromXyz(e.fromRgb(r.rgb.fromHex(n)))}),2),f=d[0],p=d[1];function m(n){var r=e.toRgb(t.toXyz(n));return[r.map(function(e){return e>=o&&e<=s}).reduce(function(e,t){return e&&t},!0),r]}function h(e,t){for(var r=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,i.distance)(e,t)>r;){var a=(0,i.lerp)(e,t,.5);n(m(a),1)[0]?e=a:t=a}return e}function g(e){return(0,i.lerp)(f,p,e)}function _(e){return e.map(function(e){return u(o,l(s,e))})}return{contains:m,limit:h,spine:g,crop:_}}e.default=a,t.exports=e.default})),Xr=s((e=>{var t=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0}),e.toNotation=e.fromNotation=e.toHue=e.fromHue=void 0;var n=Jr(),r=Math.floor,i=[{s:`R`,h:20.14,e:.8,H:0},{s:`Y`,h:90,e:.7,H:100},{s:`G`,h:164.25,e:1,H:200},{s:`B`,h:237.53,e:1.2,H:300},{s:`R`,h:380.14,e:.8,H:400}],a=i.map(function(e){return e.s}).slice(0,-1).join(``);function o(e){e50){var o=[n,t];t=o[0],n=o[1],i=100-i}return i<1?a[t]:a[t]+i.toFixed()+a[n]}e.fromHue=o,e.toHue=s,e.fromNotation=l,e.toNotation=u})),Zr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,`__esModule`,{value:!0});var r=qr(),i=s(Xr()),a=Jr(),o=Br();function s(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var c=Math,l=c.pow,u=c.sqrt,d=c.exp,f=c.abs,p=c.sign,m=Math,h=m.sin,g=m.cos,_=m.atan2,v={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},y=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],b=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],x=y,S=r.matrix.inverse(y),C=r.matrix.product(b,r.matrix.inverse(y)),w=r.matrix.product(y,r.matrix.inverse(b)),T={whitePoint:r.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ee=(0,a.cfs)(`QJMCshH`),E=(0,a.cfs)(`JCh`);function D(){var e=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],t=arguments.length<=1||arguments[1]===void 0?ee:arguments[1];e=(0,o.merge)(T,e);var a=e.whitePoint,s=e.adaptingLuminance,c=e.backgroundLuminance,m=v[e.surroundType],b=m.F,D=m.c,O=m.N_c,te=a[1],k=1/(5*s+1),A=.2*l(k,4)*5*s+.1*l(1-l(k,4),2)*l(5*s,1/3),ne=c/te,re=.725*l(1/ne,.2),ie=re,ae=1.48+u(ne),oe=e.discounting?1:b*(1-1/3.6*d(-(s+42)/92)),j=n(r.matrix.multiply(y,a).map(function(e){return oe*te/e+1-oe}),3),se=j[0],M=j[1],ce=j[2],N=pe(de(le(a)));function le(e){var t=n(r.matrix.multiply(x,e),3),i=t[0],a=t[1],o=t[2];return[se*i,M*a,ce*o]}function ue(e){var t=n(e,3),i=t[0],a=t[1],o=t[2];return r.matrix.multiply(S,[i/se,a/M,o/ce])}function de(e){return r.matrix.multiply(C,e).map(function(e){var t=l(A*f(e)/100,.42);return p(e)*400*t/(27.13+t)+.1})}function fe(e){return r.matrix.multiply(w,e.map(function(e){var t=e-.1;return p(t)*100/A*l(27.13*f(t)/(400-f(t)),1/.42)}))}function pe(e){var t=n(e,3),r=t[0],i=t[1],a=t[2];return(r*2+i+a/20-.305)*re}function me(e){return 4/D*u(e/100)*(N+4)*l(A,.25)}function he(e){return 6.25*l(D*e/((N+4)*l(A,.25)),2)}function ge(e){return e*l(A,.25)}function _e(e,t){return l(e/100,2)*t/l(A,.25)}function ve(e){return e/l(A,.25)}function ye(e,t){return 100*u(e/t)}function be(e,t){var n=t.Q,r=t.J,a=t.M,o=t.C,s=t.s,c=t.h,l=t.H,u={};return e.J&&(u.J=isNaN(r)?he(n):r),e.C&&(isNaN(o)?isNaN(a)?(n=isNaN(n)?me(r):n,u.C=_e(s,n)):u.C=ve(a):u.C=t.C),e.h&&(u.h=isNaN(c)?i.toHue(l):c),e.Q&&(u.Q=isNaN(n)?me(r):n),e.M&&(u.M=isNaN(a)?ge(o):a),e.s&&(isNaN(s)?(n=isNaN(n)?me(r):n,a=isNaN(a)?ge(o):a,u.s=ye(a,n)):u.s=s),e.H&&(u.H=isNaN(l)?i.fromHue(c):l),u}function P(e){var i=de(le(e)),a=n(i,3),o=a[0],s=a[1],c=a[2],d=o-s*12/11+c/11,f=(o+s-2*c)/9,p=_(f,d),m=r.degree.fromRadian(p),h=1/4*(g(p+2)+3.8),v=100*l(pe(i)/N,D*ae);return be(t,{J:v,C:l(5e4/13*O*ie*h*u(d*d+f*f)/(o+s+21/20*c),.9)*u(v/100)*l(1.64-l(.29,ne),.73),h:m})}function F(e){var t=be(E,e),n=t.J,i=t.C,a=t.h,o=r.degree.toRadian(a),s=l(i/(u(n/100)*l(1.64-l(.29,ne),.73)),10/9),c=1/4*(g(o+2)+3.8),d=N*l(n/100,1/D/ae),p=5e4/13*O*ie*c/s,m=d/re+.305,_=m*61/20*460/1403,v=61/20*220/1403,y=21/20*6300/1403-27/1403,b=h(o),x=g(o),S,C;return s===0||isNaN(s)?S=C=0:f(b)>=f(x)?(C=_/(p/b+v*x/b+y),S=C*x/b):(S=_/(p/x+v+y*b/x),C=S*b/x),ue(fe([20/61*m+451/1403*S+288/1403*C,20/61*m-891/1403*S-261/1403*C,20/61*m-220/1403*S-6300/1403*C]))}return{fromXyz:P,toXyz:F,fillOut:be}}e.default=D,t.exports=e.default})),Qr=s(((e,t)=>{Object.defineProperty(e,`__esModule`,{value:!0});var n=qr(),r=Math,i=r.sqrt,a=r.pow,o=r.exp,s=r.log,c=r.cos,l=r.sin,u=r.atan2,d={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function f(){var e=d[arguments.length<=0||arguments[0]===void 0?`UCS`:arguments[0]],t=e.K_L,r=e.c_1,f=e.c_2;function p(e){var t=e.J,i=e.M,a=e.h,o=n.degree.toRadian(a),u=(1+100*r)*t/(1+r*t),d=1/f*s(1+f*i);return{J_p:u,a_p:d*c(o),b_p:d*l(o)}}function m(e){var t=e.J_p,s=e.a_p,c=e.b_p,l=-t/(r*t-100*r-1),d=(o(f*i(a(s,2)+a(c,2)))-1)/f,p=u(c,s);return{J:l,M:d,h:n.degree.fromRadian(p)}}function h(e,n){return i(a((e.J_p-n.J_p)/t,2)+a(e.a_p-n.a_p,2)+a(e.b_p-n.b_p,2))}return{fromCam:p,toCam:m,distance:h}}e.default=f,t.exports=e.default})),$r=s(((e,t)=>{var n=Jr(),r=Yr(),i=Zr(),a=Qr(),o=Xr();t.exports={gamut:r,cfs:n.cfs,lerp:n.lerp,cam:i,ucs:a,hq:o}})),ei=l(qr(),1),ti=l($r(),1);function ni(e){let t=new q;return t.rgb_r=e[0],t.rgb_g=e[1],t.rgb_b=e[2],t.rgbToHsluv(),[t.hsluv_h,t.hsluv_s,t.hsluv_l]}function ri(e){let t=new q;return t.hsluv_h=e[0],t.hsluv_s=e[1],t.hsluv_l=e[2],t.hsluvToRgb(),[t.rgb_r,t.rgb_g,t.rgb_b]}var ii=ti.default.cam({whitePoint:ei.default.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ti.default.cfs(`JCh`)),ai=ei.default.xyz(ei.default.workspace.sRGB,ei.default.illuminant.D65),oi=e=>ai.toRgb(ii.toXyz({J:e[0],C:e[1],h:e[2]})),si=e=>{let t=ii.fromXyz(ai.fromRgb(e));return[t.J,t.C,t.h]},[ci,li]=(()=>{let e={k_l:1,c1:.007,c2:.0228},t=Math.PI,n=64/t/5,r=1/(5*n+1),i=.2*r**4*(5*n)+.1*(1-r**4)**2*(5*n)**(1/3);return[n=>{let[r,a,o]=n,s=a*i**.25,c=(1+100*e.c1)*r/(1+e.c1*r);c/=e.k_l;let l=1/e.c2*Math.log(1+e.c2*s),u=l*Math.cos(t/180*o),d=l*Math.sin(t/180*o);return[c,u,d]},n=>{let[r,a,o]=n,s=Math.sqrt(a*a+o*o),c=(Math.exp(s*e.c2)-1)/e.c2,l=(180/t*Math.atan2(o,a)+360)%360,u=c/i**.25;return[r/(1+e.c1*(100-r)),u,l]}]})(),ui=e=>oi(li(e)),di=e=>ci(si(e)),fi=console;fi.color=(e,t=``)=>{let n=K(e).luminance();fi.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?`#000`:`#fff`}`)},fi.ramp=(e,t=1)=>{fi.log(`%c `,`font-size: 1px;line-height: 16px;background: ${K.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};var pi=(e,t,n,r,i,a,o=.1)=>{if(e===n||t===r)return!0;let s=(r-t)/(n-e),c=(a+i/s-t+s*e)/(s+1/s),l=a+i/s-c/s;return(i-c)**2+(a-l)**2{let i=(t[0]+n[0])/2,a=e(i);return pi(...t,...n,i,a,r)?null:[i,a]},hi=(e,t,n,r=.1)=>{let i=(n-t)/10,a=[];for(let r=t;rMath.round(e*10**t)/10**t,_i=(e,t=1,n=90,r=.005)=>{let i=hi(t=>e(t).gl()[0],0,t,r),a=hi(t=>e(t).gl()[1],0,t,r),o=hi(t=>e(t).gl()[2],0,t,r);return`linear-gradient(${n}deg, ${Array.from(new Set([...i.map(e=>gi(e[0])),...a.map(e=>gi(e[0])),...o.map(e=>gi(e[0]))].sort((e,t)=>e-t))).map(t=>`${e(t).hex()} ${gi(t*100)}%`).join()});`},vi=e=>{e.Color.prototype.jch=function(){return si(this._rgb.slice(0,3).map(e=>e/255))},e.jch=(...t)=>new e.Color(...oi(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.jab=function(){return di(this._rgb.slice(0,3).map(e=>e/255))},e.jab=(...t)=>new e.Color(...ui(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.hsluv=function(){return ni(this._rgb.slice(0,3).map(e=>e/255))},e.hsluv=(...t)=>new e.Color(...ri(t).map(e=>Math.floor(e*255)),`rgb`);let t=e.interpolate,n={jch:si,jab:di,hsluv:ni},r=(e,t,n)=>(Math.abs(e-t)>360/2&&(e>t?t+=360:e+=360),((1-n)*e+n*t)%360);e.interpolate=(i,a,o=.5,s=`lrgb`)=>{if(n[s]){typeof i!=`object`&&(i=new e.Color(i)),typeof a!=`object`&&(a=new e.Color(a));let t=n[s](i.gl()),c=n[s](a.gl()),l=Number.isNaN(i.hsl()[0]),u=Number.isNaN(a.hsl()[0]),d,f,p;switch(s){case`hsluv`:t[1]<1e-10&&(t[0]=c[0]),t[1]===0&&(t[1]=c[1]),c[1]<1e-10&&(c[0]=t[0]),c[1]===0&&(c[1]=t[1]),d=r(t[0],c[0],o),f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o;break;case`jch`:l&&(t[2]=c[2]),u&&(c[2]=t[2]),d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=r(t[2],c[2],o);break;default:d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o}return e[s](d,f,p).alpha(i.alpha()+o*(a.alpha()-i.alpha()))}return t(i,a,o,s)},e.getCSSGradient=_i},X={mainTRC:2.4,get mainTRCencode(){return 1/this.mainTRC},sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1,mFactor:1.9468554433171,get mFactInv(){return 1/this.mFactor},mOffsetIn:.0387393816571401,mExpAdj:.283343396420869,get mExp(){return this.mExpAdj/this.blkClmp},mOffsetOut:.312865795870758};function yi(e,t,n=-1){let r=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)r[1])return 0;let i=0,a=0,o=`BoW`;return e=e>X.blkThrs?e:e+(X.blkThrs-e)**+X.blkClmp,t=t>X.blkThrs?t:t+(X.blkThrs-t)**+X.blkClmp,Math.abs(t-e)e?(i=(t**+X.normBG-e**+X.normTXT)*X.scaleBoW,a=i-X.loClip?0:i+X.loWoBoffset),n<0?a*100:n==0?Math.round(Math.abs(a)*100)+``+o+``:Number.isInteger(n)?(a*100).toFixed(n):0)}function bi(e=[0,0,0]){function t(e){return(e/255)**X.mainTRC}return X.sRco*t(e[0])+X.sGco*t(e[1])+X.sBco*t(e[2])}var xi=(e,t,n,r,i,a,o,s,c)=>{let l=1-c,u=l*l,d=u*l,f=c*c*c;return{x:d*e+u*3*c*n+l*3*c*c*i+f*o,y:d*t+u*3*c*r+l*3*c*c*a+f*s}},Si=(e,t)=>{let n=[],r={x:+e[0],y:+e[1]};for(let i=0,a=e.length;a-2*!t>i;i+=2){let o=[{x:+e[i-2],y:+e[i-1]},{x:+e[i],y:+e[i+1]},{x:+e[i+2],y:+e[i+3]},{x:+e[i+4],y:+e[i+5]}];t?i?a-4===i?o[3]={x:+e[0],y:+e[1]}:a-2===i&&(o[2]={x:+e[0],y:+e[1]},o[3]={x:+e[2],y:+e[3]}):o[0]={x:+e[a-2],y:+e[a-1]}:a-4===i?o[3]=o[2]:i||(o[0]={x:+e[i],y:+e[i+1]}),n.push([r.x,r.y,(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y]),r=o[2]}return n},Ci=(e,t,n,r,i,a,o,s)=>{let c=e,l=t,u=0;for(let d=1;d<5;d++){let{x:f,y:p}=xi(e,t,n,r,i,a,o,s,d/5);u+=Math.hypot(f-c,p-l),c=f,l=p}return u+=Math.hypot(o-c,s-l),u},wi=(e,t,n,r,i,a,o,s)=>{let c=Math.floor(Ci(e,t,n,r,i,a,o,s)*.75),l=[],u=0;for(let d=0;d<=c;d++){let f=xi(e,t,n,r,i,a,o,s,d/c),p=Math.round(f.x);if(l[p]=f.y,p-u>1){let e=l[u],t=l[p];for(let n=u+1;nl[Math.round(e)]||null},Ti={CAM02:`jab`,CAM02p:`jch`,HEX:`hex`,HSL:`hsl`,HSLuv:`hsluv`,HSV:`hsv`,LAB:`lab`,LCH:`lch`,RGB:`rgb`,OKLAB:`oklab`,OKLCH:`oklch`};function Z(e,t=0){let n=10**t;return Math.round(e*n)/n}function Ei(e,t){let n;return n=e>1?(e-1)*t+1:e<-1?(e+1)*t-1:1,Z(n,2)}function Di(e){return K(String(e)).jch()}function Oi(e){return K(String(e)).hsluv()}function ki(e,t,n){let r=[[],[],[]];if(e.forEach((e,n)=>r.forEach((r,i)=>r.push(t[n],e[i]))),n===`hcl`){let e=r[1];for(let t=1;t{let t=[];for(let n=1;n{e[t]=e[n]}),t.length=0;break}if(t.length){let n=K(`#ccc`).jch()[2];t.forEach(t=>{e[t]=n})}t.length=0;for(let n=e.length-1;n>0;n-=2)if(Number.isNaN(e[n]))t.push(n);else{t.forEach(t=>{e[t]=e[n]});break}for(let t=1;tSi(e).map(e=>wi(...e)));return e=>{let t=i.map(t=>{for(let n=0;nr*t**e+i}function ji({swatches:e,colorKeys:t,colorspace:n,colorSpace:r=n??`LAB`,shift:i=1,fullScale:a=!0,smooth:o=!1,distributeLightness:s=`linear`,sortColor:c=!0,asFun:l=!1}={}){n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead.");let u=Ti[r];if(!u)throw Error(`Colorspace “${r}” not supported`);if(!t)throw Error(`Colorkeys missing: returned “${t}”`);let d;if(a)d=t.map(t=>e-e*(K(t).jch()[0]/100)).sort((e,t)=>e-t).concat(e),d.unshift(0);else{let n=t.map(e=>K(e).jch()[0]/100),r=Math.min(...n),i=Math.max(...n);d=n.map(t=>t===0||isNaN((t-r)/(i-r))?0:e-(t-r)/(i-r)*e).sort((e,t)=>e-t)}let f=Ai(i,[1,e],[1,e]);if(f=d.map(e=>Math.max(0,f(e))),d=f,s===`polynomial`){let t=e=>Math.sqrt(Math.sqrt((e**2.25+e**4)/2));d=f.map(t=>t/e).map(n=>t(n)*e)}let p=t.map((e,t)=>({colorKeys:Di(e),index:t})).sort((e,t)=>t.colorKeys[0]-e.colorKeys[0]).map(e=>t[e.index]),m=[],h;if(a){let e=u===`lch`?K.lch(...K(`#fff`).lch()):`#ffffff`,t=u===`lch`?K.lch(...K(`#000`).lch()):`#000000`;m=[e,...p,t]}else m=c?p:t;let g;if(o){let t=m;if(m=m.map(e=>K(String(e))[u]()),u===`hcl`&&m.forEach(e=>{e[1]=Number.isNaN(e[1])?0:e[1]}),u===`jch`)for(let e=0;eh(t))}else h=K.scale(m.map(e=>typeof e==`object`&&e.constructor===K.Color?e:String(e))).domain(d).mode(u);return l?h:(!o||o===!1?h.colors(e):g).filter(e=>e!=null)}function Mi(e,t){let n=[],r={};return Object.keys(e).forEach(n=>{r[e[n][t]]=e[n]}),Object.keys(r).forEach(e=>n.push(r[e])),n}function Ni(e){return Number.isNaN(e)?0:e}function Pi(e,t,n=!1){if(!e)throw Error(`Cannot convert color value of “${e}”`);if(!Ti[t])throw Error(`Cannot convert to colorspace “${t}”`);let r=Ti[t],i=K(String(e))[r]();if(t===`HSL`&&i.pop(),t===`HEX`){if(n){let t=K(String(e)).rgb();return{r:t[0],g:t[1],b:t[2]}}return i}let a={},o=i.map(Ni);o=o.map((e,t)=>{let i=Z(e),o=t;r===`hsluv`&&(o+=2);let s=r.charAt(o);return r===`jch`&&s===`c`&&(s=`C`),a[s===`j`?`J`:s]=i,r in{lab:1,lch:1,jab:1,jch:1}?n||(s===`l`||s===`j`)&&(i+=`%`):r!==`hsluv`&&(s===`s`||s===`l`||s===`v`)&&(a[s]=Z(e,2),n||(i=Z(e*100),i+=`%`)),i});let s=`${r}(${o.join(`, `)})`;return n?a:s}function Fi(e,t,n){let r=[e,t,n].map(e=>(e/=255,e<=.03928?e/12.92:((e+.055)/1.055)**2.4));return r[0]*.2126+r[1]*.7152+r[2]*.0722}function Ii(e,t,n,r=`wcag2`){if(n===void 0){let e=K.rgb(...t).hsluv()[2];n=Z(e/100,2)}if(r===`wcag2`){let r=Fi(e[0],e[1],e[2]),i=Fi(t[0],t[1],t[2]),a=(r+.05)/(i+.05),o=(i+.05)/(r+.05);return n<.5?a>=1?a:-o:a<1?o:a===1?a:-a}else if(r===`wcag3`)return n<.5?yi(bi(e),bi(t))*-1:yi(bi(e),bi(t));else throw Error(`Contrast calculation method ${r} unsupported; use 'wcag2' or 'wcag3'`)}function Li(e,t){if(!e)throw Error(`Array undefined`);if(!Array.isArray(e))throw Error(`Passed object is not an array`);let n=t===`wcag2`?0:1;return Math.min(...e.filter(e=>e>=n))}function Ri(e,t){if(!e)throw Error(`Ratios undefined`);e=e.sort((e,t)=>e-t);let n=Li(e,t),r=e.indexOf(n),i=[],a=e.slice(0,r),o=e.slice(r,e.length);for(let e=0;ee-t),i}var zi=(e,t,n,r,i)=>{let a=3e3,o=ji({swatches:a,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),s={},c=e=>{if(s[e])return s[e];let r=Ii(K(o(e)).rgb(),t,n,i);return s[e]=r,r},l=e=>{let t=c(0).01&&o;)o--,n/=2,iu.push(o(l(+e)))),u},Q=class{constructor({name:e,colorKeys:t,colorspace:n,colorSpace:r=n??`RGB`,ratios:i,smooth:a=!1,output:o=`HEX`,saturation:s=100}){if(n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),this._name=e,this._colorKeys=t,this._modifiedKeys=t,this._colorspace=r,this._ratios=i,this._smooth=a,this._output=o,this._saturation=s,!this._name)throw Error(`Color missing name`);if(!this._colorKeys)throw Error(`Color Keys are undefined`);if(!Ti[this._colorspace])throw Error(`Colorspace “${r}” not supported`);if(!Ti[this._output])throw Error(`Output “${this._output}” not supported`);for(let e=0;e{let n=K(`${t}`).oklch(),r=n[1]*(this._saturation/100),i=K.oklch(n[0],r,n[2]),a=K.rgb(i).hex();e.push(a)}),this._modifiedKeys=e,this._generateColorScale()}_generateColorScale(){this._colorScale=ji({swatches:3e3,colorKeys:this._modifiedKeys,colorSpace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}},Bi=class extends Q{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){Q.prototype._generateColorScale.call(this);let e=ji({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});e.push(...this.colorKeys);let t=Mi(e.map((e,t)=>({value:Math.round(Oi(e)[2]),index:t})),`value`).map(t=>e[t.index]);return t.length>=101&&(t.length=100,t.push(`#ffffff`)),this._backgroundColorScale=t.map(e=>Pi(e,this._output)),this._backgroundColorScale}},Vi=class{constructor({colors:e,backgroundColor:t,lightness:n,contrast:r=1,saturation:i=100,output:a=`HEX`,formula:o=`wcag2`}){if(this._output=a,this._colors=e,this._lightness=n,this._saturation=i,this._formula=o,this._setBackgroundColor(t),this._setBackgroundColorValue(),this._contrast=r,!this._colors)throw Error(`No colors are defined`);if(!this._backgroundColor)throw Error(`Background color is undefined`);if(e.forEach(e=>{if(!e.ratios)throw Error(`Color ${e.name}'s ratios are undefined`)}),!Ti[this._output])throw Error(`Output “${a}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(e){this._formula=e,this._findContrastColors()}get formula(){return this._formula}set contrast(e){this._contrast=e,this._findContrastColors()}get contrast(){return this._contrast}set lightness(e){this._lightness=e,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(e){this._saturation=e,this._updateColorSaturation(e),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(e){this._setBackgroundColor(e),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(e){this._colors=e,this._findContrastColors()}get colors(){return this._colors}set addColor(e){this._colors.push(e),this._findContrastColors()}set removeColor(e){let t=this._colors.filter(t=>t.name!==e.name);this._colors=t,this._findContrastColors()}set updateColor(e){if(Array.isArray(e))for(let t=0;tn.name===e[t].color);n=n[0];let r=this._colors.indexOf(n),i=this._colors.filter(n=>n.name!==e[t].color);e[t].name&&(n.name=e[t].name),e[t].colorKeys&&(n.colorKeys=e[t].colorKeys),e[t].ratios&&(n.ratios=e[t].ratios),(e[t].colorSpace!==void 0||e[t].colorspace!==void 0)&&(e[t].colorspace!==void 0&&e[t].colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),n.colorSpace=e[t].colorSpace??e[t].colorspace),e[t].smooth&&(n.smooth=e[t].smooth),n._generateColorScale(),i.splice(r,0,n),this._colors=i}else{let t=this._colors.filter(t=>t.name===e.color);t=t[0];let n=this._colors.indexOf(t),r=this._colors.filter(t=>t.name!==e.color);e.name&&(t.name=e.name),e.colorKeys&&(t.colorKeys=e.colorKeys),e.ratios&&(t.ratios=e.ratios),(e.colorSpace!==void 0||e.colorspace!==void 0)&&(e.colorspace!==void 0&&e.colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),t.colorSpace=e.colorSpace??e.colorspace),e.smooth&&(t.smooth=e.smooth),t._generateColorScale(),r.splice(n,0,t),this._colors=r}this._findContrastColors()}set output(e){this._output=e,this._colors.forEach(e=>{e.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(e){if(typeof e==`string`){let t=new Bi({name:`background`,colorKeys:[e],output:`RGB`}),n=Z(K(String(e)).hsluv()[2]);this._backgroundColor=t,this._lightness=n,this._backgroundColorValue=t[this._lightness]}else{e.output=`RGB`;let t=e.backgroundColorScale[this._lightness];this._backgroundColor=e,this._backgroundColorValue=t}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(e){this._colors.map(t=>{t.saturation=e})}_findContrastColors(){let e=K(String(this._backgroundColorValue)).rgb(),t=this._lightness/100,n={background:Pi(this._backgroundColorValue,this._output)},r=[],i=[],a={...n};return r.push(n),this._colors.map(n=>{if(n.ratios!==void 0){let o,s=[],c={name:n.name,values:s},l;Array.isArray(n.ratios)?l=n.ratios:Array.isArray(n.ratios)||(o=Object.keys(n.ratios),l=Object.values(n.ratios)),l=l.map(e=>Ei(+e,this._contrast));let u=zi(n,e,t,l,this._formula).map(e=>Pi(e,this._output));for(let e=0;e{let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},Wi=(e,t,n)=>{let r=e/255,i=t/255,a=n/255,o=Math.min(r,i,a),s=Math.max(r,i,a),c=s-o,l=0,u=0,d=0;return l=c===0?0:s===r?(i-a)/c%6:s===i?(a-r)/c+2:(r-i)/c+4,l=Math.round(l*60),l<0&&(l+=360),d=(s+o)/2,u=c===0?0:c/(1-Math.abs(2*d-1)),u=+(u*100).toFixed(1),d=+(d*100).toFixed(1),[l,u,Math.round(d)]},Gi=(e,t,n,r)=>{let i=n/100,a=t*Math.min(i,1-i)/100,o=t=>{let n=(t+e/30)%12,r=i-a*Math.max(Math.min(n-3,9-n,1),-1);return Math.round(255*r).toString(16).padStart(2,`0`).toUpperCase()},s=o(0),c=o(8),l=o(4),u=((e,t,n)=>Math.min(Math.max(e,t),n))(r,0,1);return`#${s}${c}${l}${Math.round(u*255).toString(16).padStart(2,`0`).toUpperCase()}`},Ki=(e,t,n=1)=>{let r=Ui(e),i=Ui(t===`white`?`#FFFFFF`:t===`black`?`#000000`:t),a=r.map((e,t)=>[(e-i[t])/(255-i[t]),(e-i[t])/(0-i[t])]),o=Hi(Math.max(...a.flat().filter(e=>/^-?\d+\.?\d*$/.test(e)))),s=r.map((e,t)=>Math.round((e-i[t]+i[t]*o)/o));if(s.includes(NaN)){let e=Wi(r[0],r[1],r[2]);return{h:e[0],s:Math.round(e[1]*n),l:e[2],a:1}}let c=Wi(s[0],s[1],s[2]);return{h:c[0],s:Math.round(c[1]*n),l:c[2],a:o}},qi={backgroundColor:`gray`,colorSpace:`OKLCH`,colorSmoothing:!1,formula:`wcag2`,output:`HEX`,colors:{gray:[$(215,20,90),$(215,8,50),$(215,6,25)],red:[$(358,100,58),$(350,100,30)],orange:[$(32,100,48),$(12,100,30)],yellow:[$(50,100,50),$(25,100,20)],lime:[$(100,68,50),$(115,86,25)],green:[$(163,87,42),$(168,100,25)],cyan:[$(185,80,45),$(200,98,35)],blue:[$(212,98,46),$(222,95,25)],purple:[$(258,94,64),$(265,100,35)],fuchsia:[$(295,56,50),$(285,80,25)],pink:[$(334,90,50),$(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function $(e,t,n){return K.hsl(e,t/100,n/100).hex()}function Ji(e,t){let n=e.colorSpace,r=e.colorSmoothing,i=e.themes[t].ratios,a=new Bi({name:`gray`,colorKeys:e.colors.gray,colorspace:n,ratios:i,smooth:r}),o=new Q({name:`blue`,colorKeys:e.colors.blue,colorspace:n,ratios:i,smooth:r}),s=new Q({name:`cyan`,colorKeys:e.colors.cyan,colorspace:n,ratios:i,smooth:r}),c=new Q({name:`fuchsia`,colorKeys:e.colors.fuchsia,colorspace:n,ratios:i,smooth:r}),l=new Q({name:`green`,colorKeys:e.colors.green,colorspace:n,ratios:i,smooth:r}),u=new Q({name:`lime`,colorKeys:e.colors.lime,colorspace:n,ratios:i,smooth:r}),d=new Q({name:`orange`,colorKeys:e.colors.orange,colorspace:n,ratios:i,smooth:r}),f=new Q({name:`pink`,colorKeys:e.colors.pink,colorspace:n,ratios:i,smooth:r}),p=new Q({name:`purple`,colorKeys:e.colors.purple,colorspace:n,ratios:i,smooth:r}),m={gray:a,red:new Q({name:`red`,colorKeys:e.colors.red,colorspace:n,ratios:i,smooth:r}),orange:d,yellow:new Q({name:`yellow`,colorKeys:e.colors.yellow,colorspace:n,ratios:i,smooth:r}),lime:u,green:l,cyan:s,blue:o,purple:p,fuchsia:c,pink:f};return e.colors.custom&&(m.custom=new Q({name:`custom`,colorKeys:e.colors.custom,colorspace:n,ratios:i,smooth:r})),new Vi({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function Yi(e){let t={};for(let n of Object.keys(e.themes))t[n]=Ji(e,n);return t}function Xi(e){qi.colors.custom=[e];let t=Yi(qi);return Object.fromEntries(Object.entries(t).map(([e,t])=>{let n=t.find(e=>e&&e.name===`custom`),r=Object.fromEntries(n.values.map(({name:e,value:t})=>[e,t]));for(let[e,n]of Object.entries(r)){let i=Ki(n,t[0].background);r[`alpha${e.charAt(0).toUpperCase()+e.slice(1)}`]=Gi(i.h,i.s,i.l,i.a)}return[e,r]}))}return e.generateCustomColors=Xi,e.generateThemesJson=Yi,e.hslToHex=$,e.leonardoConfig=qi,e})({}); \ No newline at end of file +var CompoundTheme=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;lt[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},l=(e,r,i)=>(i=e==null?{}:t(a(e)),c(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),{min:u,max:d}=Math,f=(e,t=0,n=1)=>u(d(t,e),n),p=e=>{e._clipped=!1,e._unclipped=e.slice(0);for(let t=0;t<=3;t++)t<3?((e[t]<0||e[t]>255)&&(e._clipped=!0),e[t]=f(e[t],0,255)):t===3&&(e[t]=f(e[t],0,1));return e},m={};for(let e of[`Boolean`,`Number`,`String`,`Function`,`Array`,`Date`,`RegExp`,`Undefined`,`Null`])m[`[object ${e}]`]=e.toLowerCase();function h(e){return m[Object.prototype.toString.call(e)]||`object`}var g=(e,t=null)=>e.length>=3?Array.prototype.slice.call(e):h(e[0])==`object`&&t?t.split(``).filter(t=>e[0][t]!==void 0).map(t=>e[0][t]):e[0].slice(0),_=e=>{if(e.length<2)return null;let t=e.length-1;return h(e[t])==`string`?e[t].toLowerCase():null},{PI:v,min:y,max:b}=Math,x=e=>Math.round(e*100)/100,S=e=>Math.round(e*100)/100,C=v*2,w=v/3,T=v/180,ee=180/v;function E(e){return[...e.slice(0,3).reverse(),...e.slice(3)]}var D={format:{},autodetect:[]},O=class{constructor(...e){let t=this;if(h(e[0])===`object`&&e[0].constructor&&e[0].constructor===this.constructor)return e[0];let n=_(e),r=!1;if(!n){r=!0,D.sorted||=(D.autodetect=D.autodetect.sort((e,t)=>t.p-e.p),!0);for(let t of D.autodetect)if(n=t.test(...e),n)break}if(D.format[n])t._rgb=p(D.format[n].apply(null,r?e:e.slice(0,-1)));else throw Error(`unknown format: `+e);t._rgb.length===3&&t._rgb.push(1)}toString(){return h(this.hex)==`function`?this.hex():`[${this._rgb.join(`,`)}]`}},te=`3.2.0`,k=(...e)=>new O(...e);k.version=te;var A={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,laserlemon:`#ffff54`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrod:`#fafad2`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,maroon2:`#7f0000`,maroon3:`#b03060`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,purple2:`#7f007f`,purple3:`#a020f0`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`},ne=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,re=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,ie=e=>{if(e.match(ne)){(e.length===4||e.length===7)&&(e=e.substr(1)),e.length===3&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);let t=parseInt(e,16);return[t>>16,t>>8&255,t&255,1]}if(e.match(re)){(e.length===5||e.length===9)&&(e=e.substr(1)),e.length===4&&(e=e.split(``),e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]+e[3]+e[3]);let t=parseInt(e,16);return[t>>24&255,t>>16&255,t>>8&255,Math.round((t&255)/255*100)/100]}throw Error(`unknown hex color: ${e}`)},{round:ae}=Math,oe=(...e)=>{let[t,n,r,i]=g(e,`rgba`),a=_(e)||`auto`;i===void 0&&(i=1),a===`auto`&&(a=i<1?`rgba`:`rgb`),t=ae(t),n=ae(n),r=ae(r);let o=`000000`+(t<<16|n<<8|r).toString(16);o=o.substr(o.length-6);let s=`0`+ae(i*255).toString(16);switch(s=s.substr(s.length-2),a.toLowerCase()){case`rgba`:return`#${o}${s}`;case`argb`:return`#${s}${o}`;default:return`#${o}`}};O.prototype.name=function(){let e=oe(this._rgb,`rgb`);for(let t of Object.keys(A))if(A[t]===e)return t.toLowerCase();return e},D.format.named=e=>{if(e=e.toLowerCase(),A[e])return ie(A[e]);throw Error(`unknown color name: `+e)},D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&A[e.toLowerCase()])return`named`}}),O.prototype.alpha=function(e,t=!1){return e!==void 0&&h(e)===`number`?t?(this._rgb[3]=e,this):new O([this._rgb[0],this._rgb[1],this._rgb[2],e],`rgb`):this._rgb[3]},O.prototype.clipped=function(){return this._rgb._clipped||!1};var j={Kn:18,labWhitePoint:`d65`,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},se=new Map([[`a`,[1.0985,.35585]],[`b`,[1.0985,.35585]],[`c`,[.98074,1.18232]],[`d50`,[.96422,.82521]],[`d55`,[.95682,.92149]],[`d65`,[.95047,1.08883]],[`e`,[1,1,1]],[`f2`,[.99186,.67393]],[`f7`,[.95041,1.08747]],[`f11`,[1.00962,.6435]],[`icc`,[.96422,.82521]]]);function M(e){let t=se.get(String(e).toLowerCase());if(!t)throw Error(`unknown Lab illuminant `+e);j.labWhitePoint=e,j.Xn=t[0],j.Zn=t[1]}function ce(){return j.labWhitePoint}var N=(...e)=>{e=g(e,`lab`);let[t,n,r]=e,[i,a,o]=le(t,n,r),[s,c,l]=de(i,a,o);return[s,c,l,e.length>3?e[3]:1]},le=(e,t,n)=>{let{kE:r,kK:i,kKE:a,Xn:o,Yn:s,Zn:c}=j,l=(e+16)/116,u=.002*t+l,d=l-.005*n,f=u*u*u,p=d*d*d,m=f>r?f:(116*u-16)/i,h=e>a?((e+16)/116)**3:e/i,g=p>r?p:(116*d-16)/i;return[m*o,h*s,g*c]},ue=e=>{let t=Math.sign(e);return e=Math.abs(e),(e<=.0031308?e*12.92:1.055*e**(1/2.4)-.055)*t},de=(e,t,n)=>{let{MtxAdaptMa:r,MtxAdaptMaI:i,MtxXYZ2RGB:a,RefWhiteRGB:o,Xn:s,Yn:c,Zn:l}=j,u=s*r.m00+c*r.m10+l*r.m20,d=s*r.m01+c*r.m11+l*r.m21,f=s*r.m02+c*r.m12+l*r.m22,p=o.X*r.m00+o.Y*r.m10+o.Z*r.m20,m=o.X*r.m01+o.Y*r.m11+o.Z*r.m21,h=o.X*r.m02+o.Y*r.m12+o.Z*r.m22,g=(e*r.m00+t*r.m10+n*r.m20)*(p/u),_=(e*r.m01+t*r.m11+n*r.m21)*(m/d),v=(e*r.m02+t*r.m12+n*r.m22)*(h/f),y=g*i.m00+_*i.m10+v*i.m20,b=g*i.m01+_*i.m11+v*i.m21,x=g*i.m02+_*i.m12+v*i.m22,S=ue(y*a.m00+b*a.m10+x*a.m20),C=ue(y*a.m01+b*a.m11+x*a.m21),w=ue(y*a.m02+b*a.m12+x*a.m22);return[S*255,C*255,w*255]},fe=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=he(t,n,r),[c,l,u]=pe(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function pe(e,t,n){let{Xn:r,Yn:i,Zn:a,kE:o,kK:s}=j,c=e/r,l=t/i,u=n/a,d=c>o?c**(1/3):(s*c+16)/116,f=l>o?l**(1/3):(s*l+16)/116,p=u>o?u**(1/3):(s*u+16)/116;return[116*f-16,500*(d-f),200*(f-p)]}function me(e){let t=Math.sign(e);return e=Math.abs(e),(e<=.04045?e/12.92:((e+.055)/1.055)**2.4)*t}var he=(e,t,n)=>{e=me(e/255),t=me(t/255),n=me(n/255);let{MtxRGB2XYZ:r,MtxAdaptMa:i,MtxAdaptMaI:a,Xn:o,Yn:s,Zn:c,As:l,Bs:u,Cs:d}=j,f=e*r.m00+t*r.m10+n*r.m20,p=e*r.m01+t*r.m11+n*r.m21,m=e*r.m02+t*r.m12+n*r.m22,h=o*i.m00+s*i.m10+c*i.m20,g=o*i.m01+s*i.m11+c*i.m21,_=o*i.m02+s*i.m12+c*i.m22,v=f*i.m00+p*i.m10+m*i.m20,y=f*i.m01+p*i.m11+m*i.m21,b=f*i.m02+p*i.m12+m*i.m22;return v*=h/l,y*=g/u,b*=_/d,f=v*a.m00+y*a.m10+b*a.m20,p=v*a.m01+y*a.m11+b*a.m21,m=v*a.m02+y*a.m12+b*a.m22,[f,p,m]};O.prototype.lab=function(){return fe(this._rgb)},Object.assign(k,{lab:(...e)=>new O(...e,`lab`),getLabWhitePoint:ce,setLabWhitePoint:M}),D.format.lab=N,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`lab`),h(e)===`array`&&e.length===3)return`lab`}}),O.prototype.darken=function(e=1){let t=this,n=t.lab();return n[0]-=j.Kn*e,new O(n,`lab`).alpha(t.alpha(),!0)},O.prototype.brighten=function(e=1){return this.darken(-e)},O.prototype.darker=O.prototype.darken,O.prototype.brighter=O.prototype.brighten,O.prototype.get=function(e){let[t,n]=e.split(`.`),r=this[t]();if(n){let e=t.indexOf(n)-(t.substr(0,2)===`ok`?2:0);if(e>-1)return r[e];throw Error(`unknown channel ${n} in mode ${t}`)}else return r};var{pow:ge}=Math,_e=1e-7,ve=20;O.prototype.luminance=function(e,t=`rgb`){if(e!==void 0&&h(e)===`number`){if(e===0)return new O([0,0,0,this._rgb[3]],`rgb`);if(e===1)return new O([255,255,255,this._rgb[3]],`rgb`);let n=this.luminance(),r=ve,i=(n,a)=>{let o=n.interpolate(a,.5,t),s=o.luminance();return Math.abs(e-s)<_e||!r--?o:s>e?i(n,o):i(o,a)};return new O([...(n>e?i(new O([0,0,0]),this):i(this,new O([255,255,255]))).rgb(),this._rgb[3]])}return ye(...this._rgb.slice(0,3))};var ye=(e,t,n)=>(e=be(e),t=be(t),n=be(n),.2126*e+.7152*t+.0722*n),be=e=>(e/=255,e<=.03928?e/12.92:ge((e+.055)/1.055,2.4)),P={},F=(e,t,n=.5,...r)=>{let i=r[0]||`lrgb`;if(!P[i]&&!r.length&&(i=Object.keys(P)[0]),!P[i])throw Error(`interpolation mode ${i} is not defined`);return h(e)!==`object`&&(e=new O(e)),h(t)!==`object`&&(t=new O(t)),P[i](e,t,n).alpha(e.alpha()+n*(t.alpha()-e.alpha()))};O.prototype.mix=O.prototype.interpolate=function(e,t=.5,...n){return F(this,e,t,...n)},O.prototype.premultiply=function(e=!1){let t=this._rgb,n=t[3];return e?(this._rgb=[t[0]*n,t[1]*n,t[2]*n,n],this):new O([t[0]*n,t[1]*n,t[2]*n,n],`rgb`)};var{sin:xe,cos:Se}=Math,Ce=(...e)=>{let[t,n,r]=g(e,`lch`);return isNaN(r)&&(r=0),r*=T,[t,Se(r)*n,xe(r)*n]},we=(...e)=>{e=g(e,`lch`);let[t,n,r]=e,[i,a,o]=Ce(t,n,r),[s,c,l]=N(i,a,o);return[s,c,l,e.length>3?e[3]:1]},Te=(...e)=>we(...E(g(e,`hcl`))),{sqrt:Ee,atan2:De,round:Oe}=Math,ke=(...e)=>{let[t,n,r]=g(e,`lab`),i=Ee(n*n+r*r),a=(De(r,n)*ee+360)%360;return Oe(i*1e4)===0&&(a=NaN),[t,i,a]},Ae=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=fe(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};O.prototype.lch=function(){return Ae(this._rgb)},O.prototype.hcl=function(){return E(Ae(this._rgb))},Object.assign(k,{lch:(...e)=>new O(...e,`lch`),hcl:(...e)=>new O(...e,`hcl`)}),D.format.lch=we,D.format.hcl=Te,[`lch`,`hcl`].forEach(e=>D.autodetect.push({p:2,test:(...t)=>{if(t=g(t,e),h(t)===`array`&&t.length===3)return e}})),O.prototype.saturate=function(e=1){let t=this,n=t.lch();return n[1]+=j.Kn*e,n[1]<0&&(n[1]=0),new O(n,`lch`).alpha(t.alpha(),!0)},O.prototype.desaturate=function(e=1){return this.saturate(-e)},O.prototype.set=function(e,t,n=!1){let[r,i]=e.split(`.`),a=this[r]();if(i){let e=r.indexOf(i)-(r.substr(0,2)===`ok`?2:0);if(e>-1){if(h(t)==`string`)switch(t.charAt(0)){case`+`:a[e]+=+t;break;case`-`:a[e]+=+t;break;case`*`:a[e]*=+t.substr(1);break;case`/`:a[e]/=+t.substr(1);break;default:a[e]=+t}else if(h(t)===`number`)a[e]=t;else throw Error(`unsupported value for Color.set`);let i=new O(a,r);return n?(this._rgb=i._rgb,this):i}throw Error(`unknown channel ${i} in mode ${r}`)}else return a},O.prototype.tint=function(e=.5,...t){return F(this,`white`,e,...t)},O.prototype.shade=function(e=.5,...t){return F(this,`black`,e,...t)},P.rgb=(e,t,n)=>{let r=e._rgb,i=t._rgb;return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`rgb`)};var{sqrt:je,pow:Me}=Math;P.lrgb=(e,t,n)=>{let[r,i,a]=e._rgb,[o,s,c]=t._rgb;return new O(je(Me(r,2)*(1-n)+Me(o,2)*n),je(Me(i,2)*(1-n)+Me(s,2)*n),je(Me(a,2)*(1-n)+Me(c,2)*n),`rgb`)},P.lab=(e,t,n)=>{let r=e.lab(),i=t.lab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`lab`)};var Ne=(e,t,n,r)=>{let i,a;r===`hsl`?(i=e.hsl(),a=t.hsl()):r===`hsv`?(i=e.hsv(),a=t.hsv()):r===`hcg`?(i=e.hcg(),a=t.hcg()):r===`hsi`?(i=e.hsi(),a=t.hsi()):r===`lch`||r===`hcl`?(r=`hcl`,i=e.hcl(),a=t.hcl()):r===`oklch`&&(i=e.oklch().reverse(),a=t.oklch().reverse());let o,s,c,l,u,d;(r.substr(0,1)===`h`||r===`oklch`)&&([o,c,u]=i,[s,l,d]=a);let f,p,m,h;return!isNaN(o)&&!isNaN(s)?(h=s>o&&s-o>180?s-(o+360):s180?s+360-o:s-o,p=o+n*h):isNaN(o)?isNaN(s)?p=NaN:(p=s,(u==1||u==0)&&r!=`hsv`&&(f=l)):(p=o,(d==1||d==0)&&r!=`hsv`&&(f=c)),f===void 0&&(f=c+n*(l-c)),m=u+n*(d-u),r===`oklch`?new O([m,f,p],r):new O([p,f,m],r)},Pe=(e,t,n)=>Ne(e,t,n,`lch`);P.lch=Pe,P.hcl=Pe;var Fe=e=>{if(h(e)==`number`&&e>=0&&e<=16777215)return[e>>16,e>>8&255,e&255,1];throw Error(`unknown num color: `+e)},Ie=(...e)=>{let[t,n,r]=g(e,`rgb`);return(t<<16)+(n<<8)+r};O.prototype.num=function(){return Ie(this._rgb)},Object.assign(k,{num:(...e)=>new O(...e,`num`)}),D.format.num=Fe,D.autodetect.push({p:5,test:(...e)=>{if(e.length===1&&h(e[0])===`number`&&e[0]>=0&&e[0]<=16777215)return`num`}}),P.num=(e,t,n)=>{let r=e.num();return new O(r+n*(t.num()-r),`num`)};var{floor:Le}=Math,Re=(...e)=>{e=g(e,`hcg`);let[t,n,r]=e,i,a,o;r*=255;let s=n*255;if(n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Le(t),c=t-e,l=r*(1-n),u=l+s*(1-c),d=l+s*c,f=l+s;switch(e){case 0:[i,a,o]=[f,d,l];break;case 1:[i,a,o]=[u,f,l];break;case 2:[i,a,o]=[l,f,d];break;case 3:[i,a,o]=[l,u,f];break;case 4:[i,a,o]=[d,l,f];break;case 5:[i,a,o]=[f,l,u];break}}return[i,a,o,e.length>3?e[3]:1]},ze=(...e)=>{let[t,n,r]=g(e,`rgb`),i=y(t,n,r),a=b(t,n,r),o=a-i,s=o*100/255,c=i/(255-o)*100,l;return o===0?l=NaN:(t===a&&(l=(n-r)/o),n===a&&(l=2+(r-t)/o),r===a&&(l=4+(t-n)/o),l*=60,l<0&&(l+=360)),[l,s,c]};O.prototype.hcg=function(){return ze(this._rgb)},k.hcg=(...e)=>new O(...e,`hcg`),D.format.hcg=Re,D.autodetect.push({p:1,test:(...e)=>{if(e=g(e,`hcg`),h(e)===`array`&&e.length===3)return`hcg`}}),P.hcg=(e,t,n)=>Ne(e,t,n,`hcg`);var{cos:Be}=Math,Ve=(...e)=>{e=g(e,`hsi`);let[t,n,r]=e,i,a,o;return isNaN(t)&&(t=0),isNaN(n)&&(n=0),t>360&&(t-=360),t<0&&(t+=360),t/=360,t<1/3?(o=(1-n)/3,i=(1+n*Be(C*t)/Be(w-C*t))/3,a=1-(o+i)):t<2/3?(t-=1/3,i=(1-n)/3,a=(1+n*Be(C*t)/Be(w-C*t))/3,o=1-(i+a)):(t-=2/3,a=(1-n)/3,o=(1+n*Be(C*t)/Be(w-C*t))/3,i=1-(a+o)),i=f(r*i*3),a=f(r*a*3),o=f(r*o*3),[i*255,a*255,o*255,e.length>3?e[3]:1]},{min:He,sqrt:Ue,acos:We}=Math,Ge=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i,a=He(t,n,r),o=(t+n+r)/3,s=o>0?1-a/o:0;return s===0?i=NaN:(i=(t-n+(t-r))/2,i/=Ue((t-n)*(t-n)+(t-r)*(n-r)),i=We(i),r>n&&(i=C-i),i/=C),[i*360,s,o]};O.prototype.hsi=function(){return Ge(this._rgb)},k.hsi=(...e)=>new O(...e,`hsi`),D.format.hsi=Ve,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsi`),h(e)===`array`&&e.length===3)return`hsi`}}),P.hsi=(e,t,n)=>Ne(e,t,n,`hsi`);var Ke=(...e)=>{e=g(e,`hsl`);let[t,n,r]=e,i,a,o;if(n===0)i=a=o=r*255;else{let e=[0,0,0],s=[0,0,0],c=r<.5?r*(1+n):r+n-r*n,l=2*r-c,u=t/360;e[0]=u+1/3,e[1]=u,e[2]=u-1/3;for(let t=0;t<3;t++)e[t]<0&&(e[t]+=1),e[t]>1&&--e[t],6*e[t]<1?s[t]=l+(c-l)*6*e[t]:2*e[t]<1?s[t]=c:3*e[t]<2?s[t]=l+(c-l)*(2/3-e[t])*6:s[t]=l;[i,a,o]=[s[0]*255,s[1]*255,s[2]*255]}return e.length>3?[i,a,o,e[3]]:[i,a,o,1]},qe=(...e)=>{e=g(e,`rgba`);let[t,n,r]=e;t/=255,n/=255,r/=255;let i=y(t,n,r),a=b(t,n,r),o=(a+i)/2,s,c;return a===i?(s=0,c=NaN):s=o<.5?(a-i)/(a+i):(a-i)/(2-a-i),t==a?c=(n-r)/(a-i):n==a?c=2+(r-t)/(a-i):r==a&&(c=4+(t-n)/(a-i)),c*=60,c<0&&(c+=360),e.length>3&&e[3]!==void 0?[c,s,o,e[3]]:[c,s,o]};O.prototype.hsl=function(){return qe(this._rgb)},k.hsl=(...e)=>new O(...e,`hsl`),D.format.hsl=Ke,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsl`),h(e)===`array`&&e.length===3)return`hsl`}}),P.hsl=(e,t,n)=>Ne(e,t,n,`hsl`);var{floor:Je}=Math,Ye=(...e)=>{e=g(e,`hsv`);let[t,n,r]=e,i,a,o;if(r*=255,n===0)i=a=o=r;else{t===360&&(t=0),t>360&&(t-=360),t<0&&(t+=360),t/=60;let e=Je(t),s=t-e,c=r*(1-n),l=r*(1-n*s),u=r*(1-n*(1-s));switch(e){case 0:[i,a,o]=[r,u,c];break;case 1:[i,a,o]=[l,r,c];break;case 2:[i,a,o]=[c,r,u];break;case 3:[i,a,o]=[c,l,r];break;case 4:[i,a,o]=[u,c,r];break;case 5:[i,a,o]=[r,c,l];break}}return[i,a,o,e.length>3?e[3]:1]},{min:Xe,max:Ze}=Math,Qe=(...e)=>{e=g(e,`rgb`);let[t,n,r]=e,i=Xe(t,n,r),a=Ze(t,n,r),o=a-i,s,c,l;return l=a/255,a===0?(s=NaN,c=0):(c=o/a,t===a&&(s=(n-r)/o),n===a&&(s=2+(r-t)/o),r===a&&(s=4+(t-n)/o),s*=60,s<0&&(s+=360)),[s,c,l]};O.prototype.hsv=function(){return Qe(this._rgb)},k.hsv=(...e)=>new O(...e,`hsv`),D.format.hsv=Ye,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`hsv`),h(e)===`array`&&e.length===3)return`hsv`}}),P.hsv=(e,t,n)=>Ne(e,t,n,`hsv`);function $e(e,t){let n=e.length;Array.isArray(e[0])||(e=[e]),Array.isArray(t[0])||(t=t.map(e=>[e]));let r=t[0].length,i=t[0].map((e,n)=>t.map(e=>e[n])),a=e.map(e=>i.map(t=>Array.isArray(e)?e.reduce((e,n,r)=>e+n*(t[r]||0),0):t.reduce((t,n)=>t+n*e,0)));return n===1&&(a=a[0]),r===1?a.map(e=>e[0]):a}var et=(...e)=>{e=g(e,`lab`);let[t,n,r,...i]=e,[a,o,s]=tt([t,n,r]),[c,l,u]=de(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]};function tt(e){return $e([[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],$e([[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],e).map(e=>e**3))}var nt=(...e)=>{let[t,n,r,...i]=g(e,`rgb`);return[...rt(he(t,n,r)),...i.length>0&&i[0]<1?[i[0]]:[]]};function rt(e){return $e([[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],$e([[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],e).map(e=>Math.cbrt(e)))}O.prototype.oklab=function(){return nt(this._rgb)},Object.assign(k,{oklab:(...e)=>new O(...e,`oklab`)}),D.format.oklab=et,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklab`),h(e)===`array`&&e.length===3)return`oklab`}}),P.oklab=(e,t,n)=>{let r=e.oklab(),i=t.oklab();return new O(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),`oklab`)},P.oklch=(e,t,n)=>Ne(e,t,n,`oklch`);var{pow:it,sqrt:at,PI:ot,cos:st,sin:ct,atan2:lt}=Math,ut=(e,t=`lrgb`,n=null)=>{let r=e.length;n||=Array.from(Array(r)).map(()=>1);let i=r/n.reduce(function(e,t){return e+t});if(n.forEach((e,t)=>{n[t]*=i}),e=e.map(e=>new O(e)),t===`lrgb`)return dt(e,n);let a=e.shift(),o=a.get(t),s=[],c=0,l=0;for(let e=0;e{let i=e.get(t);u+=e.alpha()*n[r+1];for(let e=0;e=360;)t-=360;o[e]=t}else o[e]=o[e]/s[e];return u/=r,new O(o,t).alpha(u>.99999?1:u,!0)},dt=(e,t)=>{let n=e.length,r=[0,0,0,0];for(let i=0;i.9999999&&(r[3]=1),new O(p(r))},{pow:ft}=Math;function pt(e){let t=`rgb`,n=k(`#ccc`),r=0,i=[0,1],a=[0,1],o=[],s=[0,0],c=!1,l=[],u=!1,d=0,p=1,m=!1,g={},_=!0,v=1,y=function(e){if(e||=[`#fff`,`#000`],e&&h(e)===`string`&&k.brewer&&k.brewer[e.toLowerCase()]&&(e=k.brewer[e.toLowerCase()]),h(e)===`array`){e.length===1&&(e=[e[0],e[0]]),e=e.slice(0);for(let t=0;t=c[n];)n++;return n-1}return 0},x=e=>e,S=e=>e,C=function(e,r){let i,a;if(r??=!1,isNaN(e)||e===null)return n;a=r?e:c&&c.length>2?b(e)/(c.length-2):p===d?1:(e-d)/(p-d),a=S(a),r||(a=x(a)),v!==1&&(a=ft(a,v)),a=s[0]+a*(1-s[0]-s[1]),a=f(a,0,1);let u=Math.floor(a*1e4);if(_&&g[u])i=g[u];else{if(h(l)===`array`)for(let e=0;e=n&&e===o.length-1){i=l[e];break}if(a>n&&ag={};y(e);let T=function(e){let t=k(C(e));return u&&t[u]?t[u]():t};return T.classes=function(e){if(e!=null){if(h(e)===`array`)c=e,i=[e[0],e[e.length-1]];else{let t=k.analyze(i);c=e===0?[t.min,t.max]:k.limits(t,`e`,e)}return T}return c},T.domain=function(e){if(!arguments.length)return a;a=e.slice(0),d=e[0],p=e[e.length-1],o=[];let t=l.length;if(e.length===t&&d!==p)for(let t of Array.from(e))o.push((t-d)/(p-d));else{for(let e=0;e2){let t=e.map((t,n)=>n/(e.length-1)),n=e.map(e=>(e-d)/(p-d));n.every((e,n)=>t[n]===e)||(S=e=>{if(e<=0||e>=1)return e;let r=0;for(;e>=n[r+1];)r++;let i=(e-n[r])/(n[r+1]-n[r]);return t[r]+i*(t[r+1]-t[r])})}}return i=[d,p],T},T.mode=function(e){return arguments.length?(t=e,w(),T):t},T.range=function(e,t){return y(e,t),T},T.out=function(e){return u=e,T},T.spread=function(e){return arguments.length?(r=e,T):r},T.correctLightness=function(e){return e??=!0,m=e,w(),x=m?function(e){let t=C(0,!0).lab()[0],n=C(1,!0).lab()[0],r=t>n,i=C(e,!0).lab()[0],a=t+(n-t)*e,o=i-a,s=0,c=1,l=20;for(;Math.abs(o)>.01&&l-- >0;)(function(){return r&&(o*=-1),o<0?(s=e,e+=(c-e)*.5):(c=e,e+=(s-e)*.5),i=C(e,!0).lab()[0],o=i-a})();return e}:e=>e,T},T.padding=function(e){return e==null?s:(h(e)===`number`&&(e=[e,e]),s=e,T)},T.colors=function(t,n){arguments.length<2&&(n=`hex`);let r=[];if(arguments.length===0)r=l.slice(0);else if(t===1)r=[T(.5)];else if(t>1){let e=i[0],n=i[1]-e;r=mt(0,t,!1).map(r=>T(e+r/(t-1)*n))}else{e=[];let t=[];if(c&&c.length>2)for(let e=1,n=c.length,r=1<=n;r?en;r?e++:e--)t.push((c[e-1]+c[e])*.5);else t=i;r=t.map(e=>T(e))}return k[n]&&(r=r.map(e=>e[n]())),r},T.cache=function(e){return e==null?_:(_=e,T)},T.gamma=function(e){return e==null?v:(v=e,T)},T.nodata=function(e){return e==null?n:(n=k(e),T)},T}function mt(e,t,n){let r=[],i=ea;i?t++:t--)r.push(t);return r}var ht=function(e){let t=[1,1];for(let n=1;nnew O(e)),e.length===2)[n,r]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>n[t]+e*(r[t]-n[t])),`lab`)};else if(e.length===3)[n,r,i]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*n[t]+2*(1-e)*e*r[t]+e*e*i[t]),`lab`)};else if(e.length===4){let a;[n,r,i,a]=e.map(e=>e.lab()),t=function(e){return new O([0,1,2].map(t=>(1-e)*(1-e)*(1-e)*n[t]+3*(1-e)*(1-e)*e*r[t]+3*(1-e)*e*e*i[t]+e*e*e*a[t]),`lab`)}}else if(e.length>=5){let n,r,i;n=e.map(e=>e.lab()),i=e.length-1,r=ht(i),t=function(e){let t=1-e;return new O([0,1,2].map(a=>n.reduce((n,o,s)=>n+r[s]*t**(i-s)*e**s*o[a],0)),`lab`)}}else throw RangeError(`No point in running bezier with only one color.`);return t},_t=e=>{let t=gt(e);return t.scale=()=>pt(t),t},{round:vt}=Math;O.prototype.rgb=function(e=!0){return e===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(vt)},O.prototype.rgba=function(e=!0){return this._rgb.slice(0,4).map((t,n)=>n<3?e===!1?t:vt(t):t)},Object.assign(k,{rgb:(...e)=>new O(...e,`rgb`)}),D.format.rgb=(...e)=>{let t=g(e,`rgba`);return t[3]===void 0&&(t[3]=1),t},D.autodetect.push({p:3,test:(...e)=>{if(e=g(e,`rgba`),h(e)===`array`&&(e.length===3||e.length===4&&h(e[3])==`number`&&e[3]>=0&&e[3]<=1))return`rgb`}});var I=(e,t,n)=>{if(!I[n])throw Error(`unknown blend mode `+n);return I[n](e,t)},L=e=>(t,n)=>{let r=k(n).rgb(),i=k(t).rgb();return k.rgb(e(r,i))},R=e=>(t,n)=>{let r=[];return r[0]=e(t[0],n[0]),r[1]=e(t[1],n[1]),r[2]=e(t[2],n[2]),r};I.normal=L(R(e=>e)),I.multiply=L(R((e,t)=>e*t/255)),I.screen=L(R((e,t)=>255*(1-(1-e/255)*(1-t/255)))),I.overlay=L(R((e,t)=>t<128?2*e*t/255:255*(1-2*(1-e/255)*(1-t/255)))),I.darken=L(R((e,t)=>e>t?t:e)),I.lighten=L(R((e,t)=>e>t?e:t)),I.dodge=L(R((e,t)=>e===255?255:(e=t/255*255/(1-e/255),e>255?255:e))),I.burn=L(R((e,t)=>255*(1-(1-t/255)/(e/255))));var{pow:yt,sin:bt,cos:xt}=Math;function St(e=300,t=-1.5,n=1,r=1,i=[0,1]){let a=0,o;h(i)===`array`?o=i[1]-i[0]:(o=0,i=[i,i]);let s=function(s){let c=C*((e+120)/360+t*s),l=yt(i[0]+o*s,r),u=(a===0?n:n[0]+s*a)*l*(1-l)/2,d=xt(c),f=bt(c),m=l+u*(-.14861*d+1.78277*f),h=l+u*(-.29227*d-.90649*f),g=l+1.97294*d*u;return k(p([m*255,h*255,g*255,1]))};return s.start=function(t){return t==null?e:(e=t,s)},s.rotations=function(e){return e==null?t:(t=e,s)},s.gamma=function(e){return e==null?r:(r=e,s)},s.hue=function(e){return e==null?n:(n=e,h(n)===`array`?(a=n[1]-n[0],a===0&&(n=n[1])):a=0,s)},s.lightness=function(e){return e==null?i:(h(e)===`array`?(i=e,o=e[1]-e[0]):(i=[e,e],o=0),s)},s.scale=()=>k.scale(s),s.hue(n),s}var Ct=`0123456789abcdef`,{floor:wt,random:Tt}=Math,Et=(e=Tt)=>{let t=`#`;for(let n=0;n<6;n++)t+=Ct.charAt(wt(e()*16));return new O(t,`hex`)},{log:Dt,pow:Ot,floor:kt,abs:At}=Math;function jt(e,t=null){let n={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return h(e)===`object`&&(e=Object.values(e)),e.forEach(e=>{t&&h(e)===`object`&&(e=e[t]),e!=null&&!isNaN(e)&&(n.values.push(e),n.sum+=e,en.max&&(n.max=e),n.count+=1)}),n.domain=[n.min,n.max],n.limits=(e,t)=>Mt(n,e,t),n}function Mt(e,t=`equal`,n=7){h(e)==`array`&&(e=jt(e));let{min:r,max:i}=e,a=e.values.sort((e,t)=>e-t);if(n===1)return[r,i];let o=[];if(t.substr(0,1)===`c`&&(o.push(r),o.push(i)),t.substr(0,1)===`e`){o.push(r);for(let e=1;e 0`);let e=Math.LOG10E*Dt(r),t=Math.LOG10E*Dt(i);o.push(r);for(let r=1;r200&&(l=!1)}let f={};for(let e=0;ee-t),o.push(p[0]);for(let e=1;e{e=new O(e),t=new O(t);let n=e.luminance(),r=t.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)},Pt=.027,Ft=5e-4,It=.1,Lt=1.14,Rt=.022,zt=1.414,Bt=(e,t)=>{e=new O(e),t=new O(t),e.alpha()<1&&(e=F(t,e,e.alpha(),`rgb`));let n=Vt(...e.rgb()),r=Vt(...t.rgb()),i=n>=Rt?n:n+(Rt-n)**+zt,a=r>=Rt?r:r+(Rt-r)**+zt,o=a**.56-i**.57,s=a**.65-i**.62,c=Math.abs(a-i)0?c-Pt:c+Pt)*100};function Vt(e,t,n){return .2126729*(e/255)**2.4+.7151522*(t/255)**2.4+.072175*(n/255)**2.4}var{sqrt:z,pow:B,min:Ht,max:Ut,atan2:Wt,abs:Gt,cos:Kt,sin:qt,exp:Jt,PI:Yt}=Math;function Xt(e,t,n=1,r=1,i=1){var a=function(e){return 360*e/(2*Yt)},o=function(e){return 2*Yt*e/360};e=new O(e),t=new O(t);let[s,c,l]=Array.from(e.lab()),[u,d,f]=Array.from(t.lab()),p=(s+u)/2,m=(z(B(c,2)+B(l,2))+z(B(d,2)+B(f,2)))/2,h=.5*(1-z(B(m,7)/(B(m,7)+B(25,7)))),g=c*(1+h),_=d*(1+h),v=z(B(g,2)+B(l,2)),y=z(B(_,2)+B(f,2)),b=(v+y)/2,x=a(Wt(l,g)),S=a(Wt(f,_)),C=x>=0?x:x+360,w=S>=0?S:S+360,T=Gt(C-w)>180?(C+w+360)/2:(C+w)/2,ee=1-.17*Kt(o(T-30))+.24*Kt(o(2*T))+.32*Kt(o(3*T+6))-.2*Kt(o(4*T-63)),E=w-C;E=Gt(E)<=180?E:w<=C?E+360:E-360,E=2*z(v*y)*qt(o(E)/2);let D=u-s,te=y-v,k=1+.015*B(p-50,2)/z(20+B(p-50,2)),A=1+.045*b,ne=1+.015*b*ee,re=30*Jt(-B((T-275)/25,2)),ie=-(2*z(B(b,7)/(B(b,7)+B(25,7))))*qt(2*o(re));return Ut(0,Ht(100,z(B(D/(n*k),2)+B(te/(r*A),2)+B(E/(i*ne),2)+ie*(te/(r*A))*(E/(i*ne)))))}function Zt(e,t,n=`lab`){e=new O(e),t=new O(t);let r=e.get(n),i=t.get(n),a=0;for(let e in r){let t=(r[e]||0)-(i[e]||0);a+=t*t}return Math.sqrt(a)}var Qt=(...e)=>{try{return new O(...e),!0}catch{return!1}},$t={cool(){return pt([k.hsl(180,1,.9),k.hsl(250,.7,.4)])},hot(){return pt([`#000`,`#f00`,`#ff0`,`#fff`],[0,.25,.75,1]).mode(`rgb`)}},en={OrRd:[`#fff7ec`,`#fee8c8`,`#fdd49e`,`#fdbb84`,`#fc8d59`,`#ef6548`,`#d7301f`,`#b30000`,`#7f0000`],PuBu:[`#fff7fb`,`#ece7f2`,`#d0d1e6`,`#a6bddb`,`#74a9cf`,`#3690c0`,`#0570b0`,`#045a8d`,`#023858`],BuPu:[`#f7fcfd`,`#e0ecf4`,`#bfd3e6`,`#9ebcda`,`#8c96c6`,`#8c6bb1`,`#88419d`,`#810f7c`,`#4d004b`],Oranges:[`#fff5eb`,`#fee6ce`,`#fdd0a2`,`#fdae6b`,`#fd8d3c`,`#f16913`,`#d94801`,`#a63603`,`#7f2704`],BuGn:[`#f7fcfd`,`#e5f5f9`,`#ccece6`,`#99d8c9`,`#66c2a4`,`#41ae76`,`#238b45`,`#006d2c`,`#00441b`],YlOrBr:[`#ffffe5`,`#fff7bc`,`#fee391`,`#fec44f`,`#fe9929`,`#ec7014`,`#cc4c02`,`#993404`,`#662506`],YlGn:[`#ffffe5`,`#f7fcb9`,`#d9f0a3`,`#addd8e`,`#78c679`,`#41ab5d`,`#238443`,`#006837`,`#004529`],Reds:[`#fff5f0`,`#fee0d2`,`#fcbba1`,`#fc9272`,`#fb6a4a`,`#ef3b2c`,`#cb181d`,`#a50f15`,`#67000d`],RdPu:[`#fff7f3`,`#fde0dd`,`#fcc5c0`,`#fa9fb5`,`#f768a1`,`#dd3497`,`#ae017e`,`#7a0177`,`#49006a`],Greens:[`#f7fcf5`,`#e5f5e0`,`#c7e9c0`,`#a1d99b`,`#74c476`,`#41ab5d`,`#238b45`,`#006d2c`,`#00441b`],YlGnBu:[`#ffffd9`,`#edf8b1`,`#c7e9b4`,`#7fcdbb`,`#41b6c4`,`#1d91c0`,`#225ea8`,`#253494`,`#081d58`],Purples:[`#fcfbfd`,`#efedf5`,`#dadaeb`,`#bcbddc`,`#9e9ac8`,`#807dba`,`#6a51a3`,`#54278f`,`#3f007d`],GnBu:[`#f7fcf0`,`#e0f3db`,`#ccebc5`,`#a8ddb5`,`#7bccc4`,`#4eb3d3`,`#2b8cbe`,`#0868ac`,`#084081`],Greys:[`#ffffff`,`#f0f0f0`,`#d9d9d9`,`#bdbdbd`,`#969696`,`#737373`,`#525252`,`#252525`,`#000000`],YlOrRd:[`#ffffcc`,`#ffeda0`,`#fed976`,`#feb24c`,`#fd8d3c`,`#fc4e2a`,`#e31a1c`,`#bd0026`,`#800026`],PuRd:[`#f7f4f9`,`#e7e1ef`,`#d4b9da`,`#c994c7`,`#df65b0`,`#e7298a`,`#ce1256`,`#980043`,`#67001f`],Blues:[`#f7fbff`,`#deebf7`,`#c6dbef`,`#9ecae1`,`#6baed6`,`#4292c6`,`#2171b5`,`#08519c`,`#08306b`],PuBuGn:[`#fff7fb`,`#ece2f0`,`#d0d1e6`,`#a6bddb`,`#67a9cf`,`#3690c0`,`#02818a`,`#016c59`,`#014636`],Viridis:[`#440154`,`#482777`,`#3f4a8a`,`#31678e`,`#26838f`,`#1f9d8a`,`#6cce5a`,`#b6de2b`,`#fee825`],Spectral:[`#9e0142`,`#d53e4f`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#e6f598`,`#abdda4`,`#66c2a5`,`#3288bd`,`#5e4fa2`],RdYlGn:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee08b`,`#ffffbf`,`#d9ef8b`,`#a6d96a`,`#66bd63`,`#1a9850`,`#006837`],RdBu:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#f7f7f7`,`#d1e5f0`,`#92c5de`,`#4393c3`,`#2166ac`,`#053061`],PiYG:[`#8e0152`,`#c51b7d`,`#de77ae`,`#f1b6da`,`#fde0ef`,`#f7f7f7`,`#e6f5d0`,`#b8e186`,`#7fbc41`,`#4d9221`,`#276419`],PRGn:[`#40004b`,`#762a83`,`#9970ab`,`#c2a5cf`,`#e7d4e8`,`#f7f7f7`,`#d9f0d3`,`#a6dba0`,`#5aae61`,`#1b7837`,`#00441b`],RdYlBu:[`#a50026`,`#d73027`,`#f46d43`,`#fdae61`,`#fee090`,`#ffffbf`,`#e0f3f8`,`#abd9e9`,`#74add1`,`#4575b4`,`#313695`],BrBG:[`#543005`,`#8c510a`,`#bf812d`,`#dfc27d`,`#f6e8c3`,`#f5f5f5`,`#c7eae5`,`#80cdc1`,`#35978f`,`#01665e`,`#003c30`],RdGy:[`#67001f`,`#b2182b`,`#d6604d`,`#f4a582`,`#fddbc7`,`#ffffff`,`#e0e0e0`,`#bababa`,`#878787`,`#4d4d4d`,`#1a1a1a`],PuOr:[`#7f3b08`,`#b35806`,`#e08214`,`#fdb863`,`#fee0b6`,`#f7f7f7`,`#d8daeb`,`#b2abd2`,`#8073ac`,`#542788`,`#2d004b`],Set2:[`#66c2a5`,`#fc8d62`,`#8da0cb`,`#e78ac3`,`#a6d854`,`#ffd92f`,`#e5c494`,`#b3b3b3`],Accent:[`#7fc97f`,`#beaed4`,`#fdc086`,`#ffff99`,`#386cb0`,`#f0027f`,`#bf5b17`,`#666666`],Set1:[`#e41a1c`,`#377eb8`,`#4daf4a`,`#984ea3`,`#ff7f00`,`#ffff33`,`#a65628`,`#f781bf`,`#999999`],Set3:[`#8dd3c7`,`#ffffb3`,`#bebada`,`#fb8072`,`#80b1d3`,`#fdb462`,`#b3de69`,`#fccde5`,`#d9d9d9`,`#bc80bd`,`#ccebc5`,`#ffed6f`],Dark2:[`#1b9e77`,`#d95f02`,`#7570b3`,`#e7298a`,`#66a61e`,`#e6ab02`,`#a6761d`,`#666666`],Paired:[`#a6cee3`,`#1f78b4`,`#b2df8a`,`#33a02c`,`#fb9a99`,`#e31a1c`,`#fdbf6f`,`#ff7f00`,`#cab2d6`,`#6a3d9a`,`#ffff99`,`#b15928`],Pastel2:[`#b3e2cd`,`#fdcdac`,`#cbd5e8`,`#f4cae4`,`#e6f5c9`,`#fff2ae`,`#f1e2cc`,`#cccccc`],Pastel1:[`#fbb4ae`,`#b3cde3`,`#ccebc5`,`#decbe4`,`#fed9a6`,`#ffffcc`,`#e5d8bd`,`#fddaec`,`#f2f2f2`]},tn=Object.keys(en),nn=new Map(tn.map(e=>[e.toLowerCase(),e])),rn=typeof Proxy==`function`?new Proxy(en,{get(e,t){let n=t.toLowerCase();if(nn.has(n))return e[nn.get(n)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(tn)}}):en,an=(...e)=>{e=g(e,`cmyk`);let[t,n,r,i]=e,a=e.length>4?e[4]:1;return i===1?[0,0,0,a]:[t>=1?0:255*(1-t)*(1-i),n>=1?0:255*(1-n)*(1-i),r>=1?0:255*(1-r)*(1-i),a]},{max:on}=Math,sn=(...e)=>{let[t,n,r]=g(e,`rgb`);t/=255,n/=255,r/=255;let i=1-on(t,on(n,r)),a=i<1?1/(1-i):0;return[(1-t-i)*a,(1-n-i)*a,(1-r-i)*a,i]};O.prototype.cmyk=function(){return sn(this._rgb)},Object.assign(k,{cmyk:(...e)=>new O(...e,`cmyk`)}),D.format.cmyk=an,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`cmyk`),h(e)===`array`&&e.length===4)return`cmyk`}});var cn=(...e)=>{let t=g(e,`hsla`),n=_(e)||`lsa`;return t[0]=x(t[0]||0)+`deg`,t[1]=x(t[1]*100)+`%`,t[2]=x(t[2]*100)+`%`,n===`hsla`||t.length>3&&t[3]<1?(t[3]=`/ `+(t.length>3?t[3]:1),n=`hsla`):t.length=3,`${n.substr(0,3)}(${t.join(` `)})`},ln=(...e)=>{let t=g(e,`lab`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=x(t[2]),n===`laba`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lab(${t.join(` `)})`},un=(...e)=>{let t=g(e,`lch`),n=_(e)||`lab`;return t[0]=x(t[0])+`%`,t[1]=x(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,n===`lcha`||t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`lch(${t.join(` `)})`},dn=(...e)=>{let t=g(e,`lab`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=S(t[2]),t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklab(${t.join(` `)})`},fn=(...e)=>{let[t,n,r,...i]=g(e,`rgb`),[a,o,s]=nt(t,n,r),[c,l,u]=ke(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},pn=(...e)=>{let t=g(e,`lch`);return t[0]=x(t[0]*100)+`%`,t[1]=S(t[1]),t[2]=isNaN(t[2])?`none`:x(t[2])+`deg`,t.length>3&&t[3]<1?t[3]=`/ `+(t.length>3?t[3]:1):t.length=3,`oklch(${t.join(` `)})`},{round:mn}=Math,hn=(...e)=>{let t=g(e,`rgba`),n=_(e)||`rgb`;if(n.substr(0,3)===`hsl`)return cn(qe(t),n);if(n.substr(0,3)===`lab`){let e=ce();M(`d50`);let r=ln(fe(t),n);return M(e),r}if(n.substr(0,3)===`lch`){let e=ce();M(`d50`);let r=un(Ae(t),n);return M(e),r}return n.substr(0,5)===`oklab`?dn(nt(t)):n.substr(0,5)===`oklch`?pn(fn(t)):(t[0]=mn(t[0]),t[1]=mn(t[1]),t[2]=mn(t[2]),(n===`rgba`||t.length>3&&t[3]<1)&&(t[3]=`/ `+(t.length>3?t[3]:1),n=`rgba`),`${n.substr(0,3)}(${t.slice(0,n===`rgb`?3:4).join(` `)})`)},gn=(...e)=>{e=g(e,`lch`);let[t,n,r,...i]=e,[a,o,s]=Ce(t,n,r),[c,l,u]=et(a,o,s);return[c,l,u,...i.length>0&&i[0]<1?[i[0]]:[]]},V=`((?:-?\\d+)|(?:-?\\d+(?:\\.\\d+)?)%|none)`,H=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%?)|none)`,_n=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)%)|none)`,U=`\\s*`,vn=`\\s+`,yn=`\\s*,\\s*`,bn=`((?:-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:deg)?)|none)`,xn=`\\s*(?:\\/\\s*((?:[01]|[01]?\\.\\d+)|\\d+(?:\\.\\d+)?%))?`,Sn=RegExp(`^rgba?\\(`+U+[V,V,V].join(vn)+xn+`\\)$`),Cn=RegExp(`^rgb\\(`+U+[V,V,V].join(yn)+U+`\\)$`),wn=RegExp(`^rgba\\(`+U+[V,V,V,H].join(yn)+U+`\\)$`),Tn=RegExp(`^hsla?\\(`+U+[bn,_n,_n].join(vn)+xn+`\\)$`),En=RegExp(`^hsl?\\(`+U+[bn,_n,_n].join(yn)+U+`\\)$`),Dn=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,On=RegExp(`^lab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),kn=RegExp(`^lch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),An=RegExp(`^oklab\\(`+U+[H,H,H].join(vn)+xn+`\\)$`),jn=RegExp(`^oklch\\(`+U+[H,H,bn].join(vn)+xn+`\\)$`),{round:Mn}=Math,Nn=e=>e.map((e,t)=>t<=2?f(Mn(e),0,255):e),W=(e,t=0,n=100,r=!1)=>(typeof e==`string`&&e.endsWith(`%`)&&(e=parseFloat(e.substring(0,e.length-1))/100,e=r?t+(e+1)*.5*(n-t):t+e*(n-t)),+e),G=(e,t)=>e===`none`?t:e,Pn=e=>{if(e=e.toLowerCase().trim(),e===`transparent`)return[0,0,0,0];let t;if(D.format.named)try{return D.format.named(e)}catch{}if((t=e.match(Sn))||(t=e.match(Cn))){let e=t.slice(1,4);for(let t=0;t<3;t++)e[t]=+W(G(e[t],0),0,255);e=Nn(e);let n=t[4]===void 0?1:+W(t[4],0,1);return e[3]=n,e}if(t=e.match(wn)){let e=t.slice(1,5);for(let t=0;t<4;t++)e[t]=+W(e[t],0,255);return e}if((t=e.match(Tn))||(t=e.match(En))){let e=t.slice(1,4);e[0]=+G(e[0].replace(`deg`,``),0),e[1]=W(G(e[1],0),0,100)*.01,e[2]=W(G(e[2],0),0,100)*.01;let n=Nn(Ke(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(Dn)){let e=t.slice(1,4);e[1]*=.01,e[2]*=.01;let n=Ke(e);for(let e=0;e<3;e++)n[e]=Mn(n[e]);return n[3]=+t[4],n}if(t=e.match(On)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,100),e[1]=W(G(e[1],0),-125,125,!0),e[2]=W(G(e[2],0),-125,125,!0);let n=ce();M(`d50`);let r=Nn(N(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(kn)){let e=t.slice(1,4);e[0]=W(e[0],0,100),e[1]=W(G(e[1],0),0,150,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=ce();M(`d50`);let r=Nn(we(e));return M(n),r[3]=t[4]===void 0?1:+W(t[4],0,1),r}if(t=e.match(An)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),-.4,.4,!0),e[2]=W(G(e[2],0),-.4,.4,!0);let n=Nn(et(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}if(t=e.match(jn)){let e=t.slice(1,4);e[0]=W(G(e[0],0),0,1),e[1]=W(G(e[1],0),0,.4,!1),e[2]=+G(e[2].replace(`deg`,``),0);let n=Nn(gn(e));return n[3]=t[4]===void 0?1:+W(t[4],0,1),n}};Pn.test=e=>Sn.test(e)||Tn.test(e)||On.test(e)||kn.test(e)||An.test(e)||jn.test(e)||Cn.test(e)||wn.test(e)||En.test(e)||Dn.test(e)||e===`transparent`,O.prototype.css=function(e){return hn(this._rgb,e)},k.css=(...e)=>new O(...e,`css`),D.format.css=Pn,D.autodetect.push({p:5,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&Pn.test(e))return`css`}}),D.format.gl=(...e)=>{let t=g(e,`rgba`);return t[0]*=255,t[1]*=255,t[2]*=255,t},k.gl=(...e)=>new O(...e,`gl`),O.prototype.gl=function(){let e=this._rgb;return[e[0]/255,e[1]/255,e[2]/255,e[3]]},O.prototype.hex=function(e){return oe(this._rgb,e)},k.hex=(...e)=>new O(...e,`hex`),D.format.hex=ie,D.autodetect.push({p:4,test:(e,...t)=>{if(!t.length&&h(e)===`string`&&[3,4,5,6,7,8,9].indexOf(e.length)>=0)return`hex`}});var{log:Fn}=Math,In=e=>{let t=e/100,n,r,i;return t<66?(n=255,r=t<6?0:-155.25485562709179-.44596950469579133*(r=t-2)+104.49216199393888*Fn(r),i=t<20?0:-254.76935184120902+.8274096064007395*(i=t-10)+115.67994401066147*Fn(i)):(n=351.97690566805693+.114206453784165*(n=t-55)-40.25366309332127*Fn(n),r=325.4494125711974+.07943456536662342*(r=t-50)-28.0852963507957*Fn(r),i=255),[n,r,i,1]},{round:Ln}=Math,Rn=(...e)=>{let t=g(e,`rgb`),n=t[0],r=t[2],i=1e3,a=4e4,o;for(;a-i>.4;){o=(a+i)*.5;let e=In(o);e[2]/e[0]>=r/n?a=o:i=o}return Ln(o)};O.prototype.temp=O.prototype.kelvin=O.prototype.temperature=function(){return Rn(this._rgb)};var zn=(...e)=>new O(...e,`temp`);Object.assign(k,{temp:zn,kelvin:zn,temperature:zn}),D.format.temp=D.format.kelvin=D.format.temperature=In,O.prototype.oklch=function(){return fn(this._rgb)},Object.assign(k,{oklch:(...e)=>new O(...e,`oklch`)}),D.format.oklch=gn,D.autodetect.push({p:2,test:(...e)=>{if(e=g(e,`oklch`),h(e)===`array`&&e.length===3)return`oklch`}}),Object.assign(k,{analyze:jt,average:ut,bezier:_t,blend:I,brewer:rn,Color:O,colors:A,contrast:Nt,contrastAPCA:Bt,cubehelix:St,deltaE:Xt,distance:Zt,input:D,interpolate:F,limits:Mt,mix:F,random:Et,scale:pt,scales:$t,valid:Qt});var K=k,q=class e{constructor(){this.hex=`#000000`,this.rgb_r=0,this.rgb_g=0,this.rgb_b=0,this.xyz_x=0,this.xyz_y=0,this.xyz_z=0,this.luv_l=0,this.luv_u=0,this.luv_v=0,this.lch_l=0,this.lch_c=0,this.lch_h=0,this.hsluv_h=0,this.hsluv_s=0,this.hsluv_l=0,this.hpluv_h=0,this.hpluv_p=0,this.hpluv_l=0,this.r0s=0,this.r0i=0,this.r1s=0,this.r1i=0,this.g0s=0,this.g0i=0,this.g1s=0,this.g1i=0,this.b0s=0,this.b0i=0,this.b1s=0,this.b1i=0}static fromLinear(e){return e<=.0031308?12.92*e:1.055*e**(1/2.4)-.055}static toLinear(e){return e>.04045?((e+.055)/1.055)**2.4:e/12.92}static yToL(t){return t<=e.epsilon?t/e.refY*e.kappa:116*(t/e.refY)**(1/3)-16}static lToY(t){return t<=8?e.refY*t/e.kappa:e.refY*((t+16)/116)**3}static rgbChannelToHex(t){let n=Math.round(t*255),r=n%16,i=(n-r)/16|0;return e.hexChars.charAt(i)+e.hexChars.charAt(r)}static hexToRgbChannel(t,n){let r=e.hexChars.indexOf(t.charAt(n)),i=e.hexChars.indexOf(t.charAt(n+1));return(r*16+i)/255}static distanceFromOriginAngle(e,t,n){let r=t/(Math.sin(n)-e*Math.cos(n));return r<0?1/0:r}static distanceFromOrigin(e,t){return Math.abs(t)/Math.sqrt(e**2+1)}static min6(e,t,n,r,i,a){return Math.min(e,Math.min(t,Math.min(n,Math.min(r,Math.min(i,a)))))}rgbToHex(){this.hex=`#`,this.hex+=e.rgbChannelToHex(this.rgb_r),this.hex+=e.rgbChannelToHex(this.rgb_g),this.hex+=e.rgbChannelToHex(this.rgb_b)}hexToRgb(){this.hex=this.hex.toLowerCase(),this.rgb_r=e.hexToRgbChannel(this.hex,1),this.rgb_g=e.hexToRgbChannel(this.hex,3),this.rgb_b=e.hexToRgbChannel(this.hex,5)}xyzToRgb(){this.rgb_r=e.fromLinear(e.m_r0*this.xyz_x+e.m_r1*this.xyz_y+e.m_r2*this.xyz_z),this.rgb_g=e.fromLinear(e.m_g0*this.xyz_x+e.m_g1*this.xyz_y+e.m_g2*this.xyz_z),this.rgb_b=e.fromLinear(e.m_b0*this.xyz_x+e.m_b1*this.xyz_y+e.m_b2*this.xyz_z)}rgbToXyz(){let t=e.toLinear(this.rgb_r),n=e.toLinear(this.rgb_g),r=e.toLinear(this.rgb_b);this.xyz_x=.41239079926595*t+.35758433938387*n+.18048078840183*r,this.xyz_y=.21263900587151*t+.71516867876775*n+.072192315360733*r,this.xyz_z=.019330818715591*t+.11919477979462*n+.95053215224966*r}xyzToLuv(){let t=this.xyz_x+15*this.xyz_y+3*this.xyz_z,n=4*this.xyz_x,r=9*this.xyz_y;t===0?(n=NaN,r=NaN):(n/=t,r/=t),this.luv_l=e.yToL(this.xyz_y),this.luv_l===0?(this.luv_u=0,this.luv_v=0):(this.luv_u=13*this.luv_l*(n-e.refU),this.luv_v=13*this.luv_l*(r-e.refV))}luvToXyz(){if(this.luv_l===0){this.xyz_x=0,this.xyz_y=0,this.xyz_z=0;return}let t=this.luv_u/(13*this.luv_l)+e.refU,n=this.luv_v/(13*this.luv_l)+e.refV;this.xyz_y=e.lToY(this.luv_l),this.xyz_x=0-9*this.xyz_y*t/((t-4)*n-t*n),this.xyz_z=(9*this.xyz_y-15*n*this.xyz_y-n*this.xyz_x)/(3*n)}luvToLch(){if(this.lch_l=this.luv_l,this.lch_c=Math.sqrt(this.luv_u*this.luv_u+this.luv_v*this.luv_v),this.lch_c<1e-8)this.lch_h=0;else{let e=Math.atan2(this.luv_v,this.luv_u);this.lch_h=e*180/Math.PI,this.lch_h<0&&(this.lch_h=360+this.lch_h)}}lchToLuv(){let e=this.lch_h/180*Math.PI;this.luv_l=this.lch_l,this.luv_u=Math.cos(e)*this.lch_c,this.luv_v=Math.sin(e)*this.lch_c}calculateBoundingLines(t){let n=(t+16)**3/1560896,r=n>e.epsilon?n:t/e.kappa,i=r*(284517*e.m_r0-94839*e.m_r2),a=r*(838422*e.m_r2+769860*e.m_r1+731718*e.m_r0),o=r*(632260*e.m_r2-126452*e.m_r1),s=r*(284517*e.m_g0-94839*e.m_g2),c=r*(838422*e.m_g2+769860*e.m_g1+731718*e.m_g0),l=r*(632260*e.m_g2-126452*e.m_g1),u=r*(284517*e.m_b0-94839*e.m_b2),d=r*(838422*e.m_b2+769860*e.m_b1+731718*e.m_b0),f=r*(632260*e.m_b2-126452*e.m_b1);this.r0s=i/o,this.r0i=a*t/o,this.r1s=i/(o+126452),this.r1i=(a-769860)*t/(o+126452),this.g0s=s/l,this.g0i=c*t/l,this.g1s=s/(l+126452),this.g1i=(c-769860)*t/(l+126452),this.b0s=u/f,this.b0i=d*t/f,this.b1s=u/(f+126452),this.b1i=(d-769860)*t/(f+126452)}calcMaxChromaHpluv(){let t=e.distanceFromOrigin(this.r0s,this.r0i),n=e.distanceFromOrigin(this.r1s,this.r1i),r=e.distanceFromOrigin(this.g0s,this.g0i),i=e.distanceFromOrigin(this.g1s,this.g1i),a=e.distanceFromOrigin(this.b0s,this.b0i),o=e.distanceFromOrigin(this.b1s,this.b1i);return e.min6(t,n,r,i,a,o)}calcMaxChromaHsluv(t){let n=t/360*Math.PI*2,r=e.distanceFromOriginAngle(this.r0s,this.r0i,n),i=e.distanceFromOriginAngle(this.r1s,this.r1i,n),a=e.distanceFromOriginAngle(this.g0s,this.g0i,n),o=e.distanceFromOriginAngle(this.g1s,this.g1i,n),s=e.distanceFromOriginAngle(this.b0s,this.b0i,n),c=e.distanceFromOriginAngle(this.b1s,this.b1i,n);return e.min6(r,i,a,o,s,c)}hsluvToLch(){if(this.hsluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hsluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hsluv_l,this.calculateBoundingLines(this.hsluv_l);let e=this.calcMaxChromaHsluv(this.hsluv_h);this.lch_c=e/100*this.hsluv_s}this.lch_h=this.hsluv_h}lchToHsluv(){if(this.lch_l>99.9999999)this.hsluv_s=0,this.hsluv_l=100;else if(this.lch_l<1e-8)this.hsluv_s=0,this.hsluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHsluv(this.lch_h);this.hsluv_s=this.lch_c/e*100,this.hsluv_l=this.lch_l}this.hsluv_h=this.lch_h}hpluvToLch(){if(this.hpluv_l>99.9999999)this.lch_l=100,this.lch_c=0;else if(this.hpluv_l<1e-8)this.lch_l=0,this.lch_c=0;else{this.lch_l=this.hpluv_l,this.calculateBoundingLines(this.hpluv_l);let e=this.calcMaxChromaHpluv();this.lch_c=e/100*this.hpluv_p}this.lch_h=this.hpluv_h}lchToHpluv(){if(this.lch_l>99.9999999)this.hpluv_p=0,this.hpluv_l=100;else if(this.lch_l<1e-8)this.hpluv_p=0,this.hpluv_l=0;else{this.calculateBoundingLines(this.lch_l);let e=this.calcMaxChromaHpluv();this.hpluv_p=this.lch_c/e*100,this.hpluv_l=this.lch_l}this.hpluv_h=this.lch_h}hsluvToRgb(){this.hsluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hpluvToRgb(){this.hpluvToLch(),this.lchToLuv(),this.luvToXyz(),this.xyzToRgb()}hsluvToHex(){this.hsluvToRgb(),this.rgbToHex()}hpluvToHex(){this.hpluvToRgb(),this.rgbToHex()}rgbToHsluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHsluv()}rgbToHpluv(){this.rgbToXyz(),this.xyzToLuv(),this.luvToLch(),this.lchToHpluv(),this.lchToHpluv()}hexToHsluv(){this.hexToRgb(),this.rgbToHsluv()}hexToHpluv(){this.hexToRgb(),this.rgbToHpluv()}};q.hexChars=`0123456789abcdef`,q.refY=1,q.refU=.19783000664283,q.refV=.46831999493879,q.kappa=903.2962962,q.epsilon=.0088564516,q.m_r0=3.240969941904521,q.m_r1=-1.537383177570093,q.m_r2=-.498610760293,q.m_g0=-.96924363628087,q.m_g1=1.87596750150772,q.m_g2=.041555057407175,q.m_b0=.055630079696993,q.m_b1=-.20397695888897,q.m_b2=1.056971514242878;var Bn=s(((e,t)=>{function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=n})),Vn=s(((e,t)=>{var n=Bn(),r,i;function a(){for(var e in i=[`toString`,`toLocaleString`,`valueOf`,`hasOwnProperty`,`isPrototypeOf`,`propertyIsEnumerable`,`constructor`],r=!0,{toString:null})r=!1}function o(e,t,o){var c,l=0;for(c in r??a(),e)if(s(t,e,c,o)===!1)break;if(r)for(var u=e.constructor,d=!!u&&e===u.prototype;(c=i[l++])&&!((c!==`constructor`||!d&&n(e,c))&&e[c]!==Object.prototype[c]&&s(t,e,c,o)===!1););}function s(e,t,n,r){return e.call(r,t[n],n,t)}t.exports=o})),Hn=s(((e,t)=>{var n=Vn();function r(e){var t=[];return n(e,function(e,n){typeof e==`function`&&t.push(n)}),t.sort()}t.exports=r})),Un=s(((e,t)=>{function n(e,t,n){var r=e.length;t=t==null?0:t<0?Math.max(r+t,0):Math.min(t,r),n=n==null?r:n<0?Math.max(r+n,0):Math.min(n,r);for(var i=[];t{var n=Un();function r(e,t,r){var i=n(arguments,2);return function(){return e.apply(t,i.concat(n(arguments)))}}t.exports=r})),Gn=s(((e,t)=>{function n(e,t,n){if(e!=null)for(var r=-1,i=e.length;++r{var n=Hn(),r=Wn(),i=Gn(),a=Un();function o(e,t){i(arguments.length>1?a(arguments,1):n(e),function(t){e[t]=r(e[t],e)})}t.exports=o})),J=s(((e,t)=>{var n=Bn(),r=Vn();function i(e,t,i){r(e,function(r,a){if(n(e,a))return t.call(i,e[a],a,e)})}t.exports=i})),qn=s(((e,t)=>{function n(e){return e}t.exports=n})),Jn=s(((e,t)=>{function n(e){return function(t){return t[e]}}t.exports=n})),Yn=s(((e,t)=>{var n=/^\[object (.*)\]$/,r=Object.prototype.toString,i;function a(e){return e===null?`Null`:e===i?`Undefined`:n.exec(r.call(e))[1]}t.exports=a})),Xn=s(((e,t)=>{var n=Yn();function r(e,t){return n(e)===t}t.exports=r})),Zn=s(((e,t)=>{var n=Xn();t.exports=Array.isArray||function(e){return n(e,`Array`)}})),Qn=s(((e,t)=>{var n=J(),r=Zn();function i(e,t){for(var n=-1,r=e.length;++n{var n=qn(),r=Jn(),i=Qn();function a(e,t){if(e==null)return n;switch(typeof e){case`function`:return t===void 0?e:function(n,r,i){return e.call(t,n,r,i)};case`object`:return function(t){return i(t,e)};case`string`:case`number`:return r(e)}}t.exports=a})),$n=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!1;return n(e,function(n,r){if(t(n,r,e))return a=!0,!1}),a}t.exports=i})),er=s(((e,t)=>{var n=$n();function r(e,t){return n(e,function(e){return e===t})}t.exports=r})),tr=s(((e,t)=>{function n(e){return!!e&&typeof e==`object`&&e.constructor===Object}t.exports=n})),nr=s(((e,t)=>{var n=J(),r=tr();function i(e,t){for(var a=0,o=arguments.length,s;++a{var n=J(),r=tr();function i(e,t){for(var r=0,i=arguments.length,o;++r{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a=!0;return n(e,function(n,r){if(!t(n,r,e))return a=!1,!1}),a}t.exports=i})),ar=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Object`)}t.exports=r})),or=s(((e,t)=>{function n(e,t){return e===t?e!==0||1/e==1/t:e!==e&&t!==t}t.exports=n})),sr=s(((e,t)=>{var n=Bn(),r=ir(),i=ar(),a=or();function o(e){return function(t,r){return n(this,r)&&e(t,this[r])}}function s(e,t){return n(this,t)}function c(e,t,n){return n||=a,!i(e)||!i(t)?n(e,t):r(e,o(n),t)&&r(t,s,e)}t.exports=c})),cr=s(((e,t)=>{var n=Gn(),r=Un(),i=J();function a(e,t){return n(r(arguments,1),function(t){i(t,function(t,n){e[n]??(e[n]=t)})}),e}t.exports=a})),lr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){t(e,n,r)&&(a[n]=e)}),a}t.exports=i})),ur=s(((e,t)=>{var n=$n(),r=Y();function i(e,t,i){t=r(t,i);var a;return n(e,function(e,n,r){if(t(e,n,r))return a=e,!0}),a}t.exports=i})),dr=s(((e,t)=>{var n=J(),r=tr();function i(e,t,a,o){return n(e,function(e,n){var s=a?a+`.`+n:n;o!==0&&r(e)?i(e,t,s,o-1):t[s]=e}),t}function a(e,t){return e==null?{}:(t??=-1,i(e,{},``,t))}t.exports=a})),fr=s(((e,t)=>{function n(e){switch(typeof e){case`string`:case`number`:case`boolean`:return!0}return e==null}t.exports=n})),pr=s(((e,t)=>{fr();function n(e,t){for(var n=t.split(`.`),r=n.pop();t=n.shift();)if(e=e[t],e==null)return;return e[r]}t.exports=n})),mr=s(((e,t)=>{var n=pr(),r;function i(e,t){return n(e,t)!==r}t.exports=i})),hr=s(((e,t)=>{var n=J();t.exports=Object.keys||function(e){var t=[];return n(e,function(e,n){t.push(n)}),t}})),gr=s(((e,t)=>{var n=J(),r=Y();function i(e,t,i){t=r(t,i);var a={};return n(e,function(e,n,r){a[n]=t(e,n,r)}),a}t.exports=i})),_r=s(((e,t)=>{var n=J();function r(e,t){var r=!0;return n(t,function(t,n){if(e[n]!==t)return r=!1}),r}t.exports=r})),vr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return 1/0;if(e.length&&!t)return Math.max.apply(Math,e);t=n(t,r);for(var i,a=-1/0,o,s,c=-1,l=e.length;++ca&&(a=s,i=o);return i}t.exports=r})),yr=s(((e,t)=>{var n=J();function r(e){var t=[];return n(e,function(e,n){t.push(e)}),t}t.exports=r})),br=s(((e,t)=>{var n=vr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),xr=s(((e,t)=>{var n=J();function r(e,t){for(var r=0,a=arguments.length,o;++r{var n=Yn(),r=tr(),i=xr();function a(e){switch(n(e)){case`Object`:return o(e);case`Array`:return l(e);case`RegExp`:return s(e);case`Date`:return c(e);default:return e}}function o(e){return r(e)?i({},e):e}function s(e){var t=``;return t+=e.multiline?`m`:``,t+=e.global?`g`:``,t+=e.ignoreCase?`i`:``,new RegExp(e.source,t)}function c(e){return new Date(+e)}function l(e){return e.slice()}t.exports=a})),Cr=s(((e,t)=>{var n=Sr(),r=J(),i=Yn(),a=tr();function o(e,t){switch(i(e)){case`Object`:return s(e,t);case`Array`:return c(e,t);default:return n(e)}}function s(e,t){if(a(e)){var n={};return r(e,function(e,n){this[n]=o(e,t)},n),n}else if(t)return t(e);else return e}function c(e,t){for(var n=[],r=-1,i=e.length;++r{var n=Bn(),r=Cr(),i=ar();function a(){for(var e=1,t,o,s,c=r(arguments[0]);s=arguments[e++];)for(t in s)n(s,t)&&(o=s[t],i(o)&&i(c[t])?c[t]=a(c[t],o):c[t]=r(o));return c}t.exports=a})),Tr=s(((e,t)=>{var n=Y();function r(e,t,r){if(e==null||!e.length)return-1/0;if(e.length&&!t)return Math.min.apply(Math,e);t=n(t,r);for(var i,a=1/0,o,s,c=-1,l=e.length;++c{var n=Tr(),r=yr();function i(e,t){return n(r(e),t)}t.exports=i})),Dr=s(((e,t)=>{var n=Gn();function r(e,t){return t&&n(t.split(`.`),function(t){e[t]||(e[t]={}),e=e[t]}),e}t.exports=r})),Or=s(((e,t)=>{function n(e,t,n){if(n||=0,e==null)return-1;for(var r=e.length,i=n<0?r+n:n;i{var n=Or();function r(e,t){return n(e,t)!==-1}t.exports=r})),Ar=s(((e,t)=>{var n=Un(),r=kr();function i(e,t){var i=typeof arguments[1]==`string`?n(arguments,1):arguments[1],a={};for(var o in e)e.hasOwnProperty(o)&&!r(i,o)&&(a[o]=e[o]);return a}t.exports=i})),jr=s(((e,t)=>{var n=Un();function r(e,t){for(var r=typeof arguments[1]==`string`?n(arguments,1):arguments[1],i={},a=0,o;o=r[a++];)i[o]=e[o];return i}t.exports=r})),Mr=s(((e,t)=>{var n=gr(),r=Jn();function i(e,t){return n(e,r(t))}t.exports=i})),Nr=s(((e,t)=>{var n=J();function r(e){var t=0;return n(e,function(){t++}),t}t.exports=r})),Pr=s(((e,t)=>{var n=J(),r=Nr();function i(e,t,i,a){var o=arguments.length>2;if(!r(e)&&!o)throw Error(`reduce of empty object with no initial value`);return n(e,function(e,n,r){o?i=t.call(a,i,e,n,r):(i=e,o=!0)}),i}t.exports=i})),Fr=s(((e,t)=>{var n=lr(),r=Y();function i(e,t,i){return t=r(t,i),n(e,function(e,n,r){return!t(e,n,r)},i)}t.exports=i})),Ir=s(((e,t)=>{var n=Xn();function r(e){return n(e,`Function`)}t.exports=r})),Lr=s(((e,t)=>{var n=Ir();function r(e,t){var r=e[t];if(r!==void 0)return n(r)?r.call(e):r}t.exports=r})),Rr=s(((e,t)=>{var n=Dr();function r(e,t,r){var i=/^(.+)\.(.+)$/.exec(t);i?n(e,i[1])[i[2]]=r:e[t]=r}t.exports=r})),zr=s(((e,t)=>{var n=mr();function r(e,t){if(n(e,t)){for(var r=t.split(`.`),i=r.pop();t=r.shift();)e=e[t];return delete e[i]}else return!0}t.exports=r})),Br=s(((e,t)=>{t.exports={bindAll:Kn(),contains:er(),deepFillIn:nr(),deepMatches:Qn(),deepMixIn:rr(),equals:sr(),every:ir(),fillIn:cr(),filter:lr(),find:ur(),flatten:dr(),forIn:Vn(),forOwn:J(),functions:Hn(),get:pr(),has:mr(),hasOwn:Bn(),keys:hr(),map:gr(),matches:_r(),max:br(),merge:wr(),min:Er(),mixIn:xr(),namespace:Dr(),omit:Ar(),pick:jr(),pluck:Mr(),reduce:Pr(),reject:Fr(),result:Lr(),set:Rr(),size:Nr(),some:$n(),unset:zr(),values:yr()}})),Vr=s(((e,t)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.default=(0,Br().map)({A:{x:.44758,y:.40745},C:{x:.31006,y:.31616},D50:{x:.34567,y:.35851},D65:{x:.31272,y:.32903},D55:{x:.33243,y:.34744},D75:{x:.29903,y:.31488}},function(e){return[100*(e.x/e.y),100,100*(1-e.x-e.y)/e.y]}),t.exports=e.default})),Hr=s(((e,t)=>{Object.defineProperty(e,"__esModule",{value:!0});var n=Math,r=n.pow,i=n.sign,a=n.abs,o={decode:function(e){return e<=.04045?e/12.92:r((e+.055)/1.055,2.4)},encode:function(e){return e<=.0031308?12.92*e:1.055*r(e,1/2.4)-.055}},s={encode:function(e){return e<.001953125?16*e:r(e,1/1.8)},decode:function(e){return e<16*.001953125?e/16:r(e,1.8)}};function c(e){return{decode:function(t){return i(t)*r(a(t),e)},encode:function(t){return i(t)*r(a(t),1/e)}}}e.default={sRGB:{r:{x:.64,y:.33},g:{x:.3,y:.6},b:{x:.15,y:.06},gamma:o},"Adobe RGB":{r:{x:.64,y:.33},g:{x:.21,y:.71},b:{x:.15,y:.06},gamma:c(2.2)},"Wide Gamut RGB":{r:{x:.7347,y:.2653},g:{x:.1152,y:.8264},b:{x:.1566,y:.0177},gamma:c(563/256)},"ProPhoto RGB":{r:{x:.7347,y:.2653},g:{x:.1596,y:.8404},b:{x:.0366,y:1e-4},gamma:s}},t.exports=e.default})),Ur=s((e=>{Object.defineProperty(e,"__esModule",{value:!0});function t(e){return[[e[0][0],e[1][0],e[2][0]],[e[0][1],e[1][1],e[2][1]],[e[0][2],e[1][2],e[2][2]]]}function n(e){return e[0][0]*(e[2][2]*e[1][1]-e[2][1]*e[1][2])+e[1][0]*(e[2][1]*e[0][2]-e[2][2]*e[0][1])+e[2][0]*(e[1][2]*e[0][1]-e[1][1]*e[0][2])}function r(e){var t=1/n(e);return[[(e[2][2]*e[1][1]-e[2][1]*e[1][2])*t,(e[2][1]*e[0][2]-e[2][2]*e[0][1])*t,(e[1][2]*e[0][1]-e[1][1]*e[0][2])*t],[(e[2][0]*e[1][2]-e[2][2]*e[1][0])*t,(e[2][2]*e[0][0]-e[2][0]*e[0][2])*t,(e[1][0]*e[0][2]-e[1][2]*e[0][0])*t],[(e[2][1]*e[1][0]-e[2][0]*e[1][1])*t,(e[2][0]*e[0][1]-e[2][1]*e[0][0])*t,(e[1][1]*e[0][0]-e[1][0]*e[0][1])*t]]}function i(e,t){return[e[0][0]*t[0]+e[0][1]*t[1]+e[0][2]*t[2],e[1][0]*t[0]+e[1][1]*t[1]+e[1][2]*t[2],e[2][0]*t[0]+e[2][1]*t[1]+e[2][2]*t[2]]}function a(e,t){return[[e[0][0]*t[0],e[0][1]*t[1],e[0][2]*t[2]],[e[1][0]*t[0],e[1][1]*t[1],e[1][2]*t[2]],[e[2][0]*t[0],e[2][1]*t[1],e[2][2]*t[2]]]}function o(e,t){return[[e[0][0]*t[0][0]+e[0][1]*t[1][0]+e[0][2]*t[2][0],e[0][0]*t[0][1]+e[0][1]*t[1][1]+e[0][2]*t[2][1],e[0][0]*t[0][2]+e[0][1]*t[1][2]+e[0][2]*t[2][2]],[e[1][0]*t[0][0]+e[1][1]*t[1][0]+e[1][2]*t[2][0],e[1][0]*t[0][1]+e[1][1]*t[1][1]+e[1][2]*t[2][1],e[1][0]*t[0][2]+e[1][1]*t[1][2]+e[1][2]*t[2][2]],[e[2][0]*t[0][0]+e[2][1]*t[1][0]+e[2][2]*t[2][0],e[2][0]*t[0][1]+e[2][1]*t[1][1]+e[2][2]*t[2][1],e[2][0]*t[0][2]+e[2][1]*t[1][2]+e[2][2]*t[2][2]]]}e.transpose=t,e.determinant=n,e.inverse=r,e.multiply=i,e.scalar=a,e.product=o})),Wr=s((e=>{Object.defineProperty(e,"__esModule",{value:!0});var t=Math.PI;function n(e){for(var n=e*180/t;n<0;)n+=360;for(;n>360;)n-=360;return n}function r(e){for(var n=t*e/180;n<0;)n+=2*t;for(;n>2*t;)n-=2*t;return n}e.fromRadian=n,e.toRadian=r})),Gr=s((e=>{Object.defineProperty(e,"__esModule",{value:!0});var t=Math.round;function n(e){return e[0]==`#`&&(e=e.slice(1)),e.length<6&&(e=e.split(``).map(function(e){return e+e}).join(``)),e.match(/../g).map(function(e){return parseInt(e,16)/255})}function r(e){return`#`+e.map(function(e){return e=t(255*e).toString(16),e.length<2&&(e=`0`+e),e}).join(``)}e.fromHex=n,e.toHex=r})),Kr=s(((e,t)=>{Object.defineProperty(e,"__esModule",{value:!0});var n=o(Ur()),r=a(Vr()),i=a(Hr());function a(e){return e&&e.__esModule?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function s(){var e=arguments.length<=0||arguments[0]===void 0?i.default.sRGB:arguments[0],t=arguments.length<=1||arguments[1]===void 0?r.default.D65:arguments[1],a=[e.r,e.g,e.b],o=n.transpose(a.map(function(e){return[e.x/e.y,1,(1-e.x-e.y)/e.y]})),s=e.gamma,c=n.multiply(n.inverse(o),t),l=n.scalar(o,c),u=n.inverse(l);return{fromRgb:function(e){return n.multiply(l,e.map(s.decode))},toRgb:function(e){return n.multiply(u,e).map(s.encode)}}}e.default=s,t.exports=e.default})),qr=s(((e,t)=>{t.exports={illuminant:Vr(),workspace:Hr(),matrix:Ur(),degree:Wr(),rgb:Gr(),xyz:Kr()}})),Jr=s((e=>{Object.defineProperty(e,"__esModule",{value:!0}),e.cfs=e.distance=e.lerp=e.corLerp=void 0;var t=Br();function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ti/2&&(e>t?t+=i:e+=i),((1-n)*e+n*t)%(i||1/0)}function u(e,t,n){var r={};for(var i in e)r[i]=l(e[i],t[i],n,i);return r}function d(e,t){var n=0;for(var r in e)n+=o(e[r]-t[r],2);return s(n)}function f(e){return t.merge.apply(void 0,r(e.split(``).map(function(e){return n({},e,!0)})))}e.corLerp=l,e.lerp=u,e.distance=d,e.cfs=f})),Yr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,"__esModule",{value:!0});var r=qr(),i=Jr();function a(e,t){var a=arguments.length<=2||arguments[2]===void 0?1e-6:arguments[2],o=-a,s=1+a,c=Math,l=c.min,u=c.max,d=n([`000`,`fff`].map(function(n){return t.fromXyz(e.fromRgb(r.rgb.fromHex(n)))}),2),f=d[0],p=d[1];function m(n){var r=e.toRgb(t.toXyz(n));return[r.map(function(e){return e>=o&&e<=s}).reduce(function(e,t){return e&&t},!0),r]}function h(e,t){for(var r=arguments.length<=2||arguments[2]===void 0?.001:arguments[2];(0,i.distance)(e,t)>r;){var a=(0,i.lerp)(e,t,.5);n(m(a),1)[0]?e=a:t=a}return e}function g(e){return(0,i.lerp)(f,p,e)}function _(e){return e.map(function(e){return u(o,l(s,e))})}return{contains:m,limit:h,spine:g,crop:_}}e.default=a,t.exports=e.default})),Xr=s((e=>{var t=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,"__esModule",{value:!0}),e.toNotation=e.fromNotation=e.toHue=e.fromHue=void 0;var n=Jr(),r=Math.floor,i=[{s:`R`,h:20.14,e:.8,H:0},{s:`Y`,h:90,e:.7,H:100},{s:`G`,h:164.25,e:1,H:200},{s:`B`,h:237.53,e:1.2,H:300},{s:`R`,h:380.14,e:.8,H:400}],a=i.map(function(e){return e.s}).slice(0,-1).join(``);function o(e){e50){var o=[n,t];t=o[0],n=o[1],i=100-i}return i<1?a[t]:a[t]+i.toFixed()+a[n]}e.fromHue=o,e.toHue=s,e.fromNotation=l,e.toNotation=u})),Zr=s(((e,t)=>{var n=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o=e[Symbol.iterator](),s;!(r=(s=o.next()).done)&&(n.push(s.value),!(t&&n.length===t));r=!0);}catch(e){i=!0,a=e}finally{try{!r&&o.return&&o.return()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw TypeError(`Invalid attempt to destructure non-iterable instance`)}}();Object.defineProperty(e,"__esModule",{value:!0});var r=qr(),i=s(Xr()),a=Jr(),o=Br();function s(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}var c=Math,l=c.pow,u=c.sqrt,d=c.exp,f=c.abs,p=c.sign,m=Math,h=m.sin,g=m.cos,_=m.atan2,v={average:{F:1,c:.69,N_c:1},dim:{F:.9,c:.59,N_c:.9},dark:{F:.8,c:.535,N_c:.8}},y=[[.7328,.4296,-.1624],[-.7036,1.6975,.0061],[.003,.0136,.9834]],b=[[.38971,.68898,-.07868],[-.22981,1.1834,.04641],[0,0,1]],x=y,S=r.matrix.inverse(y),C=r.matrix.product(b,r.matrix.inverse(y)),w=r.matrix.product(y,r.matrix.inverse(b)),T={whitePoint:r.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ee=(0,a.cfs)(`QJMCshH`),E=(0,a.cfs)(`JCh`);function D(){var e=arguments.length<=0||arguments[0]===void 0?{}:arguments[0],t=arguments.length<=1||arguments[1]===void 0?ee:arguments[1];e=(0,o.merge)(T,e);var a=e.whitePoint,s=e.adaptingLuminance,c=e.backgroundLuminance,m=v[e.surroundType],b=m.F,D=m.c,O=m.N_c,te=a[1],k=1/(5*s+1),A=.2*l(k,4)*5*s+.1*l(1-l(k,4),2)*l(5*s,1/3),ne=c/te,re=.725*l(1/ne,.2),ie=re,ae=1.48+u(ne),oe=e.discounting?1:b*(1-1/3.6*d(-(s+42)/92)),j=n(r.matrix.multiply(y,a).map(function(e){return oe*te/e+1-oe}),3),se=j[0],M=j[1],ce=j[2],N=pe(de(le(a)));function le(e){var t=n(r.matrix.multiply(x,e),3),i=t[0],a=t[1],o=t[2];return[se*i,M*a,ce*o]}function ue(e){var t=n(e,3),i=t[0],a=t[1],o=t[2];return r.matrix.multiply(S,[i/se,a/M,o/ce])}function de(e){return r.matrix.multiply(C,e).map(function(e){var t=l(A*f(e)/100,.42);return p(e)*400*t/(27.13+t)+.1})}function fe(e){return r.matrix.multiply(w,e.map(function(e){var t=e-.1;return p(t)*100/A*l(27.13*f(t)/(400-f(t)),1/.42)}))}function pe(e){var t=n(e,3),r=t[0],i=t[1],a=t[2];return(r*2+i+a/20-.305)*re}function me(e){return 4/D*u(e/100)*(N+4)*l(A,.25)}function he(e){return 6.25*l(D*e/((N+4)*l(A,.25)),2)}function ge(e){return e*l(A,.25)}function _e(e,t){return l(e/100,2)*t/l(A,.25)}function ve(e){return e/l(A,.25)}function ye(e,t){return 100*u(e/t)}function be(e,t){var n=t.Q,r=t.J,a=t.M,o=t.C,s=t.s,c=t.h,l=t.H,u={};return e.J&&(u.J=isNaN(r)?he(n):r),e.C&&(isNaN(o)?isNaN(a)?(n=isNaN(n)?me(r):n,u.C=_e(s,n)):u.C=ve(a):u.C=t.C),e.h&&(u.h=isNaN(c)?i.toHue(l):c),e.Q&&(u.Q=isNaN(n)?me(r):n),e.M&&(u.M=isNaN(a)?ge(o):a),e.s&&(isNaN(s)?(n=isNaN(n)?me(r):n,a=isNaN(a)?ge(o):a,u.s=ye(a,n)):u.s=s),e.H&&(u.H=isNaN(l)?i.fromHue(c):l),u}function P(e){var i=de(le(e)),a=n(i,3),o=a[0],s=a[1],c=a[2],d=o-s*12/11+c/11,f=(o+s-2*c)/9,p=_(f,d),m=r.degree.fromRadian(p),h=1/4*(g(p+2)+3.8),v=100*l(pe(i)/N,D*ae);return be(t,{J:v,C:l(5e4/13*O*ie*h*u(d*d+f*f)/(o+s+21/20*c),.9)*u(v/100)*l(1.64-l(.29,ne),.73),h:m})}function F(e){var t=be(E,e),n=t.J,i=t.C,a=t.h,o=r.degree.toRadian(a),s=l(i/(u(n/100)*l(1.64-l(.29,ne),.73)),10/9),c=1/4*(g(o+2)+3.8),d=N*l(n/100,1/D/ae),p=5e4/13*O*ie*c/s,m=d/re+.305,_=m*61/20*460/1403,v=61/20*220/1403,y=21/20*6300/1403-27/1403,b=h(o),x=g(o),S,C;return s===0||isNaN(s)?S=C=0:f(b)>=f(x)?(C=_/(p/b+v*x/b+y),S=C*x/b):(S=_/(p/x+v+y*b/x),C=S*b/x),ue(fe([20/61*m+451/1403*S+288/1403*C,20/61*m-891/1403*S-261/1403*C,20/61*m-220/1403*S-6300/1403*C]))}return{fromXyz:P,toXyz:F,fillOut:be}}e.default=D,t.exports=e.default})),Qr=s(((e,t)=>{Object.defineProperty(e,"__esModule",{value:!0});var n=qr(),r=Math,i=r.sqrt,a=r.pow,o=r.exp,s=r.log,c=r.cos,l=r.sin,u=r.atan2,d={LCD:{K_L:.77,c_1:.007,c_2:.0053},SCD:{K_L:1.24,c_1:.007,c_2:.0363},UCS:{K_L:1,c_1:.007,c_2:.0228}};function f(){var e=d[arguments.length<=0||arguments[0]===void 0?`UCS`:arguments[0]],t=e.K_L,r=e.c_1,f=e.c_2;function p(e){var t=e.J,i=e.M,a=e.h,o=n.degree.toRadian(a),u=(1+100*r)*t/(1+r*t),d=1/f*s(1+f*i);return{J_p:u,a_p:d*c(o),b_p:d*l(o)}}function m(e){var t=e.J_p,s=e.a_p,c=e.b_p,l=-t/(r*t-100*r-1),d=(o(f*i(a(s,2)+a(c,2)))-1)/f,p=u(c,s);return{J:l,M:d,h:n.degree.fromRadian(p)}}function h(e,n){return i(a((e.J_p-n.J_p)/t,2)+a(e.a_p-n.a_p,2)+a(e.b_p-n.b_p,2))}return{fromCam:p,toCam:m,distance:h}}e.default=f,t.exports=e.default})),$r=s(((e,t)=>{var n=Jr(),r=Yr(),i=Zr(),a=Qr(),o=Xr();t.exports={gamut:r,cfs:n.cfs,lerp:n.lerp,cam:i,ucs:a,hq:o}})),ei=l(qr(),1),ti=l($r(),1);function ni(e){let t=new q;return t.rgb_r=e[0],t.rgb_g=e[1],t.rgb_b=e[2],t.rgbToHsluv(),[t.hsluv_h,t.hsluv_s,t.hsluv_l]}function ri(e){let t=new q;return t.hsluv_h=e[0],t.hsluv_s=e[1],t.hsluv_l=e[2],t.hsluvToRgb(),[t.rgb_r,t.rgb_g,t.rgb_b]}var ii=ti.default.cam({whitePoint:ei.default.illuminant.D65,adaptingLuminance:40,backgroundLuminance:20,surroundType:`average`,discounting:!1},ti.default.cfs(`JCh`)),ai=ei.default.xyz(ei.default.workspace.sRGB,ei.default.illuminant.D65),oi=e=>ai.toRgb(ii.toXyz({J:e[0],C:e[1],h:e[2]})),si=e=>{let t=ii.fromXyz(ai.fromRgb(e));return[t.J,t.C,t.h]},[ci,li]=(()=>{let e={k_l:1,c1:.007,c2:.0228},t=Math.PI,n=64/t/5,r=1/(5*n+1),i=.2*r**4*(5*n)+.1*(1-r**4)**2*(5*n)**(1/3);return[n=>{let[r,a,o]=n,s=a*i**.25,c=(1+100*e.c1)*r/(1+e.c1*r);c/=e.k_l;let l=1/e.c2*Math.log(1+e.c2*s),u=l*Math.cos(t/180*o),d=l*Math.sin(t/180*o);return[c,u,d]},n=>{let[r,a,o]=n,s=Math.sqrt(a*a+o*o),c=(Math.exp(s*e.c2)-1)/e.c2,l=(180/t*Math.atan2(o,a)+360)%360,u=c/i**.25;return[r/(1+e.c1*(100-r)),u,l]}]})(),ui=e=>oi(li(e)),di=e=>ci(si(e)),fi=console;fi.color=(e,t=``)=>{let n=K(e).luminance();fi.log(`%c${e} ${t}`,`background-color: ${e};padding: 5px; border-radius: 5px; color: ${n>.5?`#000`:`#fff`}`)},fi.ramp=(e,t=1)=>{fi.log(`%c `,`font-size: 1px;line-height: 16px;background: ${K.getCSSGradient(e,t)};padding: 0 0 0 200px; border-radius: 2px;`)};var pi=(e,t,n,r,i,a,o=.1)=>{if(e===n||t===r)return!0;let s=(r-t)/(n-e),c=(a+i/s-t+s*e)/(s+1/s),l=a+i/s-c/s;return(i-c)**2+(a-l)**2{let i=(t[0]+n[0])/2,a=e(i);return pi(...t,...n,i,a,r)?null:[i,a]},hi=(e,t,n,r=.1)=>{let i=(n-t)/10,a=[];for(let r=t;rMath.round(e*10**t)/10**t,_i=(e,t=1,n=90,r=.005)=>{let i=hi(t=>e(t).gl()[0],0,t,r),a=hi(t=>e(t).gl()[1],0,t,r),o=hi(t=>e(t).gl()[2],0,t,r);return`linear-gradient(${n}deg, ${Array.from(new Set([...i.map(e=>gi(e[0])),...a.map(e=>gi(e[0])),...o.map(e=>gi(e[0]))].sort((e,t)=>e-t))).map(t=>`${e(t).hex()} ${gi(t*100)}%`).join()});`},vi=e=>{e.Color.prototype.jch=function(){return si(this._rgb.slice(0,3).map(e=>e/255))},e.jch=(...t)=>new e.Color(...oi(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.jab=function(){return di(this._rgb.slice(0,3).map(e=>e/255))},e.jab=(...t)=>new e.Color(...ui(t).map(e=>Math.floor(e*255)),`rgb`),e.Color.prototype.hsluv=function(){return ni(this._rgb.slice(0,3).map(e=>e/255))},e.hsluv=(...t)=>new e.Color(...ri(t).map(e=>Math.floor(e*255)),`rgb`);let t=e.interpolate,n={jch:si,jab:di,hsluv:ni},r=(e,t,n)=>(Math.abs(e-t)>360/2&&(e>t?t+=360:e+=360),((1-n)*e+n*t)%360);e.interpolate=(i,a,o=.5,s=`lrgb`)=>{if(n[s]){typeof i!=`object`&&(i=new e.Color(i)),typeof a!=`object`&&(a=new e.Color(a));let t=n[s](i.gl()),c=n[s](a.gl()),l=Number.isNaN(i.hsl()[0]),u=Number.isNaN(a.hsl()[0]),d,f,p;switch(s){case`hsluv`:t[1]<1e-10&&(t[0]=c[0]),t[1]===0&&(t[1]=c[1]),c[1]<1e-10&&(c[0]=t[0]),c[1]===0&&(c[1]=t[1]),d=r(t[0],c[0],o),f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o;break;case`jch`:l&&(t[2]=c[2]),u&&(c[2]=t[2]),d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=r(t[2],c[2],o);break;default:d=t[0]+(c[0]-t[0])*o,f=t[1]+(c[1]-t[1])*o,p=t[2]+(c[2]-t[2])*o}return e[s](d,f,p).alpha(i.alpha()+o*(a.alpha()-i.alpha()))}return t(i,a,o,s)},e.getCSSGradient=_i},X={mainTRC:2.4,get mainTRCencode(){return 1/this.mainTRC},sRco:.2126729,sGco:.7151522,sBco:.072175,normBG:.56,normTXT:.57,revTXT:.62,revBG:.65,blkThrs:.022,blkClmp:1.414,scaleBoW:1.14,scaleWoB:1.14,loBoWoffset:.027,loWoBoffset:.027,deltaYmin:5e-4,loClip:.1,mFactor:1.9468554433171,get mFactInv(){return 1/this.mFactor},mOffsetIn:.0387393816571401,mExpAdj:.283343396420869,get mExp(){return this.mExpAdj/this.blkClmp},mOffsetOut:.312865795870758};function yi(e,t,n=-1){let r=[0,1.1];if(isNaN(e)||isNaN(t)||Math.min(e,t)r[1])return 0;let i=0,a=0,o=`BoW`;return e=e>X.blkThrs?e:e+(X.blkThrs-e)**+X.blkClmp,t=t>X.blkThrs?t:t+(X.blkThrs-t)**+X.blkClmp,Math.abs(t-e)e?(i=(t**+X.normBG-e**+X.normTXT)*X.scaleBoW,a=i-X.loClip?0:i+X.loWoBoffset),n<0?a*100:n==0?Math.round(Math.abs(a)*100)+``+o+``:Number.isInteger(n)?(a*100).toFixed(n):0)}function bi(e=[0,0,0]){function t(e){return(e/255)**X.mainTRC}return X.sRco*t(e[0])+X.sGco*t(e[1])+X.sBco*t(e[2])}var xi=(e,t,n,r,i,a,o,s,c)=>{let l=1-c,u=l*l,d=u*l,f=c*c*c;return{x:d*e+u*3*c*n+l*3*c*c*i+f*o,y:d*t+u*3*c*r+l*3*c*c*a+f*s}},Si=(e,t)=>{let n=[],r={x:+e[0],y:+e[1]};for(let i=0,a=e.length;a-2*!t>i;i+=2){let o=[{x:+e[i-2],y:+e[i-1]},{x:+e[i],y:+e[i+1]},{x:+e[i+2],y:+e[i+3]},{x:+e[i+4],y:+e[i+5]}];t?i?a-4===i?o[3]={x:+e[0],y:+e[1]}:a-2===i&&(o[2]={x:+e[0],y:+e[1]},o[3]={x:+e[2],y:+e[3]}):o[0]={x:+e[a-2],y:+e[a-1]}:a-4===i?o[3]=o[2]:i||(o[0]={x:+e[i],y:+e[i+1]}),n.push([r.x,r.y,(-o[0].x+6*o[1].x+o[2].x)/6,(-o[0].y+6*o[1].y+o[2].y)/6,(o[1].x+6*o[2].x-o[3].x)/6,(o[1].y+6*o[2].y-o[3].y)/6,o[2].x,o[2].y]),r=o[2]}return n},Ci=(e,t,n,r,i,a,o,s)=>{let c=e,l=t,u=0;for(let d=1;d<5;d++){let{x:f,y:p}=xi(e,t,n,r,i,a,o,s,d/5);u+=Math.hypot(f-c,p-l),c=f,l=p}return u+=Math.hypot(o-c,s-l),u},wi=(e,t,n,r,i,a,o,s)=>{let c=Math.floor(Ci(e,t,n,r,i,a,o,s)*.75),l=[],u=0;for(let d=0;d<=c;d++){let f=xi(e,t,n,r,i,a,o,s,d/c),p=Math.round(f.x);if(l[p]=f.y,p-u>1){let e=l[u],t=l[p];for(let n=u+1;nl[Math.round(e)]||null},Ti={CAM02:`jab`,CAM02p:`jch`,HEX:`hex`,HSL:`hsl`,HSLuv:`hsluv`,HSV:`hsv`,LAB:`lab`,LCH:`lch`,RGB:`rgb`,OKLAB:`oklab`,OKLCH:`oklch`};function Z(e,t=0){let n=10**t;return Math.round(e*n)/n}function Ei(e,t){let n;return n=e>1?(e-1)*t+1:e<-1?(e+1)*t-1:1,Z(n,2)}function Di(e){return K(String(e)).jch()}function Oi(e){return K(String(e)).hsluv()}function ki(e,t,n){let r=[[],[],[]];if(e.forEach((e,n)=>r.forEach((r,i)=>r.push(t[n],e[i]))),n===`hcl`){let e=r[1];for(let t=1;t{let t=[];for(let n=1;n{e[t]=e[n]}),t.length=0;break}if(t.length){let n=K(`#ccc`).jch()[2];t.forEach(t=>{e[t]=n})}t.length=0;for(let n=e.length-1;n>0;n-=2)if(Number.isNaN(e[n]))t.push(n);else{t.forEach(t=>{e[t]=e[n]});break}for(let t=1;tSi(e).map(e=>wi(...e)));return e=>{let t=i.map(t=>{for(let n=0;nr*t**e+i}function ji({swatches:e,colorKeys:t,colorspace:n,colorSpace:r=n??`LAB`,shift:i=1,fullScale:a=!0,smooth:o=!1,distributeLightness:s=`linear`,sortColor:c=!0,asFun:l=!1}={}){n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead.");let u=Ti[r];if(!u)throw Error(`Colorspace “${r}” not supported`);if(!t)throw Error(`Colorkeys missing: returned “${t}”`);let d;if(a)d=t.map(t=>e-e*(K(t).jch()[0]/100)).sort((e,t)=>e-t).concat(e),d.unshift(0);else{let n=t.map(e=>K(e).jch()[0]/100),r=Math.min(...n),i=Math.max(...n);d=n.map(t=>t===0||isNaN((t-r)/(i-r))?0:e-(t-r)/(i-r)*e).sort((e,t)=>e-t)}let f=Ai(i,[1,e],[1,e]);if(f=d.map(e=>Math.max(0,f(e))),d=f,s===`polynomial`){let t=e=>Math.sqrt(Math.sqrt((e**2.25+e**4)/2));d=f.map(t=>t/e).map(n=>t(n)*e)}let p=t.map((e,t)=>({colorKeys:Di(e),index:t})).sort((e,t)=>t.colorKeys[0]-e.colorKeys[0]).map(e=>t[e.index]),m=[],h;if(a){let e=u===`lch`?K.lch(...K(`#fff`).lch()):`#ffffff`,t=u===`lch`?K.lch(...K(`#000`).lch()):`#000000`;m=[e,...p,t]}else m=c?p:t;let g;if(o){let t=m;if(m=m.map(e=>K(String(e))[u]()),u===`hcl`&&m.forEach(e=>{e[1]=Number.isNaN(e[1])?0:e[1]}),u===`jch`)for(let e=0;eh(t))}else h=K.scale(m.map(e=>typeof e==`object`&&e.constructor===K.Color?e:String(e))).domain(d).mode(u);return l?h:(!o||o===!1?h.colors(e):g).filter(e=>e!=null)}function Mi(e,t){let n=[],r={};return Object.keys(e).forEach(n=>{r[e[n][t]]=e[n]}),Object.keys(r).forEach(e=>n.push(r[e])),n}function Ni(e){return Number.isNaN(e)?0:e}function Pi(e,t,n=!1){if(!e)throw Error(`Cannot convert color value of “${e}”`);if(!Ti[t])throw Error(`Cannot convert to colorspace “${t}”`);let r=Ti[t],i=K(String(e))[r]();if(t===`HSL`&&i.pop(),t===`HEX`){if(n){let t=K(String(e)).rgb();return{r:t[0],g:t[1],b:t[2]}}return i}let a={},o=i.map(Ni);o=o.map((e,t)=>{let i=Z(e),o=t;r===`hsluv`&&(o+=2);let s=r.charAt(o);return r===`jch`&&s===`c`&&(s=`C`),a[s===`j`?`J`:s]=i,r in{lab:1,lch:1,jab:1,jch:1}?n||(s===`l`||s===`j`)&&(i+=`%`):r!==`hsluv`&&(s===`s`||s===`l`||s===`v`)&&(a[s]=Z(e,2),n||(i=Z(e*100),i+=`%`)),i});let s=`${r}(${o.join(`, `)})`;return n?a:s}function Fi(e,t,n){let r=[e,t,n].map(e=>(e/=255,e<=.03928?e/12.92:((e+.055)/1.055)**2.4));return r[0]*.2126+r[1]*.7152+r[2]*.0722}function Ii(e,t,n,r=`wcag2`){if(n===void 0){let e=K.rgb(...t).hsluv()[2];n=Z(e/100,2)}if(r===`wcag2`){let r=Fi(e[0],e[1],e[2]),i=Fi(t[0],t[1],t[2]),a=(r+.05)/(i+.05),o=(i+.05)/(r+.05);return n<.5?a>=1?a:-o:a<1?o:a===1?a:-a}else if(r===`wcag3`)return n<.5?yi(bi(e),bi(t))*-1:yi(bi(e),bi(t));else throw Error(`Contrast calculation method ${r} unsupported; use 'wcag2' or 'wcag3'`)}function Li(e,t){if(!e)throw Error(`Array undefined`);if(!Array.isArray(e))throw Error(`Passed object is not an array`);let n=t===`wcag2`?0:1;return Math.min(...e.filter(e=>e>=n))}function Ri(e,t){if(!e)throw Error(`Ratios undefined`);e=e.sort((e,t)=>e-t);let n=Li(e,t),r=e.indexOf(n),i=[],a=e.slice(0,r),o=e.slice(r,e.length);for(let e=0;ee-t),i}var zi=(e,t,n,r,i)=>{let a=3e3,o=ji({swatches:a,colorKeys:e._modifiedKeys,colorspace:e._colorspace,shift:1,smooth:e._smooth,asFun:!0}),s={},c=e=>{if(s[e])return s[e];let r=Ii(K(o(e)).rgb(),t,n,i);return s[e]=r,r},l=e=>{let t=c(0).01&&o;)o--,n/=2,iu.push(o(l(+e)))),u},Q=class{constructor({name:e,colorKeys:t,colorspace:n,colorSpace:r=n??`RGB`,ratios:i,smooth:a=!1,output:o=`HEX`,saturation:s=100}){if(n!==void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),this._name=e,this._colorKeys=t,this._modifiedKeys=t,this._colorspace=r,this._ratios=i,this._smooth=a,this._output=o,this._saturation=s,!this._name)throw Error(`Color missing name`);if(!this._colorKeys)throw Error(`Color Keys are undefined`);if(!Ti[this._colorspace])throw Error(`Colorspace “${r}” not supported`);if(!Ti[this._output])throw Error(`Output “${this._output}” not supported`);for(let e=0;e{let n=K(`${t}`).oklch(),r=n[1]*(this._saturation/100),i=K.oklch(n[0],r,n[2]),a=K.rgb(i).hex();e.push(a)}),this._modifiedKeys=e,this._generateColorScale()}_generateColorScale(){this._colorScale=ji({swatches:3e3,colorKeys:this._modifiedKeys,colorSpace:this._colorspace,shift:1,smooth:this._smooth,asFun:!0})}},Bi=class extends Q{get backgroundColorScale(){return this._backgroundColorScale||this._generateColorScale(),this._backgroundColorScale}_generateColorScale(){Q.prototype._generateColorScale.call(this);let e=ji({swatches:1e3,colorKeys:this._colorKeys,colorspace:this._colorspace,shift:1,smooth:this._smooth});e.push(...this.colorKeys);let t=Mi(e.map((e,t)=>({value:Math.round(Oi(e)[2]),index:t})),`value`).map(t=>e[t.index]);return t.length>=101&&(t.length=100,t.push(`#ffffff`)),this._backgroundColorScale=t.map(e=>Pi(e,this._output)),this._backgroundColorScale}},Vi=class{constructor({colors:e,backgroundColor:t,lightness:n,contrast:r=1,saturation:i=100,output:a=`HEX`,formula:o=`wcag2`}){if(this._output=a,this._colors=e,this._lightness=n,this._saturation=i,this._formula=o,this._setBackgroundColor(t),this._setBackgroundColorValue(),this._contrast=r,!this._colors)throw Error(`No colors are defined`);if(!this._backgroundColor)throw Error(`Background color is undefined`);if(e.forEach(e=>{if(!e.ratios)throw Error(`Color ${e.name}'s ratios are undefined`)}),!Ti[this._output])throw Error(`Output “${a}” not supported`);this._saturation<100&&this._updateColorSaturation(this._saturation),this._findContrastColors(),this._findContrastColorPairs(),this._findContrastColorValues()}set formula(e){this._formula=e,this._findContrastColors()}get formula(){return this._formula}set contrast(e){this._contrast=e,this._findContrastColors()}get contrast(){return this._contrast}set lightness(e){this._lightness=e,this._setBackgroundColor(this._backgroundColor),this._findContrastColors()}get lightness(){return this._lightness}set saturation(e){this._saturation=e,this._updateColorSaturation(e),this._findContrastColors()}get saturation(){return this._saturation}set backgroundColor(e){this._setBackgroundColor(e),this._findContrastColors()}get backgroundColorValue(){return this._backgroundColorValue}get backgroundColor(){return this._backgroundColor}set colors(e){this._colors=e,this._findContrastColors()}get colors(){return this._colors}set addColor(e){this._colors.push(e),this._findContrastColors()}set removeColor(e){let t=this._colors.filter(t=>t.name!==e.name);this._colors=t,this._findContrastColors()}set updateColor(e){if(Array.isArray(e))for(let t=0;tn.name===e[t].color);n=n[0];let r=this._colors.indexOf(n),i=this._colors.filter(n=>n.name!==e[t].color);e[t].name&&(n.name=e[t].name),e[t].colorKeys&&(n.colorKeys=e[t].colorKeys),e[t].ratios&&(n.ratios=e[t].ratios),(e[t].colorSpace!==void 0||e[t].colorspace!==void 0)&&(e[t].colorspace!==void 0&&e[t].colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),n.colorSpace=e[t].colorSpace??e[t].colorspace),e[t].smooth&&(n.smooth=e[t].smooth),n._generateColorScale(),i.splice(r,0,n),this._colors=i}else{let t=this._colors.filter(t=>t.name===e.color);t=t[0];let n=this._colors.indexOf(t),r=this._colors.filter(t=>t.name!==e.color);e.name&&(t.name=e.name),e.colorKeys&&(t.colorKeys=e.colorKeys),e.ratios&&(t.ratios=e.ratios),(e.colorSpace!==void 0||e.colorspace!==void 0)&&(e.colorspace!==void 0&&e.colorSpace===void 0&&console.warn("Leonardo: `colorspace` is deprecated. Use `colorSpace` instead."),t.colorSpace=e.colorSpace??e.colorspace),e.smooth&&(t.smooth=e.smooth),t._generateColorScale(),r.splice(n,0,t),this._colors=r}this._findContrastColors()}set output(e){this._output=e,this._colors.forEach(e=>{e.output=this._output}),this._backgroundColor.output=this._output,this._findContrastColors()}get output(){return this._output}get contrastColors(){return this._contrastColors}get contrastColorPairs(){return this._contrastColorPairs}get contrastColorValues(){return this._contrastColorValues}_setBackgroundColor(e){if(typeof e==`string`){let t=new Bi({name:`background`,colorKeys:[e],output:`RGB`}),n=Z(K(String(e)).hsluv()[2]);this._backgroundColor=t,this._lightness=n,this._backgroundColorValue=t[this._lightness]}else{e.output=`RGB`;let t=e.backgroundColorScale[this._lightness];this._backgroundColor=e,this._backgroundColorValue=t}}_setBackgroundColorValue(){this._backgroundColorValue=this._backgroundColor.backgroundColorScale[this._lightness]}_updateColorSaturation(e){this._colors.map(t=>{t.saturation=e})}_findContrastColors(){let e=K(String(this._backgroundColorValue)).rgb(),t=this._lightness/100,n={background:Pi(this._backgroundColorValue,this._output)},r=[],i=[],a={...n};return r.push(n),this._colors.map(n=>{if(n.ratios!==void 0){let o,s=[],c={name:n.name,values:s},l;Array.isArray(n.ratios)?l=n.ratios:Array.isArray(n.ratios)||(o=Object.keys(n.ratios),l=Object.values(n.ratios)),l=l.map(e=>Ei(+e,this._contrast));let u=zi(n,e,t,l,this._formula).map(e=>Pi(e,this._output));for(let e=0;e{let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return[Number.parseInt(t[1],16),Number.parseInt(t[2],16),Number.parseInt(t[3],16)]},Wi=(e,t,n)=>{let r=e/255,i=t/255,a=n/255,o=Math.min(r,i,a),s=Math.max(r,i,a),c=s-o,l=0,u=0,d=0;return l=c===0?0:s===r?(i-a)/c%6:s===i?(a-r)/c+2:(r-i)/c+4,l=Math.round(l*60),l<0&&(l+=360),d=(s+o)/2,u=c===0?0:c/(1-Math.abs(2*d-1)),u=+(u*100).toFixed(1),d=+(d*100).toFixed(1),[l,u,Math.round(d)]},Gi=(e,t,n,r)=>{let i=n/100,a=t*Math.min(i,1-i)/100,o=t=>{let n=(t+e/30)%12,r=i-a*Math.max(Math.min(n-3,9-n,1),-1);return Math.round(255*r).toString(16).padStart(2,`0`).toUpperCase()},s=o(0),c=o(8),l=o(4),u=((e,t,n)=>Math.min(Math.max(e,t),n))(r,0,1);return`#${s}${c}${l}${Math.round(u*255).toString(16).padStart(2,`0`).toUpperCase()}`},Ki=(e,t,n=1)=>{let r=Ui(e),i=Ui(t===`white`?`#FFFFFF`:t===`black`?`#000000`:t),a=r.map((e,t)=>[(e-i[t])/(255-i[t]),(e-i[t])/(0-i[t])]),o=Hi(Math.max(...a.flat().filter(e=>/^-?\d+\.?\d*$/.test(e)))),s=r.map((e,t)=>Math.round((e-i[t]+i[t]*o)/o));if(s.includes(NaN)){let e=Wi(r[0],r[1],r[2]);return{h:e[0],s:Math.round(e[1]*n),l:e[2],a:1}}let c=Wi(s[0],s[1],s[2]);return{h:c[0],s:Math.round(c[1]*n),l:c[2],a:o}},qi={backgroundColor:`gray`,colorSpace:`OKLCH`,colorSmoothing:!1,formula:`wcag2`,output:`HEX`,colors:{gray:[$(215,20,90),$(215,8,50),$(215,6,25)],red:[$(358,100,58),$(350,100,30)],orange:[$(32,100,48),$(12,100,30)],yellow:[$(50,100,50),$(25,100,20)],lime:[$(100,68,50),$(115,86,25)],green:[$(163,87,42),$(168,100,25)],cyan:[$(185,80,45),$(200,98,35)],blue:[$(212,98,46),$(222,95,25)],purple:[$(258,94,64),$(265,100,35)],fuchsia:[$(295,56,50),$(285,80,25)],pink:[$(334,90,50),$(330,91,25)]},themes:{light:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16.75],contrast:1,lightness:100,saturation:100},dark:{ratios:[1.03,1.06,1.12,1.25,1.5,1.75,2.25,3.5,5.25,6.5,8,10.5,13.75,16],contrast:1,lightness:6,saturation:97},lightHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:100,saturation:100},darkHc:{ratios:[1.06,1.12,1.25,1.37,1.75,2.25,3.25,4.75,8.87,10,11.75,13.25,16,17],contrast:1,lightness:6,saturation:97}}};function $(e,t,n){return K.hsl(e,t/100,n/100).hex()}function Ji(e,t){let n=e.colorSpace,r=e.colorSmoothing,i=e.themes[t].ratios,a=new Bi({name:`gray`,colorKeys:e.colors.gray,colorspace:n,ratios:i,smooth:r}),o=new Q({name:`blue`,colorKeys:e.colors.blue,colorspace:n,ratios:i,smooth:r}),s=new Q({name:`cyan`,colorKeys:e.colors.cyan,colorspace:n,ratios:i,smooth:r}),c=new Q({name:`fuchsia`,colorKeys:e.colors.fuchsia,colorspace:n,ratios:i,smooth:r}),l=new Q({name:`green`,colorKeys:e.colors.green,colorspace:n,ratios:i,smooth:r}),u=new Q({name:`lime`,colorKeys:e.colors.lime,colorspace:n,ratios:i,smooth:r}),d=new Q({name:`orange`,colorKeys:e.colors.orange,colorspace:n,ratios:i,smooth:r}),f=new Q({name:`pink`,colorKeys:e.colors.pink,colorspace:n,ratios:i,smooth:r}),p=new Q({name:`purple`,colorKeys:e.colors.purple,colorspace:n,ratios:i,smooth:r}),m={gray:a,red:new Q({name:`red`,colorKeys:e.colors.red,colorspace:n,ratios:i,smooth:r}),orange:d,yellow:new Q({name:`yellow`,colorKeys:e.colors.yellow,colorspace:n,ratios:i,smooth:r}),lime:u,green:l,cyan:s,blue:o,purple:p,fuchsia:c,pink:f};return e.colors.custom&&(m.custom=new Q({name:`custom`,colorKeys:e.colors.custom,colorspace:n,ratios:i,smooth:r})),new Vi({colors:Object.values(m),backgroundColor:m[e.backgroundColor],contrast:e.themes[t].contrast,lightness:e.themes[t].lightness,saturation:e.themes[t].saturation,output:e.output,formula:e.formula}).contrastColors}function Yi(e){let t={};for(let n of Object.keys(e.themes))t[n]=Ji(e,n);return t}function Xi(e){qi.colors.custom=[e];let t=Yi(qi);return Object.fromEntries(Object.entries(t).map(([e,t])=>{let n=t.find(e=>e&&e.name===`custom`),r=Object.fromEntries(n.values.map(({name:e,value:t})=>[e,t]));for(let[e,n]of Object.entries(r)){let i=Ki(n,t[0].background);r[`alpha${e.charAt(0).toUpperCase()+e.slice(1)}`]=Gi(i.h,i.s,i.l,i.a)}return[e,r]}))}return e.generateCustomColors=Xi,e.generateThemesJson=Yi,e.hslToHex=$,e.leonardoConfig=qi,e})({}); \ No newline at end of file diff --git a/libraries/compound/src/main/res/drawable/ic_compound_crop.xml b/libraries/compound/src/main/res/drawable/ic_compound_crop.xml index dc9513a239..c82f5cb686 100644 --- a/libraries/compound/src/main/res/drawable/ic_compound_crop.xml +++ b/libraries/compound/src/main/res/drawable/ic_compound_crop.xml @@ -4,9 +4,10 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M6,4a1,1 0,0 0,-1 1v2H3a1,1 0,1 0,0 2h2v8a3,3 0,0 0,3 3h8v2a1,1 0,0 0,2 0v-2h2a1,1 0,1 0,0 -2h-2v-8a3,3 0,0 0,-3 -3H7V5a1,1 0,0 0,-1 -1m9,5a1,1 0,0 1,1 1v8H8a1,1 0,0 1,-1 -1V9z" + android:fillColor="#FF000000" + android:fillType="evenOdd"/> From 144e3c6b5d76cc8f6d6c0214f9af2bf33de90f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 16:13:50 +0200 Subject: [PATCH 0616/1083] Adding fastlane file for version 26.06.1 --- fastlane/metadata/android/en-US/changelogs/202606010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202606010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202606010.txt b/fastlane/metadata/android/en-US/changelogs/202606010.txt new file mode 100644 index 0000000000..08c06cf192 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202606010.txt @@ -0,0 +1,2 @@ +Main changes in this version: fixed an issue with devices not supporting Vulkan, added image editing before sending and an option for custom notification sounds, improved start times, several other bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 25264dd3e3b303f4b29c1e9da8b69d293197f1bd Mon Sep 17 00:00:00 2001 From: S1m <31284753+p1gp1g@users.noreply.github.com> Date: Thu, 4 Jun 2026 16:19:52 +0200 Subject: [PATCH 0617/1083] Fallback to the default push gateway on error (#5742) * Add more HTTP response code returning NoMatrixGateway Fix Push notifications with Mozilla's autopush that returns 406 * Update gateway resolver tests to match new known errors * Use default gateway on error if no gateway is recorded yet * Update gateway resolver tests to return default gateway on error --- .../unifiedpush/UnifiedPushGatewayUrlResolver.kt | 5 +++-- .../unifiedpush/DefaultUnifiedPushGatewayUrlResolverTest.kt | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushGatewayUrlResolver.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushGatewayUrlResolver.kt index 78a569a211..1155293567 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushGatewayUrlResolver.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushGatewayUrlResolver.kt @@ -29,8 +29,9 @@ class DefaultUnifiedPushGatewayUrlResolver( ): String { return when (gatewayResult) { is UnifiedPushGatewayResolverResult.Error -> { - // Use previous gateway if any, or the provided one - unifiedPushStore.getPushGateway(instance) ?: gatewayResult.gateway + // Use previous gateway if any, or the default one + unifiedPushStore.getPushGateway(instance) + ?: defaultPushGatewayHttpUrlProvider.provide() } UnifiedPushGatewayResolverResult.ErrorInvalidUrl, UnifiedPushGatewayResolverResult.NoMatrixGateway -> { diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultUnifiedPushGatewayUrlResolverTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultUnifiedPushGatewayUrlResolverTest.kt index 3f437bdafa..664ff26d15 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultUnifiedPushGatewayUrlResolverTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultUnifiedPushGatewayUrlResolverTest.kt @@ -60,7 +60,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest { } @Test - fun `resolve Error returns the url if no current url is available`() { + fun `resolve Error returns the default gateway url if no current url is available`() { val sut = createDefaultUnifiedPushGatewayUrlResolver( unifiedPushStore = FakeUnifiedPushStore( getPushGatewayResult = { instance -> @@ -73,7 +73,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest { gatewayResult = UnifiedPushGatewayResolverResult.Error("aUrl"), instance = "instance", ) - assertThat(result).isEqualTo("aUrl") + assertThat(result).isEqualTo(FakeDefaultPushGatewayHttpUrlProvider().provide()) } private fun createDefaultUnifiedPushGatewayUrlResolver( From 9eed7de7992c1431a3402cdef54820c233d6639d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 4 Jun 2026 14:33:07 +0000 Subject: [PATCH 0618/1083] Update screenshots --- libraries/compound/screenshots/Compound Icons - Dark.png | 4 ++-- libraries/compound/screenshots/Compound Icons - Light.png | 4 ++-- libraries/compound/screenshots/Compound Icons - Rtl.png | 4 ++-- .../compound/screenshots/Compound Vector Icons - Dark.png | 4 ++-- .../compound/screenshots/Compound Vector Icons - Light.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_0_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_1_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_3_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_5_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_7_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_8_en.png | 4 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_9_en.png | 4 ++-- ...raries.designsystem.theme.components_AllIcons_Icons_en.png | 4 ++-- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libraries/compound/screenshots/Compound Icons - Dark.png b/libraries/compound/screenshots/Compound Icons - Dark.png index 1209b824be..6d5057eaac 100644 --- a/libraries/compound/screenshots/Compound Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7511b9256afc6d001b53576959e69549683ab4cb81b49031aeda027d14178aa -size 245703 +oid sha256:78386a58e91be3213485f60909ec8d83cd535aabcec775aadf7b36e77d8542f0 +size 245853 diff --git a/libraries/compound/screenshots/Compound Icons - Light.png b/libraries/compound/screenshots/Compound Icons - Light.png index 58ba1591ed..f4f66317c3 100644 --- a/libraries/compound/screenshots/Compound Icons - Light.png +++ b/libraries/compound/screenshots/Compound Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83a12b138543be1e17da8aa562bd95d1de18c0093da50d9a14196f905584bf7c -size 258948 +oid sha256:477ab18ffa1ca81ca5e4c9f30f4466b19e14fcaddf641fc860c6be19a0e33d4f +size 259185 diff --git a/libraries/compound/screenshots/Compound Icons - Rtl.png b/libraries/compound/screenshots/Compound Icons - Rtl.png index 06daf04971..d0374a65fb 100644 --- a/libraries/compound/screenshots/Compound Icons - Rtl.png +++ b/libraries/compound/screenshots/Compound Icons - Rtl.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73b37a7cd34f2ffe285011f67c2b38ed5399cbea40b3115c6c5115536f2902f2 -size 260171 +oid sha256:7edeebf9876aecd262fceb7d55a4bfd30a859a69b708af8dd4538ffc0f9be419 +size 260400 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Dark.png b/libraries/compound/screenshots/Compound Vector Icons - Dark.png index 5c95b36a89..0d8e07d9fa 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Dark.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49a9372bea521e4ee948bbd4f7616310c411ee46f84ffd562d9b35bc9bfeb4d9 -size 97239 +oid sha256:cc6cc2d2e89c7460217c2075046e41bef727407ee422dcdea23f161f48441904 +size 97346 diff --git a/libraries/compound/screenshots/Compound Vector Icons - Light.png b/libraries/compound/screenshots/Compound Vector Icons - Light.png index 38764691f4..74b4c859c7 100644 --- a/libraries/compound/screenshots/Compound Vector Icons - Light.png +++ b/libraries/compound/screenshots/Compound Vector Icons - Light.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:add37e4d84f03a33caf1079eaa99631682f5ef6418096629f96433520e519b20 -size 103742 +oid sha256:4df16aee4a3a8b10c33e9724904c72b8dc502725204d2f86cf62cc381b35f4a1 +size 103870 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png index ccca24ef6a..91c617002c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a14113653096095323ecb94cb3dd694985717b8585c8cfc6b7a45cf7a2483a79 -size 402427 +oid sha256:14ad2df78cdd8422279c413e9ed2f709636d09cf04b3ee4ada5b6b53e8e42c8f +size 402328 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png index c511e0e162..74b24f7194 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:95c64e1e7055dd048b88f0e19a57fe696ee93505d74f96bc4f1915fcce769d7d -size 402072 +oid sha256:45ade3f4baaf0b91300a6829fbe42818d754ccca64b1b090195ee40eee744ee9 +size 401973 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png index ccca24ef6a..91c617002c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a14113653096095323ecb94cb3dd694985717b8585c8cfc6b7a45cf7a2483a79 -size 402427 +oid sha256:14ad2df78cdd8422279c413e9ed2f709636d09cf04b3ee4ada5b6b53e8e42c8f +size 402328 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png index f8fbf8c1a1..171ada1369 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccedfe061af8a77da7ddf6b20d23899bfff986fd6c74b87480b588e148ddd8de -size 89013 +oid sha256:c6e4dd5eae99a0454d6918b65baa3ca36c2266abfd9fb37dda961268e55827a9 +size 88994 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png index 5f90adbd8a..c21cab9cb2 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1feeb32f9dce486c54db41727d9d9801f606353008945988331c2ce391dec451 -size 75364 +oid sha256:58ba9fd5edd2aa366b62a0a8880b6a3f6f7142861180c4109ba4904c43101433 +size 75343 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png index d7cdc540f7..42cf04b201 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2bfda29fcaade9508e0d742b0de7ac230d41a358e98755e4b08f1ed7d5affe30 -size 408106 +oid sha256:43a670de0512321ca3e1b5bf0c967c6bd8504df542781c4973c8806b8b95abe9 +size 408029 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png index f06abb6c7b..84cc698a63 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fdc4e2d82297927d2062586398fda3f3b7f6febfde8888a062229caf713ff54 -size 85154 +oid sha256:6c0ef41360eb82092680b5b262bf1ef8449636387124c5aef940a727b3bc6aee +size 85137 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png index 9c80a760b7..fa2208b50f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_AllIcons_Icons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:787bcdf784abedc6858fdab6c7b5dac9e36d42a1047ac0bad181449dbb757585 -size 117936 +oid sha256:de697fcf50bd244978da1143a80f872650a424c3e308fd2c4c66005f30cbf6c5 +size 118141 From d54f10046d7dbf5e9251a1db0f016c63dd1b8c6f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 4 Jun 2026 15:20:23 +0200 Subject: [PATCH 0619/1083] Ensure the video preview can be played several times. Closes #6956 --- .../impl/local/video/MediaVideoView.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt index d89762b72e..21279a598e 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt @@ -33,10 +33,13 @@ import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle import androidx.media3.common.MediaItem +import androidx.media3.common.ParserException +import androidx.media3.common.PlaybackException import androidx.media3.common.Player import androidx.media3.common.Player.STATE_READY import androidx.media3.common.Timeline import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.ExoPlaybackException import androidx.media3.exoplayer.ExoPlayer import androidx.media3.ui.AspectRatioFrameLayout import androidx.media3.ui.PlayerView @@ -158,6 +161,19 @@ private fun ExoPlayerMediaVideoView( isReady = playbackState == STATE_READY, ) } + + override fun onPlayerError(error: PlaybackException) { + super.onPlayerError(error) + Timber.w(error, "Player error") + if (error is ExoPlaybackException && error.cause is ParserException) { + // The cause can be: + // androidx.media3.common.ParserException: Invalid NAL length {contentIsMalformed=true, dataType=1} + // This has been observed when the user wants to play a second time a recorded video. + // Workaround the issue #6956, start the playback again + exoPlayer.prepare() + exoPlayer.play() + } + } } } From e7992bfd403615479ef1c9fb0a6c312f6cceb309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 16:13:28 +0200 Subject: [PATCH 0620/1083] Setting version for the release 26.06.1 --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 69d7791e6b..f87eed1a40 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 6 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** From fb7ad271c91b6288dad9f0f59dd664b35658f311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 16:13:50 +0200 Subject: [PATCH 0621/1083] Adding fastlane file for version 26.06.1 --- fastlane/metadata/android/en-US/changelogs/202606010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202606010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202606010.txt b/fastlane/metadata/android/en-US/changelogs/202606010.txt new file mode 100644 index 0000000000..08c06cf192 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202606010.txt @@ -0,0 +1,2 @@ +Main changes in this version: fixed an issue with devices not supporting Vulkan, added image editing before sending and an option for custom notification sounds, improved start times, several other bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 488e5d1e3a5327143748207735cccf6beadbbcff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 4 Jun 2026 16:55:52 +0200 Subject: [PATCH 0622/1083] Changelog for version 26.06.1 --- CHANGES.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 9775c2fea5..f24c813de7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,92 @@ +Changes in Element X v26.06.1 +============================= + +The release of `v26.06.0` was cancelled because it contained some changes that would prevent some users with devices having no Vulkan support from being able to install the app. This release contains the same changes as `v26.06.0` but with the Vulkan requirement removed. + +## What's Changed +### ✨ Features +* Image edition before sending: crop and rotate. by @bmarty in https://github.com/element-hq/element-x-android/pull/6842 +* Use a raw key for the SDK stores for new sessions by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6835 +* Notification settings: pick custom sounds for messages and call ringtones by @bmarty in https://github.com/element-hq/element-x-android/pull/6897 +### 🙌 Improvements +* Do not show membership/profile events in public rooms by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6360 +* Use `runBlocking` for the token refresh logic by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6863 +* Move empty day separator filtering to a timeline post-processor by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6866 +* Add better logs to track token update failures by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6859 +* Read map tiler custom style from matrix .well-known file by @bmarty in https://github.com/element-hq/element-x-android/pull/6886 +* change(permissions) : allow to change ShareLiveLocation permission by @ganfra in https://github.com/element-hq/element-x-android/pull/6890 +* Avoid SQLCipher key derivation by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6774 +* change: replace the maplibre-compose UserLocationState to a simpler one by @ganfra in https://github.com/element-hq/element-x-android/pull/6913 +* Change : location provider by @ganfra in https://github.com/element-hq/element-x-android/pull/6935 +* Add flip actions to image edition by @bmarty in https://github.com/element-hq/element-x-android/pull/6949 +* Remove the `FloatingDateBadge` feature flag by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6950 +### 🐛 Bugfixes +* Fix media viewer flickering by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6800 +* Fix 'Conversation label cannot be empty' error by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6823 +* Release proximity wakelock on Element Call when call ends by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6825 +* Hide edit pencil from accessibility by @bmarty in https://github.com/element-hq/element-x-android/pull/6826 +* Don't compress images sent through the Files attachment picker by @cizra in https://github.com/element-hq/element-x-android/pull/6755 +* [a11y] Improve accessibility of video and audio player by @bmarty in https://github.com/element-hq/element-x-android/pull/6830 +* [a11y] Improve accessibility of screen headers. by @bmarty in https://github.com/element-hq/element-x-android/pull/6827 +* Add mark as read / unread in room details by @bmarty in https://github.com/element-hq/element-x-android/pull/6818 +* Fix formatting inconsistencies in latest event summaries by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6855 +* Fix public read receipts being sent by mistake by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6838 +* Fix app having a pink top bar in the recent app list when PIN lock is setup by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6903 +* Create log messages from `WebView` just once by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6923 +* Use secondary color icon for leading icons by @bmarty in https://github.com/element-hq/element-x-android/pull/6926 +* Use reverse ordering for `FilterEmptyDayPostProcessor` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6927 +* Make Vulkan a *not required* feature by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6961 +### 🗣 Translations +* Sync Strings - new translations to Catalan by @ElementBot in https://github.com/element-hq/element-x-android/pull/6856 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6921 +### 🧱 Build +* Remove DI-generated code from Kover reports by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6834 +* Disable cron jobs and private SSH key jobs in forks by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6821 +* Revert "Disable cron jobs and private SSH key jobs in forks" by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6905 +* Downgrade detekt compose rules by @bmarty in https://github.com/element-hq/element-x-android/pull/6846 +* Add Stefan's etiquette to the project. by @bmarty in https://github.com/element-hq/element-x-android/pull/6909 +### 🚧 In development 🚧 +* [Link new device] Rotate QrCode instead of showing an error by @bmarty in https://github.com/element-hq/element-x-android/pull/6817 +* Fix image resizing behavior. by @bmarty in https://github.com/element-hq/element-x-android/pull/6924 +### Dependency upgrades +* Update dependency net.zetetic:sqlcipher-android to v4.16.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6819 +* Update dependencyAnalysis to v3.11.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6813 +* Update metro to v1.1.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6832 +* Update dependency io.element.android:element-call-embedded to v0.19.4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6833 +* Update kotlin to v2.3.8 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6822 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.20 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6831 +* Update media3 to v1.10.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6816 +* Update peaceiris/actions-gh-pages action to v4.1.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6820 +* Update dependencyAnalysis to v3.12.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6840 +* Update codecov/codecov-action action to v6.0.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6864 +* Update dependency io.element.android:element-call-embedded to v0.20.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6876 +* Update roborazzi to v1.62.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6858 +* Update dependency androidx.compose:compose-bom to v2026.05.01 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6888 +* Update roborazzi to v1.63.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6893 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.26 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6885 +* Update dependency org.maplibre.compose:maplibre-compose to v0.13.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6891 +* Update actions/stale action to v10.3.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6904 +* Update tspascoal/get-user-teams-membership action to v4.0.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6900 +* Update dependency org.maplibre.gl:android-sdk to v13.2.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6930 +* Update dependency org.unifiedpush.android:connector to v3.3.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6937 +* Update kotlin to v2.3.9 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6946 +* Update dependency com.posthog:posthog-android to v3.47.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6920 +* Import compound token from release 10.2.1 https://github.com/element-hq/compound-design-tokens/releases/tag/v10.2.1 by @bmarty in https://github.com/element-hq/element-x-android/pull/6942 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.06.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6947 +* Update dependency com.github.matrix-org:matrix-analytics-events to v0.36.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6939 +### Others +* Make the avatar in the room member moderation bottom sheet clickable by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6705 +* Do not hide your own media for "Show media in timeline" by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6898 +* Report problem: add an optional TextField to provide a GitHub issue number. by @bmarty in https://github.com/element-hq/element-x-android/pull/6911 +* Fix read receipts not shown for calls by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6889 +* Reorder room detail items by @bmarty in https://github.com/element-hq/element-x-android/pull/6929 +* [Media viewer] File preview improvement by @bmarty in https://github.com/element-hq/element-x-android/pull/6933 +* [Media bottom sheet] UI iteration by @bmarty in https://github.com/element-hq/element-x-android/pull/6938 +* Add unread count to the room unread indicator by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6887 + + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.05.2...v26.06.1 + Changes in Element X v26.05.2 ============================= From 8722305e124249e6769fa37902f76feed55f5f37 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Thu, 4 Jun 2026 09:41:55 -0700 Subject: [PATCH 0623/1083] Update strings for ios parity --- .../impl/setup/SecureBackupSetupView.kt | 52 +++++++++---------- .../impl/src/main/res/values/temporary.xml | 52 +++++++++---------- 2 files changed, 50 insertions(+), 54 deletions(-) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupView.kt index 2d086c8cf5..0f8bf7d043 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupView.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.autofill.ContentType import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.lerp import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentType @@ -149,8 +148,8 @@ private fun title(state: SecureBackupSetupState): String { // Custom flow has no "save your key" step — use per-step custom titles throughout. if (state.isCustomEntry()) { return when (state.customEntryStep) { - CustomEntryStep.Entry -> stringResource(id = R.string.screen_recovery_key_custom_title) - CustomEntryStep.Confirm -> stringResource(id = R.string.screen_recovery_key_custom_confirm_title) + CustomEntryStep.Entry -> stringResource(id = R.string.pro_screen_recovery_key_mode_input_title) + CustomEntryStep.Confirm -> stringResource(id = R.string.pro_screen_recovery_key_mode_confirm_title) } } return when (state.setupState) { @@ -171,8 +170,8 @@ private fun subtitle(state: SecureBackupSetupState): String? { if (!state.wellknownLoaded) return null if (state.isCustomEntry()) { return when (state.customEntryStep) { - CustomEntryStep.Entry -> stringResource(id = R.string.screen_recovery_key_custom_description) - CustomEntryStep.Confirm -> stringResource(id = R.string.screen_recovery_key_custom_confirm_description) + CustomEntryStep.Entry -> stringResource(id = R.string.pro_screen_recovery_key_mode_input_description) + CustomEntryStep.Confirm -> stringResource(id = R.string.pro_screen_recovery_key_mode_confirm_description) } } return when (state.setupState) { @@ -295,9 +294,8 @@ private fun CustomPassphraseEntry(state: SecureBackupSetupState) { } }, ), - supportingText = pluralStringResource( - id = R.plurals.screen_recovery_key_custom_requirement_length, - count = specs.minCharacterCount, + supportingText = stringResource( + id = R.string.pro_screen_recovery_key_mode_input_passphrase_field_footer, specs.minCharacterCount, ), ) @@ -317,7 +315,7 @@ private fun PassphraseStrengthIndicator( modifier: Modifier = Modifier, ) { val label = stringResource( - id = result?.strength?.labelRes() ?: R.string.screen_recovery_key_custom_strength_base, + id = result?.strength?.labelRes() ?: R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_base, ) val hint = result?.strength?.hintRes()?.let { stringResource(id = it) } val score = result?.score ?: 0f @@ -354,25 +352,25 @@ private fun PassphraseStrengthIndicator( } private fun CustomRecoveryPassphraseStrength.labelRes(): Int = when (this) { - CustomRecoveryPassphraseStrength.Garbage -> R.string.screen_recovery_key_custom_strength_garbage - CustomRecoveryPassphraseStrength.Weak -> R.string.screen_recovery_key_custom_strength_weak - CustomRecoveryPassphraseStrength.Moderate -> R.string.screen_recovery_key_custom_strength_moderate - CustomRecoveryPassphraseStrength.Okay -> R.string.screen_recovery_key_custom_strength_okay - CustomRecoveryPassphraseStrength.Strong -> R.string.screen_recovery_key_custom_strength_strong - CustomRecoveryPassphraseStrength.VeryStrong -> R.string.screen_recovery_key_custom_strength_very_strong - CustomRecoveryPassphraseStrength.UltraStrong -> R.string.screen_recovery_key_custom_strength_ultra_strong - CustomRecoveryPassphraseStrength.Mega -> R.string.screen_recovery_key_custom_strength_mega + CustomRecoveryPassphraseStrength.Garbage -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_garbage + CustomRecoveryPassphraseStrength.Weak -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_weak + CustomRecoveryPassphraseStrength.Moderate -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_moderate + CustomRecoveryPassphraseStrength.Okay -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_okay + CustomRecoveryPassphraseStrength.Strong -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_strong + CustomRecoveryPassphraseStrength.VeryStrong -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_very_strong + CustomRecoveryPassphraseStrength.UltraStrong -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_ultra_strong + CustomRecoveryPassphraseStrength.Mega -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_mega } private fun CustomRecoveryPassphraseStrength.hintRes(): Int = when (this) { - CustomRecoveryPassphraseStrength.Garbage -> R.string.screen_recovery_key_custom_strength_hint_garbage - CustomRecoveryPassphraseStrength.Weak -> R.string.screen_recovery_key_custom_strength_hint_weak - CustomRecoveryPassphraseStrength.Moderate -> R.string.screen_recovery_key_custom_strength_hint_moderate - CustomRecoveryPassphraseStrength.Okay -> R.string.screen_recovery_key_custom_strength_hint_okay - CustomRecoveryPassphraseStrength.Strong -> R.string.screen_recovery_key_custom_strength_hint_strong - CustomRecoveryPassphraseStrength.VeryStrong -> R.string.screen_recovery_key_custom_strength_hint_very_strong - CustomRecoveryPassphraseStrength.UltraStrong -> R.string.screen_recovery_key_custom_strength_hint_ultra_strong - CustomRecoveryPassphraseStrength.Mega -> R.string.screen_recovery_key_custom_strength_hint_mega + CustomRecoveryPassphraseStrength.Garbage -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_garbage + CustomRecoveryPassphraseStrength.Weak -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_weak + CustomRecoveryPassphraseStrength.Moderate -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_moderate + CustomRecoveryPassphraseStrength.Okay -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_okay + CustomRecoveryPassphraseStrength.Strong -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_strong + CustomRecoveryPassphraseStrength.VeryStrong -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_very_strong + CustomRecoveryPassphraseStrength.UltraStrong -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_ultra_strong + CustomRecoveryPassphraseStrength.Mega -> R.string.pro_screen_recovery_key_mode_input_passphrase_strength_label_hint_mega } // Stops mirror iOS PasswordStrengthBar.gradient: Compound red900 / lime700 with the same vivid @@ -439,7 +437,7 @@ private fun CustomPassphraseConfirm(state: SecureBackupSetupState) { ), validity = if (state.customPassphraseMismatch) TextFieldValidity.Invalid else TextFieldValidity.None, supportingText = if (state.customPassphraseMismatch) { - stringResource(id = R.string.screen_recovery_key_custom_mismatch) + stringResource(id = R.string.pro_screen_recovery_key_mode_custom_mismatch) } else { null }, @@ -491,7 +489,7 @@ private fun ColumnScope.CustomButtons( } CustomEntryStep.Confirm -> { Button( - text = stringResource(id = R.string.screen_recovery_key_custom_finish_action), + text = stringResource(id = R.string.pro_screen_recovery_key_mode_confirm_finish_button), enabled = state.canSubmitCustomPassphrase, modifier = Modifier.fillMaxWidth(), onClick = { state.eventSink.invoke(SecureBackupSetupEvents.SubmitCustomPassphrase) }, diff --git a/features/securebackup/impl/src/main/res/values/temporary.xml b/features/securebackup/impl/src/main/res/values/temporary.xml index 3edbd84d73..c573a4c6e3 100644 --- a/features/securebackup/impl/src/main/res/values/temporary.xml +++ b/features/securebackup/impl/src/main/res/values/temporary.xml @@ -5,33 +5,31 @@ ~ Please see LICENSE files in the repository root for full details. --> - Enter a custom recovery key - Choose a recovery key that you can memorize. - Confirm your recovery key - Enter your recovery key again. - The recovery key you entered doesn\'t match - - Minimum %1$d character - Minimum %1$d characters - - Finish setup - Strength - Garbage - Weak - Moderate - Okay - Strong - Very strong - Super strong - Ideal - Cracking would take roughly milliseconds. - Cracking would take roughly minutes to months. - Cracking would take roughly years. - Cracking would take roughly hundreds of years. - Cracking would take roughly billions of years. - Cracking would take roughly trillions of years. - Cracking would take roughly quadrillions of years. - Cracking would take roughly quintillions of years. + Enter a recovery key + Choose a recovery key that you can memorize. + Confirm your recovery key + Enter your recovery key again. + Minimum %1$s characters + Finish setup + Strength + Garbage + Weak + Moderate + Okay + Strong + Very Strong + Super Strong + Ideal + Cracking would take roughly milliseconds. + Cracking would take roughly minutes to months. + Cracking would take roughly years. + Cracking would take roughly hundreds of years. + Cracking would take roughly billions of years. + Cracking would take roughly trillions of years. + Cracking would take roughly quadrillions of years. + Cracking would take roughly quintillions of years. + + The recovery key you entered doesn\'t match Loading recovery key requirements Passphrase strength: %1$s From 3b4a18a7908f495cc81f1675f25a6763acdae90a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 20:44:22 +0000 Subject: [PATCH 0624/1083] Update dependency com.google.firebase:firebase-bom to v34.14.0 --- 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 9657aaf15d..e9c0910ab4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -84,7 +84,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:34.13.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.14.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } From a10aa6cbe36da52fb05bfbbb2df19af2afd8dad1 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Sat, 6 Jun 2026 18:26:46 +0000 Subject: [PATCH 0625/1083] Support thread root in drafts --- .../android/features/messages/impl/MessagesNode.kt | 2 +- .../impl/messagecomposer/MessageComposerPresenter.kt | 12 ++++++------ .../messages/impl/threads/ThreadedMessagesNode.kt | 2 +- .../MessageComposerPresenterSlashCommandTest.kt | 3 +++ .../messagecomposer/MessageComposerPresenterTest.kt | 2 ++ 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index a9ce2f5ba1..ef0e7100e2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -107,7 +107,7 @@ class MessagesNode( private val timelineController = TimelineController(room, room.liveTimeline) private val presenter = presenterFactory.create( navigator = this, - composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = false), + composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = false, threadRoot = null), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), actionListPresenter = actionListPresenterFactory.create( postProcessor = TimelineItemActionPostProcessor.Default, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index e226318345..9e9fc15eec 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -49,6 +49,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkParser @@ -110,6 +111,7 @@ class MessageComposerPresenter( @Assisted private val navigator: MessagesNavigator, @Assisted private val timelineController: TimelineController, @Assisted private val isInThread: Boolean, + @Assisted private val threadRoot: ThreadId?, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val room: JoinedRoom, private val mediaPickerProvider: PickerProvider, @@ -139,6 +141,7 @@ class MessageComposerPresenter( timelineController: TimelineController, navigator: MessagesNavigator, isInThread: Boolean, + threadRoot: ThreadId?, ): MessageComposerPresenter } @@ -234,8 +237,7 @@ class MessageComposerPresenter( LaunchedEffect(Unit) { val draft = draftService.loadDraft( roomId = room.roomId, - // TODO support threads in composer - threadRoot = null, + threadRoot = threadRoot, isVolatile = false ) if (draft != null) { @@ -652,8 +654,7 @@ class MessageComposerPresenter( roomId = room.roomId, draft = draft, isVolatile = isVolatile, - // TODO support threads in composer - threadRoot = null, + threadRoot = threadRoot, ) } @@ -816,8 +817,7 @@ class MessageComposerPresenter( // Use the volatile draft only when coming from edit mode otherwise. val draft = draftService.loadDraft( roomId = room.roomId, - // TODO support threads in composer - threadRoot = null, + threadRoot = threadRoot, isVolatile = true ).takeIf { fromEdit } if (draft != null) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index be573fa92f..ade22eed41 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -112,7 +112,7 @@ class ThreadedMessagesNode( this.timelineController = timelineController return presenterFactory.create( navigator = this, - composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = true), + composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = true, threadRoot = inputs.threadRootEventId), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), // TODO add special processor for threaded timeline actionListPresenter = actionListPresenterFactory.create( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt index 116a1cfb5d..2a0ba9ff1b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt @@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkParser @@ -272,11 +273,13 @@ class MessageComposerPresenterSlashCommandTest { draftService: ComposerDraftService = FakeComposerDraftService(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), isInThread: Boolean = false, + threadRoot: ThreadId? = null, slashCommandService: SlashCommandService = FakeSlashCommandService(), ) = MessageComposerPresenter( navigator = navigator, sessionCoroutineScope = this, isInThread = isInThread, + threadRoot = threadRoot, room = room, mediaPickerProvider = pickerProvider, sessionPreferencesStore = sessionPreferencesStore, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index e8d106a80f..ab9886a368 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -1535,11 +1535,13 @@ class MessageComposerPresenterTest { draftService: ComposerDraftService = FakeComposerDraftService(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), isInThread: Boolean = false, + threadRoot: ThreadId? = null, slashCommandService: SlashCommandService = FakeSlashCommandService(), ) = MessageComposerPresenter( navigator = navigator, sessionCoroutineScope = this, isInThread = isInThread, + threadRoot = threadRoot, room = room, mediaPickerProvider = pickerProvider, sessionPreferencesStore = sessionPreferencesStore, From 165a8b776a5335551ebfe163b2a17cd81d508c6c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 12:04:41 +0200 Subject: [PATCH 0626/1083] Update dependency io.element.android:element-call-embedded to v0.20.1 (#6988) 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 70b096873e..fbfb29110c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -239,7 +239,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.20.0" +element_call_embedded = "io.element.android:element-call-embedded:0.20.1" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From 6219378ad3f8629d9937529997a3dd103ee9b4b9 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:21:34 +0300 Subject: [PATCH 0627/1083] Fix "Sent" checkmark disappearing when the message is read and "Share presence" is disabled (#6985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Don't compute read receipts if presence sharing is disabled * Update screenshots --------- Co-authored-by: ElementBot Co-authored-by: Jorge Martín --- .../list/PinnedMessagesListPresenter.kt | 3 +- .../pinned/list/PinnedMessagesListView.kt | 1 - .../impl/timeline/TimelinePresenter.kt | 13 ++++---- .../messages/impl/timeline/TimelineState.kt | 1 - .../impl/timeline/TimelineStateProvider.kt | 2 -- .../messages/impl/timeline/TimelineView.kt | 1 - .../components/ATimelineItemEventRow.kt | 2 -- .../components/TimelineItemCallNotifyView.kt | 15 ++++------ .../components/TimelineItemEventRow.kt | 2 -- .../TimelineItemEventRowWithRRPreview.kt | 3 -- .../TimelineItemGroupedEventsRow.kt | 9 +----- .../timeline/components/TimelineItemRow.kt | 5 ---- .../components/TimelineItemStateEventRow.kt | 3 -- .../receipt/TimelineItemReadReceiptView.kt | 30 ++++++++----------- .../factories/TimelineItemsFactory.kt | 12 +++++--- .../event/TimelineItemEventFactory.kt | 9 ++++-- .../messages/impl/MessagesViewTest.kt | 1 - 17 files changed, 43 insertions(+), 69 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index 9e5f5ba304..6e8974b871 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -208,7 +208,8 @@ class PinnedMessagesListPresenter( combine(timelineItemsFlow, room.membersStateFlow) { items, membersState -> timelineItemsFactory.replaceWith( timelineItems = items, - roomMembers = membersState.roomMembers().orEmpty() + roomMembers = membersState.roomMembers().orEmpty(), + renderReadReceipts = false, ) }.launchIn(this) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index 9811b07c02..bfed13028b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -217,7 +217,6 @@ private fun PinnedMessagesListLoaded( timelineItem = timelineItem, timelineMode = Timeline.Mode.PinnedEvents, timelineRoomInfo = state.timelineRoomInfo, - renderReadReceipts = false, timelineProtectionState = state.timelineProtectionState, isLastOutgoingMessage = false, focusedEventId = null, 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 0941b5c3f1..6711a7fe25 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 @@ -138,9 +138,6 @@ class TimelinePresenter( val messageShieldDialogData: MutableState = remember { mutableStateOf(null) } val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() - val renderReadReceipts by remember { - sessionPreferencesStore.isRenderReadReceiptsEnabled() - }.collectAsState(initial = true) val isLive by remember { timelineController.isLive() }.collectAsState(initial = true) @@ -252,13 +249,18 @@ class TimelinePresenter( } .launchIn(this) - combine(timelineController.timelineItems(), room.membersStateFlow) { items, membersState -> + combine( + timelineController.timelineItems(), + room.membersStateFlow, + sessionPreferencesStore.isRenderReadReceiptsEnabled(), + ) { items, membersState, renderReadReceipts -> val parent = analyticsService.getLongRunningTransaction(DisplayFirstTimelineItems) val transaction = parent?.startChild("timelineItemsFactory.replaceWith", "Processing timeline items") transaction?.putExtraData(AnalyticsUserData.TIMELINE_ITEM_COUNT, items.count().toString()) timelineItemsFactory.replaceWith( timelineItems = items, - roomMembers = membersState.roomMembers().orEmpty() + roomMembers = membersState.roomMembers().orEmpty(), + renderReadReceipts = renderReadReceipts, ) transaction?.finish() items @@ -313,7 +315,6 @@ class TimelinePresenter( timelineItems = timelineItems, timelineMode = timelineMode, timelineRoomInfo = timelineRoomInfo, - renderReadReceipts = renderReadReceipts, newEventState = newEventState.value, isLive = isLive, focusRequestState = focusRequestState.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 03f0083856..d2f0faaa24 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -26,7 +26,6 @@ data class TimelineState( val timelineItems: ImmutableList, val timelineRoomInfo: TimelineRoomInfo, val timelineMode: Timeline.Mode, - val renderReadReceipts: Boolean, val newEventState: NewEventState, val isLive: Boolean, val focusRequestState: FocusRequestState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 3ed50f34a0..bd0b093ed5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -51,7 +51,6 @@ import kotlin.random.Random fun aTimelineState( timelineItems: ImmutableList = persistentListOf(), timelineMode: Timeline.Mode = Timeline.Mode.Live, - renderReadReceipts: Boolean = false, timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(), focusedEventIndex: Int = -1, isLive: Boolean = true, @@ -70,7 +69,6 @@ fun aTimelineState( timelineItems = timelineItems, timelineMode = timelineMode, timelineRoomInfo = timelineRoomInfo, - renderReadReceipts = renderReadReceipts, newEventState = NewEventState.None, isLive = isLive, focusRequestState = focusRequestState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index 0791366105..0a306aea1c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -171,7 +171,6 @@ fun TimelineView( timelineMode = state.timelineMode, timelineRoomInfo = state.timelineRoomInfo, timelineProtectionState = timelineProtectionState, - renderReadReceipts = state.renderReadReceipts, isLastOutgoingMessage = state.isLastOutgoingMessage(timelineItem.identifier()), focusedEventId = state.focusedEventId, displayThreadSummaries = state.displayThreadSummaries, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt index 6be00fc14a..45f4a86a53 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt @@ -22,7 +22,6 @@ internal fun ATimelineItemEventRow( event: TimelineItem.Event, timelineMode: Timeline.Mode = Timeline.Mode.Live, timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(), - renderReadReceipts: Boolean = false, isLastOutgoingMessage: Boolean = false, timelineProtectionState: TimelineProtectionState = aTimelineProtectionState(), displayThreadSummaries: Boolean = false, @@ -30,7 +29,6 @@ internal fun ATimelineItemEventRow( event = event, timelineMode = timelineMode, timelineRoomInfo = timelineRoomInfo, - renderReadReceipts = renderReadReceipts, timelineProtectionState = timelineProtectionState, isLastOutgoingMessage = isLastOutgoingMessage, displayThreadSummaries = displayThreadSummaries, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index fea4f92de5..a7ab44db54 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -52,7 +52,6 @@ internal fun TimelineItemCallNotifyView( timelineRoomInfo: TimelineRoomInfo, event: TimelineItem.Event, content: TimelineItemRtcNotificationContent, - renderReadReceipts: Boolean, isLastOutgoingMessage: Boolean, onLongClick: (TimelineItem.Event) -> Unit, onReadReceiptsClick: (TimelineItem.Event) -> Unit, @@ -106,7 +105,6 @@ internal fun TimelineItemCallNotifyView( isLastOutgoingMessage = isLastOutgoingMessage, receipts = event.readReceiptState.receipts, ), - renderReadReceipts = renderReadReceipts, onReadReceiptsClick = { onReadReceiptsClick(event) }, modifier = Modifier.padding(top = 4.dp), ) @@ -146,8 +144,10 @@ private fun getIcon( @PreviewsDayNight @Composable internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { - val readReceiptState = aTimelineItemReadReceipts( - receipts = List(3) { aReadReceiptData(it) }, + val readReceiptState = mutableListOf( + aTimelineItemReadReceipts( + receipts = List(3) { aReadReceiptData(it) }, + ) ) Column(modifier = Modifier.padding(bottom = 16.dp)) { listOf(false, true).forEach { isDm -> @@ -162,13 +162,10 @@ internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { timelineRoomInfo = aTimelineRoomInfo(isDm = isDm), event = aTimelineItemEvent( content = content, - readReceiptState = readReceiptState, + // Only display read receipts for the first item + readReceiptState = readReceiptState.removeFirstOrNull() ?: aTimelineItemReadReceipts(), ), content = content, - // Render read receipts for the first item only - renderReadReceipts = !isDm && - callIntent == CallIntent.AUDIO && - state == RtcNotificationState.Started, isLastOutgoingMessage = false, onLongClick = {}, onReadReceiptsClick = {}, 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 936028cbd6..1f7f127be7 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 @@ -142,7 +142,6 @@ fun TimelineItemEventRow( timelineMode: Timeline.Mode, timelineRoomInfo: TimelineRoomInfo, timelineProtectionState: TimelineProtectionState, - renderReadReceipts: Boolean, isLastOutgoingMessage: Boolean, displayThreadSummaries: Boolean, onEventClick: () -> Unit, @@ -296,7 +295,6 @@ fun TimelineItemEventRow( isLastOutgoingMessage = isLastOutgoingMessage, receipts = event.readReceiptState.receipts, ), - renderReadReceipts = renderReadReceipts, onReadReceiptsClick = { onReadReceiptClick(event) }, modifier = Modifier.padding(top = 4.dp) ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithRRPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithRRPreview.kt index f46ba780f3..6ea1161605 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithRRPreview.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowWithRRPreview.kt @@ -37,7 +37,6 @@ internal fun TimelineItemEventRowWithRRPreview( timelineItemReactions = aTimelineItemReactions(count = 0), readReceiptState = TimelineItemReadReceipts(state.receipts), ), - renderReadReceipts = true, isLastOutgoingMessage = false, ) // A message from current user @@ -49,7 +48,6 @@ internal fun TimelineItemEventRowWithRRPreview( timelineItemReactions = aTimelineItemReactions(count = 0), readReceiptState = TimelineItemReadReceipts(state.receipts), ), - renderReadReceipts = true, isLastOutgoingMessage = false, ) // Another message from current user @@ -61,7 +59,6 @@ internal fun TimelineItemEventRowWithRRPreview( timelineItemReactions = aTimelineItemReactions(count = 0), readReceiptState = TimelineItemReadReceipts(state.receipts), ), - renderReadReceipts = true, isLastOutgoingMessage = true, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt index 12f7a52f99..b41e66ae82 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt @@ -43,7 +43,6 @@ fun TimelineItemGroupedEventsRow( timelineMode: Timeline.Mode, timelineRoomInfo: TimelineRoomInfo, timelineProtectionState: TimelineProtectionState, - renderReadReceipts: Boolean, isLastOutgoingMessage: Boolean, focusedEventId: EventId?, displayThreadSummaries: Boolean, @@ -89,7 +88,6 @@ fun TimelineItemGroupedEventsRow( timelineRoomInfo = timelineRoomInfo, timelineProtectionState = timelineProtectionState, focusedEventId = focusedEventId, - renderReadReceipts = renderReadReceipts, isLastOutgoingMessage = isLastOutgoingMessage, displayThreadSummaries = displayThreadSummaries, onClick = onClick, @@ -117,7 +115,6 @@ private fun TimelineItemGroupedEventsRowContent( timelineRoomInfo: TimelineRoomInfo, timelineProtectionState: TimelineProtectionState, focusedEventId: EventId?, - renderReadReceipts: Boolean, isLastOutgoingMessage: Boolean, displayThreadSummaries: Boolean, onClick: (TimelineItem.Event) -> Unit, @@ -173,7 +170,6 @@ private fun TimelineItemGroupedEventsRowContent( timelineItem = subGroupEvent, timelineRoomInfo = timelineRoomInfo, timelineProtectionState = timelineProtectionState, - renderReadReceipts = renderReadReceipts, isLastOutgoingMessage = isLastOutgoingMessage, focusedEventId = focusedEventId, displayThreadSummaries = displayThreadSummaries, @@ -193,14 +189,13 @@ private fun TimelineItemGroupedEventsRowContent( ) } } - } else if (renderReadReceipts) { + } else if (timelineItem.aggregatedReadReceipts.isNotEmpty()) { TimelineItemReadReceiptView( state = ReadReceiptViewState( sendState = null, isLastOutgoingMessage = false, receipts = timelineItem.aggregatedReadReceipts, ), - renderReadReceipts = true, onReadReceiptsClick = onExpandGroupClick ) } @@ -219,7 +214,6 @@ internal fun TimelineItemGroupedEventsRowContentExpandedPreview() = ElementPrevi timelineRoomInfo = aTimelineRoomInfo(), timelineProtectionState = aTimelineProtectionState(), focusedEventId = events.events.first().eventId, - renderReadReceipts = true, isLastOutgoingMessage = false, displayThreadSummaries = false, onClick = {}, @@ -247,7 +241,6 @@ internal fun TimelineItemGroupedEventsRowContentCollapsePreview() = ElementPrevi timelineRoomInfo = aTimelineRoomInfo(), timelineProtectionState = aTimelineProtectionState(), focusedEventId = null, - renderReadReceipts = true, isLastOutgoingMessage = false, displayThreadSummaries = false, onClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 5dc69bba8b..0229d2220b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -56,7 +56,6 @@ internal fun TimelineItemRow( timelineItem: TimelineItem, timelineMode: Timeline.Mode, timelineRoomInfo: TimelineRoomInfo, - renderReadReceipts: Boolean, isLastOutgoingMessage: Boolean, timelineProtectionState: TimelineProtectionState, focusedEventId: EventId?, @@ -114,7 +113,6 @@ internal fun TimelineItemRow( is TimelineItemStateContent, is TimelineItemLegacyCallInviteContent -> { TimelineItemStateEventRow( event = timelineItem, - renderReadReceipts = renderReadReceipts, isLastOutgoingMessage = isLastOutgoingMessage, onClick = { onContentClick(timelineItem) }, onReadReceiptsClick = onReadReceiptClick, @@ -127,7 +125,6 @@ internal fun TimelineItemRow( timelineRoomInfo = timelineRoomInfo, event = timelineItem, content = timelineItem.content, - renderReadReceipts = renderReadReceipts, isLastOutgoingMessage = isLastOutgoingMessage, onLongClick = onLongClick, onReadReceiptsClick = onReadReceiptClick, @@ -167,7 +164,6 @@ internal fun TimelineItemRow( event = timelineItem, timelineMode = timelineMode, timelineRoomInfo = timelineRoomInfo, - renderReadReceipts = renderReadReceipts, timelineProtectionState = timelineProtectionState, isLastOutgoingMessage = isLastOutgoingMessage, displayThreadSummaries = displayThreadSummaries, @@ -196,7 +192,6 @@ internal fun TimelineItemRow( timelineMode = timelineMode, timelineRoomInfo = timelineRoomInfo, timelineProtectionState = timelineProtectionState, - renderReadReceipts = renderReadReceipts, isLastOutgoingMessage = isLastOutgoingMessage, focusedEventId = focusedEventId, displayThreadSummaries = displayThreadSummaries, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt index 6e409f2b8d..db32b7a524 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt @@ -39,7 +39,6 @@ import kotlinx.collections.immutable.persistentListOf @Composable fun TimelineItemStateEventRow( event: TimelineItem.Event, - renderReadReceipts: Boolean, isLastOutgoingMessage: Boolean, onClick: () -> Unit, onLongClick: () -> Unit, @@ -86,7 +85,6 @@ fun TimelineItemStateEventRow( isLastOutgoingMessage = isLastOutgoingMessage, receipts = event.readReceiptState.receipts, ), - renderReadReceipts = renderReadReceipts, onReadReceiptsClick = { onReadReceiptsClick(event) }, ) } @@ -104,7 +102,6 @@ internal fun TimelineItemStateEventRowPreview() = ElementPreview { receipts = persistentListOf(aReadReceiptData(0)), ) ), - renderReadReceipts = true, isLastOutgoingMessage = false, onClick = {}, onLongClick = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt index b03aaf01c1..037d9ea45d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt @@ -53,27 +53,24 @@ import kotlinx.collections.immutable.ImmutableList @Composable fun TimelineItemReadReceiptView( state: ReadReceiptViewState, - renderReadReceipts: Boolean, onReadReceiptsClick: () -> Unit, modifier: Modifier = Modifier, ) { if (state.receipts.isNotEmpty()) { - if (renderReadReceipts) { - ReadReceiptsRow( - modifier = modifier.clearAndSetSemantics { - hideFromAccessibility() - } - ) { - ReadReceiptsAvatars( - receipts = state.receipts, - modifier = Modifier - .clip(RoundedCornerShape(4.dp)) - .clickable { - onReadReceiptsClick() - } - .padding(2.dp) - ) + ReadReceiptsRow( + modifier = modifier.clearAndSetSemantics { + hideFromAccessibility() } + ) { + ReadReceiptsAvatars( + receipts = state.receipts, + modifier = Modifier + .clip(RoundedCornerShape(4.dp)) + .clickable { + onReadReceiptsClick() + } + .padding(2.dp) + ) } } else { when (state.sendState) { @@ -209,7 +206,6 @@ internal fun TimelineItemReadReceiptViewPreview( ) = ElementPreview { TimelineItemReadReceiptView( state = state, - renderReadReceipts = true, onReadReceiptsClick = {}, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt index 7b369fe6b7..1679a6030a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt @@ -64,22 +64,24 @@ class TimelineItemsFactory( suspend fun replaceWith( timelineItems: List, roomMembers: List, + renderReadReceipts: Boolean, ) = withContext(dispatchers.computation) { lock.withLock { diffCacheUpdater.updateWith(timelineItems) - buildAndEmitTimelineItemStates(timelineItems, roomMembers) + buildAndEmitTimelineItemStates(timelineItems, roomMembers, renderReadReceipts) } } private suspend fun buildAndEmitTimelineItemStates( timelineItems: List, roomMembers: List, + renderReadReceipts: Boolean, ) { val newTimelineItemStates = ArrayList() for (index in diffCache.indices().reversed()) { val cacheItem = diffCache.get(index) if (cacheItem == null) { - buildAndCacheItem(timelineItems, index, roomMembers)?.also { timelineItemState -> + buildAndCacheItem(timelineItems, index, roomMembers, renderReadReceipts)?.also { timelineItemState -> newTimelineItemStates.add(timelineItemState) } } else { @@ -87,7 +89,8 @@ class TimelineItemsFactory( eventItemFactory.update( timelineItem = cacheItem, receivedMatrixTimelineItem = timelineItems[index] as MatrixTimelineItem.Event, - roomMembers = roomMembers + roomMembers = roomMembers, + renderReadReceipts = renderReadReceipts, ) } else { cacheItem @@ -103,10 +106,11 @@ class TimelineItemsFactory( timelineItems: List, index: Int, roomMembers: List, + renderReadReceipts: Boolean, ): TimelineItem? { val timelineItem = when (val currentTimelineItem = timelineItems[index]) { - is MatrixTimelineItem.Event -> eventItemFactory.create(currentTimelineItem, index, timelineItems, roomMembers) + is MatrixTimelineItem.Event -> eventItemFactory.create(currentTimelineItem, index, timelineItems, roomMembers, renderReadReceipts) is MatrixTimelineItem.Virtual -> virtualItemFactory.create(currentTimelineItem) MatrixTimelineItem.Other -> null } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index cf515a0b51..a36755dc09 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -57,6 +57,7 @@ class TimelineItemEventFactory( index: Int, timelineItems: List, roomMembers: List, + renderReadReceipts: Boolean, ): TimelineItem.Event { val currentSender = currentTimelineItem.event.sender val groupPosition = @@ -116,7 +117,7 @@ class TimelineItemEventFactory( sentDate = sentDate, groupPosition = groupPosition, reactionsState = currentTimelineItem.computeReactionsState(), - readReceiptState = currentTimelineItem.computeReadReceiptState(roomMembers), + readReceiptState = currentTimelineItem.computeReadReceiptState(roomMembers, renderReadReceipts), localSendState = currentTimelineItem.event.localSendState, inReplyTo = currentTimelineItem.event.inReplyTo()?.map(permalinkParser = permalinkParser), threadInfo = mappedThreadInfo, @@ -133,9 +134,10 @@ class TimelineItemEventFactory( timelineItem: TimelineItem.Event, receivedMatrixTimelineItem: MatrixTimelineItem.Event, roomMembers: List, + renderReadReceipts: Boolean, ): TimelineItem.Event { return timelineItem.copy( - readReceiptState = receivedMatrixTimelineItem.computeReadReceiptState(roomMembers) + readReceiptState = receivedMatrixTimelineItem.computeReadReceiptState(roomMembers, renderReadReceipts) ) } @@ -180,8 +182,9 @@ class TimelineItemEventFactory( private fun MatrixTimelineItem.Event.computeReadReceiptState( roomMembers: List, + renderReadReceipts: Boolean, ): TimelineItemReadReceipts { - if (!config.computeReadReceipts) { + if (!config.computeReadReceipts || !renderReadReceipts) { return TimelineItemReadReceipts(receipts = persistentListOf()) } return TimelineItemReadReceipts( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index be44c64a5a..100eb1ca26 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -238,7 +238,6 @@ class MessagesViewTest { val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( - renderReadReceipts = true, timelineItems = persistentListOf( aTimelineItemEvent( readReceiptState = aTimelineItemReadReceipts( From 5a4c0b5d58e5af2de3afa7a59a80f4852ffb7cb8 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:33:40 +0100 Subject: [PATCH 0628/1083] Sync Strings from Localazy (#6986) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- .../src/main/res/values-ko/translations.xml | 3 +- .../src/main/res/values-ja/translations.xml | 4 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 4 + .../src/main/res/values-ko/translations.xml | 1 + .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 3 +- .../src/main/res/values-pl/translations.xml | 2 +- .../src/main/res/values-sk/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 6 + .../src/main/res/values-fi/translations.xml | 9 + .../src/main/res/values-hu/translations.xml | 13 + .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-ko/translations.xml | 6 + .../src/main/res/values-pl/translations.xml | 6 + .../src/main/res/values-zh/translations.xml | 6 + .../src/main/res/values-fi/translations.xml | 10 + .../src/main/res/values-hu/translations.xml | 43 + .../src/main/res/values-ja/translations.xml | 11 +- .../src/main/res/values-ko/translations.xml | 51 + .../src/main/res/values-fi/translations.xml | 2 + .../src/main/res/values-hu/translations.xml | 2 + .../src/main/res/values-ja/translations.xml | 2 + .../src/main/res/values-ko/translations.xml | 2 + .../src/main/res/values-pl/translations.xml | 2 + .../src/main/res/values-ko/translations.xml | 1 + .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-sk/translations.xml | 10 +- .../src/main/res/values-ko/translations.xml | 2 + .../src/main/res/values-ko/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 3 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 2 + .../src/main/res/values-fi/translations.xml | 4 + .../src/main/res/values-hu/translations.xml | 5 + .../src/main/res/values-ja/translations.xml | 4 +- .../src/main/res/values-ko/translations.xml | 27 + .../src/main/res/values-pl/translations.xml | 3 + .../src/main/res/values-zh/translations.xml | 2 + ....roomlist_RoomListContextMenu_Day_0_de.png | 4 +- ....roomlist_RoomListContextMenu_Day_1_de.png | 4 +- ....roomlist_RoomListContextMenu_Day_2_de.png | 4 +- .../features.home.impl_HomeView_Day_6_de.png | 4 +- .../features.home.impl_HomeView_Day_7_de.png | 4 +- .../features.home.impl_HomeView_Day_8_de.png | 4 +- ....impl.screens.error_ErrorView_Day_3_de.png | 4 +- ...nderingMapsNotSupportedDialog_Day_0_de.png | 3 + ...on.impl.show_ShowLocationView_Day_6_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_7_de.png | 4 +- ...on.impl.show_ShowLocationView_Day_8_de.png | 3 - ...onlist_ActionListViewContent_Day_10_de.png | 4 +- ...onlist_ActionListViewContent_Day_11_de.png | 4 +- ...onlist_ActionListViewContent_Day_12_de.png | 4 +- ...ionlist_ActionListViewContent_Day_2_de.png | 4 +- ...ionlist_ActionListViewContent_Day_3_de.png | 4 +- ...ionlist_ActionListViewContent_Day_4_de.png | 4 +- ...ionlist_ActionListViewContent_Day_5_de.png | 4 +- ...ionlist_ActionListViewContent_Day_6_de.png | 4 +- ...ionlist_ActionListViewContent_Day_7_de.png | 4 +- ...ionlist_ActionListViewContent_Day_8_de.png | 4 +- ...ionlist_ActionListViewContent_Day_9_de.png | 4 +- ...eeditor_AttachmentImageEditorView_0_de.png | 4 +- ...eeditor_AttachmentImageEditorView_1_de.png | 4 +- ...eeditor_AttachmentImageEditorView_2_de.png | 4 +- ...eeditor_AttachmentImageEditorView_3_de.png | 4 +- ...eeditor_AttachmentImageEditorView_4_de.png | 4 +- ...eeditor_AttachmentImageEditorView_5_de.png | 4 +- ...eeditor_AttachmentImageEditorView_6_de.png | 3 + ...eeditor_AttachmentImageEditorView_7_de.png | 3 + ...ts.preview_AttachmentsPreviewView_6_de.png | 4 +- ...er_AttachmentSourcePickerMenu_Day_0_de.png | 4 +- ...d.list_PinnedMessagesListView_Day_3_de.png | 4 +- ...es.impl.timeline_TimelineView_Day_4_de.png | 4 +- ...es.impl.timeline_TimelineView_Day_6_de.png | 4 +- ...es.messages.impl_MessagesView_Day_1_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_0_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_10_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_11_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_12_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_13_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_14_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_15_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_16_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_17_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_18_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_19_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_1_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_20_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_21_de.png | 4 +- ...roomdetails.impl_RoomDetailsDark_22_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_2_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_3_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_4_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_5_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_6_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_7_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_8_de.png | 4 +- ....roomdetails.impl_RoomDetailsDark_9_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_0_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_10_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_11_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_12_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_13_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_14_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_15_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_16_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_17_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_18_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_19_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_1_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_20_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_21_de.png | 4 +- ...res.roomdetails.impl_RoomDetails_22_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_2_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_3_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_4_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_5_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_6_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_7_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_8_de.png | 4 +- ...ures.roomdetails.impl_RoomDetails_9_de.png | 4 +- ...impl_RoomMemberModerationView_Day_0_de.png | 4 +- ...impl_RoomMemberModerationView_Day_1_de.png | 4 +- ...impl_RoomMemberModerationView_Day_2_de.png | 4 +- ...impl_RoomMemberModerationView_Day_3_de.png | 4 +- ...rofile.shared_UserProfileView_Day_2_de.png | 4 +- ...rofile.shared_UserProfileView_Day_5_de.png | 4 +- ...nents_AvatarActionBottomSheet_Day_0_de.png | 4 +- ...tails_MediaDetailsBottomSheet_Day_0_de.png | 4 +- ...tails_MediaDetailsBottomSheet_Day_1_de.png | 4 +- ...tails_MediaDetailsBottomSheet_Day_2_de.png | 4 +- ...tails_MediaDetailsBottomSheet_Day_3_de.png | 4 +- ...tails_MediaDetailsBottomSheet_Day_4_de.png | 3 + ...impl.gallery_MediaGalleryView_Day_8_de.png | 4 +- ...impl.local.file_MediaFileView_Day_0_de.png | 3 + ...impl.local.file_MediaFileView_Day_1_de.png | 3 + ...impl.local.file_MediaFileView_Day_2_de.png | 3 + ....viewer_MediaViewerViewLandscape_11_de.png | 4 +- ...l.viewer_MediaViewerViewLandscape_6_de.png | 3 + ...l.viewer_MediaViewerViewLandscape_7_de.png | 3 + ...ewer.impl.viewer_MediaViewerView_11_de.png | 4 +- ...iewer.impl.viewer_MediaViewerView_6_de.png | 3 + ...iewer.impl.viewer_MediaViewerView_7_de.png | 3 + screenshots/html/data.js | 2179 +++++++++-------- 144 files changed, 1555 insertions(+), 1291 deletions(-) create mode 100644 screenshots/de/features.location.api_RenderingMapsNotSupportedDialog_Day_0_de.png delete mode 100644 screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_6_de.png create mode 100644 screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_7_de.png diff --git a/features/deactivation/impl/src/main/res/values-ko/translations.xml b/features/deactivation/impl/src/main/res/values-ko/translations.xml index 42dd0aa0e2..83eaf7ff21 100644 --- a/features/deactivation/impl/src/main/res/values-ko/translations.xml +++ b/features/deactivation/impl/src/main/res/values-ko/translations.xml @@ -3,11 +3,12 @@ "계정을 비활성화하시겠습니까? 이 작업은 되돌릴 수 없습니다." "모든 내 메시지 삭제" "경고: 향후 사용자는 불완전한 대화 내용을 볼 수 있습니다." - "계정을 비활성화하는 것은 %1$s 이며, 다음과 같은 조치를 취합니다:" + "계정을 삭제하면 %1$s, 다음과 같이 처리됩니다:" "불가역적" "%1$s 귀하의 계정 (로그인할 수 없으며, 귀하의 ID는 재사용할 수 없습니다)." "영구적으로 비활성화" "모든 채팅방에서 자신을 제거하세요." "당사의 신원 서버에서 귀하의 계정 정보를 삭제하세요." "메시지는 등록된 사용자에게는 계속 표시되지만, 삭제하면 신규 또는 미등록 사용자는 볼 수 없게 됩니다." + "계정 삭제" 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 c1c1ade1ff..855bb14533 100644 --- a/features/home/impl/src/main/res/values-ja/translations.xml +++ b/features/home/impl/src/main/res/values-ja/translations.xml @@ -1,7 +1,7 @@ "すべての通知を確実に受信するために、このアプリのバッテリー最適化を無効にしてください。" - "最適化を無効にする" + "無効にする" "通知が届いていませんか?" "通知音が更新され、より明確で速く、そして邪魔にならなくなりました。" "サウンドを刷新しました" @@ -38,7 +38,7 @@ "低い優先度のチャットはまだありません" "フィルターを解除して他のチャットを表示できます" "この選択中にチャットがありません" - "人々" + "ユーザー" "まだダイレクトメッセージは届いていません" "ルーム" "まだルームに参加していません" diff --git a/features/home/impl/src/main/res/values-sk/translations.xml b/features/home/impl/src/main/res/values-sk/translations.xml index 12e6284468..aab1f6dc1d 100644 --- a/features/home/impl/src/main/res/values-sk/translations.xml +++ b/features/home/impl/src/main/res/values-sk/translations.xml @@ -6,7 +6,7 @@ "Vaše oznámenia boli aktualizované – sú prehľadnejšie, rýchlejšie a menej rušivé." "Obnovili sme vaše zvuky" "Vytvorte nový kľúč na obnovenie, ktorý môžete použiť na obnovenie vašej histórie šifrovaných správ v prípade straty prístupu k vašim zariadeniam." - "Nastaviť obnovenie" + "Získať kľúč na obnovenie" "Nastaviť obnovenie" "Potvrďte svoj kľúč na obnovenie, aby ste zachovali prístup k úložisku kľúčov a histórii správ." "Zadajte kľúč na obnovenie" diff --git a/features/invitepeople/impl/src/main/res/values-ko/translations.xml b/features/invitepeople/impl/src/main/res/values-ko/translations.xml index 19214c5a79..421f6d5e02 100644 --- a/features/invitepeople/impl/src/main/res/values-ko/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-ko/translations.xml @@ -2,4 +2,8 @@ "이미 회원" "이미 초대됨" + "이 사용자들과의 대화 내역이 없습니다. 계속하려면 먼저 이 방으로의 초대를 확인해 주세요." + "이 사용자와의 대화 내역이 없습니다. 계속하려면 먼저 이 방으로의 초대를 확인해 주세요." + "이 방에 새 사용자를 초대할까요?" + "이 방에 새 사용자를 초대할까요?" diff --git a/features/location/impl/src/main/res/values-ko/translations.xml b/features/location/impl/src/main/res/values-ko/translations.xml index e283d20b9c..aa23450335 100644 --- a/features/location/impl/src/main/res/values-ko/translations.xml +++ b/features/location/impl/src/main/res/values-ko/translations.xml @@ -2,4 +2,5 @@ "실시간 위치 기록은 대화방에 저장되며, 공유 종료 후에도 멤버들이 확인할 수 있습니다." "실시간 위치를 공유할 시간을 선택해 주세요." + "이 방에서는 실시간 위치를 공유할 권한이 없습니다." diff --git a/features/lockscreen/impl/src/main/res/values-sk/translations.xml b/features/lockscreen/impl/src/main/res/values-sk/translations.xml index 14687f9272..e8fdf50bfd 100644 --- a/features/lockscreen/impl/src/main/res/values-sk/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-sk/translations.xml @@ -23,7 +23,7 @@ Vyberte si niečo zapamätateľné. Ak tento kód PIN zabudnete, budete z aplik "Zadajte prosím ten istý PIN dvakrát" "PIN kódy sa nezhodujú" "Ak chcete pokračovať, musíte sa znovu prihlásiť a vytvoriť nový PIN kód." - "Prebieha odhlasovanie" + "Toto zariadenie sa odstraňuje" "Máte %1$d pokus na odomknutie" "Máte %1$d pokusy na odomknutie" 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 338ba628c9..8f313b15ee 100644 --- a/features/login/impl/src/main/res/values-ko/translations.xml +++ b/features/login/impl/src/main/res/values-ko/translations.xml @@ -28,7 +28,7 @@ "서버의 주소는 무엇인가요?" "서버 선택" "계정 만들기" - "계정이 비활성화되었습니다." + "삭제된 계정입니다." "잘못된 아이디/비밀번호" "이 사용자 ID는 유효하지 않습니다. 예상 형식: ‘@user:homeserver.org’" "이 서버는 새로 고침 토큰을 사용하도록 구성되어 있습니다. 비밀번호 기반 로그인을 사용하는 경우 이 기능은 지원되지 않습니다." @@ -45,6 +45,7 @@ "%1$s(으)로 돌아가기" "%1$s(으)로 진행하기 전에 키 저장소를 활성화해 주세요." "버전 %1$s" + "계정 확인 중" "수동으로 로그인" "%1$s 에 로그인합니다" "QR 코드로 로그인" diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index ca0d035fe0..634d856cdf 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -97,7 +97,7 @@ Spróbuj zalogować się ręcznie lub zeskanuj kod QR na innym urządzeniu.""Zacznij od nowa" "Wystąpił nieoczekiwany błąd. Spróbuj ponownie." "Oczekiwanie na drugie urządzenie" - "Twój dostawca konta może poprosić o podany kod, aby zweryfikować logowanie." + "Twój dostawca konta może poprosić o podany kod w celu weryfikacji logowania." "Twój kod weryfikacyjny" "Zmień dostawcę konta" "Serwer prywatny dla pracowników Element." diff --git a/features/logout/impl/src/main/res/values-sk/translations.xml b/features/logout/impl/src/main/res/values-sk/translations.xml index 4fe07b2fa7..28e0a05c2f 100644 --- a/features/logout/impl/src/main/res/values-sk/translations.xml +++ b/features/logout/impl/src/main/res/values-sk/translations.xml @@ -12,7 +12,7 @@ "Vaše kľúče sa ešte stále zálohujú" "Odstrániť toto zariadenie" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, stratíte prístup k svojim šifrovaným správam." - "Obnovenie nie je nastavené" + "Čoskoro stratíte prístup k svojim zašifrovaným konverzáciám" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, môžete stratiť prístup k svojim šifrovaným správam." "Uložili ste si kľúč na obnovenie?" diff --git a/features/messages/impl/src/main/res/values-et/translations.xml b/features/messages/impl/src/main/res/values-et/translations.xml index aa5a9045d1..86b1995f32 100644 --- a/features/messages/impl/src/main/res/values-et/translations.xml +++ b/features/messages/impl/src/main/res/values-et/translations.xml @@ -16,6 +16,12 @@ "Reisimine ja kohad" "Hiljutised emojid" "Sümbolid" + "Pööra pilti ümber rõhttelje" + "Pilt on pööratud ümber rõhttelje" + "Pildi algne variant" + "Pööra pilti ümber püsttelje" + "Pilt on pööratud ümber püsttelje" + "Pildi algne variant" "Pööra pilti vasakule" "%1$d kraad" diff --git a/features/messages/impl/src/main/res/values-fi/translations.xml b/features/messages/impl/src/main/res/values-fi/translations.xml index 25f434ec25..881a5386e7 100644 --- a/features/messages/impl/src/main/res/values-fi/translations.xml +++ b/features/messages/impl/src/main/res/values-fi/translations.xml @@ -16,10 +16,18 @@ "Matkustaminen ja paikat" "Viimeaikaiset emojit" "Symbolit" + "Käännä kuva vaakasuunnassa" + "Käännetty vaakasuunnassa" + "Alkuperäinen" + "Käännä kuva pystysuunnassa" + "Käännetty pystysuunnassa" + "Alkuperäinen" + "Kierrä kuvaa vasemmalle" "%1$d aste" "%1$d astetta" + "Muokkaa kuvaa" "Kuvatekstit eivät välttämättä näy ihmisille, jotka käyttävät vanhempia sovelluksia." "Napauta muuttaaksesi videon lähetyslaatua" "Tiedostoa ei voitu lähettää." @@ -30,6 +38,7 @@ "Kohde %1$d / %2$d" "Optimoi kuvanlaatu" "Käsitellään…" + "Lisää mediaa" "Estä käyttäjä" "Valitse tämä, jos haluat piilottaa kaikki nykyiset ja tulevat viestit tältä käyttäjältä" "Tämä viesti ilmoitetaan kotipalvelimesi ylläpitäjälle. Ylläpitäjä ei pysty lukemaan salattuja viestejä." diff --git a/features/messages/impl/src/main/res/values-hu/translations.xml b/features/messages/impl/src/main/res/values-hu/translations.xml index 3cbd86e8d1..bb33520cb6 100644 --- a/features/messages/impl/src/main/res/values-hu/translations.xml +++ b/features/messages/impl/src/main/res/values-hu/translations.xml @@ -16,6 +16,18 @@ "Utazás és helyek" "Legutóbbi emodzsik" "Szimbólumok" + "Kép vízszintes tükrözése" + "Vízszintesen tükrözve" + "Eredeti" + "Kép függőleges tükrözése" + "Függőlegesen tükrözve" + "Eredeti" + "Kép elforgatása balra" + + "%1$d fok" + "%1$d fok" + + "Fotó szerkesztése" "Előfordulhat, hogy a feliratok nem láthatók a régebbi alkalmazásokat használók számára." "Koppintson a feltöltött videók minőségének módosításához" "A fájl nem tölthető fel." @@ -26,6 +38,7 @@ "%1$d. elem / %2$d" "Képminőség optimalizációja" "Feldolgozás…" + "Média hozzáadása" "Felhasználó letiltása" "Jelölje be, ha el akarja rejteni az összes jelenlegi és jövőbeli üzenetet ettől a felhasználótól" "Ez az üzenet jelentve lesz a Matrix-kiszolgáló adminisztrátorának. Nem fogja tudni elolvasni a titkosított üzeneteket." diff --git a/features/messages/impl/src/main/res/values-ja/translations.xml b/features/messages/impl/src/main/res/values-ja/translations.xml index f1a4bde02f..455996fd1a 100644 --- a/features/messages/impl/src/main/res/values-ja/translations.xml +++ b/features/messages/impl/src/main/res/values-ja/translations.xml @@ -39,7 +39,7 @@ "カメラ" "写真を撮影" "動画を撮影" - "添付ファイル" + "ファイルを添付" "アルバムの写真と動画" "場所を共有" "投票" diff --git a/features/messages/impl/src/main/res/values-ko/translations.xml b/features/messages/impl/src/main/res/values-ko/translations.xml index daede9ec1d..fbcb0cab52 100644 --- a/features/messages/impl/src/main/res/values-ko/translations.xml +++ b/features/messages/impl/src/main/res/values-ko/translations.xml @@ -16,6 +16,11 @@ "여행 & 장소" "최근 이모지" "상징" + "이미지를 왼쪽으로 회전" + + "%1$d도" + + "사진 편집" "캡션은 오래된 앱을 사용하는 사용자에게 표시되지 않을 수 있습니다." "비디오 업로드 품질을 변경하려면 탭하세요" "파일을 업로드할 수 없습니다." @@ -26,6 +31,7 @@ "전체 %2$d개 중 %1$d번째 파일" "이미지 품질 최적화" "처리 중…" + "미디어 추가" "사용자 차단하기" "이 사용자의 현재 및 향후 모든 메시지를 숨기려면 확인하세요." "이 메시지는 홈서버의 관리자에게 보고되었습니다. 암호화된 메시지는 읽을 수 없습니다." diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index 1a9dc12f1c..d8ffaac54c 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -16,6 +16,12 @@ "Podróż i miejsca" "Ostatnie emoji" "Symbole" + "Odwróć obraz w poziomie" + "Odwrócono w poziomie" + "Oryginalny" + "Odwróć obraz w pionie" + "Odwrócono w pionie" + "Oryginalny" "Obróć obraz w lewo" "%1$d stopień" diff --git a/features/messages/impl/src/main/res/values-zh/translations.xml b/features/messages/impl/src/main/res/values-zh/translations.xml index c572b737f1..e2300912ae 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -16,6 +16,12 @@ "文旅景点" "最近的 Emoji" "符号" + "水平翻转图像" + "水平翻转" + "原始" + "垂直翻转图像" + "垂直翻转" + "原始" "向左旋转图像" "%1$d 度" diff --git a/features/preferences/impl/src/main/res/values-fi/translations.xml b/features/preferences/impl/src/main/res/values-fi/translations.xml index 99f900bcc1..f37673427f 100644 --- a/features/preferences/impl/src/main/res/values-fi/translations.xml +++ b/features/preferences/impl/src/main/res/values-fi/translations.xml @@ -58,6 +58,7 @@ "Kokeilunhaluinen olo?" "Labrat" "Lisäasetukset" + "Puhelun soittoääni" "Ääni- ja videopuheluista" "Konfiguraatio ei täsmää" "Olemme yksinkertaistaneet ilmoitusasetuksia, jotta vaihtoehdot olisi helpompi löytää. Joitakin aiemmin valitsemiasi asetuksia ei näytetä tässä, mutta ne ovat edelleen voimassa. @@ -76,17 +77,26 @@ Jos jatkat, jotkin asetukset saattavat muuttua." "Kutsut" "Kotipalvelimesi ei tue tätä vaihtoehtoa salatuissa huoneissa, joten et ehkä saa ilmoitusta joissakin huoneissa." "Maininnat" + "Valitse toinen ääni…" + "Käytössä tällä hetkellä %1$s" + "Viestin ääni" + "Viestin ääni" "Kaikki" "Maininnat" "Ilmoita minulle" "Ilmoita minulle @room-maininnoista" + "Mukautettu" "Mukautettu ääni…" "Virhe tiedoston poistamisessa" "Elementin oletus" + "Element Fade" "Virhe tiedoston tuonnissa" "Ongelma ilmoitusäänen esikatselussa" "Ääni" + "Hylkää hälytysäänen virhe" "Ongelma ilmoitusäänen asettamisessa" + "Hiljainen" + "Järjestelmän oletus" "Jos haluat saada ilmoituksia, vaihda %1$s." "järjestelmäsi asetuksia" "Järjestelmän ilmoitukset on poissa päältä" diff --git a/features/preferences/impl/src/main/res/values-hu/translations.xml b/features/preferences/impl/src/main/res/values-hu/translations.xml index 4c1b988696..febc0e02a9 100644 --- a/features/preferences/impl/src/main/res/values-hu/translations.xml +++ b/features/preferences/impl/src/main/res/values-hu/translations.xml @@ -58,6 +58,7 @@ "Kísérletezni szeretne?" "Kísérletek" "További beállítások" + "Csengőhang" "Hang- és videóhívások" "Konfigurációs eltérés" "Egyszerűsítettük az értesítési beállításokat, hogy könnyebben megtalálhatók legyenek a lehetőségek. A korábban kiválasztott egyéni beállítások némelyike nem jelenik meg itt, de továbbra is aktív. @@ -76,10 +77,52 @@ Ha folytatja, egyes beállítások megváltozhatnak." "Meghívók" "A Matrix-kiszolgálója nem támogatja ezt a beállítást a titkosított szobákban, előfordulhat, hogy egyes szobákban nem kap értesítést." "Említések" + "Válasszon egy másik hangot…" + "Jelenleg használt: %1$s" + "Üzenet hang" + "Üzenet hang" "Összes" "Említések" "Értesítés ezekről:" "Értesítés a @room említésekor" + "Egyedi" + "Egyedi hang…" + "Hiba a fájl törlésekor" + "Element alapértelmezett" + "Element Fade" + "Hiba a fájl importálásakor" + "Probléma a riasztási hang előnézetekor" + "Hang" + "Figyelmeztető hang hiba kikapcsolása" + "Probléma a riasztási hang beállításánál" + "Néma" + "Riasztás" + "Előrejelzés" + "Harang" + "Virágzás" + "Calypso" + "Chime" + "Choo Choo" + "Rendszer alapértelmezett" + "Lejtő" + "Elektronikus" + "Harsonaszó" + "Üveg" + "Kürt" + "Létra" + "Menüett" + "Hírvillám" + "Noir" + "Sherwood-erdő" + "Varázslat" + "Feszültség" + "Swish" + "Távíró" + "Lábujjhegy" + "Három hang" + "Csipog" + "Írógép" + "Frissítés" "Az értesítések fogadásához kérjük, módosítsa a %1$s." "rendszerbeállításokat" "A rendszerértesítések ki vannak kapcsolva" diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml index 5cab6bdcf8..ea07a9d931 100644 --- a/features/preferences/impl/src/main/res/values-ja/translations.xml +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -54,9 +54,10 @@ "スレッドへの返信を有効化" "変更を適用するためにアプリケーションは再起動します。" "開発段階の最新機能を試すことができます。未完成のため、変更や不安定な挙動が生じる可能性があります。" - "探究したいですか?" + "探究的な気分ですか?" "ラボ" "追加設定" + "発信音" "音声・ビデオ通話" "設定の不一致" "通知設定を簡素化し、見つけやすくしました。以前のカスタム設定の一部はここに表示されませんが、引き続き有効です。 @@ -75,10 +76,15 @@ "招待" "暗号化されたルームでは、この機能にホームサーバーが対応しないため、一部のルームから通知が届かない可能性があります。" "メンション" + "他の音を選択…" + "%1$s を使用中" + "メッセージの音" + "メッセージの音" "すべて" "メンション" "以下を通知" @ルームで通知を受け取る + "カスタム" "カスタム着信音" "ファイルの削除に失敗" "Element の既定" @@ -86,7 +92,9 @@ "ファイルの取り込みに失敗" "通知音のプレビューで問題が発生しました" "音" + "通知音のエラーを無視" "通知音の設定に問題が発生しました" + "サイレント" "アラート" "予感" "ベル" @@ -94,6 +102,7 @@ "カリプソ" "チャイム" "汽車ポッポ" + "システムのデフォルト" "下降" "エレクトロニック" "ファンファーレ" diff --git a/features/preferences/impl/src/main/res/values-ko/translations.xml b/features/preferences/impl/src/main/res/values-ko/translations.xml index e2c5e8e83b..2ab3673026 100644 --- a/features/preferences/impl/src/main/res/values-ko/translations.xml +++ b/features/preferences/impl/src/main/res/values-ko/translations.xml @@ -11,6 +11,13 @@ "방 초대 요청에서 아바타 숨기기" "타임라인에서 미디어 미리 보기 숨기기" "실험실" + "위치 업데이트 전환 기준 거리" + "이 앱에 \"정확한 위치\" 권한이 허용되어 있는지 확인해 주세요. 권한을 변경하려면 %1$s(으)로 이동하세요." + "앱 설정" + "실시간 위치 업데이트" + + "%1$d미터마다" + "사진과 동영상을 더 빠르게 업로드하고 데이터 사용량을 줄이세요" "미디어 품질 최적화" "중재와 안전" @@ -51,6 +58,7 @@ "새로운 것을 시도해보고 싶으신가요?" "실험실" "추가 설정" + "통화 벨소리" "음성 및 동영상 통화" "구성 불일치" "알림 설정을 간소화하여 옵션을 더 쉽게 찾을 수 있도록 했습니다. 과거에 선택한 일부 맞춤 설정은 여기에서 표시되지 않지만, 여전히 활성화되어 있습니다. @@ -69,14 +77,57 @@ "초대" "귀하의 홈서버는 암호화된 방에서 이 옵션을 지원하지 않으므로, 일부 방에서는 알림이 표시되지 않을 수 있습니다." "언급" + "다른 소리를 선택하세요…" + "현재 사용 중: %1$s" + "메시지 소리" + "메시지 소리" "모두" "언급" "나에게 알려주세요" @room 에서 알림 받기 + "사용자 지정" + "소리 사용자 지정" + "파일 삭제 오류" + "Element 기본 설정" + "엘리먼트 페이드" + "파일 가져오기 오류" + "알림음 미리듣기 문제 발생" + "소리" + "알림음 오류 해제" + "알림 소리 설정 문제" + "무음" + "알림" + "앤티시페이트" + "벨" + "블룸" + "칼립소" + "차임" + "칙칙폭폭" + "시스템 기본값" + "디센트" + "일렉트로닉" + "팡파레" + "글래스" + "혼" + "래더" + "미뉴에트" + "뉴스 플래시" + "느와르" + "셔우드 포레스트" + "스펠" + "서스펜스" + "스위시" + "텔레그래프" + "팁토즈" + "트라이톤" + "트윗" + "타자기" + "업데이트" "알림을 받으려면 %1$s 을 변경해 주세요." "시스템 설정" "시스템 알림이 꺼져 있습니다." "알림" + "검은색" "다크" "라이트" "시스템" diff --git a/features/rageshake/impl/src/main/res/values-fi/translations.xml b/features/rageshake/impl/src/main/res/values-fi/translations.xml index 1970d538fd..5590602367 100644 --- a/features/rageshake/impl/src/main/res/values-fi/translations.xml +++ b/features/rageshake/impl/src/main/res/values-fi/translations.xml @@ -8,6 +8,8 @@ "Kuvaile ongelmaasi…" "Jos mahdollista, kirjoita englanniksi." "Kuvaus on liian lyhyt. Kerro tarkemmin mitä tapahtui, kiitos!" + "Voit kirjoittaa mahdollisen GitHub-issuen numeron." + "GitHub-issue" "Lähetä kaatumislokit" "Lähetä lokitiedostot" "Lokitiedostosi ovat liian suuria, joten niitä ei voida sisällyttää tähän raporttiin. Lähetä ne meille toisella tavalla." diff --git a/features/rageshake/impl/src/main/res/values-hu/translations.xml b/features/rageshake/impl/src/main/res/values-hu/translations.xml index 851d3f0067..db665a1253 100644 --- a/features/rageshake/impl/src/main/res/values-hu/translations.xml +++ b/features/rageshake/impl/src/main/res/values-hu/translations.xml @@ -8,6 +8,8 @@ "Írja le a problémát…" "Ha lehetséges, a leírást angolul írja meg." "A leírás túl rövid, adjon meg további részleteket a történtekről. Köszönjük!" + "Megadhatja egy kapcsolódó GitHub-probléma számát, ha van ilyen." + "GitHub-jegy" "Összeomlásnaplók küldése" "Naplók engedélyezése" "A naplófájlok túl nagyok, ezért nem szerepelhetnek ebben a jelentésben. Más módon küldje el őket." diff --git a/features/rageshake/impl/src/main/res/values-ja/translations.xml b/features/rageshake/impl/src/main/res/values-ja/translations.xml index 7c46d2beb5..53d25b364f 100644 --- a/features/rageshake/impl/src/main/res/values-ja/translations.xml +++ b/features/rageshake/impl/src/main/res/values-ja/translations.xml @@ -8,6 +8,8 @@ "問題の説明…" "可能であれば英語で記入してください。" "説明が過度に短いです。問題についてより詳細にご記入ください。" + "関連したGitHubのissueがある場合はIDを記入してください。" + "GitHub issue" "クラッシュログを送信" "ログの記録を許可" "ログのサイズが大きく、報告に添付することができません。ログは別の方法で送信してください。" diff --git a/features/rageshake/impl/src/main/res/values-ko/translations.xml b/features/rageshake/impl/src/main/res/values-ko/translations.xml index ef4978924c..1b15ce3f5a 100644 --- a/features/rageshake/impl/src/main/res/values-ko/translations.xml +++ b/features/rageshake/impl/src/main/res/values-ko/translations.xml @@ -8,6 +8,8 @@ "문제를 설명해 주세요…" "가능하다면 영어로 설명을 작성해 주십시오." "설명 내용이 너무 짧습니다. 발생한 상황에 대해 더 자세한 내용을 제공해 주시기 바랍니다. 감사합니다!" + "연관된 GitHub 이슈 번호가 있다면 입력할 수 있습니다." + "GitHub 이슈" "충돌 로그 보내기" "로그 허용" "귀하의 로그가 너무 커서 이 보고서에 포함할 수 없습니다. 다른 방법으로 보내주시기 바랍니다." diff --git a/features/rageshake/impl/src/main/res/values-pl/translations.xml b/features/rageshake/impl/src/main/res/values-pl/translations.xml index c433071584..2b0feb0851 100644 --- a/features/rageshake/impl/src/main/res/values-pl/translations.xml +++ b/features/rageshake/impl/src/main/res/values-pl/translations.xml @@ -8,6 +8,8 @@ "Opisz problem…" "Jeśli to możliwe, napisz zgłoszenje w języku angielskim." "Opis jest zbyt krótki, podaj więcej szczegółów na temat tego co się stało. Dzięki!" + "Możesz wpisać numer powiązanego zgłoszenia w serwisie GitHub, jeśli takie istnieje." + "Zgłoszenie Github" "Wyślij logi awarii" "Zezwól na logi" "Twoje dzienniki są zbyt duże, więc nie można ich uwzględnić w tym raporcie. Prześlij je do nas w inny sposób." diff --git a/features/rolesandpermissions/impl/src/main/res/values-ko/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-ko/translations.xml index 4ad64f1723..c9de19a43a 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-ko/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-ko/translations.xml @@ -6,6 +6,7 @@ "메시지 삭제" "멤버" "사람 초대하기" + "실시간 위치 공유" "스페이스 관리" "방 관리" "멤버 관리" diff --git a/features/securebackup/impl/src/main/res/values-ja/translations.xml b/features/securebackup/impl/src/main/res/values-ja/translations.xml index 72c8c90809..b9612c4e09 100644 --- a/features/securebackup/impl/src/main/res/values-ja/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ja/translations.xml @@ -6,7 +6,7 @@ "鍵の保管庫" "チャットをバックアップするには、鍵の保管庫を使用する必要があります。" "この端末上の鍵をアップロードします" - "鍵の保管庫を使用します" + "鍵の保管庫を使用" "回復鍵を変更" "あなたのチャットはエンドツーエンド暗号化を使用して自動的にバックアップされています。すべての端末を使用できない状況で、このバックアップからデジタルIDを復元するには、回復鍵が必要となります。" "回復鍵を入力" diff --git a/features/securebackup/impl/src/main/res/values-sk/translations.xml b/features/securebackup/impl/src/main/res/values-sk/translations.xml index 3e92a39df0..4e646ef47e 100644 --- a/features/securebackup/impl/src/main/res/values-sk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sk/translations.xml @@ -11,7 +11,7 @@ "Obnovte svoju kryptografickú totožnosť a históriu správ pomocou kľúča na obnovenie, ak ste stratili všetky svoje existujúce zariadenia." "Zadajte kľúč na obnovenie" "Vaše úložisko kľúčov nie je momentálne synchronizované." - "Nastaviť obnovenie" + "Získať kľúč na obnovenie" "Otvoriť %1$s v stolnom počítači" "Znova sa prihláste do svojho účtu" "Keď sa zobrazí výzva na overenie vášho zariadenia, vyberte %1$s" @@ -25,10 +25,10 @@ "Budete musieť znova overiť všetky existujúce zariadenia a kontakty" "Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie." "Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom" - "Vypnúť" + "Odstrániť" "Ak odstránite všetky svoje zariadenia, stratíte svoju zašifrovanú históriu správ a budete si musieť obnoviť svoju digitálnu identitu." - "Ste si istí, že chcete vypnúť zálohovanie?" - "Vypnutím zálohovania sa odstráni aktuálna záloha šifrovacích kľúčov a vypnú sa ďalšie bezpečnostné funkcie. V tomto prípade:" + "Naozaj chcete odstrániť úložisko kľúčov?" + "Odstránením úložiska kľúčov sa zo servera odstránia vaše kľúče digitálnej identity a správ a vypnú sa nasledujúce bezpečnostné funkcie:" "Na nových zariadeniach nebudete mať zašifrovanú históriu správ" "Stratíte prístup k svojim zašifrovaným správam, ak sa odhlásite z aplikácie %1$s na všetkých zariadeniach" "Ste si istí, že chcete vypnúť zálohovanie?" @@ -58,7 +58,7 @@ "Vygenerujte si váš kľúč na obnovenie" "Nezdieľajte to s nikým!" "Úspešné nastavenie obnovy" - "Nastaviť obnovenie" + "Získať kľúč na obnovenie" "Áno, znovu nastaviť teraz" "Tento proces je nezvratný." "Naozaj chcete obnoviť svoje šifrovanie?" diff --git a/libraries/matrixui/src/main/res/values-ko/translations.xml b/libraries/matrixui/src/main/res/values-ko/translations.xml index 09d831e348..b36a61cf9b 100644 --- a/libraries/matrixui/src/main/res/values-ko/translations.xml +++ b/libraries/matrixui/src/main/res/values-ko/translations.xml @@ -3,5 +3,7 @@ "초대장 보내기" "%1$s 와 채팅을 시작하시겠습니까?" "초대장을 보내시겠습니까?" + "이 사용자와의 대화 내역이 없습니다. 계속하려면 먼저 초대를 확인해 주세요." + "이 사용자와 대화를 시작하시겠습니까?" "%1$s (%2$s) 당신을 초대했습니다" diff --git a/libraries/mediaviewer/impl/src/main/res/values-ko/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-ko/translations.xml index 3362171d27..0a14586e6c 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-ko/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-ko/translations.xml @@ -16,6 +16,7 @@ "파일 명" "더 이상 표시할 파일이 없습니다" "더 이상 보여줄 미디어가 없습니다" + "파일 정보" "에 의해 업로드됨" "에 업로드됨" 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 1bf3802b12..5f45bea93b 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -50,12 +50,15 @@ "Avatar místnosti" "Odeslat soubory" "Poloha odesílatele" + "Odesláno %1$s v %2$s" "Vyžaduje se časově omezená akce, na ověření máte jednu minutu" "Nastavení, vyžaduje akci" "Zobrazit heslo" "Zahájit hovor" "Zahájit videohovor" "Zahájit hlasový hovor" + "Vlákno v %1$s" + "Vlákna v %1$s" "Místnost s náhrobkem" "Avatar uživatele" "Uživatelské menu" 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 ec14b73e04..a04e7aceb6 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -50,6 +50,7 @@ "Απαιτείται ενέργεια περιορισμένης χρονικής διάρκειας, έχετε ένα λεπτό για επαλήθευση." "Εμφάνιση κωδικού πρόσβασης" "Ξεκίνησε μια κλήση" + "Ξεκινήστε μια βιντεοκλήση" "Έναρξη φωνητικής κλήσης" "Θαμένη αίθουσα" "Άβαταρ χρήστη" 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 fd45849e7d..ae9ee22038 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -545,4 +545,6 @@ Kas sa oled kindel, et soovid jätkata?" "Sul pole ligipääsu antud sõnumile" "Sõnumi dekrüptimine ei õnnestu" "Kuna seade on verifitseerimata või saatja pole sinu digitaalset identiteeti verifitseerinud, siis sõnumi näitamine on blokeeritud." + "Sinu nutiseadme tarkvara on liiga vana, vajalik on Android 8 või uuem." + "Kaartide joonistamine pole toetatud" 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 88d8d712b0..096652fbd4 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -99,6 +99,7 @@ "Hylkää ja estä" "Poista" "Poista tili" + "Poista tiedosto" "Poista kysely" "Poista kaikki valinnat" "Poista käytöstä" @@ -304,6 +305,7 @@ Syy: %1$s." "Odota hetki…" "Haluatko varmasti lopettaa tämän kyselyn?" "Kysely: %1$s" + "Kysely" "Ääniä yhteensä: %1$s" "Tulokset näkyvät kyselyn päätyttyä" @@ -543,4 +545,6 @@ Haluatko varmasti jatkaa?" "Sinulla ei ole oikeutta lukea tätä viestiä" "Viestin salauksen purkaminen ei onnistu" "Tämä viesti estettiin, koska et ole vahvistanut laitettasi tai koska lähettäjän on vahvistettava diigitaalinen identiteettisi." + "Laitteesi on liian vanha, tarvitset laitteen, jossa on Android 8 tai uudempi." + "Karttojen renderöintiä ei tueta" 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 caca4b5014..37f1547a1c 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -18,6 +18,7 @@ "Információ" "Csatlakozás a híváshoz" "Ugrás az aljára" + "Ugrás az olvasatlanhoz" "Térkép áthelyezése a jelenlegi helyre" "Csak megemlítések" "Némítva" @@ -98,6 +99,7 @@ "Elutasítás és letiltás" "Törlés" "Fiók törlése" + "Fájl törlése" "Szavazás törlése" "Kijelölés megszüntetése" "Letiltás" @@ -303,6 +305,7 @@ Ok: %1$s." "Kis türelmet…" "Biztos, hogy befejezi ezt a szavazást?" "Szavazás: %1$s" + "Szavazás" "Összes szavazat: %1$s" "Az eredmények a szavazás befejezése után jelennek meg" @@ -541,4 +544,6 @@ Biztos, hogy folytatja?" "Nincs hozzáférése ehhez az üzenethez" "Nem sikerült visszafejteni az üzenetet" "Ez az üzenet azért lett blokkolva, mert vagy nem ellenőrizte az eszközt, vagy a feladónak ellenőriznie kell az Ön digitális személyazonosságát." + "Az Ön eszköze túl régi, Android 8 vagy újabb verziójú eszközre van szükség." + "A térképek megjelenítése nem támogatott" 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 ab5f64fc9e..a9bdedc1c1 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -97,6 +97,7 @@ "拒否してブロック" "削除" "アカウントを削除" + "ファイルを削除" "投票を削除" "全ての選択を解除" "無効化" @@ -292,7 +293,7 @@ "または" "他のオプション" "パスワード" - "人々" + "ユーザー" "固定リンク" "権限" "ピン留め" @@ -300,6 +301,7 @@ "お待ちください…" "本当に投票を終了しますか?" "投票: %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 303e8ba929..6336a8de92 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -8,13 +8,16 @@ "%1$d자리 입력됨" + "소요 시간: %1$s" "아바타 편집" "전체 주소는 다음과 같습니다 %1$s" "암호화 세부 정보" "메시지 텍스트 필드 확장" "비밀번호 숨기기" + "정보" "통화 참가" "맨 아래로 이동" + "읽지 않은 항목으로 이동" "지도를 내 위치로 이동" "멘션만" "음소거함" @@ -31,6 +34,7 @@ "재생 속도" "투표" "종료된 투표" + "위치: %1$s" "QR 코드" "%1$s에 반응하세요" "다른 이모지로 반응하세요" @@ -45,10 +49,15 @@ "방 아바타" "파일 보내기" "발신자 위치" + "%1$s님이 %2$s에 보냈습니다." "제한 시간 내 인증이 필요합니다.1분 안에 확인해 주세요." + "설정,조치 필요" "비밀번호 표시" "통화 시작" + "영상 통화 시작" "음성 통화 시작" + "%1$s 내 스레드" + "%1$s 내 스레드 목록" "묘비 방" "사용자 아바타" "사용자 메뉴" @@ -66,6 +75,7 @@ "통화" "취소" "현재 취소" + "파일 선택" "사진 선택" "지우기" "닫기" @@ -85,12 +95,16 @@ "계정 비활성화" "거절" "거부 및 차단" + "삭제" + "계정 삭제" + "파일 삭제" "투표 삭제" "전체 선택 해제" "비활성화" "취소" "닫기" "완료" + "다운로드" "편집" "캡션 편집" "투표 수정" @@ -197,7 +211,9 @@ "베타" "차단한 사용자" "버블" + "통화 거절" "통화 시작" + "통화를 거절하셨습니다" "채팅 백업" "클립보드에 복사됨" "저작권" @@ -285,6 +301,7 @@ "기다려 주세요…" "정말로 이 투표를 종료하시겠어요?" "투표: %1$s" + "투표" "총 투표수: %1$s" "결과는 투표가 끝난 이후에 공개됨" @@ -448,6 +465,9 @@ "이런, 오류가 발생했어요" "🔐️ %1$s에 참여하기" "%1$s에서 대화해요: %2$s" + "실시간 위치 공유" + "위치 공유 중" + "%1$s님의 실시간 위치" "%1$s Android" "강하게 흔들어서 오류 보고하기" "스크린샷" @@ -455,6 +475,12 @@ "옵션" "%1$s 제거" "설정" + "위치를 공유 중인 사용자가 없습니다." + "실시간 위치 공유 중" + + "%1$d명" + + "지도 보기" "미디어 선택에 실패했습니다. 다시 시도해 주세요." "메시지를 누르고 \"%1$s\" 를 선택하여 여기에 포함합니다." "중요한 메시지를 고정하여 쉽게 찾을 수 있도록 합니다" @@ -478,6 +504,7 @@ "메시지 %1$s" "펼치기" "줄이다" + "실시간 위치 공유 중" "이 방을 이미 보고 있습니다!" "%2$s 의 %1$s" "%1$s 고정된 메시지" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index baa2eb8506..2b34e82f91 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -101,6 +101,7 @@ "Odrzuć i zablokuj" "Usuń" "Usuń konto" + "Usuń plik" "Usuń ankietę" "Odznacz wszystko" "Wyłącz" @@ -555,4 +556,6 @@ Czy na pewno chcesz kontynuować?" "Nie masz uprawnień do tej wiadomości" "Nie można odszyfrować wiadomości" "Ta wiadomość została zablokowana, ponieważ urządzenie nie zostało zweryfikowane lub nadawca musi zweryfikować Twoją tożsamość." + "Twoje urządzenie jest przestarzałe, wymagany system Android 8 lub nowszy." + "Renderowanie map nie jest obsługiwane" 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 2acc9df99f..83a93763d1 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -532,4 +532,6 @@ "无权访问此消息" "无法解密消息" "此消息已被阻止,因为你未验证你的设备,或发送者需要验证你的数字身份。" + "你的设备过旧,需要 Android 8 或更高版本的设备。" + "地图渲染不受支持。" diff --git a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png index efd83f7af8..3419248cbe 100644 --- a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png +++ b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2e4ee3ec519388e7acdedac96636aa3f0e0d9dc4f4a061a0b3e4c345b824a3d -size 24961 +oid sha256:9af82b0e785a85acb47d0b02b682c659bc13dbff01eb969f367d2ee413b6cbb1 +size 25165 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png index b7a581021f..706b96c796 100644 --- a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png +++ b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d367fc2d1c620eb370e28db890e4f01acd85b0273b241d0b0b701f23939fabc8 -size 25377 +oid sha256:37dc07b7be3f81a8b3925e1325baecff04dc2f3cd92316140f969610b6362169 +size 25691 diff --git a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png index 0c1e7996ff..b8c5829e1e 100644 --- a/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png +++ b/screenshots/de/features.home.impl.roomlist_RoomListContextMenu_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6175b377fcdb3f70739c36ceb1d59a7e108d8f1d08b4c10ec6d28744ff0f0545 -size 27442 +oid sha256:ace88630fc2d12ce8f9f610683626ff9d8ad8d3a18564791d3abdcff5743ed46 +size 27731 diff --git a/screenshots/de/features.home.impl_HomeView_Day_6_de.png b/screenshots/de/features.home.impl_HomeView_Day_6_de.png index 467350fe56..10abd6aef3 100644 --- a/screenshots/de/features.home.impl_HomeView_Day_6_de.png +++ b/screenshots/de/features.home.impl_HomeView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cc8182e0e5413cc51f0df6d2724efae8af4101f9ac6cf21ca9260c2a2aa245a -size 57989 +oid sha256:a50cbaec05c9547c992342aba6f5042bbd0dcb6cae0a599e91b26edbafb59ac0 +size 58277 diff --git a/screenshots/de/features.home.impl_HomeView_Day_7_de.png b/screenshots/de/features.home.impl_HomeView_Day_7_de.png index 774818bd57..2e95e34feb 100644 --- a/screenshots/de/features.home.impl_HomeView_Day_7_de.png +++ b/screenshots/de/features.home.impl_HomeView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f235995960c6237f4e03e7b0736cb280e1627590b0761a334c7a969491a12da8 -size 57321 +oid sha256:b53cae15b14893fce996dc087b4907cb21104e220d143e64192753d1088c0c44 +size 57599 diff --git a/screenshots/de/features.home.impl_HomeView_Day_8_de.png b/screenshots/de/features.home.impl_HomeView_Day_8_de.png index e644082cae..5f62cc2ebf 100644 --- a/screenshots/de/features.home.impl_HomeView_Day_8_de.png +++ b/screenshots/de/features.home.impl_HomeView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba1fbfc866d6de2cafae55b6da0721f12a1acb25163ad31ae2995f6ff9016856 -size 56039 +oid sha256:d88ef28257f6c0893e8bfff2d98e5aff52f0534539e91fe6ca490989548a65b9 +size 56346 diff --git a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png index 7ea7736a31..fbcb03812f 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.error_ErrorView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06fa1d9cfcdd7e81dd5d08f584651d982136e7491041b4db6c0feb9875c2db49 -size 43509 +oid sha256:026cde07bd625e7457af44ef19c4865f6bad8fc7c8ddfcc43c7a6dbdd4acf467 +size 33651 diff --git a/screenshots/de/features.location.api_RenderingMapsNotSupportedDialog_Day_0_de.png b/screenshots/de/features.location.api_RenderingMapsNotSupportedDialog_Day_0_de.png new file mode 100644 index 0000000000..06c4be2c81 --- /dev/null +++ b/screenshots/de/features.location.api_RenderingMapsNotSupportedDialog_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3065603f9b067f0ddc89a7b8dc24921afd031f4658f6ac11de8feb0c4bf26b62 +size 23910 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png index d52980f113..0c68797fef 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e8cb1edecba35913251d57d6eaa9d48149f7b2a26c180978c0ae34d3d354d97 -size 19693 +oid sha256:6fe56f20ce5792f9dd60bf0ae08fa5c5c78fbb7a5f1a80eb2fe973716be69c00 +size 19831 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png index 0c68797fef..a49023fb61 100644 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png +++ b/screenshots/de/features.location.impl.show_ShowLocationView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fe56f20ce5792f9dd60bf0ae08fa5c5c78fbb7a5f1a80eb2fe973716be69c00 -size 19831 +oid sha256:fa435ee5d684b82c66c7207e0bcdc2d608a634e02d534530cccf8abd0f40f784 +size 21292 diff --git a/screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png b/screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png deleted file mode 100644 index a49023fb61..0000000000 --- a/screenshots/de/features.location.impl.show_ShowLocationView_Day_8_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa435ee5d684b82c66c7207e0bcdc2d608a634e02d534530cccf8abd0f40f784 -size 21292 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png index 8df559390e..2ce79cc887 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5758b86295a5cd92cd103992ee601c762b876fec28a4380c793a6c054993513b -size 35016 +oid sha256:1ee8832fede93fcbfccc7e554a7528ae77a50a3a8f8d9ed87e4bff209eb62807 +size 35457 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png index 044901ea5b..d8f4384537 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ce01cf6c3d326ad4208fa9832cab3e56164f791f59833b1f73d6f29e531dab8 -size 54709 +oid sha256:9b8b6dd8ce354e875e682b0f228bd9d4fc90b561202675aebd8f9bf83b228517 +size 55096 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png index a7ba678616..612c0d3171 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c52f77e77180d8e15b67abefac41b54107397fd489440d5aafdc4079d0100b8 -size 55075 +oid sha256:e9cf37d1b417d0626271087a6e1fa573ebd638192bc369dd376c67c67edcfdcf +size 55463 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png index 220ebf1ac9..90cddf85c4 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29ac70d223cc1f1c3a63c21431864f60bd6e199de574e1a2cded10bcaac11a8d -size 46842 +oid sha256:02f0679f2d5ffc1dc754f9bb317f765c3c49ee1e190d0aa234637c9a28ff8cb0 +size 47351 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png index 5150bb2206..c221f764c5 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f04c852c210a027d1792d7512aa9ecc3a6913d3ba9d18d8680df991f8050f57d -size 51086 +oid sha256:f753605522c268a0835a279f0680654bceb86f38ea4b76605fcb71917a77c7db +size 51594 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png index 3c5ff4c7c5..6a18dd3f5f 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0d6742849583dc21500d5dba09bf535f71a5bcd070cd129305c1dffd817d8b5 -size 49443 +oid sha256:820d30e4e8ff9329dee9d49fa6f0c28c5b1f5e4684db085c8e6ceb265fcbfb88 +size 49997 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png index ef8273806a..431e2101dd 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbf746337b88e848b7e99e526efe2ba468d28fd1536970ddc4e02e0d946e026d -size 45151 +oid sha256:a403f77984cca9eb94755dd74f1bd6db854725347dc8f15a207b20cc2dd43ee6 +size 45253 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png index b75f0d76b6..36a305a42d 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63b5fdd8b50485c835ce04e61b3c21d2f6d306d73c98675d1368772f4ca74c1d -size 49708 +oid sha256:17c1da5810c4d8ae13670fac57d5cb57b204cfbed83e71b2bcfe5657e6bf354a +size 50247 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png index 0d842f530c..c40acb066f 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d7e27bf9c1e2fa0bd86fbf986ced9f21ceabddae14c00086b691f182aa7ec5b -size 45918 +oid sha256:0043a95fd7946c8247a963e38057ad8b4f62f4112ede1df7cf6e609167dd1e87 +size 45974 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png index b6587618ec..0cb58754ac 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f61af5729e24ee0b15af8df2bd641411ac8f17a5b7f9a76899c6d05f328dbd05 -size 48879 +oid sha256:cccbcf0324e642f49c739f079bdf7ac18876f4dbb99e23d504b1c22669a376d2 +size 49352 diff --git a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png index e41b40ead2..37b41517cb 100644 --- a/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png +++ b/screenshots/de/features.messages.impl.actionlist_ActionListViewContent_Day_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f83a10070d130542d0783c8a39f588b869ec265b9c0026afaeccc0b7b50602e4 -size 38159 +oid sha256:a82d583db67f7507f0ca837b9b75897047808a1a7f3d828c7213a9a6f4578429 +size 38613 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png index 6c398bfae2..210020e06e 100644 --- a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56f7a86707c00d1833ebbb26182ad9f9f010ed8f016713076232d4134c8bb6e7 -size 329737 +oid sha256:99d5cf65c968619f2a99f382e2de07d08022f0325349f86571c5766d17fff9e0 +size 327894 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png index 25ae9b6949..3ee21f4b12 100644 --- a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6907cdde67cfb41246b9b86af19d0d46bf92914b21f9ab68d522f07dd83af153 -size 284058 +oid sha256:82b816075c7ca6898da2c295740f6828a15a16062e944f01a4401ac0b84f6008 +size 282325 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png index 0d11558b0e..7aeafb4481 100644 --- a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ec83baa6376355fcfa1e9a088faee47f5d7d87ed7608bcbe35e7438f9e0cdea -size 257324 +oid sha256:11222c39d8ef830649fdd0b35c95b31b4d934c0c2667674ef7d659d9a3320b52 +size 255483 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png index 6fadc05d09..2c62689a45 100644 --- a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17bd7ae449ad1fb92c75e09848bddf907d15cfcbbcb9554350893c7a6019add5 -size 278513 +oid sha256:bc3d7320da4451c862f1083981d628a4df4115e95f9e88db7e0d1910f9890eba +size 276670 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png index 3eba67d146..1ba1a3158a 100644 --- a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e692a9e204db51af62fa83af8c1c7dda4fdfe81077d3abced093f3f8dfdef2df -size 252607 +oid sha256:b23a3fd19bb6057dc13f61525a4589a3d1dd66a97818c4229d4db35cb6f56faa +size 250779 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png index cb1f4a9175..3f3fa22933 100644 --- a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e881c0e26edfd9f4f2eb7325e307edcd4220aae42337ce8d238cd64c88722de4 -size 312002 +oid sha256:028b3249d8d63cdf799ac1e0ab530e4a46140c53adf8b83a05153d03d030d4e6 +size 310168 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_de.png new file mode 100644 index 0000000000..aaedf662af --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24b6a36a3efa0127a099081ef711fa804879ddca347849580e80c2a147c7f4c9 +size 282515 diff --git a/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_de.png b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_de.png new file mode 100644 index 0000000000..5b2ff9626b --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7138b55da8a0a0a3ed2c049ec84d01fa298223a3b6ffe391fad7a7e3a3a3beb2 +size 282778 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png index 11e4bb1119..a10d3f58f7 100644 --- a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewView_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:130c46b4bd3589cc6a6e45a04f9793b742631daf21cbbf971f8e79a00f589ce8 -size 329628 +oid sha256:f350e78ea3bba4a80d22af4df58b8a6e415a68fe56770027c9da95da0cab0973 +size 327790 diff --git a/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png index 14abdc0caf..198bd4553b 100644 --- a/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png +++ b/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4f823bf8a422775693ba64ca10e087286967d11c8ed94a3198f108abd3a9367 -size 27026 +oid sha256:1ff21ba8a011e0aedbbcad919f46db1a26895ae6e286335055532f43dbf505de +size 27661 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png index 807e16c40a..6d9b506ac7 100644 --- a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbdd0d31786b29709c02e9f35191af1334b6f6a32cc0614a833f79d47551fc70 -size 42687 +oid sha256:cc44a5bef33ae51161dee412b729baf328b188976156d7eeb7677039ad60b7cd +size 42147 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png index ba7d60941b..2cc385f926 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e916a49d3cd4d81d8ec5f3d66f0b930bfba6e9c20f1b9c5f7d4c0bfe51895036 -size 67398 +oid sha256:a6325d21da32e6def01f35803b4823d037076f0c96c24d864fad33b0a7d9a7b7 +size 65731 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png index 0d70a656c2..1d36e3c163 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86fa2e5742ba38c173add0921615a18c1271caa783fd1a505c80a06096a3c248 -size 71646 +oid sha256:853058d4d90fc9d39115263ab74e7813ab6a52844cc56cc4a30c3dcb42e291b9 +size 70016 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png index 8e73293bb2..5f24ba6d45 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1afe6a244e864befb72decf8d2518b9588b3f59b5382c8e5c6130a2ea33e23b -size 41952 +oid sha256:c100900785c0c11cd69b60da9ed3909f135b876d0546722f707febd24e796256 +size 42510 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index 9dfcbcf1f6..e3f488bde5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce3c8e771e43c186cadcf495a7d85d6ad36c089373782c209170282e0e5fb1fb -size 49709 +oid sha256:4d7c45ac3f5fd12f909706a1da3aae7620472958966eac0d49ba3020dc52b312 +size 46054 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 26411218a7..1022a785ff 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db7a53d858a08f1396a9c04b6a253623fa25160f90de62be9dc187f72fccedbd -size 48374 +oid sha256:41931967f6bc1b5a1244764bf1c9b8bf498f107edf8d85f6fd07ab3d6c5f2468 +size 44146 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index db935d5dc9..3a8ba95641 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38e49c07c2f49bee8ba4d37f684be34ccb247bfecbfea5b1733e76246d160a45 -size 47086 +oid sha256:98e3c0f5bd719b4e5c47852e8e5620fa79724cd48d9360c4f2064f8a650555d7 +size 43499 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index d0343f2f12..00ce182ff6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f91bfd31c40b1cea5b4dd763dbc92eaaf7335d078ac496b51b05617c01f8b96 -size 48934 +oid sha256:e6da9e5dcfe52ebd26e4b590eb7cedb751a53729344556384d04d66da6f8b9e0 +size 44489 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index 12ccf2ffc3..f09ef8bd09 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d85a9aa1456dccaef8a7cb2c8b8c756e54c4fe03402d39d1240624d279449c28 -size 48821 +oid sha256:c7db4c8739f40a186a84c8420dbbf44c53aa1a079c74437348d651eb91482e8c +size 44445 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index 625ef06b29..3156bdaf97 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b65c937240f2a5bee4e4170a511fff5437c5bce47fb987674548487fcf72fd1 -size 49350 +oid sha256:3626d055f83fcfe23d0cbd79b2be99fb2238ce4e5da4c80b17bc20353849c32a +size 45859 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 0ab84d817e..cd433d98e8 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f965ec5c45372e04fdcdc1c3c65633551f83e8dede75df8e8c329f849f487bf -size 49885 +oid sha256:8e1a5175e48e200145a132a9b87cdde64ff9c5bcd14e049c7ce81a27e11c9661 +size 46222 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index 4798c4bc07..368a0713fa 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b68d23accbe81e6913d16ef6bb15712105422911905f274d66ef656f98d8a28f -size 49201 +oid sha256:1d192d1d08b4bb235e894141d79d7fe0a19e5fc7d1dfffc25d9b7b797e9f5a1b +size 44681 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index 11a68a7982..786c66da58 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3699ee438dbbd4aa0e5c5cd5a054304888421cb8c8a822dc52cb8369816f7feb -size 48429 +oid sha256:e30a3b6f61cfa1933989eadac016b2dbb565634f95bfb118c3a0c248bbbda9c3 +size 44129 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index de0323860c..7d0b7034cd 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3eada7d271b1f649d931e5077fc04e232046fd4171881c673bab8eaf990f92b -size 44452 +oid sha256:91351802609eb6468d1f544a403246d88c38a58e76437ddeda36d1530499475e +size 42646 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index 65d67f1746..3bf58a45d8 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:934be11ba08bc83461c1d859b3cf8b6f367feb89f6a779689ece209c30d8eaa8 -size 44441 +oid sha256:24238416160eb851769d2f6634e267dba824450e93fd7f193d5d6e3806741afc +size 42641 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index 637fe31e2f..67d3aac6fe 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:540a461ec0a84d22269abc644dd62444223818e337edbab2f79317f80cc24696 -size 44107 +oid sha256:6ccca13029b6f5fdbd79bd7cdacc90bfc4e4acea0ab59416785cd1ed84f0e110 +size 40637 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index bfa129700d..57782baea0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30918ebc116ebf2058aa619debfa9165d5ef95feb916a83e94e49d09377435e8 -size 49193 +oid sha256:df391568836eb548b3226c88ef9bfc60cf62ef8bca9eb20dde68c18c06ff9e3c +size 44645 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index 8a5276b209..93bb4e5916 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cf3437703035eec0dd9623032bb62f1472b1a5fe996b7b85b9050385eb118ba -size 49109 +oid sha256:615c16c1d98590e0d4cc81222a1f8fdc534681f5ad99ce3cda82bc4f024d555c +size 44587 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index a9e5ff3132..b7ec17f054 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:983d019c59d97d4bbe5b42562d6d028bb094a5b405fb2adc033232838952890d -size 48673 +oid sha256:abf088b6f30665a9e5d9d8a60ed170d0b8b7c219e8b71558ac9900986de1ef54 +size 44251 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index 404ba5c5c1..4db528159c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c79eb29314fbb2378034b03d368d5ca49ae49c6a53387784445a0b97e3cc56e -size 43324 +oid sha256:70bf1adc246f1d2b792048ea5739358c39935daab42b9a061241dffac4f8501e +size 38503 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index b492032c83..c645f66027 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d605c8379ff6844f7581231574cdfb50e5bce0b2e33c886fd43b520576f9149a -size 45963 +oid sha256:42392b475d4ef7351a0f91d2803beaff53c99dd2e3c682e6619c8edac638899f +size 34399 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index 09c0f584a7..ad9a59b471 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:355905f6a0fc25abe31db1359f24af1acb60bb3a013e697663c3ee9f87a9be52 -size 47386 +oid sha256:15f8f4091caeda71cc1a3cda9c100a0b5aab7bfa6feff4e70e6f2308258248b4 +size 42985 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index 0fd7d3e667..49d2def3f5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a378c9b3a9bde80050444029ec6eaaaf76a5182c45babc898dbea24207466a32 -size 44054 +oid sha256:2f0c96227163246012a54fd985b282386231ffb9b03952ad4c2058500a081cb4 +size 42356 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index 6392ad39ea..b8f184af2c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:737de18454bbb78bd9ca789ba1ab821f203c54d55301a5851ae01e336cc42260 -size 45324 +oid sha256:9406cb785c88cc1b370678140b57b5928e46616274529853e7700ad48768feed +size 34945 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index 425e08b224..e9a027a9d6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2ce5bb8422a493541b30fe3eb95f756367358e039b759967e1f4d96f7cf337a -size 49729 +oid sha256:68ae4856b0ea5e73705d83b927577457695b8e5908c7d71e029953ee9cd8d8a7 +size 45124 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index 6be8a7cc91..5911a811cd 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4fd1c7495908336646a05655f1c4c2d2ea0ece1e690f69164cc2946273a077c -size 49038 +oid sha256:4883dfc428a83e97ed406b172c91772ec7b51c9df074b385d7d719abd2ac1f1c +size 44648 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index 8927152505..cb17901678 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12d25ae598f1a05aa86f0125b6acbaa4137becc2900a2ac649880c521ba2ef52 -size 48034 +oid sha256:2e0782f2c450127e1079999e76c4683c0550e1c3fc6867fe6a8438c457a1c212 +size 43210 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index 86a072cb2b..1ef1806d32 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7382605cb34650919a0b9f1d1e9460e28ce963dc4ff899fc6906dfcdd73dda50 -size 50783 +oid sha256:ca9bd8eaae03a23e19f307e48200a3acad5adaf25f85b9ff996dfd34e2afa7ea +size 47683 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index b3d5dd204c..09d0b0b2dc 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6f057a687620b49fde08e0c241aadca011d87154e73b7cbaf21a22896de07c9 -size 49348 +oid sha256:8ce03c0a8cd57000abb832adfc9109ce11901f2e7299ede7f0d1d26954d71dc0 +size 45588 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index abf7a28899..8c96b6425f 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a08b46085a213f7c6a93f24c2afc04cab4a0c30369d6eaf552cc6e58f50aea34 -size 48160 +oid sha256:14e924fdb76d565050a354a7fbf423e2f2a42bf4ad97e4ea936ab774fd4c7817 +size 45027 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index 257169012b..4bc445b2fa 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e624adcc59354fc21c960547d0766929b95e1a2745b667eb57dd5e62d3ca8451 -size 49914 +oid sha256:b65295a9ef7403a39960379d005702837cdd994f95ef4ac68901052c28d3ea1f +size 45989 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index 3804c84919..f47c6ad939 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60cc99a113658fc4222b68b4801066c112d02dbd5c5b39e12471f77bb71ab348 -size 49807 +oid sha256:29964bd165474c6d04de2030c5529af2e2413ee84f3aaf9bd317303a829fcd46 +size 45922 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index 080e2d2199..c52350d443 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd16c5e9846823589ad5b22568c25b0cf3335cba8b467ceb3c9186e5b84e7fc7 -size 50318 +oid sha256:9ecfbf047383b98642fadba05e9ce0fcf74126088ee690bb4c32be65588408ab +size 47473 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index f80834a2e0..61cde4f5b1 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d3dbdcfe1dedaabb5d03dbdcc2a2f377fb6d1aafccd6b70cb147a97bf23b1c5 -size 50929 +oid sha256:9ce8737bb8f4774165acf35250efcf9ca6f05158073ffe50601ffca66bcc60c7 +size 47907 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index b43767563e..d3a81f277b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0761670005dd4463b662efb563a5270f89790470017d42001d00ce44e96f045c -size 50201 +oid sha256:592d316544feaafacec23fdcf5cdb4470a8207835ba87a723ef45b4b2f764917 +size 46236 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index 3c0a33e5fc..dc25cda13d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6361321527d1bfa1ea84b361dec64c3746a85079a4048666e4016f52d3d34246 -size 49681 +oid sha256:88816d1cd342284e6af3da0e89236a03fdc149ebe7d621d8590d8730d8c81bcc +size 45758 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index c3b0b28c5d..805a1f7fc5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5bbd36791567c89996dcd755b3ff4f956f69f1ff3f6f66595f16e1e733fe0a7 -size 45751 +oid sha256:ce7df8bc9256fad4cb3cff8f3147f1c74ac31a9e379b86c428b31d8ee0a1b3ff +size 44438 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 7dc11fb06d..94ba841c62 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bf0969b8a24c8d06fb3253646d6e2d0a94572cc346a8a9f9522ae48e5b4217a -size 45686 +oid sha256:df68b3579de58586a02141996672bb25cdf1056030a2341ae70383fbe2648f04 +size 44404 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 4fb1d5bebc..c43dfc4765 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cfbd204c871feea36d0ac5ec740049488a9d3511156cf7a3e30d724d62fbdae -size 45187 +oid sha256:f036fb2f808035db5e5891f48c51586883f1cf52116c07be1698cb901bb12a28 +size 41932 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index 96b2a06800..11bc2637cd 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84af752733042d4d487a934144525bbcf31cf9c1cb1454a5561ea9b3bf794afd -size 50205 +oid sha256:4fa2e5f4110ac0235e6e15ce5dd11b684a301e8508ef4a339f819239ed7bdf6a +size 46219 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index 3576b6b30c..cadcd1e2b4 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a5c142c8539e0a7d40f4455e96d3d5fe1003f2cef84095709f15fd63b945a06 -size 50130 +oid sha256:a8f1c358b1de30937278423b42bdc468cd36a82ff78cb0c687cd26c9e8ce3b05 +size 46106 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index 6905512be4..9ed59d7c04 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:375274f827cb0b1a56461a95ebbbc12ab8dead23a41059b0909d87892b5b7f74 -size 49645 +oid sha256:3e4d19c67a12095c513363905af5f9d01b1f96ed21f8809b3a34162fb7f4cd18 +size 45707 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index 23620c662b..784d22cc5e 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9737debc2f342c5ce2b20f48151597e164526297d2789b04bfda74e4cc70153c -size 44357 +oid sha256:dc77c07d95d2fe8482d0aa1a16f02ad1f1bb12b42b96e49613c305bb7001d85b +size 39970 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index aca9ef2193..4e841931bb 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d16e1a72ac9f47e0236b5ce3bf82c7e8d0d3ca0b245aba5fc751a0b9bed6cae -size 46946 +oid sha256:2f92411b4c22dd91cea3fe2b83e68855106f0cc8f8e98bff7120d7ad9ee08b8f +size 35510 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index ab1ea77140..b81166bff6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e483482b88e7edc6724459da394f87a587ada9ddefea5d05d9bdcfe57e34ec47 -size 48423 +oid sha256:dc47591d0c528d2690c93cc753944a3d14cf5874a76375e85280f20248e0a461 +size 44643 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index bd270b4ed0..1ca8f85e28 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c8130c023137a1c3872202df289f364a3cc85217c7b0d7d36609d1fe896e96c -size 45304 +oid sha256:6b8c3af45a0302fbbb8162acb3cff65f3ece5d9c583655c73490ebfc4d67fbf6 +size 44110 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 26e23487c0..b7df110e3c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c67de39146bb8c0049de90223d4a7293e3f42ab8f3780cc0980e62c97d10760 -size 46651 +oid sha256:2e2ae44ab89b544cb00c4cc72bc20eb4b7c1ad8964bf6eaf95499cd4727ecb01 +size 36461 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index 2001c831b0..c3363c0921 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69695044a9afdc82d1a65e0911effcbb660dd550c31d5b8ae1f6a0f674dacd30 -size 50843 +oid sha256:b626694fb5e69a36f345ff1500aa502fcc6b780d94af51670a43891702bbb0bf +size 46728 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index bbec3a797e..1bda15b8d4 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acbbccc700060f3511bdc2a44661ecd1442bb8db107c52d8a3ea93085e3cc370 -size 50181 +oid sha256:e4d3dc8b6a30ec8a716af574f5f92d33cd1804eeb33427b162a439257157e694 +size 46229 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index f1098ffed9..8764bb944e 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:891f50447359e8697ca26ac27179fb1687851c24156d36006764c874592c7584 -size 49072 +oid sha256:2dd181d7a3d507f25a7cb7717dd96a0a2e6f37896291ce160c356f8ab89b3637 +size 44769 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png index 5781478873..c69f23d822 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a78ad12392ea4d4e9e54ffbc786a6e3eec73294e088f5403db88af5269a6b003 -size 18523 +oid sha256:21e3fa2d81c7fb57c8c89581e6e6202406b25dd83c19e029fb46c0ed3ad3ac16 +size 18663 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png index 819491fece..c141aa0941 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5dc117e18612891f202c6bc093e4a2063632ee974939606af6eb09ee36deba9e -size 22172 +oid sha256:07b7bffa03de36ddcf461b74d5750d92ea67728b94c864b3c8cb8a1aac48ae30 +size 22349 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png index ad63075b13..343c53d7c0 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc3534d406c3ef468e9af1b86d8d09998fd173aa1f63627412053f4e4d76bbcd -size 27625 +oid sha256:d7b55e28962e18b4a14f4b1e57f455cb1183b993ddbc6449352222a0e338afdd +size 27748 diff --git a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png index d5df6b6df0..c631961b73 100644 --- a/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png +++ b/screenshots/de/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1d10f6ddd38cffdf7f8ba188790f6115b18b95de401ce08ba4530f249f99410 -size 28109 +oid sha256:5d3dfc118145e83a3ef346de399e4f07aaa24e3adbeb039a24387d9ba666beb7 +size 28210 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png index e7254790cf..9f12c8c18d 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7bf1f5e039bdff2ba1da2678d57637564288733b9958042b86867350277ca9f -size 25025 +oid sha256:0c80ae6573c4d41b14827623890cb6b211783c708d7417c3b9f1e1ab29462098 +size 25198 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_5_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_5_de.png index c7bfa31dae..81b5bb4a95 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_5_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a73316a4090908c2c8db15fa408e132f3fc7308c898311008f59ff62fdb94801 -size 23050 +oid sha256:09404876c06fa55c2e01f48380f7a4767d8c55f0cd46bdec78f4d7687ba8101d +size 23150 diff --git a/screenshots/de/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_de.png index 4263d29577..012c3b1574 100644 --- a/screenshots/de/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff83b8d841c355dcac18d1ba0c7a66d0927e23be66bfabe8bc791e6f2ff3db22 -size 14008 +oid sha256:fbebdd9012c183c27ed79a3cb1dd5b823f73025756d9875c0c5a7af6f126dfa1 +size 14153 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png index 5fa5394165..748733038c 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e2325778fc5bdaa5ffd421f77cb83d1927ad4ad6731337b4878a99d3fbfe8aa -size 46053 +oid sha256:f02798a686487a372f781ba8db1c08364b4b7364e49ca6084eb48889967a329f +size 46360 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png index 5fa5394165..8ad903b190 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e2325778fc5bdaa5ffd421f77cb83d1927ad4ad6731337b4878a99d3fbfe8aa -size 46053 +oid sha256:555a9ecff384c0771f9825e5d222c6094818fddf79f144e4061d933bf752fd89 +size 44528 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png index 1e6c6d88eb..3e11375bf3 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f845e0783b6f09ef7b0472f22465e8e5b086102d711e468f1466df45ff928ed -size 50410 +oid sha256:de1d4d817742b8390b7e09bd8c66ca1ce294b22dc2c8c111205bec3436b57222 +size 51558 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png index 79f832dcc3..67b61583b1 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2917a353e78569a92d5d276e99ebfce334ad8848d488f58312abb9d7bcf654b -size 33327 +oid sha256:2bc723ee90bcd7038d78ccf738422daca8a0b0d54f9e86512399230912281d9a +size 33332 diff --git a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_de.png b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_de.png new file mode 100644 index 0000000000..508383d519 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44d94152af559ac75475599fb5cf14defc96997e73e38600ff51c869903944f4 +size 45625 diff --git a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png index 1ec5f1ed66..5c0d5c66e5 100644 --- a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0321ed8731d4867c59c482a8e631291537556f6003659b9e0c2aa77d61883a69 -size 45973 +oid sha256:b64f60650f09cd069468a3860808bed51ae2d9e11f2dc0798965674a15e2e04e +size 46275 diff --git a/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_de.png b/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_de.png new file mode 100644 index 0000000000..b45beedb7e --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0a4907f2ebf197b1cec1715ac6682d21b7b1d0a80eb5d05108f1971b648126f +size 12445 diff --git a/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_de.png b/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_de.png new file mode 100644 index 0000000000..9541983cee --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e0d9c3194ce7ac6096be5007d9e4d3b8e3fc6784c0389b1d14a288b48677304 +size 13776 diff --git a/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_de.png b/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_de.png new file mode 100644 index 0000000000..d1207e09a2 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f42dca3f4cdeb760ea11c3edcb8751518e7e42a423ffbafaf12cc97d9cd4861 +size 14965 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png index c4822fa433..b81a3c6a5c 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2c35cf93948bbc2c344bc678db1159e77769577054bee9ed168cd07ccea5de2 -size 28202 +oid sha256:73a6a48d04d86e9d5e9e546681863c32f651e6dc9af6d7f042e7e36b7fd98997 +size 28178 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png new file mode 100644 index 0000000000..d8118a67f0 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6298eeaf8442246d35fcca3b9e46755353d12bd9d6bfaa8a1e0447ee5d730e92 +size 198311 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_de.png new file mode 100644 index 0000000000..090a403022 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ef79c13235d94887d873c42faa9b09c901efaeae7602336c81fcf7c62955ea5 +size 198916 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png index 16575bf2f5..25848ecda6 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5300a530f5afb27d55369a9fec9af46e4ceccfe3ae6926d7bff90a7b8cbaa02d -size 44430 +oid sha256:1a1cb205c91f54437af19cf47218a6a4b520c3d6763c36716d48a2902e9622b6 +size 44981 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_6_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_6_de.png new file mode 100644 index 0000000000..80d843ceda --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebf8c21f8967a2bce2ef74ac896497e6732f8bbab5c895bc3d33e760791ea570 +size 126353 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_7_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_7_de.png new file mode 100644 index 0000000000..a4c2824fe3 --- /dev/null +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerView_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b1e398fa1cbf25d16ba4da6b8fd0c09a96e4f10855e94e913a1e06f0cea9c05 +size 17008 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index edcd08b481..313d0ffc79 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -2,105 +2,107 @@ export const screenshots = [ ["en","en-dark","de",], ["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",0,], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20602,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20609,], ["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",20602,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20602,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20602,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20602,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20602,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20602,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20602,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20602,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20602,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20602,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20602,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20609,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20609,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20609,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20609,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20609,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20609,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20609,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20609,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20609,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20609,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20609,], ["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",20602,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20602,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20609,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20609,], ["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",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20609,], ["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",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20602,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20602,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20602,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20602,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20602,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20602,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20602,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20602,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20602,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20602,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20609,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20609,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20609,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20609,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20609,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20609,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20609,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20609,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20609,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20609,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20602,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20602,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20602,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20602,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20602,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20609,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20609,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20609,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20609,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20609,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20602,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20602,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20602,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20602,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20609,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20609,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20609,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20609,], ["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",20602,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20609,], ["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",20602,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20609,], ["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",20602,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20609,], ["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.attachments.preview.imageeditor_AttachmentImageEditorView_0_en","",20605,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20605,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20605,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20605,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20605,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20605,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20602,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en","",20609,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20609,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20609,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20609,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20609,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20609,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en","",20612,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en","",20612,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20609,], ["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,], @@ -110,20 +112,20 @@ 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","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20602,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20605,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20609,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20609,], ["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",20602,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20609,], ["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,], @@ -153,22 +155,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",20602,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20609,], ["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",20602,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20602,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20602,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20602,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20602,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20602,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20602,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20609,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20609,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20609,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20609,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20609,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20609,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20609,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20602,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20602,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20602,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20602,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20602,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20609,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20609,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20609,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20609,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20609,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -179,141 +181,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",20602,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20602,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20609,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20609,], ["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",20602,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20609,], ["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",20602,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20602,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20602,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20602,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20602,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20602,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20609,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20609,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20609,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20609,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20609,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20609,], ["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",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20602,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20602,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20602,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20609,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20609,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20609,], ["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",20602,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20602,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20602,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20602,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20602,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20609,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20609,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20609,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20609,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20609,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20602,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20609,], ["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",20602,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20602,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20602,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20602,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20602,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20602,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20602,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20602,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20609,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20609,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20609,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20609,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20609,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20609,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20609,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20609,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], -["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20602,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20609,], ["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",20602,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20602,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20602,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20602,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20602,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20602,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20602,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20609,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20609,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20609,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20609,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20609,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20609,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20609,], ["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","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20602,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20602,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20602,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20602,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20602,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20602,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20609,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20609,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20609,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20609,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20609,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20609,], ["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",20602,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20602,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20602,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20602,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20602,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20602,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20602,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20602,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20602,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20602,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20602,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20602,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20602,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20602,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20602,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20602,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20602,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20602,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20602,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20602,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20609,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20609,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20609,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20609,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20609,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20609,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20609,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20609,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20609,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20609,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20609,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20609,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20609,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20609,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20609,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20609,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20609,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20609,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20609,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20609,], ["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","",20602,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20602,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20602,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20602,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20602,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20602,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20602,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20609,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20609,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20609,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20609,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20609,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20609,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20609,], ["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",20602,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20602,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20602,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20609,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20609,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20609,], ["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",20602,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20609,], ["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",20602,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20602,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20602,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20602,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20602,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20602,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20602,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20602,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20602,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20609,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20609,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20609,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20609,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20609,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20609,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20609,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20609,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20609,], ["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,], @@ -326,20 +328,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",20602,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20602,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20602,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20602,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20602,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20602,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20602,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20602,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20602,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20602,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20602,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20602,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20602,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20602,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20609,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20609,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20609,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20609,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20609,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20609,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20609,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20609,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20609,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20609,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20609,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20609,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20609,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20609,], ["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,], @@ -347,29 +349,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20602,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20602,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20609,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20609,], ["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",20602,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20602,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20602,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20602,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20602,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20602,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20602,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20602,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20602,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20602,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20609,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20609,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20609,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20609,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20609,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20609,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20609,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20609,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20609,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20609,], ["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,], @@ -389,49 +391,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",20602,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20602,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20602,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20609,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20609,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20609,], ["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",20602,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20602,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20609,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20609,], ["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",20602,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20609,], ["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",20602,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20602,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20602,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20602,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20602,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20609,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20609,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20609,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20609,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20609,], ["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",20602,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20602,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20609,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20609,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20602,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20602,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20609,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20609,], ["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",20602,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20602,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20602,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20602,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20602,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20602,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20602,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20602,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20602,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20602,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20602,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20602,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20602,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20609,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20609,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20609,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20609,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20609,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20609,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20609,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20609,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20609,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20609,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20609,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20609,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20609,], ["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,], @@ -446,8 +448,8 @@ export const screenshots = [ ["appicon.enterprise_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",20602,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20602,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20609,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20609,], ["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,], @@ -455,119 +457,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",20602,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20609,], ["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",20602,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20609,], ["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",20602,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20602,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20609,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20609,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20602,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20602,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20609,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20609,], ["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",20602,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20602,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20602,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20609,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20609,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20609,], ["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",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20609,], ["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",20602,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20602,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20602,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20609,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20609,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20609,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20609,], ["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",20602,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20602,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20602,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20602,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20602,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20602,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20602,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20602,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20609,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20609,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20609,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20609,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20609,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20609,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20609,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20609,], ["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",20602,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20602,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20602,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20602,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20602,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20609,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20609,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20609,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20609,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20602,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20602,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20609,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20609,], ["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",20602,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20602,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20602,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20602,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20602,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20602,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20602,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20602,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20609,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20609,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20609,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20609,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20609,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20609,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20609,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20609,], ["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",20602,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20602,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20602,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20602,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20602,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20602,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20609,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20609,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20609,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20609,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20609,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20609,], ["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",20602,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20609,], ["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,], @@ -620,48 +622,48 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextNoPadding_List_supporting_text_-_no_padding_List_sections_en","",0,], ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], -["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20602,], +["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20609,], ["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",20602,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20609,], ["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",20602,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20602,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20602,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20609,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20609,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20609,], ["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",20602,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20602,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20602,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20602,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20602,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20602,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20602,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20602,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20602,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20602,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20602,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20602,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20602,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20602,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20602,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20602,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20602,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20602,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20602,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20602,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20602,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20602,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20602,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20602,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20602,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20602,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20602,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20609,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20609,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20609,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20609,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20609,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20609,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20609,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20609,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20609,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20609,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20609,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20609,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20609,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20609,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20609,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20609,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20609,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20609,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20609,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20609,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20609,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20609,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20609,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20609,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20609,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20609,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20609,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20602,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20602,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20602,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20602,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20609,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20609,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20609,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20609,], ["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,], @@ -674,26 +676,29 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20602,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20602,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20602,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20602,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20602,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20602,], -["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",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20602,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20602,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20609,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20609,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20609,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20609,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20609,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20609,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en",20612,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",20612,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en",20612,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en",20612,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20609,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20609,], ["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,], @@ -701,10 +706,10 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20602,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20609,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20609,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20609,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], @@ -714,20 +719,20 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20609,], ["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_6_en","",20612,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en","",20612,], ["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","",20602,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20609,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20609,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20609,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], @@ -737,12 +742,12 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerView_20_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_21_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_22_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20602,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20609,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_6_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_7_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_6_en","",20612,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_7_en","",20612,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_8_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App_Bars_en","",0,], @@ -751,7 +756,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",20602,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20609,], ["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,], @@ -760,7 +765,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",20602,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20609,], ["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,], @@ -769,24 +774,24 @@ 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",20602,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20602,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20602,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20602,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20602,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20602,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20602,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20602,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20602,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20602,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20602,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20602,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20602,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20602,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20602,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20602,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20609,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20609,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20609,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20609,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20609,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20609,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20609,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20609,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20609,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20609,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20609,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20609,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20609,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20609,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20609,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20609,], ["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",20602,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20609,], ["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,], @@ -797,124 +802,124 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20605,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20602,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20602,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20602,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20609,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20609,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20609,], ["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",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20602,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20602,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20609,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20609,], ["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",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20602,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20609,], ["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",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20602,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20602,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20609,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20609,], ["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",20602,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20602,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20602,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20602,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20602,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20602,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20609,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20609,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20609,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20609,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20609,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20609,], ["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",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20602,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20602,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20609,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20609,], ["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",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20602,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20602,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20602,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20602,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20602,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20602,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20609,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20609,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20609,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20609,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20609,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20609,], ["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",20602,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20602,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20602,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20602,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20602,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20609,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20609,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20609,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20609,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20609,], ["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",20602,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20602,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20602,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20602,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20602,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20602,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20602,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20602,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20602,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20602,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20602,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20609,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20609,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20609,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20609,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20609,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20609,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20609,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20609,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20609,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20609,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20609,], ["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,], @@ -928,225 +933,226 @@ 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","",20602,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20602,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20602,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20609,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20609,], ["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","",20602,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20602,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20609,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20609,], ["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",20602,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20602,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20602,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20602,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20602,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20602,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20602,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20602,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20602,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20602,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20602,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20602,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20602,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20602,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20602,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20602,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20602,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20602,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20602,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20602,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20602,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20609,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20609,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20609,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20609,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20609,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20609,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20609,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20609,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20609,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20609,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20609,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20609,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20609,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20609,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20609,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20609,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20609,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20609,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20609,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20609,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20609,], ["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",20602,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20602,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20609,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20609,], ["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",20602,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20602,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20602,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20602,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20602,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20602,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20602,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20609,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20609,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20609,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20609,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20609,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20609,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20609,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], +["features.location.api_RenderingMapsNotSupportedDialog_Day_0_en","features.location.api_RenderingMapsNotSupportedDialog_Night_0_en",20612,], ["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",20602,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20602,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20602,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20602,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20602,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20602,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20602,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20602,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20602,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20602,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20602,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20602,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20602,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20602,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20602,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20602,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20602,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20609,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20609,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20609,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20609,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20609,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20609,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20609,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20609,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20609,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20609,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20609,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20609,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20609,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20609,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20609,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20609,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20609,], ["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",20602,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20602,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20602,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20602,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20602,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20609,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20609,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20609,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20609,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20609,], ["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",20602,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20602,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20609,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20609,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20602,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20602,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20602,], -["features.roomdetails.impl_RoomDetails_0_en","",20602,], -["features.roomdetails.impl_RoomDetails_10_en","",20602,], -["features.roomdetails.impl_RoomDetails_11_en","",20602,], -["features.roomdetails.impl_RoomDetails_12_en","",20602,], -["features.roomdetails.impl_RoomDetails_13_en","",20602,], -["features.roomdetails.impl_RoomDetails_14_en","",20602,], -["features.roomdetails.impl_RoomDetails_15_en","",20602,], -["features.roomdetails.impl_RoomDetails_16_en","",20602,], -["features.roomdetails.impl_RoomDetails_17_en","",20602,], -["features.roomdetails.impl_RoomDetails_18_en","",20602,], -["features.roomdetails.impl_RoomDetails_19_en","",20602,], -["features.roomdetails.impl_RoomDetails_1_en","",20602,], -["features.roomdetails.impl_RoomDetails_20_en","",20602,], -["features.roomdetails.impl_RoomDetails_21_en","",20602,], -["features.roomdetails.impl_RoomDetails_22_en","",20602,], -["features.roomdetails.impl_RoomDetails_2_en","",20602,], -["features.roomdetails.impl_RoomDetails_3_en","",20602,], -["features.roomdetails.impl_RoomDetails_4_en","",20602,], -["features.roomdetails.impl_RoomDetails_5_en","",20602,], -["features.roomdetails.impl_RoomDetails_6_en","",20602,], -["features.roomdetails.impl_RoomDetails_7_en","",20602,], -["features.roomdetails.impl_RoomDetails_8_en","",20602,], -["features.roomdetails.impl_RoomDetails_9_en","",20602,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20602,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20602,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20602,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20602,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20602,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20602,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20602,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20602,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20602,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20609,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20609,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20609,], +["features.roomdetails.impl_RoomDetails_0_en","",20609,], +["features.roomdetails.impl_RoomDetails_10_en","",20609,], +["features.roomdetails.impl_RoomDetails_11_en","",20609,], +["features.roomdetails.impl_RoomDetails_12_en","",20609,], +["features.roomdetails.impl_RoomDetails_13_en","",20609,], +["features.roomdetails.impl_RoomDetails_14_en","",20609,], +["features.roomdetails.impl_RoomDetails_15_en","",20609,], +["features.roomdetails.impl_RoomDetails_16_en","",20609,], +["features.roomdetails.impl_RoomDetails_17_en","",20609,], +["features.roomdetails.impl_RoomDetails_18_en","",20609,], +["features.roomdetails.impl_RoomDetails_19_en","",20609,], +["features.roomdetails.impl_RoomDetails_1_en","",20609,], +["features.roomdetails.impl_RoomDetails_20_en","",20609,], +["features.roomdetails.impl_RoomDetails_21_en","",20609,], +["features.roomdetails.impl_RoomDetails_22_en","",20609,], +["features.roomdetails.impl_RoomDetails_2_en","",20609,], +["features.roomdetails.impl_RoomDetails_3_en","",20609,], +["features.roomdetails.impl_RoomDetails_4_en","",20609,], +["features.roomdetails.impl_RoomDetails_5_en","",20609,], +["features.roomdetails.impl_RoomDetails_6_en","",20609,], +["features.roomdetails.impl_RoomDetails_7_en","",20609,], +["features.roomdetails.impl_RoomDetails_8_en","",20609,], +["features.roomdetails.impl_RoomDetails_9_en","",20609,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20609,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20609,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20609,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20609,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20609,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20609,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20609,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20609,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20609,], ["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",20602,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20602,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20602,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20602,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20602,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20602,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20602,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20602,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20602,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20602,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20602,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20609,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20609,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20609,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20609,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20609,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20609,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20609,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20609,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20609,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20609,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20609,], ["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",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20602,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20602,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20602,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20609,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20609,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20609,], ["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",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20602,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20602,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20609,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20609,], ["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",20602,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20602,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20602,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20602,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20602,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20602,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20609,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20609,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20609,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20609,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20609,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20609,], ["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,], @@ -1169,16 +1175,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20602,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20602,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20609,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20609,], ["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",20602,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20609,], ["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,], @@ -1188,118 +1194,118 @@ export const screenshots = [ ["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,], ["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_0_en","appnav.root_RootView_Night_0_en",20602,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20602,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20602,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20609,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20609,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20609,], ["appicon.enterprise_RoundIcon_en","",0,], ["appicon.element_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",20602,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20602,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20602,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20602,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20602,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20602,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20602,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20602,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20609,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20609,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20609,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20609,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20609,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20609,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20609,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20609,], ["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","",20602,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20609,], ["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","",20602,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20602,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20602,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20602,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20602,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20602,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20602,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20602,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20602,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20602,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20602,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20602,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20602,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20602,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20602,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20609,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20609,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20609,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20609,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20609,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20609,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20609,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20609,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20609,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20609,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20609,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20609,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20609,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20609,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20609,], ["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,], @@ -1322,40 +1328,39 @@ 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",20602,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20602,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20602,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20602,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20602,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20602,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20602,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20602,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20602,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20602,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20602,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20602,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20602,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20602,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20602,], -["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20602,], -["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20602,], -["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20605,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20609,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20609,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20609,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20609,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20609,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20609,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20609,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20609,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20609,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20609,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20609,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20609,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20609,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20609,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20609,], +["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20609,], +["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20609,], +["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20609,], ["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",20602,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20602,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20602,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20602,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20602,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20602,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20602,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20602,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20602,], -["features.location.impl.show_ShowLocationView_Day_8_en","features.location.impl.show_ShowLocationView_Night_8_en",20605,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20602,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20602,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20602,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20609,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20609,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20609,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20609,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20609,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20609,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20609,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20609,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20609,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20609,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20609,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20609,], ["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,], @@ -1365,106 +1370,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",20602,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20609,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20602,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20602,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20602,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20602,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20602,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20609,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20609,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20609,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20609,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20609,], ["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",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20602,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20602,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20602,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20602,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20602,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20602,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20602,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20602,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20602,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20602,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20602,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20602,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20602,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20602,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20602,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20609,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20609,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20609,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20609,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20609,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20609,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20609,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20609,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20609,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20609,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20609,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20609,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20609,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20609,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20609,], ["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",20602,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20602,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20602,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20602,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20602,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20602,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20609,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20609,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20609,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20609,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20609,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20609,], ["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",20602,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20609,], ["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",20602,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20609,], ["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",20602,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20602,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20602,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20602,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20602,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20602,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20602,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20602,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20602,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20602,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20602,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20602,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20602,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20602,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20602,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20602,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20609,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20609,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20609,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20609,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20609,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20609,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20609,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20609,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20609,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20609,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20609,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20609,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20609,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20609,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20609,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20609,], ["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",20602,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20602,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20609,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20609,], ["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,], @@ -1477,17 +1482,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20602,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20602,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20609,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20609,], ["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","",20602,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20602,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20602,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20609,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20609,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20609,], ["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",20602,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20602,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20609,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20609,], ["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,], @@ -1497,18 +1502,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",20602,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20609,], ["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",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20609,], ["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,], @@ -1516,18 +1521,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",20602,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20609,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20609,], ["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",20602,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20602,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20609,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20609,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20609,], ["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",20602,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20609,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20609,], ["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,], @@ -1536,44 +1541,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20609,], ["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",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20609,], ["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",20602,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20609,], ["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","",20602,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20609,], ["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",20602,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20609,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20609,], ["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",20602,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20609,], ["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",20602,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20602,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20602,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20609,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20609,], ["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",20602,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20602,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20609,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20609,], ["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",20602,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20609,], ["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,], @@ -1582,8 +1587,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",20602,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20609,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20609,], ["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,], @@ -1598,8 +1603,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",20602,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20602,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20609,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20609,], ["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,], @@ -1622,84 +1627,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",20602,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20602,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20602,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20609,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20609,], ["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",20602,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20609,], ["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",20602,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20609,], ["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",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20602,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20602,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20609,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20609,], ["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",20602,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20602,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20602,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20602,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20602,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20602,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20609,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20609,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20609,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20609,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20609,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20609,], ["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","",20602,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20609,], ["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",20602,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20602,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20602,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20602,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20609,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20609,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20609,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20609,], ["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",20602,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20609,], ["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",20602,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20609,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20602,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20602,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20602,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20602,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20602,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20602,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20602,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20602,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20602,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20602,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20602,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20602,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20602,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20609,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20609,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20609,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20609,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20609,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20609,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20609,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20609,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20609,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20609,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20609,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20609,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20609,], ["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",20602,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20602,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20609,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20609,], ["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",20602,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20609,], ["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,], From b910c4bf64da43c30b94f49d4de09ce0a657ce49 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 8 Jun 2026 14:35:34 +0200 Subject: [PATCH 0629/1083] Update release notes for `v26.05.1` (#6990) Add info about the handled security fixes --- CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index f24c813de7..84fec2badb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -131,6 +131,14 @@ Changes in Element X v26.05.1 +Security fixes 🔐 +----------------- + +This release contains some important security fixes: + +- Check the user ID in the `sender_device_keys` property of Olm-encrypted to-device events to prevent sender spoofing by homeserver owners. ([#6553](https://github.com/matrix-org/matrix-rust-sdk/pull/6553), High, [CVE-2026-45056](https://www.cve.org/CVERecord?id=CVE-2026-45056), [GHSA-wfq4-36m3-9g42](https://github.com/matrix-org/matrix-rust-sdk/security/advisories/GHSA-wfq4-36m3-9g42)) +- Reject invalid edits as candidates for timeline updates. ([#6454](https://github.com/matrix-org/matrix-rust-sdk/pull/6454), Moderate, [CVE-2026-45057](https://www.cve.org/CVERecord?id=CVE-2026-45057), [GHSA-h97m-27fx-42rx](https://github.com/matrix-org/matrix-rust-sdk/security/advisories/GHSA-h97m-27fx-42rx)) + ## What's Changed ### ✨ Features * Make Element Call screen work edge-to-edge by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6634 From b1b468d6a6859a3681be9cb3302f0f73abe52da3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 8 Jun 2026 15:29:35 +0200 Subject: [PATCH 0630/1083] Ensure that the application rotate the QrCode if one day the SDK emits the `.Expired` error. --- .../linknewdevice/RustLinkMobileHandler.kt | 4 +++ .../RustLinkMobileHandlerTest.kt | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt index cb387a9d21..a44a8d5943 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt @@ -51,6 +51,10 @@ class RustLinkMobileHandler( ) // We emit Done in case the progress listener was deallocated before generate() sent the Done _linkMobileStep.emit(LinkMobileStep.Done) + } catch (e: HumanQrGrantLoginException.Expired) { + // Note: the SDK does not return this error, but is returning `.NotFound` instead when the QR code expires. We catch both just in case. + Timber.tag(tag.value).w(e, "QR code has expired") + _linkMobileStep.emit(LinkMobileStep.QrRotating) } catch (e: HumanQrGrantLoginException.NotFound) { Timber.tag(tag.value).w(e, "Error during QR login grant") // Catch timeout here? diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt index ad751cc86b..3d84e34f45 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt @@ -147,6 +147,32 @@ class RustLinkMobileHandlerTest { } } + @Test + fun `when start throws HumanQrGrantLoginException_Expired, the handler emits QrRotating step`() = runTest { + val completable = CompletableDeferred() + val handler = FakeFfiGrantLoginWithQrCodeHandler( + generateResult = { + completable.await() + throw HumanQrGrantLoginException.Expired("Expired") + } + ) + val sut = createRustLinkMobileHandler( + handler, + ) + sut.linkMobileStep.test { + val initialItem = awaitItem() + assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized) + backgroundScope.launch { + sut.start() + } + runCurrent() + // generate returns, error is emitted + completable.complete(Unit) + val qrRotatingState = awaitItem() + assertThat(qrRotatingState).isEqualTo(LinkMobileStep.QrRotating) + } + } + private fun TestScope.createRustLinkMobileHandler( handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(), ) = RustLinkMobileHandler( From 5b74afcd79b83628b3721564318ae8e6ea88109a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:43:16 +0200 Subject: [PATCH 0631/1083] Update dependency io.mockk:mockk to v1.14.11 (#6977) 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 fbfb29110c..3e3e9f242a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -166,7 +166,7 @@ test_corektx = { module = "androidx.test:core-ktx", version.ref = "test_core" } test_arch_core = "androidx.arch.core:core-testing:2.2.0" test_junit = "junit:junit:4.13.2" test_runner = "androidx.test:runner:1.7.0" -test_mockk = "io.mockk:mockk:1.14.9" +test_mockk = "io.mockk:mockk:1.14.11" test_konsist = "com.lemonappdev:konsist:0.17.3" test_turbine = "app.cash.turbine:turbine:1.2.1" test_truth = "com.google.truth:truth:1.4.5" From 9fd5277a489ea6ce2b79c3e70144b2944279cfe8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:46:52 +0200 Subject: [PATCH 0632/1083] Update zizmorcore/zizmor-action action to v0.5.6 (#6845) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index ceaa86016a..d460eda633 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -336,7 +336,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3 + - uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 upload_reports: name: Project Check Suite From 786c53ac06deaa9d947080f650900aa67700f553 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 8 Jun 2026 15:50:56 +0200 Subject: [PATCH 0633/1083] Make `BaseRoom.getDirectRoomMember` change when `roomInfo.isDm` changes (#6989) With `derivedStateOf` this wasn't working as expected for some reason, resulting in the dm member being null and displaying the wrong `RoomType` in the room details screen --- .../android/libraries/matrix/ui/room/MatrixRoomMembers.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt index 098117af74..f09447a083 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.BaseRoom @@ -42,10 +43,8 @@ fun getRoomMemberAsState(roomMembersState: RoomMembersState, userId: UserId): St @Composable fun BaseRoom.getDirectRoomMember(roomMembersState: RoomMembersState): State { val roomInfo by roomInfoFlow.collectAsState() - return remember { - derivedStateOf { - roomMembersState.getDirectRoomMember(roomInfo, sessionId) - } + return remember(roomInfo.isDm) { + mutableStateOf(roomMembersState.getDirectRoomMember(roomInfo, sessionId)) } } From a201b3766e8494c86ff366b6d2e385a6c245eb8f Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Mon, 8 Jun 2026 06:52:24 -0700 Subject: [PATCH 0634/1083] Fix jump-to-unread requiring two taps for an out-of-window read marker (#6943) * Fix jump-to-unread requiring two taps for an out-of-window read marker * Update features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt Co-authored-by: Benoit Marty --------- Co-authored-by: Benoit Marty --- .../features/messages/impl/timeline/TimelinePresenter.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 3ec31b1a99..e8e932b48b 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 @@ -333,7 +333,12 @@ class TimelinePresenter( } } - LaunchedEffect(timelineItems.size, focusRequestState.value) { + // Keyed on the full [timelineItems] reference (not just .size) so we re-resolve the index + // when a focused timeline loads with the same item count as the window it replaced — e.g. + // jumping to an out-of-window read marker in a busy room, where both windows fill to the + // same page size. With .size as the key the effect wouldn't re-run, the focused event's + // index would stay unresolved, and the scroll would never fire until a second tap. + LaunchedEffect(timelineItems.map { it.identifier() }, focusRequestState.value) { val currentFocusRequestState = focusRequestState.value if (currentFocusRequestState is FocusRequestState.Success && !currentFocusRequestState.rendered) { val eventId = currentFocusRequestState.eventId From bea2903093d243497c1cb30f4b01aa69226d3207 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 8 Jun 2026 16:32:13 +0200 Subject: [PATCH 0635/1083] Click on avatar in moderation bottom sheet opens avatar preview (#6991) * Make the avatar in the room member moderation bottom sheet open the avatar in the media viewer (#6962) * Make the avatar in the room member moderation bottom sheet open the avatar in the media viewer. * Fix issue with avatar overlay not dismissing the bottom sheet: the bottom sheet would eat all the touch events until the first click, which would somehow cancel this behaviour * Fix lint issues * Update screenshots --------- Co-authored-by: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Co-authored-by: ElementBot --- .../messages/impl/MessagesFlowNode.kt | 36 +++++++++++++++++++ .../features/messages/impl/MessagesNode.kt | 8 +++++ .../impl/threads/ThreadedMessagesNode.kt | 8 +++++ .../roomdetails/impl/RoomDetailsFlowNode.kt | 4 +++ .../impl/members/RoomMemberListNode.kt | 7 ++++ .../api/RoomMemberModerationRenderer.kt | 1 + .../DefaultRoomMemberModerationRenderer.kt | 3 +- .../impl/RoomMemberModerationView.kt | 27 ++++++++------ ...impl_RoomMemberModerationView_Day_0_en.png | 4 +-- ...impl_RoomMemberModerationView_Day_1_en.png | 4 +-- ...impl_RoomMemberModerationView_Day_2_en.png | 4 +-- ...impl_RoomMemberModerationView_Day_3_en.png | 4 +-- ...impl_RoomMemberModerationView_Day_4_en.png | 4 +-- ...impl_RoomMemberModerationView_Day_6_en.png | 4 +-- ...impl_RoomMemberModerationView_Day_8_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_0_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_1_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_2_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_3_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_4_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_6_en.png | 4 +-- ...pl_RoomMemberModerationView_Night_8_en.png | 4 +-- 22 files changed, 111 insertions(+), 39 deletions(-) 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 0a2c9772c4..7bb7ba1d00 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 @@ -190,6 +190,9 @@ class MessagesFlowNode( @Parcelize data object ThreadsList : NavTarget + + @Parcelize + data class AvatarPreview(val name: String, val avatarUrl: String) : NavTarget } private val callback: MessagesEntryPoint.Callback = callback() @@ -327,6 +330,10 @@ class MessagesFlowNode( override fun navigateToDeveloperSettings() { callback.navigateToDeveloperSettings() } + + override fun navigateToAvatarPreview(username: String, avatarUrl: String) { + overlay.show(NavTarget.AvatarPreview(username, avatarUrl)) + } } val inputs = MessagesNode.Inputs(focusedEventId = navTarget.focusedEventId) createNode(buildContext, listOf(callback, inputs)) @@ -562,6 +569,10 @@ class MessagesFlowNode( override fun navigateToDeveloperSettings() { callback.navigateToDeveloperSettings() } + + override fun navigateToAvatarPreview(username: String, avatarUrl: String) { + overlay.show(NavTarget.AvatarPreview(username, avatarUrl)) + } } createNode(buildContext, listOf(inputs, callback)) } @@ -573,6 +584,31 @@ class MessagesFlowNode( } createNode(buildContext, listOf(callback)) } + is NavTarget.AvatarPreview -> { + val callback = object : MediaViewerEntryPoint.Callback { + override fun onDone() { + overlay.hide() + } + + override fun viewInTimeline(eventId: EventId) { + // Cannot happen + } + + override fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean) { + // Cannot happen + } + } + val params = mediaViewerEntryPoint.createParamsForAvatar( + filename = navTarget.name, + avatarUrl = navTarget.avatarUrl, + ) + mediaViewerEntryPoint.createNode( + parentNode = this, + buildContext = buildContext, + params = params, + callback = callback, + ) + } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index a9ce2f5ba1..1152faa433 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -66,6 +66,7 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo +import io.element.android.libraries.matrix.ui.model.getBestName import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard @@ -136,6 +137,8 @@ class MessagesNode( fun navigateToDeveloperSettings() fun navigateToThreadsList() + + fun navigateToAvatarPreview(username: String, avatarUrl: String) } override fun onBuilt() { @@ -319,6 +322,11 @@ class MessagesNode( else -> state.roomMemberModerationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target)) } }, + onAvatarClick = { user -> + user.avatarUrl?.let { url -> + callback.navigateToAvatarPreview(user.getBestName(), url) + } + }, modifier = Modifier, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index be573fa92f..3546696816 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -67,6 +67,7 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo +import io.element.android.libraries.matrix.ui.model.getBestName import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsService @@ -138,6 +139,8 @@ class ThreadedMessagesNode( fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToDeveloperSettings() + + fun navigateToAvatarPreview(username: String, avatarUrl: String) } override fun onBuilt() { @@ -315,6 +318,11 @@ class ThreadedMessagesNode( else -> state.roomMemberModerationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target)) } }, + onAvatarClick = { user -> + user.avatarUrl?.let { url -> + callback.navigateToAvatarPreview(user.getBestName(), url) + } + }, modifier = Modifier, ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index d4108a77e3..7574863962 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -258,6 +258,10 @@ class RoomDetailsFlowNode( override fun navigateToInviteMembers() { backstack.push(NavTarget.InviteMembers) } + + override fun navigateToAvatarPreview(username: String, avatarUrl: String) { + overlay.show(NavTarget.AvatarPreview(username, avatarUrl)) + } } createNode(buildContext, listOf(roomMemberListCallback)) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt index 750b111fc3..eec2a44660 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListNode.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.architecture.appyx.launchMolecule import io.element.android.libraries.architecture.callback import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.ui.model.getBestName import io.element.android.services.analytics.api.AnalyticsService @ContributesNode(RoomScope::class) @@ -41,6 +42,7 @@ class RoomMemberListNode( interface Callback : Plugin { fun navigateToRoomMemberDetails(roomMemberId: UserId) fun navigateToInviteMembers() + fun navigateToAvatarPreview(username: String, avatarUrl: String) } private val callback: Callback = callback() @@ -82,6 +84,11 @@ class RoomMemberListNode( else -> state.moderationState.eventSink(RoomMemberModerationEvents.ProcessAction(action, target)) } }, + onAvatarClick = { user -> + user.avatarUrl?.let { url -> + callback.navigateToAvatarPreview(user.getBestName(), url) + } + }, modifier = Modifier, ) } diff --git a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt index 8fb1ae0c03..efc87d8a40 100644 --- a/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt +++ b/features/roommembermoderation/api/src/main/kotlin/io/element/android/features/roommembermoderation/api/RoomMemberModerationRenderer.kt @@ -17,6 +17,7 @@ interface RoomMemberModerationRenderer { fun Render( state: RoomMemberModerationState, onSelectAction: (ModerationAction, MatrixUser) -> Unit, + onAvatarClick: ((MatrixUser) -> Unit)?, modifier: Modifier, ) } diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt index 05bf00c7eb..0eeded6434 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/DefaultRoomMemberModerationRenderer.kt @@ -25,10 +25,11 @@ class DefaultRoomMemberModerationRenderer : RoomMemberModerationRenderer { override fun Render( state: RoomMemberModerationState, onSelectAction: (ModerationAction, MatrixUser) -> Unit, + onAvatarClick: ((MatrixUser) -> Unit)?, modifier: Modifier ) { if (state is InternalRoomMemberModerationState) { - RoomMemberModerationView(state, onSelectAction, modifier) + RoomMemberModerationView(modifier = modifier, state = state, onSelectAction = onSelectAction, onAvatarClick = onAvatarClick) } else { SideEffect { Timber.d("RoomMemberModerationRenderer: Render called with unsupported state: $state") diff --git a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt index 08d9143e0b..ff84b62669 100644 --- a/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt +++ b/features/roommembermoderation/impl/src/main/kotlin/io/element/android/features/roommembermoderation/impl/RoomMemberModerationView.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn @@ -64,6 +65,7 @@ import timber.log.Timber fun RoomMemberModerationView( state: InternalRoomMemberModerationState, onSelectAction: (ModerationAction, MatrixUser) -> Unit, + onAvatarClick: ((MatrixUser) -> Unit)?, modifier: Modifier = Modifier, ) { Box(modifier = modifier) { @@ -73,6 +75,7 @@ fun RoomMemberModerationView( user = selectedUser, actions = state.actions, onSelectAction = onSelectAction, + onAvatarClick = onAvatarClick, onDismiss = { state.eventSink(InternalRoomMemberModerationEvents.Reset) }, ) } @@ -214,6 +217,7 @@ private fun RoomMemberActionsBottomSheet( user: MatrixUser, actions: ImmutableList, onSelectAction: (ModerationAction, MatrixUser) -> Unit, + onAvatarClick: ((MatrixUser) -> Unit)? = null, onDismiss: () -> Unit, ) { val coroutineScope = rememberCoroutineScope() @@ -240,10 +244,11 @@ private fun RoomMemberActionsBottomSheet( modifier = Modifier .padding(bottom = 24.dp) .align(Alignment.CenterHorizontally) - .clickable { + .clickable(enabled = user.avatarUrl != null && onAvatarClick != null) { coroutineScope.launch { - onSelectAction(ModerationAction.DisplayProfile, user) bottomSheetState.hide() + onAvatarClick?.invoke(user) + onDismiss() } } ) @@ -282,8 +287,8 @@ private fun RoomMemberActionsBottomSheet( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), onClick = { coroutineScope.launch { - onSelectAction(action, user) bottomSheetState.hide() + onSelectAction(action, user) } }, enabled = actionState.isEnabled @@ -340,16 +345,18 @@ private fun RoomMemberActionsBottomSheet( @PreviewsDayNight @Composable internal fun RoomMemberModerationViewPreview(@PreviewParameter(InternalRoomMemberModerationStateProvider::class) state: InternalRoomMemberModerationState) { + val isDoingAction = listOf(state.kickUserAsyncAction, state.banUserAsyncAction, state.unbanUserAsyncAction).any { it is AsyncAction.Loading } + val modifier = if (isDoingAction) { + Modifier.fillMaxWidth().heightIn(min = 64.dp) + } else { + Modifier.fillMaxSize() + } ElementPreview { - Box( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 64.dp) - ) { + Box(modifier) { RoomMemberModerationView( state = state, - onSelectAction = { _, _ -> - }, + onSelectAction = { _, _ -> }, + onAvatarClick = {}, ) } } diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png index adc8e30fdb..202f8a06db 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b15da251ba8ac26c61fd21079f09e3b614fd20e8ded4805cda0da180631afcc -size 17347 +oid sha256:75880628a454ca00a186e5d1c5438117e7af4ab9b23eb6fbf9c9696210234169 +size 17246 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png index 1e3ab791b8..9186ac2de4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc4a3ba905c3599ad8f6451787906ba61f8dc716464d81e8c1c1bc86023032c3 -size 20345 +oid sha256:1fe61c20e2c6a7bb72e82aefd546469dfc49bf736b6d12f4c1927628df1bdb3e +size 20211 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png index 5253ae2439..ca8464fad9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5704d02932451bc129ec92f3a9dab7fd66bb55bfdf3e142a4f3a436ad1d3b129 -size 22722 +oid sha256:ca3ee9a09bbbc69f2ba7e8b40cdc5196cc53745fe3222282d98bcf948dc16745 +size 22596 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png index b905c2d8cb..945743ff26 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8755fa3568186a798047a7fbf05404c0f738b168ca77f16afecc815bbec084ab -size 22828 +oid sha256:96971a8981aea8918c01827403933c9e75275a2fda92716f803e6f28ad284bae +size 22702 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png index 46dead6c87..eb96c3e39b 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e611504d154db3889c1a5900e6af392ca058462450d66f0dde762ab4a45e1b76 -size 29532 +oid sha256:06ca0aa653033b59313325ad508c5916e2fedf29ba6dd3a5f714e90d01f4bf7c +size 29644 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png index 9399857173..9b9542917a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6135b24d94d7732342ec9353cdefb115ce5e9a799dfaee5d57b2e8e0a7ed631 -size 26505 +oid sha256:ebfb75986cd385e9837a24a5f279e07f0744bab5613fd7cbaf0a493d021c7699 +size 26606 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en.png index 8380d60ccd..18d1be85a7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bf31df95e781eae5530ed98ab9773f3e7d0f4fd4152226596b78328b88d69a8 -size 27223 +oid sha256:a58e6ed7f10d7014c9c3b55fbb769e04619313212449a8fc582501d2904d669f +size 27315 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png index f4922aad1c..c1b0c4ff1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba469dd7ffb3b27261cc4f227584b7cc03bf2ddcb974a4a1150c9515a075ac78 -size 16562 +oid sha256:bc96eec2d61713f01d43c92812bbf27bc44a202ce55f0fa1dc8e8659dabcfcf2 +size 16347 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png index c79de434d4..16b567164c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d21c293e519e998d8820171766f1651d2440b18dad6f002c6580ca3fe2f24d69 -size 19397 +oid sha256:56c4df7da32b71dca109a1db1f4a797a2930e3b42c00eb51d72f0e1f5b99bf48 +size 19200 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png index dfa20ea763..ec10d3fd8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24a1a6004dc058573f264a5f02ffc85ca925e9f0c01f7ceacbaf972b3335d327 -size 21819 +oid sha256:592c6ec197b193803679eee5df7769fa4858fe883a2f3a1294f39ad87f9f4ff1 +size 21610 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png index 07547bf79a..5ff44ac3a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf93cbb2ce344639162524714d254c0db21cab448dec38ee1d4820265678a7ec -size 21909 +oid sha256:62e99b8070a394ea5b2d666f3a8abf0fe41ea4a34a382223903f2de4085195dc +size 21710 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png index c5d3a63af7..2f5afc02b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:641f434040dfc9f040622fd0f17519d353f0bc45a17603ef837e53fad2b529c2 -size 27570 +oid sha256:793cff43740f6e477a255af566985d8bb7b0242d89484b3f0fc5cfec3b4a2af8 +size 27608 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png index a06978178d..4a9b30b4cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d9c0f0c69bd55b5c9a925cb89587d959998a833c5927873b4ef358959ce4ece -size 24944 +oid sha256:ad842be0c519bfd7713eb93df2a7216d159970aff1ea44725641c5db26f3ad6b +size 24995 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en.png index 4c39cde004..4964d7d1b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f17c5df90399b6de382af8111ba36b0ec072596f42103f76477692a801493799 -size 25515 +oid sha256:541b9ad607838fc9d44d6d3759d61df54c178257fe646366304d96ebda5f7e77 +size 25565 From 3312526055b915eae5822336b2e2d6feb416261a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 8 Jun 2026 16:28:13 +0000 Subject: [PATCH 0636/1083] Update screenshots --- .../features.messages.impl.timeline_TimelineView_Day_9_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_9_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 7e8f621890..05d98ba4d5 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:f90a31ccde2880e01393be2bd36e9554d8087aa52bfe36e29b8514a32fea3dcd -size 752143 +oid sha256:a3bf3e46b2d6182102866d609efe16ee4f2e6c32b9d9b0da211eb26e50f977d3 +size 751324 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 180c910e51..31bf4ec48a 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:a853885aac641afe3fb28f3a1d9ebf6744862f153ea22bc2d511ff957b814a19 -size 747294 +oid sha256:62c7dc85dc08a50a58973ba118eedea31a7ff5923f4779f4925067aaf6a54717 +size 747178 From 8b4158c8245fc72c2320398684570291a96a0c4d Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 8 Jun 2026 18:17:45 +0000 Subject: [PATCH 0637/1083] Address review --- .../io/element/android/features/messages/impl/MessagesNode.kt | 2 +- .../messages/impl/messagecomposer/MessageComposerPresenter.kt | 3 +-- .../features/messages/impl/threads/ThreadedMessagesNode.kt | 2 +- .../MessageComposerPresenterSlashCommandTest.kt | 2 -- .../impl/messagecomposer/MessageComposerPresenterTest.kt | 2 -- 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index ef0e7100e2..ff039da1b4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -107,7 +107,7 @@ class MessagesNode( private val timelineController = TimelineController(room, room.liveTimeline) private val presenter = presenterFactory.create( navigator = this, - composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = false, threadRoot = null), + composerPresenter = messageComposerPresenterFactory.create(timelineController, this, threadRoot = null), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), actionListPresenter = actionListPresenterFactory.create( postProcessor = TimelineItemActionPostProcessor.Default, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 9e9fc15eec..3526a6fda1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -110,7 +110,6 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes class MessageComposerPresenter( @Assisted private val navigator: MessagesNavigator, @Assisted private val timelineController: TimelineController, - @Assisted private val isInThread: Boolean, @Assisted private val threadRoot: ThreadId?, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val room: JoinedRoom, @@ -140,11 +139,11 @@ class MessageComposerPresenter( fun create( timelineController: TimelineController, navigator: MessagesNavigator, - isInThread: Boolean, threadRoot: ThreadId?, ): MessageComposerPresenter } + private val isInThread: Boolean get() = threadRoot != null private val mediaSender = mediaSenderFactory.create(timelineMode = timelineController.mainTimelineMode()) private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index ade22eed41..f26a47ce63 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -112,7 +112,7 @@ class ThreadedMessagesNode( this.timelineController = timelineController return presenterFactory.create( navigator = this, - composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = true, threadRoot = inputs.threadRootEventId), + composerPresenter = messageComposerPresenterFactory.create(timelineController, this, threadRoot = inputs.threadRootEventId), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), // TODO add special processor for threaded timeline actionListPresenter = actionListPresenterFactory.create( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt index 2a0ba9ff1b..0b3da9647e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterSlashCommandTest.kt @@ -272,13 +272,11 @@ class MessageComposerPresenterSlashCommandTest { isRichTextEditorEnabled: Boolean = true, draftService: ComposerDraftService = FakeComposerDraftService(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), - isInThread: Boolean = false, threadRoot: ThreadId? = null, slashCommandService: SlashCommandService = FakeSlashCommandService(), ) = MessageComposerPresenter( navigator = navigator, sessionCoroutineScope = this, - isInThread = isInThread, threadRoot = threadRoot, room = room, mediaPickerProvider = pickerProvider, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index ab9886a368..9fd0ccfee3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -1534,13 +1534,11 @@ class MessageComposerPresenterTest { isRichTextEditorEnabled: Boolean = true, draftService: ComposerDraftService = FakeComposerDraftService(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), - isInThread: Boolean = false, threadRoot: ThreadId? = null, slashCommandService: SlashCommandService = FakeSlashCommandService(), ) = MessageComposerPresenter( navigator = navigator, sessionCoroutineScope = this, - isInThread = isInThread, threadRoot = threadRoot, room = room, mediaPickerProvider = pickerProvider, From 6b9aa31c192f66b7778ba66e9d5e22d4d1bbb8f8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 8 Jun 2026 21:56:22 +0200 Subject: [PATCH 0638/1083] change(location): ensure permissions are always requested at least once --- .idea/codeStyles/Project.xml | 34 ++++++++++ .../impl/common/LocationConstraintsCheck.kt | 3 + .../DefaultPermissionsPresenter.kt | 14 +++- .../common/permissions/PermissionsState.kt | 1 + .../impl/share/ShareLocationPresenter.kt | 64 +++++++++++++------ .../impl/show/ShowLocationPresenter.kt | 22 +++++-- .../location/impl/PermissionsStateFactory.kt | 2 + .../common/LocationConstraintsCheckTest.kt | 17 ++++- .../permissions/FakePermissionsPresenter.kt | 1 + .../impl/share/ShareLocationPresenterTest.kt | 37 ++++++++++- .../impl/show/ShowLocationPresenterTest.kt | 31 +++++++-- 11 files changed, 190 insertions(+), 36 deletions(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index cdef735570..8151cb4ea3 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,5 +1,39 @@ + + +

~WJlvE=--%Ysmm{^T|J!j z+Y$}c=Hg!<^8$6>_A!k0{0iN;4GzgiO0!TE20f;?_s(_CqD%s{rDrHR<^mp^}p(e>w>Mb~8L#lJAei@r`$g`_Lx$(wK zhbkyzhS}(m4IVf%?=*}tnL49kCu+AEYYq1_tDJL4ei3o5I=o6v31Z2T+*-)l^ic~m zOnzpy(d+8Uq}{$2Jn=NXuTAdlFVF_J5GMu6v0YuvI@>8% zzju}FnC)0UhRaOoHDA!E#9)*&wJJlOi>4Cv{=#Q+o9Kzw%cbE~*djvRxjS6E8C#=< z?aN9nd^%yyf#+gPPBZPSnLk1o;}eFACetFMxlBk8EJk|U*?*CcOvaXo84XtcOH}ga zi`Ce+MGe*KNnc^s=!Ubl!jzm{RKbl_6jARAIArPcY?JP19!t-a(iem8@wah8d55fA zS?%d>f)~U^+krO1eT`VgwX@z`GHNZZ)=XQgR)Bhm04gXUZJd}=Xq(jzTW540cHxJt z#~jR+nJJP#HFf;NzfoBO`&;0*86=zkY7Js&A_8>Yr*qm$sU;nR&0dd0t~hPi(Ny@}X=C z%V_P3)mWpQmO+cZh}O9BIquu$2DOaSc6GCikq-o38iycC>w-ZK8U`~nRbQdE4A{K1 ztxa()Y?{ehf7dy+AI_Fa^Gjq|Y}$G*$OQk1iu5Z8^jMx=OG>;}ou66hFH2>1rziye zrI3AvfOqu?{H2&qTavd}?>~%x2+IpG1#Ft=v&2KK`fHw4guMQTRiCwPH8(o<2%dby zyvX^PjA(j(D~%hx$0eU;{?EF(v_qNss|R}V;=rrT`c4Pwj!Qw@8q_bddik_hr_$mY zq^jl29(?hbuI63pZ!8R=)4xWyp^ivO@RzJ6ydydqEwfa=(2pUMj?-3~j1CIa6D{rZ zJ2<3S@U?*T&si6XLZbhhD1HyO#$)ngZ2In*N-v|RGT%VHQ@`}@~lgLL!^i)zh0v*~w2%2*s z)uJ+*U@=9hSkJ3S%9r_ z?p+aExjNiK=)_3paEEsbHa|#;_bA0Y|^j-zl3bam>**{#Oc+wXVv zpx(b`HNl?EjS44i($38E%2ua72vmJ5@$p5OYCksg5`k9tu>cPExYV$Cbr#jH1q&Co ze?w%0dHk1Z1bwv8!w{w662*^82HPjK@Y97Xg(=s-b3B&gI8)yga1yV&z+N*r*-E_v zyu97Nl?=UT`=Y-4?ZJOO2Y;13C_3mKd+^bi`lDEtkRH2J`)B*#o(chtB&Z=|&!{b> z-0>DuHo(~2jd^BUkN66=tP{R}DfiaSGN8u!ENI;#TYE1Tm3*5&ayTL(fPVyB&H7c- zHD3A?LcmjTpsVdA8G$a43P$z@t(~@Bq30sJ& zkU_lIy&XAz$#9!FgnFWMcyk29oKgmJn86Eby)}i9(=M2w=j+xYDg`Nv3!;pSP$wC@ zxy=%zKy@uziDq#JmPo95hJU@Tqz&?#O6zWZisc`94xqc``>0us4GEG=8>fJdYFi!a z;d#r~tG9NrsTwm&<9cX=ZxT#rnLxypU5#e*WKs|9uI`ojwh`B%fz~8lmx)M zk=m4xR?YDsAnR)+GGZe}Ecfr+J>-YAto6Ef( zGpFt$um2icuhdYYyfB=}9naJt#dH1^W_L9%eXny~YC#W(M3AlKvEA97OSV*j(us0l zxz|L~MfvURCYSI7YgiF&Z!-JkvF^IuChVi_`BbU8KT6QkemrtcQ+~_yMK<6hP@?&K z8ILEI06Ht{jXpH@>B3l(W!cE$@lKQTGk`uy-tGMit79gvpydpZy6 z&oun~AXU}1uF=a9;8NCGnn>W`>Zd)#6-evuHl%5`rs|fA6SHx8`lZmh%W7>+huf99 zS(0e1yM2VIq7`?FN?fki@mIo~9Xsf%6>k&r0U1oc!eN+>CRtwwven?FE&PZy(83~3y zuGmDWR8D^dNbu?gg7gkcs8o3aA@o4d7}RDZFAXvuuKGIy@<@AgIAqKJuNC6|y=0cs z%2!68pP&pWfG6k?gs_H$_ID}?$EvB1VGgr?+szwA&$u?G?S$}eMw}bX2I&irl?Z9P zw^L7~tVia|=Wz*MLeBG^C~>th>N}wY=aD8RB@~4QaqWsa=HR#)8{vlV==mfB>V{0# z({*lyghfb_4~0WC9ThN>J;tzSQzy__(pn}rPv$zS;vej6w(eEzERksXk3pSnpOeb% zr*^;}ymo~q{JZDP;JB}^iY^UjikO<(e_S;wrL@q1N`E^1Ejf0cINK?KBVE`39xSeF zNHz&SieR{T#OL~=BQ%t*Z~RxiK#yJHd;D-O`ETO{iaj0W<<@FET=qv&qQXd5kE>Lt z4A9PydAn`|PG?IHW19c1bzUNCvr7^&qV99TB}K8{dcF<_t7hIeaJ7j zo%b};RNq9XgjbwR#gw#6R>-S0xW^^qbOtmeq=A64;v5OJ^KjQV?6HG{)9-7C($5`6 zc?3FVCF6E}pr%uEm!{FNkCcn^H7}~&uc3S*iq`)w&`rSo7JI98&}#|c*&&L=$;Cs+ z&CbKXWoMF7y$~e3^_APJy5WzXT9vJNFXIY(6Bclm9pbdLEhU)du za1KHG^*_+BOtQtPRPYgI5Hvv{0e5S;7s`^%83*cZk}F{ zgXEoe1%8Vp+F6U-rO4+eGWmn zFaL4(7`xzsv<*W+4Y)4Qh0YG`7Pjo3$kzL~aA!%>Ud3N(AMAv$jOvFY;}&4Z&BbHL zUOfe0xEx?&_9_2|SJ>Hq3^Z5Tc=89(l?vv=1+{G>#+Qt_HgU$Y;kTAet`c5Yeo4qa zxmcPDjrDFC2pdffF_nG)HkU7l<16Ahs-X{G*Xi}&qaU*oB7J}_P2J7o4B;c&?x%@a zdm$t(${NvPlI83*Hc0y4y7wtbx?C!-Y_4P`Js)MoFaCWuAZweRfKRw$%vpQO$kQ|O z4itI8$tqwM?(~2HmY3|a)SxOZd)OkVix2z-ymMG*Yle=D+}IiS_Lsnn7`$wXY5t2Q zIDalm{;Q|IYoq3M6K-^qI+1fxk-*G_%Je?I-|iNPaLdgEJ~(T9#YFfZUhK6*GG|m| z(WUhuko)kx#oH-Z{S1o)YiT{kKe62FBc~?Op5g0W*f>P|q5{C_D9Ey(Dsk5@?d*X% zRI0?fpvA4b%^4i=ePpd8$nawL)$HOVGv=CYsD2^Iu;xvNo{46T_j_}8A%XaDS?VO; zuVMM{LGD7Z?s}&h>#ObL^g#3x%t+Uv$`tDsJ#OiOXM`^$w?;1&Y*MHF?d>_bcpAjs zSjg6`YbZ)0gLL+hi0jw;77?Aoz*R@T>$m_1t}Rk)tG>xjug>=LlMi(?Kst4D+F5pS0> zRrF*z;gVCk8AYkzZ1lSKDB}YN1j8Jv5mx=54AN^Z+mLE~>8!kX;cTA1yA{z-`VeNKSqe4i&*KS#PbI+r@`%;X>2k9j?4&9qAaJ zi>JDZpBimt^X_@N;@AM%8?U0jbEKW~ot0M2j$h^g(|2tsc=2-gQN7mR56GugBON`% z1c{u3)=;-rc%oxkUf1DWPu@3(fw6p&HFCO>AkRur4L$wa);`+iHt{VYI~y4B7w+)X zxmyV;>wMj!I-m*Xwp3xsw9o5wM1TFtU+*w8g5t!8XRR6d_4g)V%$M``Zm{WT0opkh zjQ?IMTl!i{QH2n&t~Pq)-_8h>lLGuyD>HURZo72XaaU3HSRrh&SAZ7rXIJYu8N3)% zzMj-p?|{RTGpU+o&g=BJRtvC_Fx_}In3{+4743eAuUqqyMr<|3C9E$i=>j&j;XbrH z1+rNkYN4F%sU5X9H@^vTyH>t77R-==a>64Q8ycNMudV!2`kHWV#u056LM+2omLPS&}*0^MOSM;6QhZ5MwTT5vozJV(cF`ECC{n$E*7$@TI3=bVO> zm8Z;=rj?nMgUm#6KpibBQ%=WHbCHu2oVZ1(OwCDVZW6W#0z_P>OjrOOX>>@4^>tKT{`YS-vZ z(JB<4!>VgaiARg^DQ++3xf~3yz0FP=$ck&5jH?8Nw4~(%zusIZ%W>ug5wSuA-5mbW zsi6_nz#W$kXZe%*eYq$j6_%14Hd8L%AIn}*KRlfk)`9Lx_}EL<*Vymc$1Iq==> zj~}vP_JqYtWHq!Eyp!3dfDR0z%bXJhxU5X2Xn2A*5>8JD75mOLzl7q8C4PPT-XsA6 z97n&PMyDmhYAT8m@kd_6GMdL-CNms4i}LlqwL;gvr|=fxklb+mu&Lq)2PIZ2j!&6; zr32}#5hj?g%&m@bbcaz(Lw!Kd$OvlDL8{eP(E!g#RCNH*dL2*f+4Vj-1j6|pMoGP$ zNn9W#syhro>k#$o-BpHj=AV7!=yGrzg>qDW$Eu48q&88$E8BV?6(;RNtE z_duuPMk*=a=KSzsEh?Ag^jY3DV))&dhRzp6*z9L;6ZZ;JBi}W~!6DTp3H2wnAiNn5dg*eH z%5Go>U|0OI4uN*c`PFO;6-G)biEqCg8r6zEda=4o9v|Av9eZe`b1toM)LIyvtL1(w zhiX4xrh9{|cSO-Ra!1%7pa37UIB3)h-#CJnnwc$7I!ESAyZKGR7VLH}tLNRwiDr!G zc@BTF`B&)Uzjjhiq{LdXHlt7^JEE-?!9Sle?V{o(t~ZWzgCj zzWj3;*D>+~J^BNvc*hFns9Yg)fYjaOvu81mz|y-~`b|PIx8Q@joK0zw;D9tq>10}r z1w^pLdaD>E;VE%l>Z!FS<#lo=euvlbUhnNuf{=(uyZO}6OOqGM5Jw8hdVW4xQ+uUU ztkowG6*JNGif(Q?vT)EngvpP%LC4x;{V`5@5h%16;?s4JjO>JO>+B$*r%)8C*I?Rc zIiWcx*%jH7uJ?;$i}|W3wkGQeuxQbvqvrf6S4q{LQI1|fg5GhgnV9%HB4nuT>Qooi z%iV_LgePxqW;4$bik=#-mt6JATlz1tgS3}D|5cV1gLrYIj-O|OWJ#8XA2o*Wu+`zh z`sywp*v;M@tR*tiu&o*3-I(Nbxg!oh+60so7*7O}hc05~@nH+Vp_BFVHnxlOxVW7Q zJt*ToNqO44sgs6sf?^vYj!~{Z=6XmS&k&@gaAd$Eo!*P@T@U-wZwfydivXkMr!tT!(#ry z47Qu{5(<+4s_(9`)KBcr{;P#KwwIqqo$PP%Ao!ah&ultzmS6VYEQeN?4ykRVtu?>V z9Gh+X^S7tvO*AUGS$CNV-Yw{1$l!xL>s!3CTJCrA>vXCn*_E?N4Wn6=`0U#1TWeqT6m?6MhB2ITTeac>&&IXcFQ1SW ziO*!>f3O9U;;ZsmqBhIjQOi=Kx5HwnVk_C*)#W`8nZi|2DY)ab;R|pM=AW1nn}UNQL@JF4 ziBhy3^L~0{3uAb zuIP#<3C`0aKUgR5Z+%{$3RDiN*jb7fAQ$6ocmKO&6|yO#m|N=VX+0$a8JpHSufAW- zTf1J7yOw&&4S)ecnqm4jBUy0NE5YOB2_*qC?DSIp%cF#QRrF6|O|O(9hi+=v2AX-U zLv!y|=ueFojkw9>SIj-TiVUW@yQ8p?FkIUK?6QS1fqKicIvx%IknRU)V+I;DdL_W?A=|u*Nv03>`A7wCFjxm zwc7DB)6tNi1V5|8-c2Xpw3{?4L;_nLAC5ER6j+MZXetgH((xC~`L~0b5}PFWfS1^x ziLG_lvio9+0S9Gmn|%%+v~~~seB)BT_=~$vI-=H8Y(ijI@UrI#M=+b;I?^~6>Wwmc z!b5)hhj$dM^^{uLo>@%n_WU8H9r#oU`|D%7)SdWF$mTR0=b9%!`Ci%FXvHR_II!QY z2S~(U{gCF&+5Bb+p8Uu$3g@*wN+GQ;|0^q}{8L@gLt|2jNq5*FHG0^N(;m*!sOjL^ z`E#4i3UATPmvHxVfX-uH=H&E7RxyV{GgjAK7n`om0Tr=Pw@=5e?=RbWv+6n&YFh3Y z#RVeb$>?Cyw!HT0NpB&#E4YHTxYqesD3ICgJ9#)s|0#}_ zr?(Gw7p1kM9ux@}nEh>YCVhhyd)tH_tgzdG6Ly3YH!UUfG*YtG4#G&?F#4L;uz{_D z-aP5iF0K0UN+qYvQVDDm$tH}BZuCm=hqradq}y3Ax_%TqXPoBOYsB;_-ds0bXfc=uNXeex*yv(`zcl`C`@Lsdt^?AYxc6_hFKu4z6S(K~m&`a?hd@#3;jM4? zBFg2aGExMxKkNd2>O=d^)($C(&E-6yB6I99vgUSu2i^9$KrWpmcM$&}{Xn3rp4=Ne zWqy?RQ)k7sK3#Q3o8KW1Jq|H)9WbZ;1b9ZBvk@Fm%;-L*$UBKQ6%P6}h(D&a#gB@R z-Az&Od3MG5unYBVx>4?^(dh1onvuX;p6SLr--x#Lqlwt=s<3=OX>aB8(y+9tmdmK? z#d;dOCOIst36t8ePW{ONdY?-dd9=)Sp;K4jDptSH&&~D6c#LyVMZ%8=pX7qnp{(Sv z0svib_CI443kT!CN6@a@;d0T2au5*c)}*6gcsIi<`F2rf9BOGy40Mwv2I!r(p{Ji7 zaV%>3AMSR8Tqc*Ybc!@=pVmuR@p8!pMax0PN8@eD4QXzO-n4dX{5Y4Hn>daTROmZ$ zF@7SQjFIF~=+IlLveI^Nb7no~W+;WQ%IZD&1D@WH7{$oVNaj_?vyYKO?nX^zWk^S# z{1&=U!#EUUsREdyq;cA06(a1>8Rc-LWg6%270wM!pr8vtlkWJQLLe~*;#I~ zo?LD@>}aOqYpm}D#E4oFZefFFr9(J^r#hgm0a(cJ+w6!mqBvx~TqmNz z)swc;H_wJ@QNuQ$`3&7b*mgth=nA3JZ>nbq;NrG$E5Fg<5*wGF>DZb%!(#q|<+F(! z)$49~esi2Wsu+3QbqvoOnReECsk=M$CG63WlJPpWY+}?>Q%iI~?IuDf9!4x`C&iV> z_fYMYH?Z5)*vOJHiU>2KU?li8+D&>hXq7z}8M$8Dm#OC{T9(tJpQ$k!!h8mH#1v)A zNhokvl2;&0mf4H1;|4dh+6N@a)2n|rz>kzxDR-WrUo@soCK9(xgtMwf%q&l$0Mr|T zvagz6b(GwAO&h>-5fH&5UIh_1O!l|6D%80GccMe<3$#GRHt5u^vPndx9j|VsXSlvz z|2}JRd;Zs30i#*h?GPYyZk^qz880JCYDx3+sp<*EU3|+(bEzhQz@FK2g@hq)QY~Zg zriNb|Ds0Q3bp10HeeplxyX*Y|bOnhg*byOBHr|+7 zIXSQ+a;1}#+_RXb3LsE@{#tck>H{%nUG|kkyHKEU6Bm?dr;X-^OM@wHWBXT*DC3Us zyL40vL`$~5n*+_3Q_27JT)dDy_zj$|Bc{vQ_O9I6yHG3 zlU$<|YG=KaXc;0Z@_6prKf&VphP_StecGD11{zT3odE)0A^QmzB6XUOEfiX?nu)z{|3%_sdSlZuqdnzfhv%?{X@o zo!M;`?HS3)MB8!x!^k3IuN;fHfdL>{Clp*}X_fPRYRBJPcs;V}y{$X#Hm@rc4zfj8ot*;Nv!?*5YyQ*ubY=j%_$Du#N zUq0O@qgXp9V+?a$|E~!WZan;vH%+*&Szw%bne)(jR5+bg^{Sl?r$&($V)Hf!Dm{1l z&(>~kSp!w)^Oh!G&`(gxQ?C3)=pfJ^up+ETrSUWVCfeF6@sHIf;KZFXN#5vln zB^|@N=LI)f(V&>#^h8%btye|V>VPXQ-gnQBnRKL0bzc-!o_H(tBxbM0^^8ezRB@xe z4OB$ST`bi@{{b-acRz8Uj$a1VSFEHBpS_Z!t|6K+yhCb)hIKz!SYw?LJlNokxSQs-^`Xi$j{RJ^zu8H-&BrgC|(!-xr3;^KcM7^AV# zwB(j6r83gn?De*}<7tV-A(c0PS8ziOSFv7^UA?W|e)6HDx%3qtB$zLp?^b3uxRjTh zHO%@{Hp2a8*{iN&5#QeDJN36JuD-9TX@)vmjn9vS5LELBJ0?QfdqM*VUGs7?r(e4& zsdI&<3elN0It4IfH7{mwpx>a&knc9P=4`M-`(X}Ps1#sETDH$}V6w-wtlVinDzg*b z7st7K-a86@cSDrYm+b#J-jqAHcpGs11LEnq>%UVK@y~wrCJ#5fJ?d)u%1P$ASxF~> zzgQWzSW3SW3Wc27(o#}>SO-)*T>h>jt3?_Yu1Fvq`LdbZhF|r9sm!h#)a^1<;sKfQ zsALUL*<-Dn!nF{Cej2x2!2q2hhc_^M&eaX>RLqk>(0u~YJ$8)GrQ_>m>0wpLP?`l$ zp|tBdd1YE1hW=feN;Qd`HDg6tn3v#@Tr}0#9o2Sa*tK`CFW3HfeFVt-viTx#C@VBm zW4};_Ab4ZGqI2S{9>w2-prjDI*BVgn>J-c+SkY&i;HDFH(o+$oZbfUHOz}_ZaHJ@a z`FaJxb(w4#nYukvKIprBTQr1*y8$FhPSH(8!&@>I0U6~R+nhXc{TJyYM2vYs4u|=N zWqiH49AGSGkC4I6I{okahI<4Lv@jA}W}I|RmQP=Y7EY)OuouX)McGaX;cv#ub#+?c z(BI)NqjiwhzM~W6Ub*PLy?j}a?L5CC9p_~W8Qc2yo|ogI9oG0HWGdV{Wiu0;{hsq( z+t{^qWv$-xNKXdvTO5v+IS{AN#N;H|3S9sz!3`Ic!8YOYBe9i@-XFsshhk3x13W^r*>17 zqJ|wlnm67$@%?VB`;Au!O&SmugS@WU^YM7IO=6*1yHy=4)vJe++Xp;Xe@MIqD-EU} zdRnw4+n^s3cTQ1Dd7H5{@s9zuW$saks=9_vkzHB0N;9E$OfgMWTDwRR=L1}I=apvI#yNak~;hRwhA;GALa>XOw1S`zU0AnT6%}-WO;mlkJYRY z3Iugu(}dOX-$d1)d|;zK4!?x&C^GYynsyZqrdphiQTcuwlqTEN6Qr(wkN(3IX}=++nr@6#hoUsZz$DR zwdoH}3OswrCjH8nQcM)BVT2>=o&Xy^p7WJ_YXf?sIr4xu{E0@c$hikm$Y|?|N((8Lqq8m=K$x8MLk7;{lD|uwOObgK8LF8NbADX)K}|6bOwp^f6zmHDt8aOW%(tA zstDt;!C$Z48jH^y>Mr75apV1$np;>kc6Xvz0XU!&5JK zJvr16cdrwnqv_h2+8U&pR9Yo5%P@02Dh`UYSEQ0ao%ySmXq(oPVQQl3)gMn3#o-_c z)l&AfgP*}x@OjeaT`+d^aa-$L>*J)E{@E6JWuG>)kkMWnt?;q~=j&)~7R4l2KW?*^ zv!V>tt)>ThSgK9E{c^>Z-?~RFe87DBD=(Y{rRQB)e*QL@tO{WAuq+r+XyX$h5t&ip z>S;Qq=SHZSNhfo1l||^=8WIB(XNVEC>4US&O$2)S1v#Z0<)e{%xs=++>$d|B$_adp zJ7>p~viOY7taC;lg_hxX!?rFPj=kPSw3+Mi>d|!7%6K@mX#3ysqQ3Tw=phJ;d9wTI zZjA-_RSp6c^>OzXaE#@ycwTSOHtSz`2cq6CTYnlZ>;PcBTfz5LmgCk4(f?YteViIJ zxj2!Ya1l$i4;YoO-?*w{7@A$%7I}!7G+5gei;i#HzDQ=P$C}^=oXgn8?xXcP8s^`Y zX}4B&v{YEL-F5ZE_@}tFbg95WB*sQFM|Uy8Wkty|jx=;*IA+Epv?Ql)Zm|nDud(Ir zGpSpC4^5c{yfqQ7+?akiPrDq~(Pjs_D}NEwlOMztnPeHxCA(ycC0G%kWvmXE za+S8F3(Bm=FE5!d%9nsjfy(lo9q-qj-Fj>=gLWM2kjk80vCGwfTi4pZC0;#Dm)JKC zlX^ju7UOJnC8$_UADt8C@TcPLe$Y{MTdfmQTEp2smHSMYPv&=%M!Ewsn#irfdBooH{+k_s!2BMb0!&g`5H#{?c*$$d1VSAB=IOT8%2iA2mV92BWl#nR zXmuE4i6^`Hd`=q6G^B@%d!;o*nG;-+bI(Dzo<@{7h?!iUEUGqn{Yt~c`9gn)>%fR3 z#~$d!7QBX-fyXH{r)|nwSzhIe_B@KuDIfiqIFjE2!!VTJUjA_eam9Q&Pt^Zohg;5` z-mR-YIGbKNA$RbvF-HAfzvvcoAw})lAF{;eb?Ue1SmVq?dCzYhC0VH4EZ=9D(%SW=yzVzAZOKb&o;_*5!b+y6#`3Cl{ZgnF;(7P{3Q2ua@ zdYXd(*=LYUyYGiAP0S}@oOE~Z7=Aw zO?1)l>th3Y80{v`%N}0iTni>x_ZcN&&5$qqPf$yh8gK`Ma;D^kqWcD%4eYtmu)~qnhr!Sjb%)>ZVVKOMx5~31VKv?}h zD;D&ptzM^SDUuS9yxYF?T*|q2A=gW)sP^_-oVPio$3F7kyUQ@(kCXEhN3gPL{pZ|M zp6M@zs+)=COwEm?8Ie}ViMg2;)o3Wh!K6E*oi5H+dq|KmBx>9Zrw)iFW9#RuT#z_C zwgR$`dg+mP#8#?jrPkyC_g({WZBE+PjMVVmYq_#G{)|aT-#w5knFKUmY)AF^Lt>jo zLG;a(<|idn8ByWa809eE4n4o(;AZ`!aX|81mxTz?NllkvW&;d|p5$zyEXzu(bY=Oo z&%s6%_5u|{r%vwMm1;e|@d7uL46WEctFv605owJ2i@I=l^uwK*EFOb;+Yoe6&Gu|Z zVZ?yAD**Ipdvhc(sPjT@yidv^9(B2@hR0Fd&!7J9g!7fPMc(oS;o@3OuILWakv?-? z%2xabI-%lgs15x4A?Sr)wib|+3N_?R?bm}!s5vC+uZx#;UjQ)Yl~L%IDEW=DxT(4Y zLLMs>pn~MUPmQ$ByKN2QJeAlLG^>!VOghonex9T2(}URxD)(|GXe+wg-0_>$cSd=P zi!nRq#G0S5v3Q@H`nIs-_7M-j`sokKFSFkT+SKc`n*(Xzv`3Xa?Ny7=?$K6}Mu#H> zCw+4p@w;n`%NTll#l+*H0^N7$o?vZtToZc0_u;8uQGawE_+<76t{x9RU@i<=FS`IQiWwIy@2_#Wn2uI}17I#cWuX{h->`@fUxJ>ksUl!5`2rw( zrp_emca)f@rmqEjr!RW4IsldG%Yp0+Kz63@Xr~-{>_P_o(TTV|K4SD}O)~#%`pe?u zjHe$2uRzlJJ2R?vEVyd8V*7`4wru${y_7X1QVMwa`>7Q76VGNUH+>?c{AXg`9Ia3P zuZH7hyxrCkvM+r((Ce;mN}3!NoL~}FR2z6YM1Ll1I)f7#MM?l2p6=a`4=YM-kpK#^ z#Gi|;^X7;vY^BH|&OP8&_pUenHPrC&poMb*c(ZW-D@%RY=3-mH0~l}ilxXHbNYcRYWyTdVv zYIG;B#|^~HnCx%=N+*D2;N%22so`x)AWt6RcO#^@U}v{+HOjAGk52pphiuAh75{C( z>usc11mxCoiond4t6WlwUp%7EMt)gwaBCCeDtI!?0~CS8(>#B7AQgcnZc z7FmS1HB|>MCLV^z={`K#`~b|joiy}gR0g~JiPZVYT12DUikkCplv@EQ`&6vcOTw%8 zOav##@w}i5YwXj2Y|0_Q;Ll95HyPTWhIY=J;&u*krr$Tf)HgJz!_zdA9w%RfO#gZ- zQO09fC_+y0d360MU$lAe*^o$=e~rSl*SXzfVfR@2;r~fm^*i?O^}Kd7R=Y$=>AS&b zUZn6<#V&kivurIw+_+U=5#JVi-klp6Q45#N_d8(0$vR-Dr4)WpZQ$9118NWOeaL=z z`;5bVNtgb$5z{SX|Mh`bo$x8c?-m5jt~d->$yjzO`)o+Y64zvQ(eV!N-x{7kH>7F6 zv>Nm}1+2gcb9X6iQqN`BsxaDC{m%Ay?190Ynb1h#O&ZeKDE^38K2rAW(wz{$Sig`A z7SAH4Vr9xT&Pr@3$E?1dnp^A@i;mrZvAIG?oWKTOwF%H3@XW}+jL$jx! zP-Cpxa#s+Qu7Q@>TPCmVOh<;dV$vsjT6&=KFYIr6C!MNtkgRQY&_Nz5;oUPXvZW(_ z_n^bRc@|{Mz7I#!(av;cWpKj2qml2p7Rcpx1>JB|Wpy)w>eUz3ioGUBBT5hSY+IDH z@a9?1r<_rX5VP5w!tI8UUm1zZ?LR8k*tWC(qOlH7b4~soO5 zi?I;r5P+90HqsDXlW_ZJ=r8he2c=z)b=D?RK$QU;3$W2cGa23 zh3s-ev1<}o{|zQt#KcehZ@so|yBxAzUbG_Q{#YtWx92Rk50Z88LaXLDa}&YAnDm46 zZNjb1XS17u0ZhWJ*YKK@o#<7R*b2OU@R{qM4u8adXD)*kd?X#tu4&o;X%|7r--=AA zQv@}Q{reFH{3A0?0?=hu^aK|V7Ih^&L!!Q!YybE8o1y0P)m60*(IW<|#a~uNjDH&_ zT4uHVbuVi(@txuoMak$yClo@&I7h&j{g%iG zA5F8U89~Wz#+y}9W4_39$SHIPTrzRXpWi*ro~E}*q*;p=yY!-pxb2y-387Rr$YDWMOj0&Et4Ye~L$=6O= zYq5kuE=jPzO3=}17vmN)0iGy-JGU(e-whJ7p+V+ogp%2c5J{F$CYo@3Z%ufWc&a5viIR77>wrQ^j> z8)xsiYU?P4-TwCSFV@qBceIQC*V~DzE_3I6w6zuJyphXR)%$*xxjgMCTm8p6)J+NO z`BPB6mTsOUEGbHn4tTWg>A zt!H}=z#P|BOunBF_3BnRTuF-YFd_&dQ$_%7VP6~rI;65j1``Xivn+CvhFixJ(sz;= zt){Q^0%XtVU17Srf$4F<&*J)KBDF)yfr8-L%-XZ^{|XS}!uB7{&f0B{qsZG6t0Y{d z@d=Ay(<%^Gw3(+zxPG37zsDKA;ms}2qUCwRe^9zNtg9db^?1x6MFJ7_S{t$}KC ztAn!go;tmnn;SZqd`*Ht+I&6)_AKGlROT`|*s{!-N27HQINuE_8z_IC{U($zXgIg) zPBXP8)ntRHVn-Q`TJ()Qs^Z>dQD$E=SNpY?U7z2GH2F2B4yxjRHtqwJZPNaZBQ@{` z1T%wHX!k^qWP%i@C|U>4;Ks|fL1S}G_9X(2VZ<+r?UhjMM(8SLiHPxbnD2w^3RhsF zS=b7OEhkQXiMicVtD*&*Xklelw6a)eB@LAH^aQ?7?s&b#Uxzd(@#@%X>s)}HA+VY z3+m8?S4%C8UGKO1{<9^XO2Damrh~H#Y@O+Y5HQ(Z^ovkK%L=n;tOh%mCYG$r;7#qF z>OTb5F9BhQ)w1_1Td`eADq?Dw!+`fNm1-Kl{?GET!;Y~Es)7Ye5k@oxQuYwyGDZsMkPMoV@^CsubRS0{G<_fUux z5JZcF6`@J%|9%fsJ0kJy>BOqAcXj;#`mGZxyKEIdY}%5fP583HQz@OA-{$<0)>Bqm zm-NRTZ5tHNr;}O4m>DvbeMg;!)FW9&ig7-Ma{tD}`StHj*7qCfyd9L7UwK*f8jKTh z>*e9$!-XQ=)XYHxMJf@JR(c+U2WHo<1?NG{!DIiUitt}O zY~P%IWC3$*lyA`G=K5hO|CA64;ZVg~*Vcj1__k5@jozD&m8CwBk4z@Ru`}PH%Gk-r zqZby%Fn+e4?U-X32WMNfsJhu=8uFh|oI<+@@!)2%4CnCZxMan?!h-?Cyqq1RH?gl1 zw(b2h>jrPctmq+1#oFQU<#fqNX!2Kt?fPv`C$33Ut!wv0$Pb%lCzIIu~IU z$eJ#Yk?3Z#SZ^`%aJbvo7z$5XkBa|Dt_C!}X0>W>6t95hUJZPRbDeyCR0a12x;h%N zu5M+wEQxr8GeA{vX2vs03%906=;g^H59GArC-Eyzl(~gDw>~TIP{^o$yYe{g2Os$c zXU{>XNF7DD=IY?LR(zBr*j9sx0ObB&^ttpBvtb=f+18vBo7ZhB%ez! z?tb*^WS_N_=!S^ukoDQU02T3(0}{F6KwftU{of%ZVj~Z-m4}~$i0F{X9qN>j%D0Zg zisrGTZHhiAV1tO=B8HNA7UZD+O@GXXVg>2g+G*yh>LYiujiWYZUhbYtj{LAl4mJ*v z-rR%4h3HORB+GHL$yMZ?WHZU&-dj&!4X!rXUim8-ce47AFz)md$18K^sh}#8iZdc5 zPYpF#v%riZ+d0xA?{G8%9pd?qz@KXRHWx-b(;iw{dc;ViygYjaw)lPKA7sB(O^ zBU^2tfWGk;19nBDc~Pb>;KdQ*=3H-p1RLF{3O}_WBu4re>HLZt4*x3}EXp1r%ap2B z`35Byj5!Fxj~Karn;Qaic5l9@L{o-GRXHYK*jlJwOnC9Gm@?E@GQ5agPFz&mxB^4- z3*PsB4u6}|Vm^#n>OM?<)o-7nL7WY%tV~hSATL2edZs|gxwZj0`9ZvJA#dnwaKRDD zsF1ENQMh@`tnyI#O%6?$1XN+g;d4meT_a~Sz*h!J*ypMqsliBFcolls^ruAq_JPS! zC`9xNAHpFBUt8GXQ*0bbNKKW|-0K~0aY&CbCFO8qCR|fW8!)*UAs(pEZPcSgJkvaNW4v-V@dd}tR}UoTnNSa1kJN>Ml_`hu1F(l=5 z)LR*HXU{x4x%aG@@%u-&NV6863G#=|lWrV4cj>cS!oh@NGFhM1Zn}DVTt5-!Vt0Bl zNB_-opC4frMbRZx^1Eq~g!ydvcSlsOPW!ezN`xU-4modA{V?3~yT$b@qft9d*pz6f zRfKYShuCsiaik|ANO90>xi@$B@~%rApB7r04U>g~Y0}UAF#V#@JmvMzk+}`SYMx?lr3?K$U@klZI7hZn-e)o4kmMb=QtuPX!6x}sg@Y}M@ox7t=4>zcl?-Uje>FYs!tJ?X8SBl=iJ2&!(W36s^Avmbsx zH*ga}wU3vxWal!|HX7*ewzldfw?5)ix_@FjCcWRSvw|%5ER|*%6dhfw3wiu_x$Pj4 zZSGLqD{lFCY#@*weL!%;RWe`(qs)_i;zfBMC2Oh3+z+8BAi*v)k$q|4Omlqn6MU_2ej_N_NQj zK&7<>7J}pY0ZdQwvYPwd>ME{xdz8*tM-Os+7~$nMpG^VcU3q|4`x$o-mm> zi3xQ615`?;C+DM)X12Un+9LPptVi1qu5G>QGZ)qC{6(1wRo|n+NQa7Erj`hbhM#0a zg9zIQhlY=Gh6%OUTl0tS?%q$;^4}g(U%t^!(`7pLWEb=<@~wk-mi8#b!mnb)0aEdU zBBm|4ChBEz`Onp~00o1PLSRR7b`9*9DyB>IaZ&agbFS-iE1xW8|1XvxER9Go;HEtq zMLKHJ777u5B|+{S8O**g;LM<5-tX-;btbDY6Z-g+uM<89t}t+&@;Y3%{AVyFMrk&i-rj)ju8xb%6?s%0aXB-!A*`GEEcAJs@e5fMs$+PeG5l>jhyPG!Y zgOdN~?++U~ZDsUIZ_)VHOI^R4v}ZO=;Y+&wM!m*=SZ-yRC$89kL_;SHk`*;I5U$wtz@vEEio29Lf$&;C0SJ#&!JdQwTi)r{Zx8nN}& z3%)>#sL`AVVwcuUt7j)3o1nPnNx1%%<(D=lRGZ3JOvkg{a7=cltx-|nSVB!=O|~QF zY9yKYq5&E?fO=S$7W$c}{)lK-J6U?q=bIE*<%82QLh7qi>16fljL8?+dbU}l#_*6q z|3vOZ8~>b(3(42vcXgPQf#mmg!8ShPC+BuhWffneB)D`nOC#M$rN|?i{oFL{YEXwH z_UkaI*9=;#9XcTTLcc^Qm|&upvP0N6kmD`28;cPv5xgtISde~~L{EoS{+@S)ZT(F5 z4TNkqNv(j_zd(J4BO{x4Brqk+Z)Mksy*67(|eRkg;L5~#r{>W7MOUUy+<>)iQ`vr%`pOMy9{LS`W)Sr`7=x;6^bSY3% zAqA8Tyzvcr#%M8@#wn*bMN}LzEh*y7O&68~oc8+%_+ei{<;|mzYs~(Z<#PRrBJQ!H zS`TLr^xmvg7?D3AUC}ul9aTna%ePnjtOy9ZHp!TJDdGHcnDbEZp`=eVx5d)wJ#V1n zSKNmweNWKT63q>@7Ak@Rsh!sxCV%f~`0crKr?+Uuww{`3S#_6SXz@#F?b@F+W9Q8Q zGrwZ=L_zUt7}Pe}3AV1z_1tFAORCn<_f&namMwb*v*^-$NIxIYLxU^DUTD(Tv0;ph zB6;&n3fKA|LZHu8=-u*Y`DI!)xbAQR(6=%&hlq1}Qj|OkrORcPI@Z}_UzKVp_t3hJa@Bdk=?tuV&`{~2d+3jzb$2_$ zmA1c~*j=)`{^G5Olj`b_e00d(A-1}HW)U;Zujj3D>)K|phE6t69Xsl?^AZ`j_E}Hx zmwzP>54~{S-+K3BZ6UkDB_)l}cT~kqClzj~#G^TA&Zt2f4c$4%iUWeSF1pRERgVz)!QB)eDIPl%(3@=r^^j;qJ6L3CYgNrcrc~>lS?i~R}u~C{ay~Q zs3oPH>Fv)^n+t;@*;!-VJ5DbZp`fSGkgEmB;)=!>54@uN%OeArsv>^Q`CVhCdvp-t zja*d27W!vF0*vH>rmR(jc_reagQ(Zdhw`VouQxq>F|e+*EGG z2A@9qy(obCUM^G zO?2Jd>s<#Bn|0TdLnk!1UlG7%9jPNvNJo491rJ=p;;i3;4vW|RAkN%_{u+f>hiH2{ zN^^JpS!c}i5VM2`0gSDVf(bh;k3z1#1cW6IAi%SgDextI!Xr!JRgA%p6LXAAw}!dX z+f|+Yk~#ja;!4gDi`+d5FUFpurNkMT2binrgC*>&z(gN@0y(suI{Tx}5FbG4^Q2OL zIChsrfpaQ=K6MlA2;*+8T^n-SF%vZWAJG>TCdu9wS*WHOPF;>PK-(J^sq3S;m9WL( zb&xsU81q#sq~>v7WhZLXAbcS~E!*T{sP9WB$Hv;rKDp~5S;b>MIoQBnA|}2=a1Tr* zAORHDr+$=`vm}`**Do9O9GZCu8w#znRdgUHks@wY+oLEwOamjUvg_HcC;Z@?+q`s_ zjpfsMH7{KBU-l}^*M{{5>pWvphrn7|R)cNf!mRcFk?`y11wmiA-Or2X-3RVX{Ah|@ z>a^=7cUPQo+Dhzd?~@Q{#I4vS4F+yJ66QQ1X0rzjALa~iCNx$~o+vxI>N0Z!5YfM~ zP2Szs2mLR!6e>P!Y_E_Ar4j_*NA=}NepR(kRl{Z*U@~gG05+j~&QY?1Nbq&5D?jF( zvpD;B>t9k?4%B^bn{KxJ=f&?42>*V?7C$aN{N>+k4;?3Zu4Fvw)yuzoZTjl|LtjIx zkG&{vNl=x5ME&&?m$&dtDaN$?AA`n^AEc3G_PWL2M(i%DRj&eN#}^&y4*7C^Jelin zQ#2v}VXSCR;B|IDqXHgTm(67AB*`@r;cc-b#rUXzyD7>=4e#CXRZDo3=v{Dm$*h#Z zlT&FJ(-b-W%)zgU#%r71dz?BUw>`_mUF28@VE6Tdr0M+SIo{e+bk!c7w|!%0v?Z=j z{)jTqKF&1IVQg=5I`W0D=0r*Ctk0ZAc7#9IPSYrC-8+BePzOW*ys2uQ-OR<@{$V2b z>$9=?M3X=I(^t3)J-z54xYCiTs17y(g_U7{PN+}{c2T}8 z(K~x-3HXt3>Ej54fub?Lwgx+DLrLi+N`Do2Jq|VZKGa5OCXs*EWTMv$TpW@?*eh2w zpXN@ecZ<2xuW+_?yKRf`F-d-s*ckt73Z;)tc7?kON zEZL2&7tcONCXA1)vg7xDdUn5uZAO;2)WEMQS;h6(8!zZ%;m;D7=#Z5;w1WFj+?ma%N0Z z>awoo>OPy&&0PyUd%~2xy@B1`(Ap3lAV6L3iQsnuEq+%PG;-%i7CBZXk0)x-PO&0W z&QHP=$G32(Ui)_p^W;zYTpxbM_8;>Pq&{_;ruk7eKoUEfDqJ~5Mc$5J%{Xw7g@Iwmgb~PzHWU1|^ z^1>tlyBt$YD=2=@`#SmUVZoUJP;uz)%rIVgXTjXB5$1E;+K{D=t=KUlbB)GKV@s|J zq((?Hqox;52GVW}HEiVa!=w{@w`&_SEqSRrh&@^&4j#aJ+<9IV_r zKvhN1vF!bzs>BR^9rN=!goUJ=_0MGG7}N z6f|-U{NOej!;x=SREA^#mE2O+?;1AD-aO2`Gdb!aD-}7i@Lzp&PC##H zz;Qt3=Ma|5l-Ba~vkC}^$3tC!h*$c)isL+I3}bfMC_a%AmfI}L@2LV#{!RCo>5o77 ztz@QPz8bH>bu~1b2xvjC5sC*}!Jl(C3xl&|Ia&r1HEE80P{T6#sNyVbO%;qNEM$%E z%z;5OXJu#eM)K6GPt}z0*6#%V--N5PxM}E1c(tXbzB@4*{)CV{+%TtCPlW6&){7NY z$Y|rvvftENZxqwL-#n!*5Z4A4^4>~D^#A^%OiQ!my@u+v$MHw?HrVY!yIjahpD%jP z-o8pi`*1E|*b(bz{5=aBxxG0}!Oz46hA$t(g|${IoV}3n2Bq}J+LJvBh+cz=Bu`DZ zz!Ag8KAck}N+mMieRKO$O>LV_qfWK#8@j5W$M_amNjr1;p0JFqk-xtGt%*BS#ACHQ z>;}?VXC;(z?o7J5#2or(uR*gqDn%VKbyX)(pXT4+o8jA$m+r2Qd%H9HXYq*5h(Eiy zuF%q9zD@_s8O+M=u&s;@-DfN)EvAM?G#42o{}O&sVYC22bc?|AB|1@UHG06{k+oD` zy-`ctx&r*X5+{`M|7d#exTM?n{XerZ8&X+W&ZgFF>TM1jh?$j@gL-?XIVm+U7jBVh zS(!P@$_0$H|Gw8b9im zLkh%G*7e=gUu_ghNP?zilOf5a{|>gEwp&$bPuwhO3hMdxZQ^C@Vc+4&pOUoRN9$&_ zQ8&4qi`mg#c5Y39hMOCy#=abNCvYCIzWk#`w>BvSZxPU!NyMxu^|n0Y*;fNIVM>6? z$TNmRGr4K&853L6Vv$&U{Fp~~@B^YeoAwV&3)|?`FJl>Y+zfT%bu@D-rbS-Gyhfx& zdFEl+-AC2H!84#;-Th5CyKQ?pPL*$==^>6uNynUhg@cH<=mTV*Xj=R?$#_%onp8#- z`!zm>k7zexN7p(BuB;P8xymEu+T;9z^5y@t>o%Kkf+j=Kz=fpgTTL{j9qt%>X9Et0 z3I0DjmtU}h?1lJlEzKX^9y3*BCyf2oDq<9Dgbi3*=_er^2 zom!CYb<|i6#E-hUpO@XJ{%zY#o)yarj#WTpIkhD7VKvjGvtGa)L1LXJeXCRe`KXMM4u06+1gD2h1G~&1$ zR54Kj4H(pO;u{`jpH z!Ped?9|zOTNvXSmJShetsHGluMR94HJLMEUU+OMp)qBDzz$!C-`6pj6otYMa%_=my zsgagF);L?_tztG7t{*bBdCx;_oBty;4k%{JnRfCibdg3icoBRzevroB7s)uruhMBJ zQV1yS%P3sYs|7?N%5V1q_yV32dKp=Q&!4fN3ilj4FENxUjaBVqz z^`ynN3?DK;rd*B9qX9pv1US8@nu6#GAJ`ZSMJmB}!JHObJ^&6od9|3wg)v(yQ;5hX z@w&5w2a1Nf98@f}nlBpTlru^dk&V_ODU#y-#(4a)@#uEt#2mbEDpcp3)k0IM){mND zv&eu4qx35OK&BU#R(ad_Nl!nhmQMDa=GJShYYt}Gg;8HhI3G$sxbZ#E?uz?jmyOrP zi;9dBMHl&t53hag+_g(K_s$KI|2(j&Tj*3&bF6K+96Jd{k@|Abr|wYvQZ-n4e*V7EYy*$H61pEhw$C6zeLsgpp`wh%i>4gl#UKgZ0e=)vPvMz{B0gMecy9@icI zpUIEkA%(}nkJnKSS13yxXPXE{+`^*Ztv)f(Rc{xQw6ZUZM-~^1ILKe~*CX=396b(( zRI?P{mv{W3w%bc#TGqfIs}jhktzU~UT}F1W(`uDijI zI>Bw%%f)MHg()?x4n++kH>Oy|%p2n~@s5ww@Q3|5S7}Fg*NDzIbmw)%e+&cGR+lEMhr|waDXHyzV{52$lU(l z-2_qkMHn-QDq~m`UJ;hyHzrxcD{`r7ZG-Ub(_E3+%kzz~+lnqzqvE-Pu^ug2`*<~$ z%XLXE+OB_M(f!e}bnJEYHHCPL`(L3WF7NTRB#>9oa&P3TE3t~&rHkLOw!#NDv0@Ik#Ub)IxbCpJJzpPCxXZ>SX-JRI@ z@snOuoEj5r9j zNlRsBz&r1*xUnK8)^nm*FJ+=72gJSTQw?p0zt-Mg{L)W3WhGd;ny>gK7IM)M%C&7D zk{#nF%=EJ>b^LjqwQBZ zuCO9B5wu*8vov^zNipJu8^?AqB!a5V+|v9jeEc{?WOc!VO-4tSek2WYBvxN(_TEI; zNbp5Puh?uy0lj4{>c(bLz(B1wPpFx(bMdi=suP_(Wg6Q8rU)L2_l5O~Ktp7)qEVHP%nD(dsH^Px)bRW@N6WG#>S-VBj4hvt;iy{pc`#Pbbc2jDGYsaq zsZgJvk5&r(j$e6mdj8R|Q$dIN>LJ9_qlc6WUVM&hlEz8dX<3nHRO)Lajs|hpy)WN$ z+hw9v#&UY-eNPRkog+AXg$dh>)E3N`S77;%^MV89HaQZJ5)EeV0o;115cT@ktGE^Z zn>`)x3*#6!0WrU4vLX55*B1>_8D?@5w}LoDo%PH$F;d5YnHL$1Z(3EclgFH!U2V&{ zKRfLisIau->_wYvjLw+C#$MjB`02DQnry8}VE2UK=A$2nwNlX11?-{Ncs)qf!hh)K zr~Z~!7_=yscc_yg5BwIrj-FmWC`p80fQCL(lPjMG1T*HuC4^@++LPiwQvYcjQ( z$z@8ezDr&kzala^)o9oQ1A4OH(?HVQEyky<-vI3DNt}qXFRY2V{ULjX?!b3a?Mq<3 z4Ft(?28Q;>EUC;DZA;^HmCM60f{v9wZ0vdCKUBH=Zcp==HxNxT6)C5Y#RvZ~-b};{ z#%L;RT;Y96yXP9zJ)NyFHlQKR4*LKx#!c#M=-WOQTn~l*xf4=CCiYtqsp1)F0hi~D z;pn(yc9n{V%?8VTgcp!X2IKg&6u=s3Fe}xOXM@?K26hv#l?= zb~$ERVa>a(NnzULPnF!lNbi6~+oKRvSFaiUY~8^uXSw#8KX@kDjSct;PfMp=G=7sL z`?*+zcX=@O@Y4PfM0zI^KdVT5f_oFmm(p^dd4H=unD8)1LAM;={$RZD{nmt+knIhX zdP92n0DALtSYb%GTpNz3S@4-uaMmGPf%g{EsaCp}C|P0ZABDf-8jI!xsyXFl9t{nC znC`ClWpJg}Xb`@hyi_;dsas~al99;67f@v;h!r;i$FcpNm(l0C^%H9ry|Hhx^rx+} zgtbwF>hx-@Tb&B9s|Kj3*bGfX)|CyXn>Fgwn@?DD+rd`>&A5tu2bURx!>j)R8OOR*-)-o)sMRVN=R1SY;TEvsB zg#JA^Dz>I&NEO{~nUN9I%T-=mD9O26%)xi-qB7*kmeTS68@7UB4j!n^b}>#94;+-5 zbhgUhRU@F|3iZlN4p)%n2|3`mmnbcrHbv7qQp+p=_7!na)rrnX z+&X~7Zt8}4Fg);JZf`gkxw;S?rH`9@6S$G^G((Z&8G%vXbICPtgdO&72}F%#2sZdZ)qQ8P~E0a9B&z zlZM!)`a2?r~eM&Cp9Ybnw`*gL!E>!UF#V`6kyqRBRZo zh@6K^IM@+!w`gQSOQzqV(j@Q%?>3fSWJs8kk5d?fq!c8?ZVlKBM|bw#?EFcQP1j{8 z=LMFfGrRT8mOiB5K#eUGjDpkC-=As@h^Fk!rU7Vr3lzD?I!TDMKqD zfx=tZxq)UnG?D0G0{3TI2jQ||dh;FMXsAg!e|>C%-iA3Cj(*byAb#m^4`S%-3pKud z=FRWt*F)#`A5-=s&)>a^;HZ*5-909ISmSi}LK?g|Qzl4E!R_uphDeEviX}6lN00w! z6)J|8c~C-47htyU0+*ujYAr6&U%I@ex^?kahb~DCf2E3iPLF8)^g&i$+rS>Ycq7Gs=L(@3Av_=5%7HYgctI$9?2xu);K~zAtlML-^s@mQg!e3+f^UZMXZ;EJnn|58<1D=(s3HJ9T1VI?XzaiK)63EJ~u~|07 zO|QK6$5c`(R?vh)Z(W!cwK|Z>1eN5>2jUZ3wG-8tb;fB5f}AxcH^C)$?qqWNvcaX) z3ll_T9)FO8-4vy7N>>AGrVfuN`JfUIT@k{G?(ILZ@G`+BuA0PB{)VcO+x+f*F4FnY z_Wb&Cm0?^xE2072bp$}1qLDQ98#~Z{Hu|%UJioPTTK(>uy$?quo*(;fo|OhU-}U5E zsU%C8BA-V-nI`AUwp)`rE>|mkqac)Z;b@l;BaryW!f8IQe85pjYI}yE{B7N%<&KOT z_4h4|_Q>S?%bKT|l@ASvXo3`wEg|2J4J+8!sg)CYwGKX(C1{p(eGcDAEbMh#$2MWRPn}##*iY|H8 z^HzKKT9((;9pVWB+fL1Zvh@|UuxN5qv2Xu&i{97B#f2H|VbiNt^{|~jX-MI9*Y@SQ zisIAi!vh7a<1>WP37A=hH@&)sN@4Gx2%8`O?l>jh=pEPn{cPzB@xKY)qr9y~5Bz#A zY{_|h!4|H0LqcF$9ZFow7@@{TDw0-by#6PG-*M$zAE3MsnZqC<56u>MGetx^i(&}h z9p}tuI7}D_CC~t57i*{0W4oCzSD*QIM@#cJj@Su7gfwe~YlO&6^V`M%$6kv?x_4hf z?vm+vRU!P}wY)pm1RqEKJpq-n5|VrMTmgIBIxh4)&btxx?=UB5A7r)^Z85p5 z9wH~=nKJuhTC%K3*NYMx_l0}`l(Un|Z%IH$V?uwueXG$z0By}=yfBxL1$Y>JO_`HU zC9g)FscthIDYiA9{j|4NWSBwf6A#Xd2U((epD2u{$NKp4?m4ui)TGsE)y!<2Jx%@h zW*!kn!u#mvq9-o`scxe&vDTYQAa$F@h=Ksmm4`VeNb|M?dw|B=RI^so2sXxdV}RDJ z)T0wN!0KRMlpsYP)mt*ztww5yixu47uSBbd)BO7OVGTwc3FNn>}ggOoviqx=woQAij3ma|Bi z;&|A%2`jOuMc)zmE)Ci%b=|W8L?wG`L$Hy1Ku96PcsY;flI;B*lB$2ZyfWP@;CKGQ zMOluj(rAX1C~EctL}(~K)p)H92QHvZ|EF{~?32O0OoX9zPqeZVxrIWc4@iln{xGgW z43^TFRr=K#Fb}?GqJN3CD3Da9F>lzUxTh(b!0&##^p<_3V@7n~l->!Y(gF~vjvIv& zr(2Z<50p()Lbk&e&E!_V+lm|fyVgv`_gC(DHv>On`_nX9XsV(~N~gxh#Sn%Q{V#)$ ztmsynI;)?L)0&%!imZrA6hxULJCB_#nYPD#*Vof5S22XWF*FLQOKRd=P!TCNaYF{Q ze$duWm0EgL>2-fQR(Sw^Y%3^V$g<3z$=`nQ3KyUo_&lVOamRM9P`?g>ho>MSnjv+3 zjRD2o*rh?N&nAz8!*2fHjIW6Yg1@a2%e@34XZf$^7z*9t5B?wEUV`e5b}kWx!>i`m;_|1WPS;?|-;@|U#V0O0JZ)7uYj#P<;lfWo5PVE4n` z81cYeDxHYgW@}anCeHSB%TKsd!PJA?*~1xnT~8F;tk(|fuXZqD-jmI{xjYl+!|Iss zPm$-F#0sc>YjtU0_#X|{Me2H#uEe6(6$(Ao{-hbP5cln7AnsY|N$!KrhHH-Qf;WR4 zTz;fR+4|~ypQS-;|MlR?R$uG@Vx{xDO_t z(K480a?O`@=avEOFs^?a?2y%I$}*#6A9o_K6PJ30X#3d|vmEuguyiB!$$%RndT6S+ z#DJb}b0E=8B`tkcZIZrP&R^;B15fbOuA}#G%hmC!T zU^DRro!7U_g^NG9%C-L3cTO>1e$y;AH>Fddfyg$8@gk##pe?FM3hZW(97((m__z^W zGoFfJClW>#FJaehalxAr#@q-wVT6)kQn|;tRzM|eQ)6E_mW63$O1xaWEcEEJ4Jm~2 z#h}|yiWRZDcg76AWcZJO-(G8vdT~Eo>}*Y#N$T~3r(|WGgvY--{-oLHy<*GZcWzftrT+3 zeq?`~vrWoWqS0)b?$*o)Irhvq`?k6HT*yu=uhS;@f%E+9&4k$AxHegsN*F`!B>F#b zmoMbZ*ySSc3XPdu;_)r-r=6jtd;YMDh4T<5&56UA^$#y zo)-z7>$ZdE?pstvl^*0cLI6kvhn#VLz`>l}XXxMEvF`i)XWM-CVRHGgp`w-C<}$$} z+YmGOa{FqiiZ5F^zHq$-vTs}v3nn<&W)nM)-++NfzDw>kQ!`@MA6+IVztX4U<8 z<gt@AtC`@H8fr%sFts_7U=R?hLT8v*^$8vMd51X zit}dG;F2Qiwb>$A$ckSX7jBfp%L*aZux0;u*)Zs4@}lk9>g>OyBFsi$NAe11@^IOX z_tKd!`^BbYZ%6r?oZEk4kH*}3ZMBTCqE{j|?TUumm$pYmiDKCw9wCP=-+Q-&@?bS4 z`dmB)*XEyKYYFEwFJ=!}jJxcHSc{X@De0m{-~J0z5Erjv6$#D>jcuh9-fW<&5~OU+^y)}0Y!Uc zTZOdqW=L=R%id+wPBlPiY4y=#8z-(s2y6UDlHoKN;c7I+9>}q9rUg0!l}X%hIcT8D z;6w50&XbjOwqqqyw%~b>xX=Y{z@LJ^nlt)H8HHdks6La<*FDXl8{KZVZviu{n?CbO zG~_t_=ZTVu*y#e#D;u-1aTxFu>0!3*a;|-A}Gw=2%$wT(C+@`+(j;@ z5Q83=_9o4<$`vsiy?J(#OiLY|cNwd!HRG_BjXR?6{) zutY_FJ2o-BdurGm8ur`O*(#>{c^b>#wPvpduZc{irsD)om}KJkZY{viWLDh%I85CT zHODH(&}=gOG=2Fq8*+%A9OI&es##tGX(QHts~p4jGfosB8ka@5y2c8zvzI2lANP7G z@gN+_)ltD2PB9?`m?f`J2zpw&+RXSH~|OZK?bdg;aY%lBQWai31<*jyxQ;x2q1DcP4e zbWB|LNJ2`|lmdS<47-V1K`PxbP7rb$0=)qSAm@%&SyaF(nkkh zyJZmyrx9A&=JZhu)_EngsyE}K1H3l4aV%uSN7a}5OcVXc%0@i2mg!`Bnsym(1xM4p zccF(x?A&-TR>a<}r2|?<(Q6%TTjQI=+2v5uRzUq>V6H&4$4VrLevL7c^U-tG$l}6t zAsUMo>AXGKx{OC!P66l3Bw37XMRYI01s}pVYg(Y!(5aZt{Q`et^M{(W2yxb{TVYtc za{fMPE+AR>LlwiHC!5s#^}}olJXNXij~1*C^)njZvZEC%`-<=5vxw+}X8FTYnfw+~ zi)&4z8OeT|gW-$fCO;F~E*ew}fD5b~r=w4Cp&HnwOz=YH01^F~%KhKx^tTjeSEDWJ zzcw1zh_QyYtvZUrc71FGT9=Tp(<{SSB#$`4ahOSQrH5b<9>R}j`K(*kcF%i*7}Qiu zh)U;BIi`>Ie+g(bJNT1pKa@D zF`*wvmwZDVDBz04o}}gJ$h2SIR0<@hn#=shxyp_j^G`;G^gXO@2^eRRw)2dtz>c3r zPr?W7D?PWnTHpGIX@U35p2`cRNExLH3=KJXd(-@OQA&Cpl`N1Iy+d<>Tk#W}{`c}1 z+6JFSWd^qm3VIE<8r)+j24y=9`wKLdUH(xD+%BTwOV?&qiPNedvyGOXwvl+i9rv)m z@N5k$77l_%FH493eAR87AbzJ%PzMmyA(d9Y$kcj>+EueDRHrmwyOk(WFK)RSa4e{o z{TH%s%YkkOw*4*X7d;m{nHc=mK3IPT5H}f8T6WO&FRfi$P|~Vl3c>d*29g> zP*r~nm7s>0Hx6_UT}J;=5zVhZCT3^&&rzS(F?T#4MRZAbX-YeuQyEL{++9~+__V1p zUA=5iN1S-SOG$zNUp5u}>~PQ#UqfhAwFuLmp{i*hB|_LN8chpLTr&=rKG;nE8rAYU z>rppLB9S1Z^ZpH#Q&%*Y|3}Jb$LNOl(kF%IPo*)#339}>k-ep+t_y#RF(5bE1wEuE znxNUK>C~9+45nL4aBY;wd%L2wcKR$)rjDzPb%QM^S+sE!0KL!Usdv6r!}qvcTUJ>J zLS3Z`Fi*J^HfO81etwP@{jq=%u9e?WG5xqrua;hiW@`_QIH(`ltfXLUh=TJ;hroGS z#{js@L7HStePr79M?ALj5`ZP+MeI&fD_Lb-lp*rIZJ1FFzph*d&%h1VHwa#_;4oe= zdGppQM7IHRnpPhZIK2ip2f}22o&GL9$!}5ubvl8_jFwlGtg~nX<8*$&+4$Lql30p|?eGscg{*rPFPs z?ed)v9#4eU%pQg#>g|mSM9;Fx@Z7(mf}K`Tr(idVlPKGxl(804An&h8F#8wS4xQUR z+$N1*eKC7K9y!Anb?*j;QQMr$1b_Rc?MKF6REga4LOB8nXT28pG0hjbVnqVF84WE@ z)Qyw0}wgGD)Vo( z4#;^v7L5>hm56@0T5K(k80u>6{d$ukMI=)b%=b<-l1*>uTL4pL*v#uj1nTXi5hX}POVR*Jz9X4l470iT+TN-s;*f-xFm!kR4P4;{J4K@x9w>Z1 zaAgNDWlI*X=~V*JKc&Og5<2so25){E?-N4;)mDRovr=Gfh=bJFY~II}IFKzVmH8pP zYTVgVu{9HIsnE&r8;DjwkslVv(O0Kzo{gEW4+yk3%^H=Qts3m|8xLd`Y|xB+{Mm_c z9xUIN>vO2VU2VzOOL90m&(*-aW+tP5*&Ot`ixn;bdc<2O5H8I6$D>An))Pe?@jKhI zb`<1*XCw$eXS5R5M%W6(`C^(8)HWf5{nNJAGrOtMZ*CU5S-rykyNKGLg6N$!Hj1=~ zV%E1XMHj_cQ6V?SkJ>ma5>Rq@74fw8g-8iW1K-+p`mEw+MN_5G@681p@AC15jyEZZ zYlF|GL7P!8V!xfx+xtmhzZ;m6d$iI^>)Vm)2LvbhlQSD(9ZnwTbDCkR zI*=r=gGV=$)^-cArq&<_2}EZM`e}^^B}9?dV?r+Sqf1rF1+BnZJ+Akm)o?`7;|!Kn zvVJP9rB}~rgjX^mw-4>NL`wpiaGcWCo*A!l=vreAhScaRl~A*nOI1Ip*Q_#hGBR1W zNcWU*UOtCgYrU$r59FQ(5j!J0y(&YCn>FCeb`(x~Y1>EaLF(u|!vpcmSddp0x%);blzl zGG_m_0N7ToO_(+$5(G1)zSu{bC$ep8rXxev1J^tgeF5S#!fs=}S#{)_Ej11F)WIat zHId-N>`DU=tNt^ZCiP})5bW31veL%OdxN(KhyP1luQtriXcwj~N=G@(^yL~1{$8Gq znYg|G-c@^#wNDNH4MVTQ==#|b7d08D3Be^>MvE=iG~rOH zrXd2O{n0l~)@LC#z7cqEliCZ1&P@4sd#LM1Ze=Brp4zBh>xAmc!XdQ5`b}ck0LDe} z)Ph9j%o7K%>368Y*Ts$*1Agwyydl|#8ify_tK{Vev8YD||5+FN&bzseQ+hrtPximi z9BsmkHswKK$iHo3*bh6AB9AmliT75C+TWR1t>v;K2_6aJ^-ZIQbEuDFkP{z8r4R|l z`>lj-L_!zF`&5o`=gSmDg`F_=!3OBmXh55={ESP(gicC<^qbT9dJZdE035e|@Mm7K z=F$CkuZW4=RfKuJf8S`Xj;&ad&u{d5`yL&a+7VL3t0{%d zHKah!02VI3UFN(54)*MY_Vh|L86SaOT?h9ZGep)j9)s{X4x=I9uvy86Dq(@rR|A7@ zf22?eRd1^GxQ88Qr1FgH`H9~)FKu(+z42dG&|cmU(MVM+d~tu#BMgFIkTOscme*yluPDT}`e&OqhQ-ziZZ>1qvQK8di{-2T@49d1Pk7P()rIv(b1m;IFwD94^ z&>n|)4UDzBp%pfoG(N{Z(hT*2Eh?MGIhDI(Vc`l-5NaUrF!oqqI@g=Ri7t<0Ugj>Hb<<&ouw#y^a72HIO4WWX)^?7|_XA36^)YxGs zb>gApyQ;!!VXIk1!4+*zXk^iZ77FTX7u@xvc4*&p@J_!T$+ltnNhbv~eKcM#^uuMu zA+aYXFn8Qz#Ly=!t|FdCX?^^JpWL$tD1GIuXi63Rd7${k+k(BiK5o*rnpOJy2hlh2 zn9I7>Ko1wgJuPnrla+j=)&!k423$QP$~M=^%8uNR%}Q*S zPm^F=g%I#KzDtR+mYFpa6twyzU(HcB>yTiN&L3s!QX=aWA)lII!BzJW>===>)k@W|jkSy|N|{YrV5wZl@pNvM(0vRbj(2X^4g3T(29 zy&M7u4re3M+t=ZU9=UQQXx%8kZ?Zs%vjK5;QgW>FE*`W)^7dZP-);=~xE`WA$sPS14}{LQlY&;8h91+NHP<|xH)x&U4A3%m!Ht^B zxk%#WliDG>!B$Rz@&KX0Wbio9?{<%*#E=+E4yJ)yl`o0_HfNRY%4<5ilh~~y6Q{5) zZjcvUz=?^p#-F-0LR=sQFX?w~Q`M z&bK+#>kKY5+D@U}iIB+&_M}uqJqs)ogWY2DMRRV3b<4?}(Wa!g*8qz$v1l1jZGLY` zhZXM^^)L}8igUIo(Hum2aq0I0XCH@Ei<4Wx z1l#=IQ*?3{f2}0~z@ITO_7qJY>*6qvN zi*wgDZPO-Iw6hDe4s|N-wVp^XXeicT=)D1l%_T3p^($>HX>!SfKZRKZGO{veyy@a} zPx5^CAIpr!>eK86 zH*_EP@NV~sE0N)m`}f{6aSPhedd&DV_)0qb#{OOTHx|Znd*Iet6NU$7uDyiGkDY4Q z-&*u#(R+ah-A%Z^^W7}*KU6UD+{QYBB&m5v# z27%v2XKTuinD9*Iya@8$b~RK2tHYnwtH1Ol6MWhzgLlJOUTa)%4%G~XGP)^4#cx4W z29)R+jfX#??|j9!BlWMwO-sV;gV%hcgfSZ;qe!O+>L1Gm zt9kxLO3(f1WKZ>GTd%i@pnkoo=m^k_$TU8~bG&j&T2dgE(ehx^W23$AU{XE<2zu>~ zel3NQPk=$0F2iU(Dm||EIt@r@)DA4npoura)K}bko+*k_4Ejc?U*X$~*YJhW;Tz(s zzd4$tclbe$KLvNZ9S`GEGE?f=d7H5kXwPEDa$l8oO+)Xm_4sThOQvIHaSgq7BC!hYrKyigF7o;O$`6SriF2;zEla+XaR zo+z~KMGw+lF5A=ueHS|eBzIz9uiURd>_LiWhK9D^eqArn|LbAdjk7loZJ@Yrtgy(*Hj+1f!y$t~(nRUeD~(Z^h+n*FfK|E4y6 z8nMi|@S*u>VjNmqD$9rnnOLwQkQ zN}KPP6L$`9et=y<%fyaEAgT*v{oEQeC4L+_>v#03%W$(n4e}lWCWhTnzsV|c> z!XfEMy@To>1#L}FqtQkDr>KjI&dn0m5^^U~p$AG4MWMHCkqavEnuI*Nsy9l;(6x)k zWow*;wezDTdu`ulMOY>{a=r5!Od{vJu8|xsC}B4ol$4i{r=uaUQ8%U9XaA>;TvdhH zsyc`4BDIo`Q;{|qO_?fz={Rc@tl$3fY{y}y&4j=3b>8;<7(dzDNr>91Px#Ewa!saq zb!LCq*N{xwipy1{3-ij+5G}GqGvqal|LYsj_>Btx{&tKc0GGa5$7`67M4yX*o2Q{| zJ=@hqJkd)6aaJRhrK`L)T`18}{YR1XuQK4=(Nq2qKNFqgv@P zD%mf7sdxWmOjaUJP&H>{j5H!_!1|U}A~CzCNRQT<#@T>X(0`m0*=Q*4{IeftE@_Cq zrj*b1--<7r%p>>QeINbvmXyfyj{WuWNctJ`t6RLQOF(dI{K*`}osz>8UpXzgRWZlC z`2^rT56%f(73*|#<7V3IRRu(&j?bqjX=4mHwoAqWHKiuRKHKyrt?fBRv@78M|mz`~I4i-2s2=y*$Sr5n19*>_|);0yV7FU&$c-sh%zrLB{{Qfhdd7D2$Zjq<9ZMyyO<lnpEV3yo}=8A`!-8rv%)o z>aW*if1X%myJSxo*&Z?wi`hMRX}4C_aSM6;fzJ}Vt-hIEe|GTet&eL+{wQKoa<7ro zsYHjDKn*kA(GkZ>{>f`*$Lf^K$#HnA8s7cgj3IJ*9ug=E7B-}*A=??s1;3x2RvJyu zwkCKZSM9k^#gz;$k@JYtX`lh8LX>ACBvjae$i|JZJcBl`gXLPRoV7vTe^g!Wp_wy# zG^XEs1&oz+OR!C(Vpd+?i)*y8q#6gDTb9b3mr0ul2svA+mf^(wmB+FZXACI4B!IFX z=f-jWagOv{38%{;*W;RqoM6*?hehi-1MkO0eorukeK%rAgd+M-eAaGukOQ1wRGjTR zW?ROSWSbreBwB@NXwm&5`FTWBkW56e`XjpL=t)v(Y<#*-QBzEsA#P?TL5iuYG(XdB zn3P)}ck_%bBGT}wstY)xd!Nab~3p zYl^kb}&t~N=p{(tU36n(Ht;7HYV3sIa;$>yJEj{AVuqs%2D7rw|zaw zLIi~ujP_@H)v2}p%@fs_V5?0O33rXC93}5CjJLCk0g{^!HzmSgT`5}SYEb?+Xcbx% zK`LYyCDnTKVkfwGQ| z_og4qA|ht}TDU~sjrtJ*%kV$OJo%XM?G>S$kbbk5Z5H za)M8ZAOxJc_M6XiQW|z0P(~9cBa4DRwZ4AG6>AVK`f(yaV+iO zwF&QJAYzpz3;)dhlaxsx{5ioNwQv2FMeIKdBCNZG7w*ds2Jt@6nG@Nur2d$&PrjqH zH@%hJwHJjx&c3z%LPK20R%8Giw>4rLR_0qVN>|TlQ?aj8KF3j#L6-+EMH=ylgLqH8s%);yoU~-=p&IHdFN$?ZXNLvc4jm4lCW_+!JsJkU1~}|why`)S17U>9|!5J zOU~?R#u)plPR!=XPkW`S<2ES2t?*VsThbRMhCffGF%QbXjkXxjDB8sgp62a2Pi4E> zTN5+z^!yf$R{>hVa?zRS6gUQuXBKuUDs(Tfl;AiIU6n2rmT>66SbVA`>ZaHxS z+mwRjYf{^pv8sk7}T;bfY6!qNp9CBub2t9V&uT#uNIAzsd1He*+t5e zk0k+4Trb~*&i;T3(B(PFYZ&+q2Mpnm#}7YlKDw^Oh(7$-DJNeLGlxf5`zW0z4Ec1p z&;qz`=Y|T9wc1|}7X_E5y6N$GvvD3IVtzK}-3YOFI#YXDC|D8{YC2n;PAm)5O`#^^usOZUtv@qjD~D*rw(rJzqu^*5y&x?d-<$mgD?- z#@7WOvSL}vSZH8o7)_1cnN1w-?VHha(ny^~534MGUYae(YyC8C2D&e(q&=0u9xS~r zWEhew5Sza_4rZ?pld~4>BQnUnk=(x*#69xuuN{iDzfGE#C-ZMsckIrVFq>altj<}Y z-;Qi|BGun*zMYaHXdqxb3e=*K@fk+(Vh!8+~UT!11ES&O=(+}okXu( z9blZkkYdGbPb1DObEoT=@8#v-H48>6ii#gKK9~3W-mW_Un0Cy_R!@82+CeS z3ugm-)4_RB!cN(Km_ezItB+u`wZHC%_r*X38aYnP$4UrinJ%+_c&3`q0NT8kk3 z!XkF}@T$_%t81Mq@D(|V=JdvUcI8K#?SVpv&E+J>`;1%Wt=-wdL-_EyweW16*}~0N zB+Y~O!Pnk(zD5k2@AC&&;f1d}kleMI>2$H%lb1@t3kQicbpl_w7^R<>y;eK%oq@c+ zHGOF-4cVS{PDm?{^cU+oQ_P%7p=dAh!;Lvc@w)UN-_BbM1`H91Z?NN!>CwtPLP|s8 zc2#0+{Igf3@Aq{52;Tua=-jny&$NWc`E%h*3$4$l-?>#7k3e=&FI@p z^!Yy7I15T>m0R_l{YXuDh^yn*y>zXI^WS^+LhMzb_)oDyf&b9+Q0Q?24fFFXUQ4Gy(mjEGg02@? zor>S7ju>WcV4}f?iAp&{PS21MAag;9bA#r|3v_60xicY$2+#RJ3O)@K{&l0|p^i3$ zJ;T2u=keMB+DZtX${4qBzL7P#Bf+^wNi!DQ#@z?_=u798FOK0o>SkDu#-?Lkl4`zv@j(9;j}HDm^B%~y*YW*o9pNlv1q-$zaA^Yz8%*S-(Koi?F`PE zafXtJ>Bpf#N$c{jKtd~68FCIm3=k{^V^%Q&Z(7uI6A9piAbNHIFj0d1)5pLF750$t zk+XPza&K%Jl(1V$?2uyud>1@=sywDdh|7?^yjW1ni?*ic)x@Q;oUeakwvm~aF4?%d zes`|hcYEh9%2lP2iJ)@s%&xPRQ}sKOsZXBc!xkFK&pS6;nHame*K#*b zNhsH=7|NTO^{}#jXn)$daO65BB2&{5iVfg(=UeNA%-acT!l#a$Q&s1ijMmSW8mn=q z3$Ehz@zcq@rLuYaS4Isoia!^>O0Rw4AEFIm&U1fa;@2PhXib%R|HtPv95ajTP^FbS zrFjH&O4YGngu3op>0VmE2Hq;}y~JEu`4M@~`)kgQ3t_WZD-H5=ap*gG%;$F$2WJzR zSCv^yMKMlZlRLWkV&Zz&q|q32$TF(`qQ}1xGjXeXJr05+$B#~_0U)am<~2LWagKI@ z@6Eg+Br|NPw(I?z#QDso+i>b&t>61zTH{MBezL3ct+EB$czgaRCWIN|%j100OvHgB zX7p)IsXBFcN28=$eJB=$kB8F&ekL-oE^8nA#h;U$hz_V;;F8;~XP%U&BI+AlP?C4u zKDp5av2}rxJT?0|*N4)1laclcR1uggax@ii^AdWCZgb7PVjSxqmb=dkK39sma0o(J zp(GwSeFH@1^MeEcgGB69nO03<6b-~&O=Mg^W^7j$xLgp#V zbb$?+8>DD$>{{-wm3@12EF87CC3IO7p0mL^eZ9T)TL>MEQse*Vv?4A>hKRL*W1XEa zAv6^z=oK+1f^lLj;*6+7s4@Fg483Noiv&cNumQr67Uz&bqDSm@a76P7wQ^*iCW^rW z;_IKXfucFMme?t!JY@C+y&j2SjS7bJ(U|UO3;4yXQNhJXDRV&LQI?+q!1BrB$*J6x!Vc}(7sdS77hhbf{1H7=bp;=KdJbp8IGas9-h`1# zuDcrtpr^_!n+g4O>%tGrOQQ{?CZBwlX;aXOWX-P+RI661@uq@fJ9h&wT-B;(yUNpCgX^%kAw%0OVVTb`m%g&3o)|Wy2+o-V^CBa1V+= z?C%s~-Iv^cvspnJzrFXzIc_6=flT5Ccj6>4GkKtycJI{-$kvC)@i;o=g!ALp@I+kv z%4p}No|2lvNfRecCv`E@fYNGd?U%99*nh>)ne_zO7xh>LSpPF@r?W&xczsw(Y(D>a zq6PF0a^~0Xw-C3!Y(lQs-N*fE-(|)LI?-+*=m!~OD3=EBahEgkm>GCG!H}|c#?_xSc;yW~TaaEW%LLf#9jagpq`2h)Hw(smtb66HYW z>%;Kj-QKAlknPdVOfr8Vn6Q1|!T)npwL{SztAV0C!+J07R~(N@5u+|5?bDFSYc9RR z?>1qTW4QR9N9ZSP!-HCJji$H4q{^;mq5eubdDPW`0L*$f+&wxBTQjp2cUOnS z>GM>x%q}Ort^JDWI83^OF*vNM{BU(=m$b>n&EfV_gio;m{mn&(eBQ~;r4)F1lZW^1 zVrn`)f2-*;+}T5|1CqrL?e!%aH_sn%x<+U^fXk}PuP7-fDFqGYl>5f%wXvMn)pOE` zt(!jUUz)nvr!_YMsXHI;XDQWFLn`_P?LYS2)*hGM=y_2M4$3==8tQl1>DKP~1inJz zUOx(2ny0#20U={Y@-Uu0%}_$vuZW~y(6G54H$=Qx*0(q9wvR5YX#A|u%`sA!CzV;| z8LI_sNXw1b|Kz3MxaSu5FhvsKldh8(*{%>2(hsV97%Ceg|Ix<$&uTPCV#7lS)P z`D+xDd^&6QD}wZXnEpqa=?dv6GablKyE;|B4UreyR-9AwO(|zO70@#Z+5ps&`LK7Z z_{-%OiUISVc8a5eUnpcjEvAy+Bwhmzi$D#+MP$$7IkCeIRxM2PfwZDmy)mJG6waz; z?i(og%_M5OJ{7|j&t{C|v^qC?k4Ul;)&Yw=v%nTz3pyGaU9l9S-&vfl#GU7rCig*gZPT8lz+eAXJsL*0iKLfcukOY*9>`P! zsOrKESOYks9jwY1r^;acDrj^ym&CFT&7E7&0-^k_Z@i2mwfly5gAR}MUc~B5V@4-nG>x+Hd$+I3kA`h08gCzNAufeNOy{6^>FYp}c1loy732o+;T*xClZl z6>Hw0yCVE^Q-~Nsa#uJ--j0kFp;!B3>J$QG?@yL+dH?}tk7yw{T8(u;5O zfR()Nw!EMxMji866*pRU6h%Xn`HQ*X;D)DRzZ8cZgQU*S-IeMgbiG>|>tT9z=(*?L z9Vzvix5vT6-bUlP8Rnp=Demx@rI_J&J#+j9#F?LJ;~DW1c`!QWIxsEXq>s}ZsI^=#K6FVN3Pj|h5E{T+T!vt(B{)s^Nw- z$?%+IOi=uV#BvE;;Mv)qoh+OhGZ*=Z><~KFXWo6QHr~5$>9+YrmBA!$C?|dWOk{Q2 z_|e6v%kVET3WxeFQC3@T%Fzh3X2-6gOI%pIOKw`xI6JEZ(4T8{%q>XTiQw^vmCG6FxNW(5?ug%yl2=wWfuv4P(^dz8g}P3S6!fg z$NQ^Q;_xMg>r+(`>q1;FdO8YtckRda(=z-y!3*MsLaK--R=*i+*p}@7A_RryXmNrB z&dr%zKl48?g&A=ICJ=Yp{3;e~)NDCl;4rShSXVj?QT>Km!pke-_-Fjto_m_n#aczf zYn7v&Jj}^mHKAdc-`!W@(#JP4uu_+-4nN=W%{~?#8aZ6c^Jof%v@Jqz_SctNC{#O! zibfsaId{RBEppL1 z0=KOt;)@k8N*j8mEd)NXMm`Wee*##|p9T;fZb3ArzHj%JknRcsSE+{AR}SlLW5jme zxqbLVMX6mzspp{vN5VzDUBU(XhY>H;qZH;Zzt9ah+qCexvE6WfrSHX5d}09KuG^_j zyO|pW!XhBD7!%;GxBjSAnojJLY_ z0Ufr74y_%)1%F@f{gyx9855kFuiX6AV_`t~U|7-F_aGNk9o5VWmykQ()E4??YKc=R z)Jwe671SLN#NE^3SS^R?1836>NmqHjGn~h$PJHOfuU#{2>i5OC%rp-}k_wBI|QC#*FMnMH5S55G*aHjg!FOUI;3U11|NvyvYu2a*w%EBRelwT&_ zPeC~IvB1C`(|Is|x-#tSX@kuo{N3qBX8Jm!KG&BSQ0`il1Vl;?om4+@%YnQvt;DK-Yj^lK%^c-8_aB3nEhLGVUW^oxDIJxmFEdWUPiDKI;or$v*TVl zEr;YXv@IPZ^qTaoJ#nx*u>i&JCvKBNxqn(`C|L9oHnmNd-X?AVtb@CtxV_@Bi1LT* znK4WfBDk*qN*T2%9~#f6CX-Uddeb7B9T6CNq2?>U~Pv%2Q33G+r~v27~8Y8malnNH{Z#+b`={$twe;Sc66JN{Anl1E0xEsn5B;@cwA?r*y10(RhTSi~Nz1^3}jWrd+b{ zwajz&(@g#YGQMQ>d%vt)vDOD#G^tmRgeN9&TSdg=BX2mcE`^X^$~|?vXEE zX@>pSq;~EeU9AiL_bh3pJu-5SmZ}{XRwOIZH(_KteUCpj%4)4#twa_(u5>dYYGENY z#lhNc7sw?#u8EpslqGIc<=Tl6TJ)o_abEDR5JGY$-9a;Cr;2 z2K&ohDjipVdV9ObWHIzn-P&!P5BU&?>9vW9NQVugDzcm!RV#W}bfl+Y%}`;jMa04h z`)QKR<79fpWd43p+n=7BNqZ022;HD z-HJ5;6tUc>Jw=Msgw4gu8H@FIWM77b{9^fTVKXz12Y=MVRZmLKy{A;^_% zdHN2W*XhDofLu`~n783M&bQ7K=N$Q*B?7n-dvdt z=Vr8F%-BeHk$aYIUf{09g_Z~4aLviPVgi=p;@Pa=5^xd3d9#|ibG}VwZgAtP79;3! zkc*trb<$0P=}Up#%tx^}X4p(zxnFCGmy_DYQJ@s{8U`trL`ogk*x68@u-sh4-{|u} zHmI=nMyj)Yk?d5@qE~1_d)BU!HppfTxIj}OlF(Qn^%L9U2y>j4RzwNi(@6el@=I<7 zD&s(Y0D@$%u0gjZ$Z-EbX=(a9cx&1kdi7(&`ia?CNKySr^CMLDUyMD4j>cKl#+E9a zO8>9HNyWMI6y;k0$J*|}eHSY)xmKqS!q&04Gd^RN#9O5_E4P?akzwSX{ z^4WxbrL_m5MYr)v|DlxZV6)K5P@yurs21qB?Ge~>c>4=iIu!G^J*qt)HI`olI0)y6 zT!<5#IOSo{IMrO<=_^6rktEuD#E+oOSlt@1#siUZ=u>|gc*OF?$H z<-*D8#L!Ku$#r2BKUu4F$im0bnf^U8i$EQ2NywKCrg*PENerA6Yz%>6?S2oIbqW31 zbq!Ubjsug1^00c`H*Gc0m~ZdVw+i~F4EZ2O6+>aR&Vq@w2%dB2W5PxQClz zSPR^&(fE_Ik;+t2|A2XGgvqZ(S;?udq?!!J@#S20H<4CNUZ@Q#@c5yq5XtoIq7W2xJ8rJc~sMTTgs!|&Em1vVJ99K#tTfCGtDs3*J zkHf-vu8<1t_fwYop`QDm*zNyloE4$j^zgs6#@2gJd*U;C(wh(JL?Rt?4#p><)cq?o zlQKi%xKGnSV*@V?7K2`-1YJ3(?R<9jrTFQ{Js2qzKL9Yu4LxjFmMqL(?+k1eWSRXb0wC zc3M=v(bC^=u2ON9K_#HmGF-cuRc_JU-sxSpdWPp-+zs6~I#ov`_$#z@2HJQEMo36xagAziZzdEIt!zaWpM0 z@P2V?%aq{mk0!}rl`b>+wX#j!JK$GM@sT?3qc|0FZ;f1%W1+ycq~gnzv3#kpICi}& z-jDhY{0TDI-EQC_O|!zi>vM(IVFZE~s0$D&GtJ8F0^6t1lc|m*a@22V0)EXK$Py=; z$#hln57U(g07o(S(O&Bh>#@FWEg0`eJB8~V=m836fH{%>Fw`HA8f%AF(EaAkx;So^ zAnN%O{ohaBZ9UbpmJWYZR#k?~X?yz5A613bOM`d{ULY?f)vve>^9kL{o zSeaSNaZiLZVr}-Dc?F+HBb@Pe(ryghuo3cKS=c_Ui)g!G zC$s=zfy3WGsSGz4bo2B~_ti7&lwDk*{Ud(Wmh8tMlt5%m!$cnDa)M1O;UO?&h442f+{pzA!Zx;^gLQSpbE7hDQ+PDcWJ+Goy z-dK7V891NVeh|#!M*ri?>Fpb?14r`0dgcm&WZtJh5jG*qY7%&u{5N8OZ#Mf4z7=!% zXO7u@JbO16$Fsvc4*!EjbT&#;EyLDd7PR;SB4ln_~6V*tsOcx$4k97Df4$Sv| z`s_NJpc8)k8nOcyOBeS&5yFh)hhPpr{5bSrWQGX`E`6m z|Ch-fY2D~KR@R%Vuwe^=$Kt#5;D4F*aXdQ9wg zZGWC=h7J$HXWAMEP1V>(+a>lc=gaYD*hLaKOePa>Fp}@m$}PS<>{INYKY6dBKUmK1 z0tRz9fvmPeZ%!P25;il$XwP8oCn)a|B}Lrtk!DDs$I~#xP4(XTxNVqgJ54C%&(GpE%Rae&~eGb^W0B|I@)>sm$lXJ^VXKM zc8NPnAz;4myL&M+QhNfCqN6;L}V${E{w{dWC>6G@}wxz#d?rf6$Lf75G zW-~^5LRHnh{$;t@g#OT||B@*vk?mGVlMYpSfAj*J(T{XV9E^=FmclOYN#K9_Y-k)Z zxn2|EF>Yq%aatuO$c_0glZ6w%MN($#6PVNx?AVp3h!lxzGs;01YVx*eOR#$yUl>ocP1Cv`LzGu`f{wm1*pMWHG z6x$bJX4*9s#m2u%@f!BBb#iZtZOo$y4OY+79nYT4o}2PKrA>%km6BcRJ$FmmhJ$)$ zU%`H{KP&zt-Q(Yw?5gCIV~tWr0r%98R4}Fd3UtHE?lV%_B=dWzH@tQ8A@x+Nwjpfb zhxPV>;rkPZl3H-*FnyWu;To|OA4ncl5Dli8lnzmBFA`DpQ3HFhuCE71nU zs#X6^DQuI`fQqHj)SO5Og{FDP>YVS2eIKmiiIdGgm3bL7outko4@OP} z{TQU>#2vlhFZQ5^x|{b4Q|WKy15Vk;QM?$|N+zg_MFnl)0EF2*J`6nIqUK&lk+SuR zc)#RQJn_xg)DB%M2mA(4bIieTomC!x8W|ZM8XCerY}OQVIzJfSZySCxT{>9rgnr%z zcLH})V{&>HmKt(Gwj=FDqe}Q8LGqM-lNs3=vdqt1P&>)D-g&4A9U_$N+QQryrAe-u z2XLKRifTod0yITC*0s0c$ICGTP1}BBBAs1zf1qh;e_kBUY8y|a3m=O^YWCV7G~KEP za&2TfBlhi)10ewiFUy>~n>i?Zz!Y0)n_`jafBNZ+25@n4xBs4CJ5^XsyYgIHlLbOn zOR&T>deq{6so658$ZgJ5_rfSV2hEv}V*)2XmKJSrJoe+{_!5vEIjqkzIf?t8ke2Gl zpB*96**h4=kLcX4qPT6^>mD)A`kA<+X!me@|0gJ#GyAg5G{>uR#Du0ALmzHl67(XUVI3VjTQJik`ozP;y$0DF~zYc z2`7LA{gk2aH)HPyr00pyb^g-1{95Ke*=`%@bEVQ3wkv3{SXD#d@{S=O3(q%wJbO+5&!;h%DB5Si@bI9DWq)A=-wIVXpI@ zYnndzU!q8e^$C71_UQegLld*Y#l-Lk<@}?Uep{(%PM@hbb4JeT?#Uz5(uW_!TnM_j zl2QWwCw;+f)!LPz`hv~+Wzr!YHF;A)J;dLnC_O9-hMd_jiCDov0NkmrS*#~uQ zz;7y#Ds$AXcra&iHF@#Id88~7>!>7HQu&2ieU>i@mTo)R8JFq(_!^RNT<#ylKW%5} zf7e-OBD(ZMgP$DIgVP;3^c}7@v=p&2IJ8-|Tcv4{c(v^f<~Fr7^&ES5ehHD|Q^RqK zXW&gvNT*>II6LkEB@A7pYZdBJ#I4_n#3RrWdak7Kd8hDt)xV(8&pDG39R41n_^9mM zXE!KB7n+a0#-em^M0J*dhOKOm;en;WdC8-p=2x_{khz~bRdCY#N(Mtr=aE4qg}O`V zbY<`PY;%@kDELag?vw33S@@K|6QDtC0QdP>5j`iGPk#;JOAg}bpAM&F0`&6?22hJq z#(a7AEJr1RrJ;xUYA=l7-ZNcN`t}sY;_2);HRk)OnSs} zMrz{eJwWXk5sZ#J+QJoO#>_wT^UBfR$xW}58>^Jf5DJk} z`J9PgkK6srb}g{7npCBAuOSys#ZK-Z{CmbyD~^CwM;~rlpRSE7oo-WoID8+hxpC{FDdigKDI?%C zx!rj!N9&*AQ_9?NrRmq9MOhXn;y-R?$vlqW{i`|d5A6A8_?KB$>4(x=e)EAtY2o4E`0!5RX4{1PtbfseGJ^_) z*<%H&JHr?mHOJ*`CnMyse!RX1rmHDBVk7KqHdv(uGro37U48D-!w$Wn+EL8-xX9Cj z7`!+v#3!$=+iZG7OGm#4x@|A_v-F7@G2F@Z@Zn+ue(&c=dt69YB9}#SB2Y64UILrv z_|W>LD><45mY^Cje5KYIVh56hSMe%1jA(ASMq z-X>|xHuik-Ul;ctZ*mv@^bYg*&0#q1_vBOvpW_vxVuLrAP60T7{e%LWhM^7yy?KCF zw&%86%+?)ESd^b(%V%5^+_j!4Y`qXupUPN)o$z{d>l|K9R+Zy=;6Kd3Q?4Upx}YuO zEkk59?YLB07Cqp`WQ%$JRUG*ARE+s}56BIKO6x1tXD`;?9ef{N-7ac}P-fZ(#~f2I ztY#u=Z`) zxw?h-r`qn!As^?spsHAnHcOXgO$Gc+n%hk7y(Yk#kXeqHvVU!A#K~@QUTcI4voP|< zm6?}53jSf&hir6>|?Lw z?Q9^vI1(7E5H+On?FPfE<56tFk{x+o7GPnB4u5OTdbno->b=K{Ra_$3sIGdz3IyYF3=#%|v4_8no{JudTUnR^sYT+~zy1N?0# zSAVo$N}6#N!dY)kAUssBeLHT2!(<2Ys}6|5+iBjnoGd7IdY*yyf?wEb71)_yc-A6} zX-V$ec;CcS{8FG6_Jh0Y|< z`pYjoCH+_h?()Oy5)d_^xVs~gYRC~X`NXF0TP8q$QSDrhFnpv)tz>y7dp)9!cNLG< z=00HOs&SXtnmbSjb%?T2qOSDG(w`^9nA~xbH$F(|!#9Fn$;g&U@6}@}SAH-2OC8(UB+jee&21%@{m#<~FAI0XC3a z150Qw+fD7jE~F4X&)mH5I1ayj-DI80!zqtm<6?D=3o_8b27H==G*(82@;@7X0)_L~;T8u1%_$ z*)tsRnLsU}IxqW(40~efjvU`5SDt_2MoJ;!mtj_r525f)j#>OO4nQ1Q5 zSNXQ>#8Fhuujx)8lbUaC^Yptk$QC7oJLeQa-GR&jul%UQ*nc+KsJZLy(-l_wR#xxE z{(fmAlgZ1|>)G{g49!ubiLaTcP@c&3QB`pX%snch#u}PZdAWW4BCoQha>cXVib{1#EnPjxVfCTeKBOxArI}K|Qlm z#1rfLUc{kKWbPHXVMGdKTs}0J{$eH1bs1u-A@uGAzHLL2;51h)O39IU@?c^>Nh|g} zJN{0$9`Q|%ZTZK=eD~GCljM)R@mL%22bgQQItz#X_J;Je+47dgTHn^Ej8>w5y&r z>>hlx4GDv%F6oE;gUDRDUKI^0^3W-h{w9IGI_C~=Jfh59iqNOYD$LEE8rJL`jgmz8 znLY)iB(!QHzkkM(19E`Hx#C5TomzVxdz!diFog^R0%h?5^k}%+B)e7fAo%qUJb`6J z3<~G<3%4k~@W^q-EBm^K+!!1uhN2xhIf+?U`)|e90K$1X8P%LCrVr?!mkam2SY|Ad z&%b>_Lf0wLeZTvCM<)ad$##?a@S*f8ba%Z@dMp3NfqJ`CIeuxTjydlMTDB6E09_Owc(*90; zYGQQ-N8hMCM;zOxO^hB(^{2{Mq&fi|;d4E5#vTt90D=7m4#L^NF}P#)!qU9NwzGV4 zH~FpjY@rUW3WfmrG|9g3YYN*9DnLznQTb9OHv`PnB(i%8W4)PgiYk6Jdm#4=v_79( zzRyrqvLEMCO}>1sEdJriuT6qE3aC9~evt2TME|1F$A#LE{?|^t4rj1SA&^>qf=#() zT@)XjlF9IqZRi>|s65-GA2G@sRP#hRZc%eaHo8Y6W2sM-;?2`&MR)WYE-O<4SoJaNu1Fzzd|o`jo>;ds!>XcbJv8MGOreUPF)K z&}`AE9Qt8HZD{0J{}47-jGP^}o4Wbq{I`i=tj9m^nRsjS3ai}`X@hNr@pEC7dL`WP;Bu&-2;pHW#&vel z@8lcTOH2hd*$4(JB6q4wQxn`>{O;sUTA6l3`qmL^SvTzc{-t~|Jmrp_Xa7fgv|Oz+ zS3Sk@UG(oKFY(uN?qqGoG3yZDGU&k?b%Ov?)WQax3b?fSG21PnQaWZnB59=G4@TlX zY1I@48w6!PTX)fbagY0z?U0)Y9A6`at*>pPUQUAyx%Hc5jxxs8mm`jxh}s#;_QVL3 z!S^k{s?N2uw}gq8rA1=7$)RwC z4~qN&$fFtV`iYE#SN%E`0M#*uB-}xO;jw$wvzeJ_t!kDk1?U`>FGNP$?PA?a2}|hL zM_urBCk zE?@xo=qzlxU-Qn7GW%ZY$Z|XG4BXn*b|w7$q+2V*)pE1xb6Vniq#k**NV=}{7PyG| zy!xs<#?yN9A*a7#u?KEM7?Jk_Q*R;UM^5+5Jv9A0b=FP#*7$OtanWH56V5-r+08;0 zx5>*%b*bPiH$}Ie-|+~!p<6k8+};sbfdJo@XXvj-u)fl5=S1jU4L#2anqgB zT0MycwInv z+XXTK-A(;dE^a?5c8fIug&XX)p@T9io2Y}w(v>_V;*5j#?AjUFSJ$MGKG-|?uSD#j z9P5~CVrk^yZ>e$9Um$dz`Tkb5Xx2&@6T3 zZrWTE?S5exU14}2@){}bO#N^P$bRS;+1ax&UOL9_L7AO`^#L4gMF5-AoI<*KODv*E+1-rBHpT_^?+*>mpnvAHH<5`I@ojZR zbCwHV2*_mpklgn;#sVTfq38zwobQE;_o>#j zgiHoiS8TmC9!_DwgMUj}BqSvM1WN{vD|JtN=twEuT~E^&$8OscGNIlQCE-69niLQi ztXx`IZnhY9QAg=QevP34q+{_+6yQxRYwbtcIy-BM4xo9ig9s+dS(QWLhTUbN;LIB1 zrZvl#_EZj5P(B;MoN>epx$m_y4Wl;cL71A?sx3_n+6l zg}d^oUNbdG)9HaJIGZPx*q8iXi#FZhmrdr+V}W4Cse)a}664&VMYCaH@bY_Q5OLz# zEuSMh)!;R+jJaRsZB)XxM=IiDfdV6L(2VgX2ybw$MgFd&_s0X2g5a|dy7MX+IBvS) zXa#1Zk?BspWbngvmfL%i?`;E7?)%rXdMiB^M~$~!OTroo3s}IzIxeOT9{;Wze1?*u z5vQ{dlP@Hb3VJFl@+U2$p!VRPHTKmV;^Mto0A9KU-UaY@nq^b%Gi@xFCyS&SU0-;} zP3$Xef!2=xhMJ~(I@X2r={~;iG!;Nu$U8Da%_`F|6~}Eil7V-{=LY=TYNC<59u3Bc zFq>=o7RmEQ1DmX_B;FIrm-aUfN$oixReYIP_KGRND=POi9DAdlWFGVB%ZxP+d3<}d zgdWpX6BK;=PO#De>RN~)0s%<;Rg-ii8RH zNQmz5iQupx$aCFF#-4?#ih}w544t5?o1&asX5TA$%ByC~zI5<6{N{y-fusV{za|R` z#C!dgE@@dZO;z;W&(28rA)7sua&)HCBHyGe%7L#EkY> z3Y*GdKhX$|#a&%D}&4ev7}};W{$KV?kfamu*x-VTGxqFI~)%DGJx10fXXZ+OPc`*`~j~ zW(0=cFCzwPWFqm$JZ8VTG}{TjP4YJXc2$_#9`eh2edHL;fnL9}~1nnoVK;fJIhdA~p=N{f81y68`bua@3zrdwe*0e4yn< z!i{|xdv%33MkXdf{ZbGw`drld?yA|vFuyGRR$kBGQ-59&pyVrwG~2PpGE)*)j!?ee zXI>`v$0`tFz5oDy-p_nneImyD9_%8qbjj1uQS(~818FL^9L>&|VR7D5U6&BuApH}I z#p!T@#V>T8w${x7}=}Vl|d#z@AMJ916RwSR^ab=aeoV(ie5Ba4(-t{T} zA5G^T&jkPe|4Lci$|{v|THO_O3rWmz%iTfcu2yBT${CKE%JxYJ&Qqwu@f|9jBxnMJ?TSTku|vXT&Yz)z;77)QW+HLFU>Bc&NDzVj`H2%#StzpX+h&G@* zD1%BOZ?h;&SOJZFoBHBtHdM;}pH_L#=0xO%Yjy$&2ANIhO}vra zI%B=@I6E-9v)j45(Xz@x9Z~v7(VcRSzVM$NG!=pF4nNqX?FRqJDT8uf^-JHUkn;(!LOhWCXdfg=}(sDHbo8&U(_>n?VUA0=$rE@ zFtHRDDVWo+W4(z4uD?|YTWX(fL7KP1MV&_+xM{6?9y#D@D0X*1 zc4i8SG7e*>AptwC8;m+v0b?8oNj2GS8iH^4-UlwUf;5DUKrig*w}(8vxw3~9QPEHl z$7M&1FZSnlTC~DvM5LXa9pO^9hWKHt^laN}c{M5hFDy>htD~mT=ihY|CFz;RGH-It z&&Uzk%2Cjo*x!i>x|73cKl#;hDn-~37uvaaRAT9ym8VW#&-~s4TU}sL9=!)vpPERE z@uP!77HO>W5hrtZo|f_6^cpMkE%{@ZkKl^V(rOQj&*XIISAvaQG9kkKPHfeZ-ts>8 zT5Thcvh#yyN;2!MV40=bA5H~6k3AIiy&q*ahsQB&g?6n$d#-L9#78C#22~6?1WciK zy{J4 zF%sU8$-{>R>$@n2tphcxeG`|;qSbSKH3p?WcsKq75>@CJ7}@vr!z2E#%}st6#ES$g z3T6ny9nG2Im6uR=w%$&uMp4G284Bb+M1^MBWut9b+p-I2t1?}=lP_SMC-pUjEd>bk zU={kr6qO;u&QeiHNW{iw1(qaOXUvK+kti&fSF|%H+(}(a&Jg`i=UxhqDpHZ=Rr7cg zI(u)HD1W|@^v5V$HIA4$-F6{y_hrUNfi-|gmkTKb0$DBdt*K1-Cje1|6f z+or7?nY_yPi5nkY zV*<#l#aZ9cX?YOi^&dmx7ejJNp%9lCv5;Hy_^U8C`Lg?WKJy-}@z%16-S%OaxTjrk zhPW%BpoqJ!Nm|l-wgfIbo*-sTe$@_m(?n}}5L7b+39}cRP6YDR(R%jiXQEGEVFX7T zU)N?`pS47><2>9)@2w=1+48tq`<4ul#*B}`7)!7$ z@cQ>uFNwxY?flpJK5^f&>+F-7w1mZp!D${i-9G<4A{o0~MSYf+)XM@U}& zq4mJ&&kj_WibSdOz>7|O>+8J($LfmZN?mmQM!?P)->=IOpRFd|xx$Ob1e81eco^uh zt129~W{W0=#KS-$ey+#YLdiZ>d9*!8XG4reTBMvWm6BW7flf*w z7Q^&h$Os@&XS>&0=x3ooGv;J@{G#AME5(l&25kbnTOB+Z9y3Le|`>Mls8(u8TvMI0`q9o?2)zxr*O$dMW{tIam{xQY)9VmYJJGAQ)?Om?J2vgikD6z>aM7Kc7U&-QYE{?eheU`$k; zx&>1}Q4Nz&v3W@;nWvr0%@u1zFhQ4j(=lYAFC3{+BwCBw5iNE9&ni>-vhkRq_G?0i zJnAQ;rt|f+z};WNl2ly&9W$JF`>gY-(?ox5ctC)S>drp*1^*DjOg<@0%01+~5NBda zs*K^8w9aTt&i+TRH*CQegM$TwmHSnIL{zx!3{`Jp?n_djPYtgvBWS8~(~@V?W2>;V z-e|vmN4?Vp^}frJ7gUZKIrU9F=)3hmaZQCrSy7kVuc8S7;Xs`b8g=S?=E9|sJ5UNd zG#a_kp*}j$Z6o@P*l|;A06beWv+FJEbx{R9t;p#xttdzI%)4n^!+{~#0#U+&HCdCY z+KQ3SB*@4JxpMuAr#W$L%m4J2xBT?lk)5|VEFpkm9LVQgo;y?D{##a5@loNF-kN9f zcD3odxvcc0CiXe4)}R<;YR#3M7WcoxYUWecna66Q;zjbB^~G>X?=7b4I7!9#`W8cHJ0TI}9O zi>*>GG)TIllpocBpWbU%f_36tY;`$!aM%VothC^V+qY|13|sj@jd!C;v!;$)gs%U1$jr%W1y}*!rph_%;I|`-SHHb} z*K51zu1F}BRcwek3bip@^f)`VaaR8KAoj=bR(7V>QPzOP_HwV_UqG|VrMPy2$hK^- zd{f%p;GyoxzEhxj2QITMpkghNE}H`J6mvq`NX#NgUA^=$HG7WnkF4m7+W5#hSfwe^ zewKuxw-W^6wNmlfI7g1{rk6$6a(bc_vJ8_V-b$Gmgq1Hee)Qs6x%iHLhtXz@qi~{x z&w7(hKL8-zT(naa7Na8JJ7Rz9vbC)6c6GWz)4thJZuyLznbybk&(7$z<3(d;#1Ruh zwWjFs?Mj_`CX>n&_-liyRumyG$DXQn{J)t=`;@8@0cCE z{$o!Pj>MzYEJRf3-*M*O*!cmgV^7WHB5+7bsip&zm>jWw%-C@#9e*|$xibCV+1ap; zp|C^CU9S`#pp4AQRE{m$woZXYdw6#OdC&!qofUjEo|gO;1TvyJvYJ`I6IE~wYj!Hv zS%eW78L-Ukc%~-Xu_$hZMo|2lC+6`l^W&es{paM{r&@ zV)L}|D&|c?m<5pku`E!N2|Fz{*O3{PspDxT6ii?Dd7sMm7-4 zS_b6i1Cp8WP z=@rmd1Vu&CLeoWqzh}tO_7yq8Ao}%00K~wi%9_wK8$ndXKqb0qhKo}PoORVz_40Wo zgoZIpN3@CvOHG+hNZc}ge=@K3k;|sbm#Gfg7o#$mO$e~G^jo#w;&l7Uwx|}~QgI?f zTvfqZ!x$b8IjF+YL0cE6vSs<`qorV;>&4WGMjQJCH;*Qt=jly)=B-ObcL*}SECQGd zXTE}5{+0QiN$PJcC-fXgzH5PEb=h_YpI+Ruse5a5&9uqo+i=-e?l}zncy5EX3sSqMQ3`MQ;qR9m zg~*a#2KXhIf^0+BHV+ql*KgrV<$97A|4v_p#l{$-DsM_La{p@k5R!#mgGiLa? zu~z?C0sy@jcD61Y$U24(Xend37)i)ZbjjKWn;|hA&;IKxEiFtyG~1u0erZg0-f`w9EY_S-m3u`Zm>^6pU+`MI)c=ARgB&q##S`fRjc zf4Ph04BE*g`5lAt-8Zs}Paq*Dw_mA&L+VZ(Xk+N;V)8@Ysl@Gwk(R=@m?PwiVg1|p zsZR&qj@w7qr*~C{cAP9FD}#O*1pUEWoroX8!5|V_659V6$ychB*_5gLw(E25zS+MA z{Q^rHcz)erR(yYn-bn^5Z<}l}0CZ48?8q6oGWO;6gh1#vv%-zB2tKE@x$#(wCDa-L;4c0BE=RLjS z1rQAv|A%&C&5}@`wP_rDG3}m`^NO<29y*dV*V3{KJes$}&Iat$AcXt70~?&Y@**5x zKSI#9Z#~ua_VUom!a!b~ntKp!7PXiDyz0)iCg`V^=T^`BVn|N5N#%4uO=`9IX?|G& zKgIO9BWJ|MV}M6m1Yf`+k3Jc*TAnSHd^2%lAjcdOOsw;}P&r#3G-?(SpHlph5CjeA zRJxZZxZJ8P-rirErKS(L%J*;5DJ~6Tc~S-DGQ*b}Z8f|p??e~BWhPV_+ntqO*-9Pk zolw&9&v5~oa27fh61BGq-dsO(Ie@aNG2!v1sWr3SwcS+(&i|DiZS`*B@qb;p&)P{R zF0`cLqgs@a3^H-{zLw1JuWY3kzD7Q(-9a7tO9t2CmnV{TniJ#7n`OzPl{q2t^N#Ww zM*S@x96YaP3Z}EErk6rFpv#*ofu5j`5#<%GsT%|JG`pooNDA{h<1@dT{vABl>fwUv z?|DmxiNu1KX!j2utfqo>OHR}#a!~Xixf`dG(QhCuv#5oQRPxjy2vd*2!q9KQ<4Wf& zE)pVo_VgiTvM&J6c`LgwG@mWzs=k~_NEPt)R_;mXs5ym*x7CeFsXmQBM{#8gqMirGWsH~Vj0Z@Fr zpaHLB*7T7G5w$Ztr>;%Zrzdf+1Ml*sx_De-((2QM18C65GsqVstEk+yk^7N@C&KcY zTt}%hDyu?1Ff9IOSeYypVLzCtx7>9ubL+K0fBS!c>c8>Vz>>OBR-do6P}`iR*{1G- zXVW8zPp&W zE~wn?D67b|F_I2hD=-R`O&#^fr>_y7szQB-V&uw44BLG+?|W@|_m*{c4t!Fdw*hnm zYb%*|i+FpUyE-L-d;PYO=Y&!?SEnp0`g_cFdx1j8n|mtimp7~-9m#sJDx;1u1c=5`S?JlX(j_QaBW4aT zezsI^Fpz0y({reB;a@ad_c#cnlcD&owsOO`r*MsX$`#_8>3?yq!T5n^P`Jl9cxQgj zJ$%J9wQ^9FV7%#gsYT$hamHD@Xdg>9kRHqZ4`KnmJ%iiot_6s%j^*o@*1e>upe5s; zKt`|9narm_;%x_!iL1S-=GXaSRd>%Rag{L(@eP@`r&J1FCids{$KE1AK^?aO`pAv~ zOAxW%CtzOVwKvv6Z|9e}k@u2?z38VEffTeYrvbM!^C0P5fY0VuC(7u>I@(!essg*u zgmL>QO?yL#3$1YTQ}C(H=UF^$PB&@Ow*Ho^-dKKOt@GJb_cs}QBQtjQUip!MmOvZ3 zIqtk~F{~2aP~o*4sg%C1x;^JN{;I{gW`QcR?flDF1MWQLM+aD9aS)wxHcdxg&kz02e5|qqla@$J0ZnD6Cot9lOR<(201Uq)W& z(m1BLBJ+4g0z{LgX}5P3Z{F`V94$44Vqaqj>d3&g%hh&!% zYEX*6U&-(W(w)`@QX6mI~<%bnR?dpPPVU z1J5w@4$Z3O6x-R146GXOu}~icEf-Cd)H6Q$u!n{_BG8`o`&tr!8r<(RbQUH`}@TjAOGSyXficoA-QgT z@t1j64DFn5yzE24(k`7wg`p_2O6Z@Uj`H@ZCkAZU>pHlER+y+DXnoDkoo5ONm4QQ? z|1%#i`lR9Ilco}SbI?4y8t=0*i|Qlfku^jC;hjKk7S99Y3Ad0;Yh~P%D%*@z99=># z%L~6-(}O6{q20&Tg??klON>7%706!Ti~er8?l;k_BMcAyBR3e;38LfnVIIqtL2DX+ z)pGwNkwBfvrhU}(WO*=x=aWH&(UBH07eiwavjdRj#{h+OiVo~nz!z=ueOdZSWg&GtI4BKW9|25 z88$+VdA=Ms*a*oz7ua*Jv_Vrf?Mgx;V7KEiPww5pmT)>iXQ&+&-!@}{R#5YG``OK zDB9DHX$H)gVjFL@Cw78i_jNwrfx*t(rh8^pVoF`8iFqxaj~ zmLYxz3zzB7#Ra2kvi^g!%czZXe|N|aMWq6NPLLzEDu?MZ%B5a^i48uyD5oJeM*kI( zsfTq+SOz2GpaHAKzs4SdyJey40LV@mqo7<=4~Rb6`|LlnhNoSZ&-ZRh_+eai;{6(P z0Z_xtHCLs-Jq*2dlsw}PLaoLBhRY~~mhqnod+a^E@>aMbf!aOl3Jyo#+_J$I2o`k} zi@s)T%wJ|49yo*0Xff?<&7WH6xBn6AIz5~hVI*+uvKiZOxi%i5hufrh`+Ka=DLq`= z*%RR&-oR>WUQTQ~lr`sH)#`W<7#yGF0%W9(Wru+{JZj#qJ9g)PI*+Y$KfP{^-!KmtI`~-fJ4}i2^3)>i z4RKnx9|!2A;lI1Z9OUUVB~>h>SD?ei^X!x`_7~*BKf%p8v!K(F$qMOTKAV1v%4KIo zGOve#f2nd0XLFsUjUJAi9>g3&Ur9bDTEM4tovp(Ho0DfYD9KSSS=x6aiD}xc>Zp}H z?#Ju3)9trE#10&~jPb>!gSPh-_$F*l_nEZ{#m^)<$DjSvHsaN$>uLDzxzjqg9>W7?k-C~ zDj#yA4QSBJW|{&P&tIN`T`3@)^?CS7TmkbJ>9{>QE?Sa0-AQ^fF%`VX|6Q6gjCf*R zuj_T&rzO^>6!{*BiUsB`)m|+u+)A1_ zcE0~%r!wz=Cwul*KAWtovV&M6+ea(5#VGh)!22}8QtzO9AhcRH{34?`<#*rb)H0Y` zApwO|>a5_oTi9_*m8pSgL+!M>jaT`?jzgc2=hh}%kfSjd(YzE8x~^y+c;mc!u3`S9vSGIS1=vX875RUw2*Wben6o5rACwtd+iaS zkT_Y8O{ZshS*A)*zwK!}CWzh|@xM#adevFgAj%JkCWC2Xf+qmPZ@3S?6CB1{!i90^ z3>S?lpuq;?1dTUu7tH}4)f@X&n!h*4|v0WSZ@yim zA-Z}q|G;<09;~;0jKY%|Zqr`6IZgNPi)y`v)Ot;TCst?{gya?u4J5}f8qzz;<&*v` zefU{>6=7t5U)}kVAOm$l8f9me7;s0^KC~Jwsh?l|9pAs;=k8WWxu)Gm__D(J^b1yv z*m-iwRcT3OmQv?uWVZO+)GF|4fEC_dxQdvZTtW*P#6WgWB`;b6doM^Td zh(hEM+z$STAI^=qg)jWXs|FySz2`d#lzoc za@B9nMszEjaPgVa0<8xexGbbo^?OW$l2Zn%M2M8yX>`Hz_u%`H?i7VlDnn$gzV)oV z(csPZeKdEuCO}KzD{2rN9ox-qwyj%>Enm6G_!jEaF|Iu{$1Op}x!|@^u-{C4etZ?& z38NcUtMH;82dUk7cxby$()?|C3hs-Hr@L!1XIT$cXwCE zctA&gC)1nk(~wyBpG-D13?j0s^sL7ObA57}LUz-XCbaz+*~osqFq3K58AjH)^M9v3 z|Nii5aaqz)S8{=#UHb38mEZL~NIhPk(vBNCx$_|kA8%x6{#UT90u6%-Zz*E;?gqCq z&r5NqKdTUq@5&h6B|MhTk8RXTwX9L!2gi1NuY21%to@_~W&zPSl|vGw)4hImpQ)*u zJGqkZm`~!D_x)&}*7PENF3?x^xA#C{2i(x%`ktP$$l`O+Ly(m5No~ytp#6y zaYJrjM0wyBn}^J_;{`K^yXx^J5R5NPWNnwOY1 zO>qc@$4#Ry7{4o>kds9N`zfD-djTjfXXuEjTi#dZ#sZRe7_ZIz8&H%HPdpAchfQpR zBDPaZNoQGG%dAUF_NGHr&QACWm(JvEgjeJ*_Zf{kwi3_JGdU}6*w zm6<6PAbXW!WOIv09~fZoH{1IMd8((8taKEU|EwR$hs?=`lnk zG_{V{WvJ7w^!K?noi=sil0|Bg`l+Qikq!VVCfyg!pWoxRYioXe!1_NJTE2hE2?%!M zGY{_cQT1e%e%kx0tv0`PS#9xmE8ftWTwMrrGF-45x9)E@^0zA}F%a4buhB~fYx-dU zg%qnET}Vk`3%V}(tyU!l8AqjAhq25qSTEmgl2s>OL@(2fBxZ{+7I$?0{HX%}eosgD z+_6!(f37SXA<^SV$PnDMxiV-p`lT|?+MvBh$H?2Gy3)*HevO%4f)+kYY-%zou2ML* z)H!>I)`3V@TArCQxf;{}je3LaDx%3gMIv{W?)eU-=$yrId(-c?LplHGhCYVvAAHyZ zr;39Qj2wMS)q(?aI)3E_bNg1R-I*1a%%Ci}N-sG?Q*+UY7#TG~$Da#&Pggm5n;jct zHb8?Z19_9WWTAk`2`@!1$Kz|(r@LWc{C>}<)5FtuFXxP;-KbN$W-*2IRh7OXGj~U8 zj*iO|ExAV~c%`q*tW{6;FE84OSf+3@=GkOvevXn;#blXh3%gGO>OTeOC!J+5v}#%T zborj-kwnwrkMerp6ZChLqVqS04cFZG$*Yvxo9|cW)w%V60Y7tL`{1;m2~OGCQ!^W@nTJR3L;h^SQ}wG16`xIUdwrJ$w7+>_;R_)OM9`h0HxsDfmi&(mohq-1KSTmiPc%@?^Ch>7oLT$sD)=com#vi~7Z_Pj!J)CH@K=~CdPuj_(yZm_B?~8! zMd)Vl%ANwty8bv+fxto-HT9$@7!|}?%k?BTuBN$QuC(V^;xoWv3O;#a^x(NbWv)?^ z@tLeQ(_U>sry>FEI!|K9+teOPfdS?0)$!q}-bjIKI@W3ZMUzC)y#2`Q$|v;2SUsZO zZM6-)n& zHwnV;QQd2N)vSnTY>xNZE;#!vgR3|DM45c|`dn@3nG4ElkA^bs1**&HSK1w^wJuqP zU_#4g?nm#1M@DHT@fhI@D=)&iSrn`LyeH|gwunpcwTzmu z1T_oc@r2miVukOa2sCl&8bHgUs$O#^XJTf4`PIv9H^bR-pOB4c%vIrBIOZvyG`$rY z8{+$^a_Be=3#nY?vF_Vd?<*a2zJ#csDzz9W(U)Yj7|9m!s>yZdt`CLItkI5p#h?Zs z>u==gA47($Ew!IR7pe_0|H)mtX)2;3g?GbAxB23Oig%HHgnEqY+f%|!Cwh|3o+*yE zeRt{wzDp;kT|O4IcK#-)j5Q{>G}wEqj&)uobwrtf6;dP>4xc*}vE7eC{rv|c^KVhq zo(AQ5*F5n^RDM7}f8u%kc_+0IErDeIJfsuu$=)&*Kb9NJWlvElKpQc7eDMT0E$V_;ou%}i+6h~Gt?B7siRY%rI@0X81% z-qDxoy#RqVZ2Gu7Eyhjbbt+C9i5A$5EuV5#pHA1iW!Z1L@vNZwM_>?YFilxrEz}lc zx%$N@kU-**lLxJeXW*O8W45ss74wPE8bd#6V6G=&AlU_i;e91E_#h3js8$nMQVAiJ zLnjHTq)@2?nx`&Gt`&-$d?LVlmQNBTqsV76H_l6jB2ke5&o=7h+Ix5lGcG4-Z$KNb z`THZ+_8cnym_XQdfhU*&L29^*<}w-0Z#b4w^@7@q9f^8YXJ;)7(@@-@zoxBJOD!g^ z@rGkSWF?~Er|N;cy2VmWq@Q0~=w^nwlkYsr=ot_@O6GVln#%AROJD6s^{1)4FZ=pQ z-aO6cZ00O7pxuHn>9CgN58Zs_lE=?;;OU&N#QfPfTx~bt*bYkBje6>pMsUAn{y@bw zi$|3=sm(L+t8^?`#$G{a)B2)G+VsG^b3z=68ME^MUw?<7xd}}TN!8(5Y~~tf8p&hk za*mu%N0t7 zMB#S6o^Ly;=6AMEgzZ=!t=c&^V{XOfI`2QV=xus^aZ+NW6a zjGk^|fng$Kb}c{;Q`XoRedaW1_&4u4J^9*UWCfiGYq>?njrw8l7AQpc{++CJ%#%m~ z@a>0NicSqgVyZ6Pa0>3LX|UbU0v_F824=b42C|E z5DVE{JCjC~YN#%;17#>7R;unO3Ms8l!i8GyN{;a@$W#M65*zMPeqMHlm53uA5VuSp zNDkcEaFhZYANqEr05OX&YvJDmHU3Z)c&ZsZ>u-KNYTas?i`{DPs*Gr%Xrg0Txo7P~ zX12PTQxfg0SIAg;h9}m%dVZw&dYF#FjT((xc+GP=eYUKc8B;q^M<6f7Cy9j8%M=WW zgj)9|@}SifmDC|hW$+%9bXsY?c8-+2Z#^S>nA<%xQpA|nQYTJRdN3zDAED1>%pNb; z^hEluCQ;8Skb>ES!v0)`<*&$%e(=$ksCQ?C2d{){UWnJbc+YB7`CB&Fo*rvjs~kuAhi+j}95x(~pOCCPtm z2v052widp2cc1LyYZeYpIe7J~{}AsLMS}8!3Bj3sPf2xP$HHixnZ84d%#Y3JsLrU1 zWG}AY4Irt4RsP>5BT{`)niO?U)3y>bDA)P5f*Vt-V~6o>Hqkh(k-HX@*qMt!SD#8j z8PvZ754r!&Jd_s5J-|$<3fgi_T(yUyOEc#SCQ6K>AXxt*@~Ve?|9gl4&AHA!;1~a# zOf&{7O7nOhCR!}9Tg-OCn)j{=qjaxD-*JN624Kt?;Z!4@^{-i_cbkN29L@nGyI(}JEoQ1 zP>U1~n`_BZhmeOe6=ho|Unpq5#;FGh{CGIZ`Cawr&PPT$tZ$Bo+j}eh%l2$z_jISI zUxTEGUTq(@(?8I;kXPcfCrqTphHA{k9AGC_vm+A81oOHJwMc`Zi-pj)8Ke%zFFVXg<#KTOX&K% zffJUxR3Y4Fxg=&)1&k2EaI)0_qlnp!-xW8;1a6cVo+Kp>t1E1M>4tOEoWY_0+y2{d zV$cRMb9To$j6%_^wgTeS7ePOl|55R-oPErX16@_|U54~{ahfsC*_*Wt`nTD2XtN&b zALX!Px1^iDt5x`CszYm%m!AY{{6$}=;os0QVf?|o!XXQURxULfpT_fw#O&VAk$>OW zrAO^>cCnime*nXNE0Xq&b0G$q&!-yU(zL5pHdtXf^3)F51&+aDj&#KV-W8DoPE_j^ zaezy0ppAt(-!CAtEC9~H>C7HBx@htIideL zx9R+MoyrO4KFYImqy@0EDs*i_R%!TTGga4U)Ni#{nTA-lk!_x1e4Pv@JiCj2B z)$!gT`8;#~2kM{QC@JIkEjQ*wlX*rdE-)!kHuz?#Me|5VEL1G^%@`8(yJYcFK6b~dreP5|!FlJS z1`T0GpgicZIcS6q2)PGRT4kfxXLdTYHen7cPgWefS0Y(oUDlmliX4`konTLzgvW>b zckRI1Jq~KjWMiUD3d^>nLVY;b&WN^5w@rDWXPyxM0(ajD27?)Qm+{wKfK~Gp#)pds z&{eLmaqF;=<1+i<3f`{Miyk%2AwlusxFReaN%YZRpCz;=Ps$m(kBmYd@LZsRMwW?Y zrB+kzjz=s*X*8^c$YNIAT3`LyujqlU(!=7XKqK|MTGDo{+F!4amibiaj_)12FfvS( z*{c*&)U7shcCI^7CUnHulmrpnjndHD^Q?6`Ku`C5dlBDq=dPt+!hv(Kq+M|qSi;*t zCk#i^(@cO^N^UxZH@6aX*p&rAUkQ%oS=XtDCfBj!?-{vKzW#Zl z7Wv*3rZ4AG6wqfQ)|@wcZW(_0X$-^<_Wy(LNggN+zNoB;wnPvrpfNUr`O5BD)3-b4 z`T9fF8()>XzXof;78SI~Eco3qUJ{fCW_h>RqQklA!ObDxTGR$L!o1(`@bohvQTLRF zns9b)*ObRr_Y`w#BeG6nhuTzeL)Hk3SuJg9q`}lNtmaxFd)cRGe5N9Fi#r`2WBq7N>tlT{M@Snqq)FkIi{rOw74;1JcGG*}aD=Px zSrb=V#23C+Max)Og85L|>e{I5U=|>-WTRF3kDZ1`xX0&4b5Jj(Di4woRQs;o>>B!D zRxTI8G|ClINE2h8e(cBGguw#ja_O2+s}_PDN~T3JZXlGVx}OMJP>{q7l<=|!#NM6X zFgNX1U@k>j`rQo~c`5}9^JP=D-i_xLP~D)Z)X|HHBtI&(loBId$0Bb}WfoPAgdXrK zPLoKsuY|s}=`q+j*?C;#yLEIL?FO+%^NdiUZQ2eNuR=5H;x)vq-bZ|Z%h+zn09`yB zUQCbl%t0|6CyOY6*y6j!m7EUS;jD#$CX8-0Y@Y6|j_o0fL&1(s)Fzo0a1`J@Qko?5 zX|OjgKsfNC)RZHnr)A+laBT2KZcuxeh$kMkD|bFgyVBzx`QnQDPjBhlLS32aa7>-I z!Y&~8WrN0$UB$&blGaPodikRs=p9%o_3N~LyDG8+?wj-K_7mb4x zLA-n3if?hS@>Wn1Z(zM-FkG;AAy>-6YrwMnkp-QGV41n9Rln~|R^R-qFBP;D*}_-c zn_zw`hE$%kJiqiRdoJNI!wM5SWVDok5e6tr@Rse`bs z5qgsn1m4rj5x@cwAC-8lJ-bQuHjshsi@e%Nyj0EhYhtqd`WP`1M|^szFnR2wlTQ+$ zzzV;%KL(*;Bxuru^0J(lM z;A_1ndWK-N2=A4=BI2m>;PCM-tZs--)2g(?@xA)!XYNgUV(lC0%j7bGn^3bbc2XKN zLJkbz6-^r6W;Zkd>ZTi84~_(i%4(F(7R|e`xyfkeXuP*xiotwq|85k z$-|}lRWirRD^w=p7HIt0sM%y`ZkT+$cJAn4OTK@NTq_#i)0#5}s(-4ZzBOH``Kt(c z6Sv%HMH6aWUX1edA21xX)Bn9pQOCw-*5+rMPriq)I92k;P-l#KEt);d?Kmsu%@!^7 z2%vR6%S7 zq!uiNUeH3+NpX?;1inz0zlczbv8(T?zg9mATJu8x5~oPF9#00I$8sY{qdguoKj2rk z?0k_E3UEm@ch?LM?zY0tT|`Dc zCq9XMa@B#m_ST6E<``=%50ru5vU}~u&{x>z5BuXoHLki@g&o&nb8fII!u3yA9CC`-N^S zPX$_uM5{X@wcN|Q4?gxfXYv*N;)FG{=Y|iStgH*kQ4iIZs=A|72rGN_T~}9Qx7z5Z zki`T%|K0ihYte=C=f~{!g(t&;*!{B+k?#P~dKb6W|Es;o6PN4?f7xJXt|_@pu#3ER z4yOMI3ocTolx;rFelSGQK`f5q`DwLvwus8|h|B_hyH4xUd=t!QQP&P(@Z5T|+6Oy% z$E2XVQ^Sze*lvT&Nr=Jr3?^+|J#{(Eoorv71{-t{7EWA^N(8~UT$>PXtGgX|u*vhM zEZJeE`B`_&O?ckmT!_X>?QeYCsBh7}trMKu?@}6kdk&g4_A$~lJ9$UouGD#`#!%J( z61p*^5HTnO#wuJ06jMIOgJhnkR6{ zaJi5ZMa#jk8FW=?tb1nOab2z~;%0dA+k zGR|I2$wjt7pQgY=gOfTj46H2mU|!lHIJk-H^ha16n*zQXSxtO+@vV_y9z2jy}7rM{9iP%Y(LH~zlM30)Ex}|LkU%8^$Xy>%F!!qKPL)do7jysgSLdE3nj&ln zLz-c8H4_`qkl-tl^}LF?fMF8CYu%}QPUP-+72x3~R)&CA8&OcWfBkQt>f?yR7GBL% z%#9%(@XT5}0i+$d+6^9=X`crKW>j*EmU#!Sy7*Ytb|0#f&15v-nu`SOMuD~b^KsEs zc^Dzj)bnTkZ3E0%RxVV?Dg`O^{OKu#*Xd=VDFvHquxIRYtjQjBw%I(kt9>V$J1qq~ z(yC=hTfal78+0!u0ihFE{o$Sk%Eg>gGv!_xPqtua^&1Tx3igBZ8J`4Bhhm)AUZSfpWk+vpvDhIPc6bu0Hi}4_spR1 zpQCPTQVm@!h8`x^v0_06BFco*B6+o5hdN^4ioPUq1^2lmeu-J>L_fI+5nF!#wjDqjDDRYujD8g)FTf zt&0;!aeW=shkTA|aTv|Vi>lLq7DnEw9l#c+cQ)CB(LOhFO{Hhr@K(zK`*p_x2Wl{% z=$%TT?XdC0sC54{GYyq7c_!iVEW0tiDX5>q{aT@QOEaH-%4Yjr=uN@ar}fjhjGWRv zdV*!+meL9M(}I|(`=5g8@Ze0S-fmi5Gj;5f(Q(Wr>hkWbcgymrr1kCJE96xrXW)*? zzmRMG=^CxWxVis;M>n9>)Uz|~(DeQvc4`hD-63H+v3r|St~{7NRZ_fp_=)9TwukqX z+AxxbQ~Uf#r8eq{Wkk<=J8K4`|#0A5Nn-sq{66-3rH2?dF%yyz4X;H z!irXMLJc(zb(m^b#<>`x%hqGarlzRb{4*LYN`KO2=fxA6=cv)DEf82@-9A?TAwE)M zUt+Z1d>pD>R=B=Q+;UN~Hf5FterqZaiAYUS>?Y{D4IooMh(eO|2G65Ml;`y0kd7W4 zx)~hH1g0o}6r^j1Td3lPHf!TDd;)s=^w>;aPOzFYM3h=~z+U zsP9=ZS4;A{+F($JN?lcFpk_8%FntH0ME9GIWax&@wEryn$y%&6-lJXC>XiL|G@W}q z)BXSdmE!7BRw*inDMejkNzQCsDs?%mE}xR)Dnf=~&UQ$W3L%xlFeR3pF6Z-zjA71) z9Otw#=N+)k%x~X6et*9I+U&T45z>@r??OmxzVe^Wi;10mzu9y8Pn7eh0W9 zef+8HV4MsQeQV-8RY^5vWTcRdG`MSrjIQRrWM4R*5cI^Uo^=V?GvYef+1q_gzK!(= zoLOdTy!xyFH9{(XUr*RUh^%YL@jG|Rl-;w7aJgMrL1)lOC+F1(hN;2iSi+_VgJjpf)4`Y6|NsQnSYk6W%4uA>j5pH8I3ja@~ ztI?|5Mw$}i@Bit^946rlgKbgQ{@gtMf>;p!uIGxJQjDmZN>&N~__r8?vi;f^wIFUH zed1-%3?6Z@zd395cIZx0@!Ns~x<$mr`}b`w=b>&%sZ|ZHe{AGn446f6liQzHHMMkh zXsxK=nNdAZU=_1$R>C3#wcKKz2;|Q6Pl=)vIE1knmVJXMgjM z-7}{*7iP+ES&iGLU~CtcIY&qKyO@pD(_PNq8$9;Mnx|yMR*`Sp@wF>^}mQ;*bsjOWIk;ig!fIg_PNgPhw z9sK7N*u#BxqcQr_yg4JQ(Kd|Yv1>e|vOm?^SEpA?NbMr0te)HOquETg4V zlnZKRCgr;C?_Bl(@GKBYBRqWFtETsO!%IjafjUx!{CoGcgA6dEhS$iSeqmoI>ccHnV8;UBSQMe_z$yIrW1P|!=^^vK zNB}@#LgO;pkTDMzvAZZcxrn`|4?vs}WB>|< z=jixq*Ll%k);|&qg+z?Sffs*e95m*@nGd7_JSUBWIGVQ<{QomZT~GOuqdBKzy&N^1X6 z&Ft-$ZC$oxW);-OaBW;gCLB(P%tS3-gd519)w;8$gEV**z|jxsj|QyZA-BQg$px)OP|q!$WN zk8^Vl*aRryF@O^XBfDhB=?h<`qE`E84E&_=i_Bz7ibwA~Yl zTb$~0^s)jx$1=EM2{FEMj!)ZFRP{@LKuYc3C=nwOqarl{716+N^!bHvkdHMcBWh=p ziL$_m)urBs=6N%5hoCpTZFV*EKLM!3$zQh$L?1g4f;U(**&JK0g%12FC+9T30(NJSAyXR1_#vetILv}3r!kM zeYY3jm1(%p@eK5xQpeB;%5$yUNb=20^*Q@d_55tdabl)pfdfIjutl${IY_2c)(H>g<psVOorm98^fr<7p`YJxC6^b( z=pY}iPi34+_mBM-c0VRZ%{i3*^Q*x-msMV0=zyIA(njvF+$zn`gmR4d0H{EG+j~2J z@fwfvD%FC-9dK&cRIFO~SA*HOr6%H=dlOjJq^D{d|B%i#C-jmAB*;o(u8+GBHFI5~ zpNL1U0@XnQVST-7!7oC8)72uzpb4K*^VUmKk}jc!^En>lQ3SbD37BoWX>LV|^i%E{ z0$bmRCX~nulc}E4K?QiS-NEDiHw5`Y42@7qOmNi;KcjBVFC<4h{T8G2rD5 z#Z(6@{T|i0jnG&iv|ds{TTuyb8|!eKgfW;86xhE|>I7GVOw&){8~cdU=8EZ!PEsF+ z_4Ws4C$H3~Q?Kww-%z{m>eu>6PlB8S0I=9<^j{gqKlNZM=g{58S!E(PHs5CGQ%WVz z3mREZu@IR0yz8n7?|B#ztz|f^41rg}sz?hjIjV)$ZqYj^;yJtKIj{2nfw%-B{je|nn$cLM4@yRFcaar}TOC6FXj+CYIx{)% z?BW7cBz3Rx{-?%yv?=nSoR2DL_+R@bcjQQ zKShb)nU46a*kmQ%oVvV2kX9IT-n;;Dl$$PafbvR3f~^4q=G^DOxmMgdH@WGTE|5|X z^9#7oZFkIiH*0|EA(#NWKh=g*+H9k|ZTfo{6Uk_6{nD-+R3#z&{DY!aak$Dfl9@6} zh9jQuMckL8q^BZ>_(p{NE1tXxekz_ma^L#qopL3_+DCS^O7mH7iQS!#E2;XV5RdW7q%$JB2H59tUGeV zD=9_D;H+3(*XvMI8%4LcMLqCl+k^NS&_+My^qr7E{jl`o(3**WN|u^k1P+BFj6cBg zeOq%JUj!&)v>c(E0l6EGsb4?F)VgO%^PFgURR8pw{m`euf0DhI&6bz4;?>6V7 zd|NiaF-nu%n`5Js8?e>&qQMCT(w%W4J`x@vfLqoQ)Vyq49X2XS-9CWI{CQlr+L zhnJM8wT>lE?Bq@7&yQn6B}68U&&ZuWbw+uV$r~GmzaajAY7B%t96axJ>nOUQ4YJd_ zzBX*byy&PvVqbC>1enEWxkQ|H;q|xV7I;pt2q*{)`?IZ(ch2KlPrSwfpU#%dbBm8q zB2@c&8*M`(kQ>_IZq8kLoxdr0R}kvc1G_@Yx{y!brqZySDs7#d1;ap2^+if z9>ZNch+*Z1^*}!n~PHGsJ&sri zAKm|mf#SBhbRc#4(XorVKxX8E?>v?q2zPE6&Izkjd($W$$EBZBpVqy3Bq%xw=dViH5 zZUY%tXoaTl{n>%Ifv%NYwZb#cbRDCL;b-HV(GfQR#^J&eo-$rY*W2$?ZDOJyQ)p;6 z(5GsrHCl&*f0J2qS5GpD#Z};SXg2Y_6#3SLh{$GUfk}`-Sb-M%Z)n|2Tis6cKhx6- zaXyG2N`qR9`ujhs_4YRb`O8k-4;55B2c9Re~!eM6jt`zZprar4vlV5P&n|PxEC5K7p$km0&x(S_#GG48 z((rVE&m-=;7~-lYff#?yFSMVRqzD$T2wY?QPSu==LbQFUB&5pJGS_@6=o|S@?U5c= z+bO(na^^KUMZ9T+63(c;Y`Lf_efK5NvUupbQ+MsndPLSHPUf-8Qbpd_4T-TY*l64B zJeb>uV=x7t@#3eR=P(Fw6tD2#SBX(SO%XiCBsgj{$(1*lT zi)N+6P-rMR6n^qivI|j^kRXEn#9VR5_O|uQ1h-uQo41agit#rfL-@>7+O+{6vq*3u zQzBW`*N0~&H`DIy_E0g!SX0&iC2KA6Z%s-L@2yaQxu~+w!MO%4WHswm&d$L{9e`XX z3gMx#7x|M*XmA;U%D=b!LaBDV%R)%}KNx7M%KSLVgl;`y6g}t{>JwnlcAwJ+t@p};w)draXCknX#!#Ue6Z4Aw%rTm zu=l5qHmfxK*?!<8FvGw~0v5oR>D>B7!GJ~3EW?r3N|@ITM}_zx2CD}cr=uKv4|HY* zwc6=i!7eNSN*)dWj0=lb#}XP%vX&TA^LIym)`p_1x5gC4QoS9#4)oA3Nz12%ZaJH3 z=0O7&9fNgAt&*r(Wi_bx{K{7;yd^bAE?W=M9gER>%Hjpup+ib}zm0kLX{Cz`%O(5# zlIqD>k=H9-8}khIe!^&m0;|mwcq-!)a&Qs1=0_(xYw+A(9&>mdCt^qO zi>f(Bl{=%-H>V`LY*gV^FX>9{QYGhGj&Rwos?gtbXW_1m;uzBK+k7d096qDC&KXNC z-!4F%uGYEWTi0RKtTqTXPZ4C-cgmctTk1m~TE$@s4sxjD05CH9QtxLi$Wq|jBM>a} zK&IPNuGyj*}6usES*PV6Y^V}vM2nkKb( zgyuP?Q~=tDc8gIq~ZYY22rH$Hj;H*y1L+}XE zK=2^3I+YOc_tE-4RE^u2L;v0ZG?(;hnfAQS_Q@zdrUfp$MLcZ3>1o@3JOU9hw> zI$JT8UQ^GB)pjuuo6|Y3+S;-Rmr~mMvfYstb(ZR*%WZ|BroaB~FrFa?MU!OtL-Okx zK!PWn_z(#Bi0NFvB0#TMo1ju4VS(j+dQ`6=oybgjQ(Y#<7Hzo0Wk*n`S4;?-4A|CL zJ4v^#sl?$o8jo)S1Asa>V}&%bJv5u%S4bM;IiV z*W$u5!~SZg$-x98`K^CVncb*r&O$Yeb5(61wPU^Qq4J|F^KMjM$eFJeFr^tD9D0Bs z+EQKJGGR2NU>_LHI<1s_V7ojA2op7$?22b-8O_dHX8DGX;l(6XvkJBF4(eP(KpP@X z?cBs_Eof2F#dtYyw-PL`8BzW@1I|xHj16W*UBUGr1)zA*|5EGqes^%K$2{OYXxgn! zVcoS2uMu1*o)SJIm!AG_!LSU`Ef4BP$q6;S({6Elaw?_hE2~=U&U}-n^cANeAPtEd1cYE^;hOSas)Ra9v(CwE4n6YQAF-M z+=~}2&JbPP=JFjFMgP|$Jna*nugP}`ohf>D-Oc31rPj}wwPiSJvj9fUe}GKR3_LwJ zRJx2^_t#p8ahkCF#rhxMq<2Z}F|`;)v01Ls&g--Z6Gb-{?T&=nAHty;aEi=)cG?#PrcyHlduz=+RMJN>Uc0uZb}yWl11fPseHTHvq-HIyfX4yNpR zpUr{SH+952{ZK@)o)>SKyqNvusFSzh@==&?hvk#;%0kkjgYJ4O)@Bsh?|zi_t!nEc zb!wERnOZihRG+C^nC$hpN&Qe1-|sN}l|m{jzRmVnzvMg1wf|iAqFp^`Dy_jQoo4`( z?)x4h!hGV*A6HucXz@=x{wQq5U5wk&KLPpQ-)fQo4&i7<>7iMM-v^DNSYK42-4G)` zSL%$U_L!|E-+Y2o)`pOCLI4EMn^sGc5@t8$=FQQm0c}^I?<~Nye^=Jte|-X-Ev%Z2 zjqDMD-kB+rAPc0lyYULDKXp5nRy=QVP zVM+^KPkv_XC^Nrcphk0(B1Nq%5KFf{CfyOTsRh@TPZ{X6xHn1gs+O+|=geF!(G(z? zvU^b#Kvw`+T=W<9Y4%dzWN`%Y95@$%gF(K!Af` zkj@U%P2)xoyuG0C#7hRh*?)J2Pg zC=I{Y%`u;a3a;7d01^(|bngn_Mwi@R2OX9TjU+m3#WI_i3QZU$9MX zCzj38n)ARpV;)iIC0lOZ)~p!7iUN)BS*eWcw36{Iw-SyGNIK#k2Vdp>_JoA9V_|~1 zJ-dUK0u3z~%cig06*Wic8w| z&)g&Cfko!?cPEzECQZOrU&B0SV#g=Telj*%58&g*{Yu&ABpnuYSa~;mteQ+WsvN7C z{G?)l+iMhDawN+4I^7fy?#G=jhIGYEIq({@@S22k2EroPZqDF>O%TFaM2 zE4^G*Wc*X5i(>Uo*)(yw@Fs`!FLw^c@J-gbQ@cRny4*w%y)?{5lIO=CCJG6MC=V(% z>;k^Xt~DWh+oGDBD5$P6g$?GH!Hus?;$KaOVK_q$<;1xOw;8d9uJOTv`~*E?$W(06 zr3(IL+g$|HlU#PfS38*7QF7L<)-f#k?T#*yi!acqGT9XkWL8Q6tizp=RR&A)cL9g{ zlhvg18i-*}1{*@Zw-O{6FL8@n;mr9oBoq{}i8>NTXxs!9`Pg(mcjYAkQYzIUPqS85 zt~`A6NRgtK#VS9d2>zP$AjcE8 zw`F$W)|rz-_JjnKO0q>txnF>|!y)fMxJ>??k(N79A6`uXgxpxMt?Azh z=M6jbE!$e}e1y!4_NuZRY)VFPkXAc`urlzNpN0@Thzf{tSvxJMkeCu$xT_p)Oqv~W z`aqDIHcrb4D#=#kc{@3DVKK4MB^Y-*Ecgzp@XYT#N6oFVpe?_L#hckB*Y?J9N(7*w zt7>LJ9>y!ynhKL5^U<4&7OIbs_R_ty1REV2e3Xr(xqg5bj5=#6UXeT4oi#( zty!3}9H|i?tYQF2MWD0tRA4?}QAVfvbsc${gyPO17 zy|XlCzY?ig5#ZYsM|oQ%X)gL@8+^k z7c4r0a!%;Z{ajK&oQz3`%YAfU@zuBLpZ#y;PIZVhUx|m^;1T0rbB_6bnn(oz$?}V? zqSL}O@3o;5HX@TUYVQ+x%W8rzjeoidFAE&{tk-sMKoRXT2xv-ywb>~}e2BNh3A$G} zz+NBlOc?oILv`ER63TCdanE6QDX8>9xzilpusjMe7r*lu3a)+b0o}ghKYUL&mZ}dK zeKhCH;4XZYP7!!9DS{+eyC0KgE}yaWzxB;X6P^m~I+&;aUa$@Lo0f+No&_4c&QJDr zH5d+7aV#HHun}-#SK-k*+X0s_$VGQV&rqpxbI|cVJd0NE^r=+`yBRp(V>2l~<*F#L z8Qxd1Xs14f3=jPeF>B_5H_mhx93+ipVd&Ifj3~GHG{ctX&{;L;o^4&uUvDavnrY8d1D0R+$I7tUUAN{-y3o}6#0_2PyZzY zKaCHnme(J8Fry9{zkh%C4x)x^(fh50g*5h&1v+mgBgVAIIp42Mp0CQD^F(bmgA&U0=|_IP`r8E6f-i&2XQuSAz83 ziMRIj=|y$OcsjQydvnM+8}84datgS!qy9CVTq>ymvNeC$mU;qdkEf?^3@3=d7n;&V zrLKvz81HA*d*+V5gegB3ZuMIeN!UGl4v*?KuHi+w%>6ILk8vd?S=JdxK+H!f5*&@- zrkOVuw><)S9G9hjV+%CUfda3duw(z>d^mmufa-X?pRE?CN*Nd=A|6;z39h{^In~6W zbsV0XVt<)j?^pGu!83f>=czq|CcpCE9zm8Q0=EWk0rzJazu?%H)gCiZlAff9L|9;L z*;x>OTls{m&(U&Mryf_(Ugc z=<*j}d+|N(SkSNL@sh}2E}&T8UOt-7Q6X}kl{3dlu-IwG%e-Li=Qe%mQH=^; zV6&-_X}$b_JaB}mW=XOOX4aG~*L#0=50c#L9=u+{n7_LqFEt1Wo!5O@dL{;B*QSqr zjaXL+YzI=WWKiTv;zOdni@26&V}0oVNgk=Jmg_a&(*#skUrxm3ZcRegh8XeJ>KKOD%@O#j|&E%>$Era9C zo<`{*D9l#l-zop-c?IR-o4mSOpWg^tT%F5J*UuPUtwgOnaRm{dtL-gvx4GmV|h&f7a9PVt>eoU%|B(76TIQ5OkHHvOPi@ zJv6z!dX$uNNvee++`){c|5WynhtCE)d}(lGvB0+H)?nS4%-4)-LhS04s8NON|KiE2 zRL2Od@&NGVD;c+w@(}iI7Ww^;QH?{#T~YgsAwAGPEt%tvbP^L?znRE)_0J; zfE2UPVbg3O>t-%B({JYQ8O4ofw&B2`0@AG4d>itQ%{fcS2-OSr+^0~B8}r`7HrV;m z5BC=W?h=e0HX{TK=;9Fj{;oEZrH!1QEsOzI$W}X%w>kk(V6)Vck>18)r_XD|W+{I# zG(DXc3-)JLX>NNiG-!#w$i@7n1?SmL$eyTWVrQx3?YtvqB|_aZVN3bGqDw2J_AB;a z{Wd1z$hebS@`lQ`2k}PMR{SS?0(n< z8mgH<2K-BcdpCN1&=2Xa6ki(^-JqW#rglLT9#`x5T-|4B=mo3_en*K-Q2+*j6H_Xi za#7$+`n%rH?)%{X#8vmzx(U#-!0y^vqKA(apE}h zwl^Tr77Ep+koN#0#k0R0YbK`xhQS8;C*LYV?x0k-{s98oS5sHPDKu z%Aj@)euM56>j1)U^kzfm(NrjM^Z*gvrvMZGabD-Hnq#w)SKRcYJ%d-{&_&)sVx#P| z%i+}r3&V6{+uR7(aK0&k^~FRX3o#smD(U|$#f*5f8KEu+@TG--tBLcV*Fi^tz92Qq zE&l4hWG-gAt9TsAXQWU`OECl31>j}7O+2RKqU6uD)J8jh=Bv2It-qyG9CN&vr& zl7cHXAR)7p_AaGtbX zqZQd6CR5VXGi>O>ThzzN>}YK90Mf(LF4H4|ZiS9U3aGJvX%z3;usL!#GeX`yeEMIT zQ72kX70{<{BQ;*r}5F+m&0B%9cY8saLw(| zDYYrVl)S=4itWyox(}m-a>HepgZnQKdg9AR{%2I_l`Fi|pKp@w`vVfbHTxrn&!aw5-LID>xH=9ya^Mt**2jW?S~_AYf~4n~ zUA}i9%f+C&z0Y2WS=*Nf8oLWETL;p=3ZPi#K&j*cJ81l87j)k<-MAixR*5`shQ5}m zy?&c=R^AEfe)N9UT!yMRo-N%JYWWYUk}FR>}`K#yb z{@5`52(94EiKNSHS$@I3K*C{V4}smCu!HD^7xzXmJ#ug=Q-k^q&clMs#I$P=D)WonU8yhQD zV50K?Vl+mx1XKx1)$FRvWy$qlPe-v+D=#P+I;xE2XKveJMcCa&e@{>W0_}j~Pj|!; zf}B@rl+dmEGj@UsmExW<49_y?RC|zc08*We*o*)nb-~z0wYn(rZ7fZ@R+aNF3)7Qdx5~* zE3mSDp49I&Vi;TUsk{6h@Ec=KK zNWjc-v)I@7U;}967PY0 zBXiuQ_LH6O!ZX&Rl%n`gK$t$7o$}sA)r!B|1yA7Vx@HQSBl`PC+eKm=NCfNKNd1$3 z`*qF!eV1olxQrmvmvDey3ff$2LuYv1#U*{;YiRG2Fl?qw$%(G|STD^lVSA#(G^k?H zXKMz$Q5G|{KQ2>Zu*gfYneTDy=e{Z4<|YHZ!bgGxj2|vW)fYiZVkL;RLu;e)3@cd8 zsBc%2li14tdblp&adS47Liut=6`1MWkzAgo<+v?j5GnQhSi);POho{AE7`f-Z!pBw zRIahV+kShN!DGeWw5mMyxcQIE;-o+8@$vxJNqIy!6!>Q+-E;o1@4JJzVBMCUc9(1; zZ~4E_ZikjgHwncNwW1 zh%U+0?V}C|ikM7*FW|?ZXB%+;pY|Bll93zy^w>c1k#qwx!2rmWCg;uTj0;?RQsj3( zm^`2MvzuNdG15`A&gn@Cm_KcNbN3IQt;-{gP914@`4H_O2wb{yJ0Qqz?Rgj0fS^|g zHh8S0@W+xLHr}H*#(IXyw01XDG?v^hUH-uAZM6h30rFo$x<&C z$eJe_I|QwFC)-p`^CXK?lS@o)$1bL?RS>9;x>+;NuKi~b3&g}n&<}$YBa|iA4hPm` z;P!@~;cG?D3&?!#z=1-hRK*u&}9k&A%7LehX_63Z(cl( z)beG!Io;E}_fH)2K!e!E)xwkUuVLBamQN(?@h-&E4KYV5goRgeB;_o(cxJ4HS(N9* z3?oXo(9-zr5^ir{p@1-<^t6xrEsWlkH9guUs-!=-na$MIXZgng zi!#QH7H%|-X|}UssHlSte#+B6e)9?56y8xiYbgKMid<~UA6{0g?OcK}(YzUOFKeh0 zV-R1Zg%+k(yxqTpHaNH~cJKXSLvy|fZ~65G=1Aw0aQfa!O4eLopNZIeUpCEQ(bJaC z4NWg zFjEzCNwim9?(qiB?_IuOP&7hwct2vC9t*?@{Bbz}sd2`$2b}I60ez2rf0fPQV_jLIowvBbabCnves)H)0=&HyFUg^o z8y-TY#`HARyw60T#w76V{Vl_JE3$x-W2>sElrdd3Kkd(C_6a`y3u+8+#L?e$WcLp_ z1ziCJNO^#oqpCAVl28a(5Lke)^Yb*hiLKbs7GM53MvnR(@or`Oo=I`|@M2*-dDP_| z<;N49tc0SNE7WrX65KNJ7;N!@2F>vDG(klYaf}4 zN?@eRUmXY1Ggbx*HV%>kXYzsIEM&lkeO?wYkUa%{25a3Jj=K5s%#kSR65mctg*z*| zT@IYHaHfhE%my7x^#c8wuNw?k71hTa1NoIUC&Gc;p{=(iJG+RSYH`1%(@Z}VY&6N36H@x;L zlvGSVIjx^Y22NXl1wLt(1CIrc7T2A#XtGcz+E)*{ht`ngpavZqK@FYO;kBjywc|rA z$wk!Ls}gcHD+kA@5_a5<+jWfU;I%Z`O>h~Wd_~Si3P{2E=zZj5%)WI@8YSsWAFu3LyrOe$&6rQM zk@z8B`8e~3_-J8d1O=;0Fwu7ItXb@uEwhmvN7*!#U>D#;!><;0&6rS<%f z3PM?*+P-mM_;X+B9ad5kYIdIU0M@;Iq>Sk~+VCvIm2Z`j%&``pw#XA)YN{f~KzAnD z-O0?9N7$_b*xn5peDawCmqa1vX1}8sWw823wyY0<1AMZM%9_5{ojwIdE41XKB!*UU zc|UKP(P5b9E6Gm=Ll5iY!ebKWa46gL#4K{t_RfMvM?hsZfivzYbEFw|1 zz3Dq-_Vn&>QpOMe+G`sD1X8>+iB577@OrV+^cUUVwjSlha1v;v5W2L$eM&d15SJw9XuuWMUvx{Fe9>Oc{&?n31BdC$?U+? zt)A$0Osi^LdU5bhAnf`M&Nd+daY39;L^KWE+WH#Y+_7n!$2Hk4 zi%Sdf!QV5<|77{L-AX8U#h8Da&@(*pPY(4ppl{$whWB-K4U~_-&5R4p*@pK*V4NKNfs_g5{{cG?O@*^n(oC`vUM5S$i0c%*9x5}I&q zdg2Wfs9hbw%jCFKcpF|8&dD|X<|CC>;PX?4dcuy;?l)?%8CB<|P&o5VZ1?i+P!uBC zHL$8Xq1LPXS@~9EmNjZcsEu}Bb3r;02gne+?JnDS?)G>nIZ9-+BFuWoZL4`SD=dgyp zJHoYQpgm4hA)`RH*!ezUhHg`awSI_$)r}!+LVqb znL8?wTNR_YOP$hAyImY+YF2`&I+dl;>yT1e@_Dj%1}AQi)I_2UgwAy-?k&Fn2R%+; z;5K+4-lM7*3}JfK_;b)?4jOpYvuOLmsKN5@C!DPNy+JL-rF%EwnZFa_hfCo!YQaRU z%N$|C@LDj)*ZRNN4}cZ-&R`duez@-u?X2f|F#hW&V1J57ak~*LzJ9SN!;q zb+xY0*V8D|zPiA8)-uBvoS1mlcMAnx^?PAL%4a2C3( z>Qddz*|{TBeZB>pk`p$ZZka;K54!>}xzhp2+GG}m8Qrj8e%cpB_|iksbIJ1)fI0sI|`{SC9YSJ7v^2M($UOo#5;l`0u^n7YFYH^0D;960bdVXtd93p6ipvIg&K)z}7 zD<__o^e|$O25&lJj{#YQJ4_=20Fzn&)JR)C!F={S$neFC(M;z+*{N!$8V(pd8@=egCo{H zy?Yw=6(c=`dz@^^%)7C85k7fAU5~^eKe)E_I-+>0d_TiVi$+~oG&00TZuPw0LV(s4 z{;5JWAE>bvjLna=`uu~~ye|-GWz7x*iXA^A@FoClN#8yoXEff}o6cT$7|0{?nKwq} z2-5A6%1<`ZLApI&Nmr!nMkYcN|^SPqV?t zKTiRkRyIKHchWAR?*%PAs2!nmQUkNLe^cwdpMrU5NzS70A zt(~Nd_gCo4T4e9jQT}LSq*K$@EPNajb4Qw{J(gdcI^%?KD*$6hxFi0=V&RPuce|!7 zvc#Te;CNxblV^6Y{3J69D(LSKsg<3S%lSS>n{; za*t+u_=eKTOa`@}Bx0UpaEL(XiktkhIzlWaRk+or@yAdI*f;0S{RJ2)th`mSb*{1U zBW&D_Glu8AjJWa*0s1Ux9yAB+1&EJYzN4q?E7$sL^2DWovCpD++ypZG!>5<@ZO>G^$ zoG+v8DG-zF=C%a7-}A|zmoX??%$6vbZ#*@lagg&lj70i zBM9drLCk6)e>Bwr#8aV~wnQBYV1;E9Ixwt+Jy3iY&>u_$~%U(`+Ehr1#@ z7ygqCy{I`vq&DrX-dCBu=X>zrf$B&ddrw90(|Q>BqF;pqavs!Z>rArxbCULbzNVf_ zok*3nP<_6-A8KDGmO*%c(>IZMi0%JP{`{N6(?kDSbUaj(2I3CKkUU?MxOKdXgw3&h z%!51J6402sQ(y1~coe<@yq`u~G@z=*2*{CDly2j~tr+kZpwEQ~ryk*g2?4KJw-|K@ z(!E#oWaOM<8wj*KsCUAzIFzUGG1(xC!)Ml>9rvgR{Jj5M@2p{Yn$ST|6wms$mT1$C zviwxMurVepj-OCx^G-rK8QpgLmRZL6gYVHb@ZY^7)guq#G*g?Ig=amz4mhS7$k*6y z8NLRJFZx27YS*0`ltg=fEqKtN^tg_&V2Ml<4L8)Y-=%Nmj}*dm`uBb;4O{4(eZN|m z5~M)Q^?^Sgk8#CWzo2)wV5wG|c>l6c2UmW~%*Qix&o#)WGh*Wf-qxjU3Fg~_AsvKG zuBm~ZFXSum-vKwxYIJgubld5SN6$n?+9Av=g$w9ugQGXFyJFyKPGxw zkCZA~J~Zwn_d)Q#E>T~Jg%b0$ok_Di_hbp{-^&OVv*IyBT@LrM7szESMg9euVVxJ@ zUEBnM{!%Io4pnq>W@R=`TlJ+O3Xa|212?aTvsAFlq&)ZYxOw^y<8(WHABgX58)1&K zQ3*!}D}7?GOsAK<@geN0uHic~2(C>=qro`eI_!m10_1Es%YSZ0oV&2abc~^ABVY?> zG^Yb;wsr2Y66qzLBVSFTtizdUD`Mciwo_{leRRhjSU%N2r2OvQpG&K2dA^2?r@flg zS%pSW|Akq1#2BYaRjx-%XY4)>J8c^_QE*G274R3HtaE$gz?W8Y!60VWNaXYSKFfhZ z%93Ezf2V=OtgOgo>jLm({ZML(H3hx(W!hBdjAC(ke+hjV4m!*yGzz3k^2AZwbK9<% zYNbtuiR2Oe0ehUuws=!Yb6!e?_cGKFyiM3A7yI}ZaaUUwb841uxZ6q7vy^R+UcFlQ zZHb2D7$QpxEgd5qnW+~E9`qo0zpE#{QFTy0SbgQsU&+tf`W7 z*_9w~5q8(Nsx4>puR6bE#5Ox*4jhgZw%Bf|t5KlH7bS>{zOG!}516CLjFIHh-S#5j z#XM}=QN7W>jddaW6r(pyHM4A^ELR^^=W_X`e>|Oe)@gcGeCLnKlL=tMdywJPZx*(Y z(bvmi!xQ5#MyqAH`Nc(t6H6v$(g49PgZ8XUxWAL?U9$g!lE$7-?+~)`RgB6rnO1^0 z2yoC+Ekpae4u!})fZlc&&dh=^a^n>Qz!HUo6#5k^bKc>unCk83 z>332cuTFC<#nta~K8ETpNuGTF8KWP21nhXJN)~X9juf`g;4&v*^WI}zwVQZ>pRcs^ zc3aZXbGwoLhMUXmuH2>_toVmaAEEj`ZKKs^ysab1tFvFx6%RE!8pl7db(3{7=mhZ; zYOWTX7Q$)fFhh?NypA7h@i+rNjSFeInFy%;)b zdv6~F&IiP034S2nuOv<)T44M4??S{3{F7E`@ z!lx_BAq09K>B|~FLObDGq*b&1@zd=R^MiF^>(Qy0O6x4)2n?KWkIcKxEg$&@T%^m0 zXx=58ZYf{TaV0vlH^=OsjU30g_990Ap8YRrgGG zy3krbB)3#xO3g3H1W+|yV*guPNn@~!hqDvg>;itck7MtYJ$_S44TE@Zs=v2<&7^Wx zEdl&yad2rr=w@sdRyT}U-PFwX=a&|1)ot3Z9LOpTytP9A(8ItQS9``LITOdJ#n0=V z=tfh;zSCm~#Tt?k2AQahFHI!F9Us6+dJe9Jmu4{5tO;FK#EcWAQXT0T5p8T9|-L2mGe*6{g?CWlFtgf+D(pq&#a{9WyUk2fegz+ z|H?lR*uPYF9?CTt?S9{xNrZ4-29;Ra$V1_w?`fujo^tP%dNJx!Thlnyf@8AVR&`}p zVAccG-ONRSO&u?J3voRp7@RQ2R6WQO6+-6xDHc0hE zPrGHDd$FK%_R>EAPMgxFLgxn4kB1u1mg}|i1A~9lSFZkhedVTGgsd!>*k^}bF-AA@ z9*W(B1%0LbRxOFo*5}EAglS#FU`NeRty`kkepMjqXj-!1r3@+^<#h3^EOlIcIUdDb zjBc$lI%e5`fXDC~YFBq8xTSV>i@%j^*Q}Zx=Y`ilDV&~Ppq9%~wf5)iX>4%}NvX+t zhmin5rKxd8uG#B)_zp-)cKe5~oqc+7Fj~??X+Girke4HoKwCeBWx+t=M*T9m88f?e0&tnWHcZU8SP3Qj4^#A|= zN+l`ll}d7|SD{`)5_8&CsnpA1dR542MIpm5XS0z?juVx$DV5}WK5tHQ$l0(Q=eS`` zn_-)6zI%Tzm+wEYAD*W@9{0!fcD?<(14icJEft(msDQ?*j4)sD@SD6qe|h9J3*4G? zqJr6~OP+$(9lTy*2ABPVmz&Zh#gr@+$pJVu?0l6dsI~XiQmR{y7!O|==}lg?fvhn` z;&;0<*FX~&f;WhtV;%0%4N3%~0&koFp(8~-6asNl>u;tLw1f*+o#9K1;{Tp7^%J`; zc0gTP{rFXoTYsW~&1SnV^Ly2G?GS^Rw3|#tnZj^AF#dIb@Id!oSx0S2HVq(b=be$Q zAH+g%v%tfhrnM2WjwMcc+5(nvr2L?$%0*jJ@9O(p%o{uZl*F+}+aRBRhN+QvfGWkyWy1=|HmxMu}{zLZ56OYQ(6o zQp=UXF#jY6Z1-6Z5zM#rlyDGJJt5}y79j&glT=Ae>vQ$+x>hvDHl*kC+10~m3-DvB7o&C-^&wbpE zcLSTqF@8}-#L{)@vkEJ1WEi9p?iqKYGolYH`z-Cap0y3r!35@B8&|Q^P3weHv>6%aQlwS!ceyO_W3B zttb_vTA^5nRhz%v@=%phrxhG7Q>eoZ7VV8nM@7q-kEVoSRES5K^^MhUKzrmd%$0eO z$tqNQ7Nz!({P`iQf$zpGbp-0@NU|_BDT{Gue=71)Mf)-OVjoeg1??DKyZYwmHQtTP zps}QB#=fA{=W@&4A?2|%W(vIdE|wP;9Vx>yvuj(n-yL|~TY(BF>5sMc7$Vw(KGjhR z3_d&ic+VGnnF4RWb{X;B?fsSQRe27+^rOWd3andBUT5TeUojaq+6#G+Wi1)2i>q*1 zvy+(HSpFJuw0`Z?qKj+C(=U{}X+h+%`Wwil!h1_;bYqHE2yTbU-kkd`cnJw~uMuyr z+{M)gd}vgtNkg~QEvpo6Adit#42}KilB)K#u`LYIJL|VJ0t4`2NmNJ4T2j0J9tXF_ zNo+i{ntLB^c(ug3>4>cD#blqd;RBaTtYz@C&MLg__SRwlMp{k}2$HP`KlWqNW$cqe z;h(N>1bky)zmy4VW+3eKX@D)|??%$hzY*w0>YE4QMnGrlKx+;ySpe@IWzkf(yK3t5 zHM(#dtIY#Dls!IW+~B;&A!$Y8hp$4WOO;-`vW-B%q8l^cVzH zL>@9Bzy8t2x7RCVd+BM&{i=~5M$es+Q%02=-vCe+cf=kp0jo_UIMd&K(WasOkMC-# zg#iDqbn+;CPO~9B&>JoGTcEQs&I?zsr^RGSvG zy(_5#|H_H9$8E>=e<(VhL&L2E_@E@;3qRQ1t`$Ck|<+Ocuq$aJw z0nL@q&G=gkll!0R3DqL(f6-e~>f`Qh0ZYDLzKh#K&ZR`DL4J$cv&2>o7%-g~%{{Zp zyml_<3=|)*m`$SYOM)?8?FgL(@?5IeN96*Uy1e7f6DiTmTZen!(bMv&dZ4uC94s?+ zZG-Ge%JbFqbfHRF!Iw{^X~wbh?iOIKk%M}*!6C)e1VCptRC?|_r>)|V!UU^`onY#3 z(5Afr6EKs;CqCftmk1HqB7_#`TbK`-5)Twy7Gk1nu%ar`Ht>$|8ASxfGgCvv=%YDl|#eG8Z-F@&ikq}P&!U6B&b5} zF*V%0ww&mF-(OpPb-cH6iuXi+ISaiT8Dy?9KhZTLmU)xUaoVvYaEGOy1|PKRy~PS$ zR<3bWwF&KBMwBm(d8!b$I+E5%1*fmKKU>ysvn-Tg=2D$WxtjDX6i7QyuL>S(=fqZ~h)>7Rf z6p9)XMU6{a(T1#IwRW~|B-MHrnu|A16)G_-FK%!>_qGvxm8-|?g@b~#u~SL6!Ikn( zaz@!mVv(cZ7d+x6?QCfxEgm)+5LY$PeKt`w2X!+^>U>VdUjr60q;{X4`kk*w)MOan zRR~d7en7&~OBZ#CMPoHkC*kdO9fnWF@N=`sEg(_ar6Y|2vqv42bSCWK38|NZ{*5DQ z;0kwM7(WBY7vP`{ufm;`uia7#d^^ukVdQQmPS_xv%~GX+Ub-6VOgU_2;Gnv)0}CQKf1(k}UCEXSze2ds z%j=N$5^$sMy574VFXXS7rz?NLdJjV zO$h9A_lhzGuZVi81x7^Y)Hhs`uP}5DDo~}L`KI5n(k&>LM9;EvOm1j9H(0gLB8$rV z?&cN7IzvE0tf?=wR&z%US@dH#29dg})I4En1h6UQtON{p|dS%+(oxk<2a)hMU zYhOP+Ka__BY#0%Itxbr?Wsv8VFSkTGh?}hA7qcWv!rC`}lr&(Tnm#nzjR`bDVxN-j zE6J$uWoKaVa<%Ek{S*2IE{xoXANn<955g{XkB!CYD8EvSe00e2SzdPEq5qg21MADH zHE5=i)Vj%_D_o8yg92}oUS=OJH3W{gakPBn4d6dmi#L`CycsvJK0>wbvlY-)|ipXzHb32vy>Xtj9~C;rr1_l-orm&pXt_xoKI2%Lr?KS5HC{NvK^83x`K=;lr3 ziSL5?&%Bto0H%t??$_EKZ<82ejio+mCnYCfpi`!+EY+d?i=mA?=PO{y9f?TCaU~J5 z(@$S<68Z9HNJVyY+2Mr_W_#IuZOyF1w&<~D-Fv2a`qLMh!8s#&CCeQ=OQ@$>P{+0^ zqW;kztbFJ@FjC>@bw}JKL{7igI{^1nyHP?Tm*UROvg{b)hCwxkYq)p#-gt z=KNRKIpbJmwIUio<($O+VJc6hBrb)6?XT?skgh8xBygJqKhbh8c`cUHrT`OMkTY_6 z{loFl(|x3zly523^8<>*FFqbbjh5+fl@5SyNNx5I4$2|t_A~L!LN^+emnRpHR^Ggi z;VgqG^`r;Po(dH`$FP>YrA;E~aC6l2g$ktcgBQY*kgKDT6-?U zv?;R7=9jaa97?s$u-_icVbB6clA1z4Lxb*EMQpyi7Py5t#L0U}ORbD*N*}K)Z^{>` zl*y(U;uRC|ZIs(KSLOD_5MA90d_>efdk=BNAmfIC@s7F|>80Cd14cU+GDvIo5Wbrh z%u_;Y)`pOB0%+4dJ6^Wg*wAzAF_1c3B}T1CwEzfiCkFjgyZbO>dN`-$ZbZWnpV;tj z!an0M^5qMx@|f`$%Pho`H^_7!jIz`J!k+FhP3g3R$fLODZB-T0M@tnU!q#TitsC`| zP>|q(M=i_ujDhJo?d!=}+Y|~L*8s~ZCS%2H=bIWxU{+j>zgI6Ap z^R^8oW^FRut~MT6Uh-J}bgEvvIXA*2G90$+$@BUEFv<7w%A)uE-GTF&9q`|J+=mFF zwsd^#!fT^~T#5G-#!U?}2680$$WV7iet25D?0(D()exJw4y7T{4V{0r^93e)8?`w0sTq6uN*Jh&xCu#uNnR`7o7_3X^-VR?A+ZRFv06qH8_H~uTY;_awa%(!1|6c7Hn5_5dBjhD2=Z! zd|oEoPq|Q4J+k#$O0AC3Q%wSTAsQ%pv>bMj#g(k7? z`g3>mpRy#9+qXPMjXORCVOjA4(GQ`v)MzVs7vc7Adf>+mVCj0C6tN-+1n6ZdpsaKmT$&2EU}rU&4FrZU?ioxytLSl!f~ zBpNAgB6j)b1DlX!gF~;|?>u1D2e!03CUBJ;lti!^c;0;_{6@fNRTErM_o?5wmGa&% zT)NnSyo}=<*29=sz=C0zZuLG%JB?PHfMq*2=!|4IO{(Xru+KQxI2gi?arReH53bpS zN=M*jMG)}T7n1w9L@U$As<4i`1cir%N-({z(y*gTv*b6ramqm&H+qc<{_tnheP1BM z=urewu^`)FX1Vk_yh?LKS{Vg6$%)0^W)8ovc#bFrbbJ^~hM$+o%e09Z&S+>dV0_V0 zE4dqCwW`koR{4Am_x}0`phZf(BJh@8R|HSmSWHl>d?)RvY{sP@g{;1r1*&fiFgm4W zQw_=#F$@07HAc8eUCiw1T?5+<$3DVrrp8nYEh2VPvp+o-gmi--bN6dWtiQF|EI2gm z=BR_I$>q1}Nb`elYdneI^-D<=Th65fS7>Bfqlns^Y0L9-2`YN|(gnL=B6`-&%A8wB zVqaWHV@j{JW8Yg~mPow#G*t(M1{QwT9J4p!X|MZyrMDXuqPecvr5M_v-|m3YeyH-l zjaMXETRyygLt5`KH5-J_n*58|J!|TakP_JkFxbl8B!3$u&(H360X5FUZm_uX?61!n zyPMvzc^~3DRbW2ctA~Bwip@9eKTybf0STd1vWi!~Ql6lH^fII6*S}#@LKtUYUdfQa zqLJokG03_2;7tSM`p)6*o{yu+5R6H%B*p_m$pN(c%wVg~s=6V_<-=cu5~x~HF~HN# z$kWq-aN*wT!(~SHd;I%&2JKZ-iZ)b-O4-26U?$W>@-Mjiji??8m z?%eASxi@}+5sx5(9Mu5WZQ(Y_ntT8`j-6(e4n^OI=nhDQxmP?}&;QZ#eb;J!se4;v zDyjb$aajkq@{%+B1>7*Rc_n4B0x73FC*-K(R>M|$HGlHIR+#n;saEk45Tya2Hzq0D zY0^;iyrsJUSeT*RLLA3a>q+vx5gWvm2{%$n4u)wrxF^J-BeU{v8{G9Wn^i60YER}$ znmH)$*Ktu6M;!QJkZC9x)@CG`E-M><^-%Jv!xxpGeNvL7Wr{?o6rTqEz>&^>xyz z1hxbxDZhH5v3l$N6jcT47RClF)g8`M^>xiGd|6~WpfWzKFAD?&io?=RBv*B!@}A1T0*OTpY|S=f84BI?Yt=CiR2E8@thtc z?Xq_rI}G2P6e+Ye-)p$mtWTq?Cynk|Bpav{cp0>j^S?_Q2iYKcuWv8fx0QzcQea2n z@V$q9th+Kk%y#){$85S+j#zLv`V(XPe!IWP!OqK&&vcc`xx3G~H|)$NLRO7dsxwIu zqUG4aN;PT3-e~G_XL2M=#Nfa_&_ca)337`ua`nyd$U z&+-j^;TU%xZ6ZOZjr7Vr{`RQ!VM|+S9e{cuVt>q~ss=Ad6Gpx@c=fF(jim=Z>{?YH z)~y?P2l@hf7%j1WG~pF*#JVI@I=e(Rd5$WHJ39jvDpRIFo*P-?BFWZYq|(3oLn*4B zoWCWu7BY`gL5o%~RU1oRHvOcNcYJ)|lX+0&v2Fq)i8{^5W!Y!xDWMD(QIU<%$>7M#Yy z9~}7;>{&iFda~@y4a(^2;9Su4oaXKGCD&=KQ3wOcZ|lFGH~EyM2W=lHe`tIFzc_mT z40_u=IqI%WiA%7I42GLvS~Q!=Q~`nA^_q$L3|3PeV_p;u#IY-w;f0U|Qpl^cf?OL2 zYW2I{nkvLGxw40lZX>I0tUB?9_+QA^U1gshLw4@&2w&I8O$(?w!ixsK>V#&ZGHa)Q z*cu=zCZpkP;R0dQCTJX%Uw69S4vFwYes5``guhAqZHvpxgvU9XxUQOqWWq^3FA%Vj zcHI|$qBk$dFfU-XDa-(OLaA@8_8#XSi!5~Qlh{ znS;{cRSvVk$h_6Gz>t!Uby`&NHvjqFOX;8Jo~nkzmQqdgt-J~#Tf3R-xz7S{Q~21T z^5ut2J-a}!Gg$N;bGJQj;Q{Do-q<~I)p}9e9nsPIMx3Jr4LMF@U)<-ZD@L^L zg{kD_PGsv4g8+?ATx3*xUiOEge|ecl4vYpum7JqD0aWY_xFt*c3g@P%VFSaT~tOo`ub9C1_uribA}{AL_e?+920w2e$Xq%bzxh(D(-6{g;mr| zIBmtIj8aeauW)ta*XHE**#EYuVh>eu{QJt*Yb?h!xj&ApH%4PsPv9A??#F=a4$)u4 zm#UQ#Gp$G1qqRNGwEN)b==>0i`USN~BFWmrwmvP4(IheYYFuzWg0*wejCW)(C3b@q z+9|WDs0!jO$iOD%So$JHY3OW)C}F=HfPoH-*J&+|piQS9>r9IzAta+=`WNIt55-SG z6Qw|biBfOi`4#s~)XrfRyVQNS2H#s|Y@S1D^ADVL9HXtqB|X9IdB;a0U#y=y4_oPg zio!XRXyv`a=R5Mk19y}|sSw1Y7V9kBBpf15BsqHREkT7Y{7socRIAi#=IR9nrdWf) z5SXTr;vJ9T3X>{QAdC}_lM0~!X1xDLOqCaoSGYcdbXdR34Z(9t8vv^Svb zYhdLX%LugOFELw=KXN<27rW45m9KJ2Mh_>eXJh2DfcR8LX2)I4gcGqtL= z{PO_HkRq!e)3Vk4IVRPJ{L4#9{+hendwtYAe4CS?ux-*Wf7%`nXzaq2=pbG@3{*;J zH`B1gQ{Uv4NyCC$&Xo)DJr&D#UJ*WogAn&`u()mn;3O&mpew>VgarIKVaa1N^-rn~ z)aYH(IUky?edhfGj|0;`uG%{?PYxV-j~P@w!tRzHiu(U90FU$pov^r-isB99pBlOm zf|Q9xR==|WAIIIIT{>quzd?8SrVQCw+aH|NJk+G%SW?Y4mncJC#Rp7TkJr1{+@L;b zcnsTcZS8x1CfhJg!Sot!Q{CocHhV;NQcti_=*QOj;>G)4OkLN2@kB(3`fd~rQ=x)$ zHpXM1bC7~7$mL=a54*&+tgU<{Ti2$UYh$SRj*)vPZU?R{seFl=1iG*KuI`R{$n302 z$mD$+0PzGUZ6C;qmsZ!>)_tcFrUb3XntG3$4W<56u!*-_Wh?o5RI_F~WyhX^8 z_0~H=`2y*x8~2}bl!{sTQXa$RjW^MfBWmr4yt?jikdEQBh8O;rR}9n}elaJ^Rlh_& z;Lza?{Sw&w3kF?O(IE@t*7i{kI zgNv7~=icLIX#stNkyBvjn>7nYyZ7LEsH)1+s^#?U-lekkdo|bBQO}jr7P;ig3<3=Q zAt3U@Cx4~5**5M;+l0=Vn+1(W&-S+7zmwSiNOLUp%`0c6qf;{)a#Qz$9ny<)5VMQt z6|$~Ocs4L{8;Qv%^h=0br*<1gB0n(e;<&@<-JlMqU}|c2raZgq;KG0C-I3?=sZmW> z)h|Fb@*_N+{hJ))OVolarPuGQ6m4&+D14>u{fk{MsNmFaA?=)F5fs@}4Cd&Wvo_&9 z1tSx4750;lXU1$hvj#MP<8EJJl2JmZ2K!eJa&=>Pe;By&9lz(?t+bLC3NYP4Q3>iI zM{5D>RUg~OTWe~c011uCdOz(hhDjj+O4M(9ztA1^!|B}tzx(o4bhe&(6zt#nde3&4 zKg3wX1WOnD?JP@9ML$ALwq)xiZw=H&Y+|1>0&mU9NB!`7y|Oa=)Ii;R=^$w@mr{F! zY6-YUd?d>tNt!8q+aoQ)^=Iq{OMN@uRS;pp|J6hjJ{O=;H3+Q{0VK!zoG#m7FIS0R z4G0ax{n%?fzPfk6`|BvuP3!OY&Ll@kg}AE*G9LSGbv8;(e<2@2ye=Tk2P($ih%-BrO*m=HfheL5xO&ls_8R*nDNXf6u;3KNNw{A8JWjP* zyE=kC)BoddJaq_rBXIFl8poti_I(NdOl#TkOmMSIk#02Y+-mCH3YAjf_D!8n?hiJV z<2(Ti@%F&{A}wvo_FtI87RQrYM${?&!$<8#UZ=%_?coPr